diff --git a/roles/ntp_client/tasks/main.yml b/roles/ntp_client/tasks/main.yml index 8f9c83f..0584a5c 100644 --- a/roles/ntp_client/tasks/main.yml +++ b/roles/ntp_client/tasks/main.yml @@ -1,5 +1,12 @@ --- +- include_vars: "{{ item }}" + with_first_found: + - vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml + - vars/{{ ansible_distribution }}.yml + - vars/{{ ansible_os_family }}.yml + tags: ntp + - name: Check if systemd-timesyncd is available stat: path=/lib/systemd/systemd-timesyncd register: systemd_timesyncd @@ -10,20 +17,12 @@ when: systemd_timesyncd.stat.exists tags: ntp -- name: Check if samba expose ntp_signd socket - stat: path=/var/lib/samba/ntp_signd/socket - register: ntp_samba_signd - tags: ntp - -- include_tasks: install_{{ ansible_os_family }}.yml - tags: ntp - -- name: Deploy ntp configuration - template: src=ntp.conf.j2 dest=/etc/ntp.conf - notify: restart ntpd - when: samba_role is defined and (samba_role == 'dc' or samba_role == 'rodc') +- name: Install Chrony + package: name=chrony tags: ntp + # Always close port, it's only used as a server on samba DC, where port 123 is opened + # by the samba role - name: Handle ntpd port iptables_raw: name: ntpd_port @@ -32,23 +31,17 @@ tags: ntp - name: Check if ntpd is installed - stat: path=/lib/systemd/system/{{ ntp_service }}.service + stat: path=/lib/systemd/system/{{ ntp_ntpd_service }}.service register: ntp_unit tags: ntp - # Samba DC use ntpd, all the other can shut it down and use chrony only + # If ntpd is installed, stop and disable it - name: Handle ntpd service - service: - name: "{{ ntp_service }}" - state: "{{ (samba_role is defined and (samba_role == 'dc' or samba_role == 'rodc')) | ternary('started','stopped') }}" - enabled: "{{ (samba_role is defined and (samba_role == 'dc' or samba_role == 'rodc')) | ternary(True,False) }}" + service: name={{ ntp_ntpd_service }} state=stopped enabled=False when: ntp_unit.stat.exists tags: ntp -- name: start and enable chrony - service: - name: "{{ chrony_service }}" - state: "{{ (samba_role is defined and (samba_role == 'dc' or samba_role == 'rodc')) | ternary('stopped','started') }}" - enabled: "{{ (samba_role is defined and (samba_role == 'dc' or samba_role == 'rodc')) | ternary(False,True) }}" +- name: Start and enable chrony + service: name={{ ntp_chrony_service }} state=started enabled=True tags: ntp -... + diff --git a/roles/ntp_client/templates/chrony.conf.j2 b/roles/ntp_client/templates/chrony.conf.j2 index 8f9c5a9..2c67b1d 100644 --- a/roles/ntp_client/templates/chrony.conf.j2 +++ b/roles/ntp_client/templates/chrony.conf.j2 @@ -1,11 +1,12 @@ {% for server in ntp_servers %} server {{ server }} iburst {% endfor %} -{% if ansible_os_family == 'Debian' %} -keyfile /etc/chrony/chrony.keys -{% elif ansible_os_family == 'RedHat' %} -keyfile /etc/chrony.keys -{% endif %} +keyfile {{ ntp_chrony_keyfile }} driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync +{% if samba_role is defined and samba_role in ['dc','rodc'] %} +# Running Samba DC +ntpsigndsocket /var/lib/samba/ntp_signd +allow all +{% endif %} diff --git a/roles/ntp_client/vars/CentOS-7.yml b/roles/ntp_client/vars/CentOS-7.yml new file mode 100644 index 0000000..cf8b402 --- /dev/null +++ b/roles/ntp_client/vars/CentOS-7.yml @@ -0,0 +1,6 @@ +--- + +ntp_ntpd_service: ntpd +ntp_chrony_service: chronyd +ntp_chrony_conf: /etc/chrony.conf +ntp_chrony_keyfile: /etc/chrony.keys diff --git a/roles/ntp_client/vars/CentOS-8.yml b/roles/ntp_client/vars/CentOS-8.yml new file mode 100644 index 0000000..cf8b402 --- /dev/null +++ b/roles/ntp_client/vars/CentOS-8.yml @@ -0,0 +1,6 @@ +--- + +ntp_ntpd_service: ntpd +ntp_chrony_service: chronyd +ntp_chrony_conf: /etc/chrony.conf +ntp_chrony_keyfile: /etc/chrony.keys diff --git a/roles/ntp_client/vars/Debian-10.yml b/roles/ntp_client/vars/Debian-10.yml new file mode 100644 index 0000000..1f3c307 --- /dev/null +++ b/roles/ntp_client/vars/Debian-10.yml @@ -0,0 +1,6 @@ +--- + +ntp_ntpd_service: ntp +ntp_chrony_service: chrony +ntp_chrony_conf: /etc/chrony/chrony.conf +ntp_chrony_keyfile: /etc/chrony/chrony.keys diff --git a/roles/ntp_client/vars/Debian-8.yml b/roles/ntp_client/vars/Debian-8.yml new file mode 100644 index 0000000..1f3c307 --- /dev/null +++ b/roles/ntp_client/vars/Debian-8.yml @@ -0,0 +1,6 @@ +--- + +ntp_ntpd_service: ntp +ntp_chrony_service: chrony +ntp_chrony_conf: /etc/chrony/chrony.conf +ntp_chrony_keyfile: /etc/chrony/chrony.keys diff --git a/roles/ntp_client/vars/Debian-9.yml b/roles/ntp_client/vars/Debian-9.yml new file mode 100644 index 0000000..1f3c307 --- /dev/null +++ b/roles/ntp_client/vars/Debian-9.yml @@ -0,0 +1,6 @@ +--- + +ntp_ntpd_service: ntp +ntp_chrony_service: chrony +ntp_chrony_conf: /etc/chrony/chrony.conf +ntp_chrony_keyfile: /etc/chrony/chrony.keys diff --git a/roles/repo_samba4/tasks/main.yml b/roles/repo_samba4/tasks/main.yml index 80db7f3..8d64cb0 100644 --- a/roles/repo_samba4/tasks/main.yml +++ b/roles/repo_samba4/tasks/main.yml @@ -11,6 +11,7 @@ includepkgs: - sssd* - libsss* + tags: repo,samba - name: Configure TIS samba repo yum_repository: @@ -19,3 +20,4 @@ baseurl: http://samba.tranquil.it/centos$releasever/{{ samba_major_version }}/ gpgcheck: True gpgkey: https://samba.tranquil.it/RPM-GPG-KEY-TISSAMBA-7 + tags: repo,samba diff --git a/roles/rsync_server/tasks/main.yml b/roles/rsync_server/tasks/main.yml index 1b1dafb..d5707e8 100644 --- a/roles/rsync_server/tasks/main.yml +++ b/roles/rsync_server/tasks/main.yml @@ -1,16 +1,14 @@ --- -- name: Install packages - yum: - name: - - rsync - - libsemanage-python - when: ansible_os_family == 'RedHat' +- include_vars: "{{ item }}" + with_first_found: + - vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml + - vars/{{ ansible_distribution }}.yml + - vars/{{ ansible_os_family }}.yml tags: rsync - name: Install packages - apt: name=rsync - when: ansible_os_family == 'Debian' + package: name={{ rsync_packages }} tags: rsync - name: Handle rsyncd port diff --git a/roles/rsync_server/vars/CentOS-7.yml b/roles/rsync_server/vars/CentOS-7.yml new file mode 100644 index 0000000..a166ecc --- /dev/null +++ b/roles/rsync_server/vars/CentOS-7.yml @@ -0,0 +1,5 @@ +--- + +rsync_packages: + - rsync + - libsemanage-python diff --git a/roles/rsync_server/vars/CentOS-8.yml b/roles/rsync_server/vars/CentOS-8.yml new file mode 100644 index 0000000..a397531 --- /dev/null +++ b/roles/rsync_server/vars/CentOS-8.yml @@ -0,0 +1,6 @@ +--- + +rsync_packages: + - rsync + - rsync-daemon + - python3-libsemanage diff --git a/roles/rsync_server/vars/Debian-10.yml b/roles/rsync_server/vars/Debian-10.yml new file mode 100644 index 0000000..71f7cce --- /dev/null +++ b/roles/rsync_server/vars/Debian-10.yml @@ -0,0 +1,4 @@ +--- + +rsync_packages: + - rsync diff --git a/roles/samba/meta/main.yml b/roles/samba/meta/main.yml index 67d3fd6..c02a913 100644 --- a/roles/samba/meta/main.yml +++ b/roles/samba/meta/main.yml @@ -1,6 +1,7 @@ --- dependencies: - role: repo_samba4 + - role: repo_base - role: mkdir - role: rsync_server when: diff --git a/roles/samba/tasks/conf.yml b/roles/samba/tasks/conf.yml new file mode 100644 index 0000000..07f38d5 --- /dev/null +++ b/roles/samba/tasks/conf.yml @@ -0,0 +1,188 @@ +--- + +- name: Setup env var for ldb tools + copy: src=ldb_modules_samba.sh dest=/etc/profile.d/ldb_modules_samba.sh mode=755 + tags: samba + +- name: Link our DC keytab to the system keytab + file: src=/var/lib/samba/private/secrets.keytab dest=/etc/krb5.keytab state=link remote_src=True force=True + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba + + # This is for DC where their principal is added as uppercase HOST/FQDN + # it mostly work, except for ssh kerberos auth which requires lower case host/fqdn principal +- name: Check if the keytab contains lowercase host principal + shell: klist -k /etc/krb5.keytab | grep 'host/{{ ansible_hostname }}.{{ samba_realm }}' + ignore_errors: True + when: samba_role == 'dc' or samba_role == 'rodc' + changed_when: False + register: samba_lc_principal + tags: samba + +- name: Add lower case host principal to the keytab file + command: samba-tool domain exportkeytab /etc/krb5.keytab --principal=host/{{ ansible_hostname }}.{{ samba_realm }} + when: + - samba_role == 'dc' or samba_role == 'rodc' + - samba_lc_principal.stdout_lines | length < 1 + tags: samba + +- name: Add a tmpfiles.d snippet for permissions on ntp_signd socket dir + copy: content="d /var/lib/samba/ntp_signd 750 root chrony" dest=/etc/tmpfiles.d/samba_ntp.conf + when: samba_role == 'dc' or samba_role == 'rodc' + register: samba_tmpfiles + tags: samba + +- name: Create tmpfiles + command: systemd-tmpfiles --create + when: samba_tmpfiles.changed + tags: samba + +- name: Deploy rsyncd snippet + template: src=rsyncd.conf.j2 dest=/etc/rsyncd.conf.d/samba_dc.conf + when: samba_i_am_primary_dc == True + tags: samba + +- name: Remove rsyncd snippet + file: path=/etc/rsyncd.conf.d/samba_dc.conf state=absent + when: not samba_i_am_primary_dc == True + tags: samba + +- name: Deploy sysvol rsync password file + copy: content={{ (samba_sysvol_rsync_pass is defined) | ternary(samba_i_am_primary_dc | ternary('sysvol-replication:','') + samba_sysvol_rsync_pass,'# No password defined') }} dest=/etc/samba/rsync-sysvol.secret mode=600 + tags: samba + +- name: Setup cron to sync sysvol from primary DC + cron: + name: samba_sync_sysvol + cron_file: samba_sync_sysvol + minute: '*/16' + user: root + job: rsync -XAavz --delete-after {{ (samba_sysvol_rsync_pass is defined) | ternary('--password-file=/etc/samba/rsync-sysvol.secret','') }} rsync://{{ (samba_sysvol_rsync_pass is defined) | ternary('sysvol-replication@','') }}{{ samba_primary_dc }}/sysvol/ /var/lib/samba/sysvol/ + state: "{{ samba_i_am_primary_dc | ternary('absent','present') }}" + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba + +- name: Deploy dehydrated hook + copy: src=dehydrated_deploy_hook dest=/etc/dehydrated/hooks_deploy_cert.d/samba.sh mode=755 + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba + +- name: Remove dehydrated hook + file: path=/etc/dehydrated/hooks_deploy_cert.d/samba.sh state=absent + when: samba_role != 'dc' and samba_role != 'rodc' + tags: samba + +- name: Create DH param + command: openssl dhparam -out /var/lib/samba/private/tls/dhparam.pem 2048 + args: + creates: /var/lib/samba/private/tls/dhparam.pem + tags: samba + +- name: Deploy smb.conf + template: src=smb.conf.j2 dest=/etc/samba/smb.conf + notify: reload samba + tags: samba + +- name: Check if there's a shares.conf snippet + stat: path=/etc/samba/smb.conf.d/shares.conf + register: samba_shares_snippet + tags: samba + +- name: Deploy an empty shares conf snippet + copy: content="# No shares defined yet" dest=/etc/samba/smb.conf.d/shares.conf + when: not samba_shares_snippet.stat.exists + tags: samba + +- name: Check if /etc/krb5.conf exists + stat: path=/etc/krb5.conf + register: samba_krb5_conf + tags: samba + +- name: Start and enable the samba daemon + service: name=samba state=started enabled=True + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba + +- name: Reconfigure sssd + include_role: name=sssd_ad_auth + when: + - not samba_krb5_conf.stat.exists + tags: samba + +- name: Check if winbind_cache exists + stat: path=/var/lib/samba/winbindd_cache.tdb + register: samba_winbind_cache + tags: samba + +- include_tasks: member_join.yml + when: + - samba_role == 'member' + - not samba_winbind_cache.stat.exists + +- name: Start and enable the smb daemon + service: name=smb state=started enabled=True + when: samba_role != 'dc' and samba_role != 'rodc' + tags: samba + + # Here we just read the actual policy. This way, on the next task, we can update only the items we need +- name: Check current password policy + shell: "samba-tool domain passwordsettings show | perl -ne 'm/^{{ samba_pwd_policy_descriptions[item] }}: (.*)/ && print $1'" + register: samba_dc_current_pwd_policy + changed_when: False + with_items: "{{ samba_pwd_policy.keys() | list }}" + when: samba_i_am_primary_dc == True + tags: samba + +- name: Set password policy + command: samba-tool domain passwordsettings set --{{ item.item }}={{ samba_pwd_policy[item.item] }} + with_items: "{{ samba_dc_current_pwd_policy.results }}" + when: + - samba_i_am_primary_dc == True + - item.stdout | string != samba_pwd_policy[item.item] | string + tags: samba + +- name: Add default zones to the list of managed ones + set_fact: samba_dns_zones={{ samba_dns_zones | default([]) + [ samba_realm | lower, '_msdcs.' + samba_realm | lower ] }} + when: samba_i_am_primary_dc == True + tags: samba + +- name: Check existing DNS zones + shell: >- + samba-tool dns zonelist {{ ansible_all_ipv4_addresses | first }} + -U Administrator --password={{ samba_dc_admin_pass | quote }} | + perl -ne 'm/pszZoneName\s+:\s+(.*)/ && print "$1\n"' + register: samba_existing_zones + #no_log: True + changed_when: False + when: samba_i_am_primary_dc == True + tags: samba + +- name: Create DNS zones + command: >- + samba-tool dns zonecreate {{ ansible_all_ipv4_addresses | first }} + {{ item }} -U Administrator --password={{ samba_dc_admin_pass | quote }} + #no_log: True + when: samba_i_am_primary_dc == True + with_items: "{{ samba_dns_zones | difference(samba_existing_zones.stdout_lines) }}" + tags: samba + +- name: Remove DNS zones + command: >- + samba-tool dns zonedelete {{ ansible_all_ipv4_addresses | first }} + {{ item }} -U Administrator --password={{ samba_dc_admin_pass | quote }} + #no_log: True + when: + - samba_i_am_primary_dc == True + - samba_remove_unmanaged_dns_zones == True + with_items: "{{ samba_existing_zones.stdout_lines | difference(samba_dns_zones) }}" + tags: samba + +- name: Deploy pre and post backup script + template: src={{ item.src }} dest={{ item.dest }} mode=755 + with_items: + - src: samba_pre_backup.sh.j2 + dest: /etc/backup/pre.d/samba.sh + - src: samba_post_backup.sh.j2 + dest: /etc/backup/post.d/samba.sh + tags: samba + diff --git a/roles/samba/tasks/directory.yml b/roles/samba/tasks/directory.yml new file mode 100644 index 0000000..9e60125 --- /dev/null +++ b/roles/samba/tasks/directory.yml @@ -0,0 +1,18 @@ +--- + +- name: Create samba tls dir + file: path=/var/lib/samba/private/tls state=directory mode=700 + tags: samba + +- name: Create rsyncd conf snippet dir + file: path=/etc/rsyncd.conf.d/ state=directory + tags: samba + +- name: Create samba scripts dir + file: path=/var/lib/samba/scripts state=directory + tags: samba + +- name: Create conf.d directory + file: path=/etc/samba/smb.conf.d/ state=directory + tags: samba + diff --git a/roles/samba/tasks/facts.yml b/roles/samba/tasks/facts.yml new file mode 100644 index 0000000..edb2505 --- /dev/null +++ b/roles/samba/tasks/facts.yml @@ -0,0 +1,38 @@ +--- + +- set_fact: samba_tls_cert={{ '/var/lib/dehydrated/certificates/certs/' + samba_letsencrypt_cert + '/fullchain.pem' }} + when: samba_letsencrypt_cert is defined + tags: [cert,samba] + +- set_fact: samba_tls_key={{ '/var/lib/dehydrated/certificates/certs/' + samba_letsencrypt_cert + '/privkey.pem' }} + when: samba_letsencrypt_cert is defined + tags: [cert,samba] + +- set_fact: samba_i_am_primary_dc={{ (inventory_hostname == samba_primary_dc and samba_role == 'dc') | ternary(True,False) }} + tags: samba + +- name: Merge custom password complexity rules with default ones + set_fact: samba_pwd_policy={{ samba_base_pwd_policy | combine(samba_pwd_policy) }} + tags: samba + +- include_vars: "{{ item }}" + with_first_found: + - vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml + - vars/{{ ansible_distribution }}.yml + - vars/{{ ansible_os_family }}.yml + tags: samba + +- name: Set a default samba domain + set_fact: samba_domain={{ ansible_domain | regex_replace('\.[a-z]+$','') }} + when: samba_domain is not defined + tags: samba + +- name: Check if domain is provisionned + stat: path=/var/lib/samba/sysvol/{{ samba_realm }} + register: samba_dc_sysvol + tags: samba + +- name: Add rsyncd port to the list of ports + set_fact: samba_dc_tcp_ports={{ samba_dc_tcp_ports + ['873'] }} + when: samba_i_am_primary_dc == True + tags: samba diff --git a/roles/samba/tasks/install.yml b/roles/samba/tasks/install.yml new file mode 100644 index 0000000..7d70759 --- /dev/null +++ b/roles/samba/tasks/install.yml @@ -0,0 +1,96 @@ +--- + +- name: Install common packages + yum: name={{ samba_common_packages }} + tags: samba + +- name: Install DC components + yum: name={{ samba_dc_packages }} + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba + + # sssd-libwbclient breaks DC so only install on members +- name: Install members components + yum: name=sssd-libwbclient + when: + - samba_role != 'dc' + - samba_role != 'rodc' + tags: samba + +- name: Remove config files + file: path={{ item }} state=absent + with_items: + - /etc/samba/smb.conf + - /etc/krb5.conf + when: + - samba_role == 'dc' or samba_role == 'rodc' + - not samba_dc_sysvol.stat.exists + tags: samba + +- name: Stop samba services + service: name={{ item }} state=stopped + with_items: + - samba + - smb + - nmb + when: + - samba_role == 'dc' or samba_role == 'rodc' + - not samba_dc_sysvol.stat.exists + tags: samba + + # We need to have our correct hostname before joining the domain !! +- name: Set system hostname + hostname: name={{ system_hostname | default(inventory_hostname | regex_replace('^([^\.]+)\..*','\\1')) }} + tags: samba + +- name: Try to join the domain (as DC) + command: >- + samba-tool domain join {{ samba_realm }} DC + --dns-backend SAMBA_INTERNAL + --realm {{ samba_realm }} + -U Administrator + --password={{ samba_dc_admin_pass | quote }} + when: + - samba_role == 'dc' + - not samba_dc_sysvol.stat.exists + register: samba_dc_join + ignore_errors: True + tags: samba + + # If we're not the primary domain, and we can't join the domain + # and we haven't done it yet, we must fail +- name: Fail if not the primary DC and joining the domain failed + fail: msg="Failed to join the domaine" + when: + - samba_dc_join is defined + - samba_dc_join.rc is defined + - samba_dc_join.rc != 0 + - not samba_i_am_primary_dc == True + - not samba_dc_sysvol.stat.exists + tags: samba + +- name: Provision the domain + command: >- + samba-tool domain provision --server-role=dc + --dns-backend SAMBA_INTERNAL --realm {{ samba_realm }} + --domain {{ samba_domain }} --use-rfc2307 + --adminpass={{ samba_dc_admin_pass | quote }} + when: + - not samba_dc_sysvol.stat.exists + - samba_i_am_primary_dc == True + - samba_dc_join.rc != 0 + tags: samba + +- name: Join the domain (as RODC) + command: >- + samba-tool domain join {{ samba_realm }} RODC + --dns-backend SAMBA_INTERNAL + --realm {{ samba_realm }} + -U Administrator + --password={{ samba_dc_admin_pass | quote }} + no_log: True + when: + - samba_role == 'rodc' + - not samba_dc_sysvol.stat.exists + tags: samba + diff --git a/roles/samba/tasks/iptables.yml b/roles/samba/tasks/iptables.yml new file mode 100644 index 0000000..7ccaff5 --- /dev/null +++ b/roles/samba/tasks/iptables.yml @@ -0,0 +1,27 @@ +--- + +- name: Handle DNS ports + iptables_raw: + name: samba_dns_ports + state: "{{ (samba_dns_src_ip | length > 0) | ternary('present','absent') }}" + rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_dns_ports | join(',') }} -s {{ samba_dns_src_ip | join(',') }} -j ACCEPT\n + -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_dns_ports | join(',') }} -s {{ samba_dns_src_ip | join(',') }} -j ACCEPT" + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba,firewall + +- name: Handle DC services ports + iptables_raw: + name: samba_dc_ports + state: "{{ (samba_dc_src_ip | length > 0) | ternary('present','absent') }}" + rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_dc_tcp_ports | join(',') }} -s {{ samba_dc_src_ip | join(',') }} -j ACCEPT\n + -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_dc_udp_ports | join(',') }} -s {{ samba_dc_src_ip | join(',') }} -j ACCEPT" + when: samba_role == 'dc' or samba_role == 'rodc' + tags: samba,firewall + +- name: Handle other ports + iptables_raw: + name: samba_file_ports + state: "{{ (samba_file_src_ip | length > 0) | ternary('present','absent') }}" + rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_file_tcp_ports | join(',') }} -s {{ samba_file_src_ip | join(',') }} -j ACCEPT\n + -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_file_udp_ports | join(',') }} -s {{ samba_file_src_ip | join(',') }} -j ACCEPT" + tags: samba,firewall diff --git a/roles/samba/tasks/main.yml b/roles/samba/tasks/main.yml index a03a1d5..61f7d6e 100644 --- a/roles/samba/tasks/main.yml +++ b/roles/samba/tasks/main.yml @@ -1,377 +1,11 @@ --- -- set_fact: samba_tls_cert={{ '/var/lib/dehydrated/certificates/certs/' + samba_letsencrypt_cert + '/fullchain.pem' }} - when: samba_letsencrypt_cert is defined - tags: [cert,samba] -- set_fact: samba_tls_key={{ '/var/lib/dehydrated/certificates/certs/' + samba_letsencrypt_cert + '/privkey.pem' }} - when: samba_letsencrypt_cert is defined - tags: [cert,samba] -- set_fact: samba_i_am_primary_dc={{ (inventory_hostname == samba_primary_dc and samba_role == 'dc') | ternary(True,False) }} - tags: samba -- name: Merge custom password complexity rules with default ones - set_fact: samba_pwd_policy={{ samba_base_pwd_policy | combine(samba_pwd_policy) }} - tags: samba - -- name: Install common packages - yum: - name: - - samba - - samba-client - - sssd-winbind-idmap - - openldap-clients - - policycoreutils-python - - tdb-tools - tags: samba - -- name: Install DC components - yum: - name: - - samba-dc - - ldb-tools - - krb5-workstation - - python36-markdown - - patch - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - - # sssd-libwbclient breaks DC so only install on members -- name: Install members components - yum: name=sssd-libwbclient - when: - - samba_role != 'dc' - - samba_role != 'rodc' - tags: samba - -- name: Setup env var for ldb tools - copy: src=ldb_modules_samba.sh dest=/etc/profile.d/ldb_modules_samba.sh mode=755 - tags: samba - -- name: Set a default samba domain - set_fact: samba_domain={{ ansible_domain | regex_replace('\.[a-z]+$','') }} - when: samba_domain is not defined - tags: samba - -- name: Check if domain is provisionned - stat: path=/var/lib/samba/sysvol/{{ samba_realm }} - register: samba_dc_sysvol - tags: samba - -- name: Remove config files - file: path={{ item }} state=absent - with_items: - - /etc/samba/smb.conf - - /etc/krb5.conf - when: - - samba_role == 'dc' or samba_role == 'rodc' - - not samba_dc_sysvol.stat.exists - tags: samba - -- name: Stop samba services - service: name={{ item }} state=stopped - with_items: - - samba - - smb - - nmb - when: - - samba_role == 'dc' or samba_role == 'rodc' - - not samba_dc_sysvol.stat.exists - tags: samba - -- name: Add rsyncd port - set_fact: samba_dc_tcp_ports={{ samba_dc_tcp_ports + ['873'] }} - when: samba_i_am_primary_dc == True - tags: samba - -- name: Handle DNS ports - iptables_raw: - name: samba_dns_ports - state: "{{ (samba_dns_src_ip | length > 0) | ternary('present','absent') }}" - rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_dns_ports | join(',') }} -s {{ samba_dns_src_ip | join(',') }} -j ACCEPT\n - -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_dns_ports | join(',') }} -s {{ samba_dns_src_ip | join(',') }} -j ACCEPT" - when: - - iptables_manage | default(True) - - samba_role == 'dc' or samba_role == 'rodc' - tags: samba,firewall - -- name: Handle DC services ports - iptables_raw: - name: samba_dc_ports - state: "{{ (samba_dc_src_ip | length > 0) | ternary('present','absent') }}" - rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_dc_tcp_ports | join(',') }} -s {{ samba_dc_src_ip | join(',') }} -j ACCEPT\n - -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_dc_udp_ports | join(',') }} -s {{ samba_dc_src_ip | join(',') }} -j ACCEPT" - when: - - iptables_manage | default(True) - - samba_role == 'dc' or samba_role == 'rodc' - tags: samba,firewall - -- name: Handle other ports - iptables_raw: - name: samba_file_ports - state: "{{ (samba_file_src_ip | length > 0) | ternary('present','absent') }}" - rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ samba_file_tcp_ports | join(',') }} -s {{ samba_file_src_ip | join(',') }} -j ACCEPT\n - -A INPUT -m state --state NEW -p udp -m multiport --dports {{ samba_file_udp_ports | join(',') }} -s {{ samba_file_src_ip | join(',') }} -j ACCEPT" +- include: facts.yml +- include: directory.yml +- include: install.yml +- include: conf.yml +- include: selinux.yml + when: ansible_selinux.status == 'enabled' +- include: iptables.yml when: iptables_manage | default(True) - tags: samba,firewall - - # We need to have our correct hostname before joining the domain !! -- name: Set system hostname - hostname: name={{ system_hostname | default(inventory_hostname | regex_replace('^([^\.]+)\..*','\\1')) }} - tags: samba - -- name: Try to join the domain (as DC) - command: samba-tool domain join {{ samba_realm }} DC --dns-backend SAMBA_INTERNAL --realm {{ samba_realm }} -U Administrator --password={{ samba_dc_admin_pass | quote }} - when: - - samba_role == 'dc' - - not samba_dc_sysvol.stat.exists - register: samba_dc_join - ignore_errors: True - tags: samba - - # If we're not the primary domain, and we can't join the domain - # and we haven't done it yet, we must fail -- name: Fail if not the primary DC and joining the domain failed - fail: msg="Failed to join the domaine" - when: - - samba_dc_join is defined - - samba_dc_join.rc is defined - - samba_dc_join.rc != 0 - - not samba_i_am_primary_dc == True - - not samba_dc_sysvol.stat.exists - tags: samba - -- name: Provision the domain - command: samba-tool domain provision --server-role=dc --dns-backend SAMBA_INTERNAL --realm {{ samba_realm }} --domain {{ samba_domain }} --use-rfc2307 --adminpass={{ samba_dc_admin_pass | quote }} - when: - - not samba_dc_sysvol.stat.exists - - samba_i_am_primary_dc == True - - samba_dc_join.rc != 0 - tags: samba - -- name: Join the domain (as RODC) - command: samba-tool domain join {{ samba_realm }} RODC --dns-backend SAMBA_INTERNAL --realm {{ samba_realm }} -U Administrator --password={{ samba_dc_admin_pass | quote }} - no_log: True - when: - - samba_role == 'rodc' - - not samba_dc_sysvol.stat.exists - tags: samba - -- name: Link our DC keytab - file: src=/var/lib/samba/private/secrets.keytab dest=/etc/krb5.keytab state=link remote_src=True - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - - # This is for DC where their principal is added as uppercase HOST/FQDN - # it mostly work, except for ssh kerberos auth which requires lower case host/fqdn principal -- name: Check if the keytab contains lowercase host principal - shell: klist -k /etc/krb5.keytab | grep 'host/{{ ansible_hostname }}.{{ samba_realm }}' - ignore_errors: True - when: samba_role == 'dc' or samba_role == 'rodc' - changed_when: False - register: samba_lc_principal - tags: samba - -- name: Add lower case host principal to the keytab file - command: samba-tool domain exportkeytab /etc/krb5.keytab --principal=host/{{ ansible_hostname }}.{{ samba_realm }} - when: - - samba_role == 'dc' or samba_role == 'rodc' - - samba_lc_principal.stdout_lines | length < 1 - tags: samba - -- name: Add a tmpfiles.d snippet for permission on ntp_signd socket dir - copy: content="d /var/lib/samba/ntp_signd 750 root ntp" dest=/etc/tmpfiles.d/samba_ntp.conf - when: samba_role == 'dc' or samba_role == 'rodc' - notify: systemd-tmpfiles - tags: sambai - -- name: Set correct SELinux context on the ntp_signd socket dir - sefcontext: - target: "/var/lib/samba/ntp_signd(/.*)?" - setype: ntpd_var_run_t - state: present - when: - - ansible_selinux.status == 'enabled' - - samba_role == 'dc' or samba_role == 'rodc' - register: samba_ntp_selinux - tags: samba - -- name: Restore SELinux context - command: restorecon -R /var/lib/samba/ - when: - - ansible_selinux.status == 'enabled' - - samba_ntp_selinux.changed - tags: samba - -- name: Deploy rsyncd snippet - template: src=rsyncd.conf.j2 dest=/etc/rsyncd.conf.d/samba_dc.conf - when: samba_i_am_primary_dc == True - tags: samba - -- name: Remove rsyncd snippet - file: path=/etc/rsyncd.conf.d/samba_dc.conf state=absent - when: not samba_i_am_primary_dc == True - tags: samba - -- name: Deploy sysvol rsync password file - copy: content={{ (samba_sysvol_rsync_pass is defined) | ternary(samba_i_am_primary_dc | ternary('sysvol-replication:','') + samba_sysvol_rsync_pass,'# No password defined') }} dest=/etc/samba/rsync-sysvol.secret mode=600 - tags: samba - -- name: Setup cron to sync sysvol from primary DC - cron: - name: samba_sync_sysvol - cron_file: samba_sync_sysvol - minute: '*/16' - user: root - job: rsync -XAavz --delete-after {{ (samba_sysvol_rsync_pass is defined) | ternary('--password-file=/etc/samba/rsync-sysvol.secret','') }} rsync://{{ (samba_sysvol_rsync_pass is defined) | ternary('sysvol-replication@','') }}{{ samba_primary_dc }}/sysvol/ /var/lib/samba/sysvol/ - state: "{{ samba_i_am_primary_dc | ternary('absent','present') }}" - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - -- name: Create dehydrated hook dir - file: path=/etc/dehydrated/hooks_deploy_cert.d/ state=directory - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - -- name: Deploy dehydrated hook - copy: src=dehydrated_deploy_hook dest=/etc/dehydrated/hooks_deploy_cert.d/samba.sh mode=755 - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - -- name: Remove dehydrated hook - file: path=/etc/dehydrated/hooks_deploy_cert.d/samba.sh state=absent - when: samba_role != 'dc' and samba_role != 'rodc' - tags: samba - -- name: Create samba tls dir - file: path=/var/lib/samba/private/tls state=directory mode=700 - tags: samba - -- name: Create DH param - command: openssl dhparam -out /var/lib/samba/private/tls/dhparam.pem 2048 - args: - creates: /var/lib/samba/private/tls/dhparam.pem - tags: samba - -- name: Deploy smb.conf - template: src=smb.conf.j2 dest=/etc/samba/smb.conf - notify: reload samba - tags: samba - -- name: Create conf.d directory - file: path=/etc/samba/smb.conf.d/ state=directory - tags: samba - -- name: Check if there's a shares.conf snippet - stat: path=/etc/samba/smb.conf.d/shares.conf - register: samba_shares_snippet - tags: samba - -- name: Deploy an empty shares conf snippet - copy: content="# No shares defined yet" dest=/etc/samba/smb.conf.d/shares.conf - when: not samba_shares_snippet.stat.exists - tags: samba - -- name: Check if /etc/krb5.conf exists - stat: path=/etc/krb5.conf - register: samba_krb5_conf - tags: samba - -- name: Start and enable the samba daemon - service: name=samba state=started enabled=True - when: samba_role == 'dc' or samba_role == 'rodc' - tags: samba - -- name: Reconfigure sssd - include_role: name=sssd_ad_auth - when: - - not samba_krb5_conf.stat.exists - tags: samba - -- name: Check if winbind_cache exists - stat: path=/var/lib/samba/winbindd_cache.tdb - register: samba_winbind_cache - tags: samba - -- include_tasks: member_join.yml - when: - - samba_role == 'member' - - not samba_winbind_cache.stat.exists - -- name: Start and enable the smb daemon - service: name=smb state=started enabled=True - when: samba_role != 'dc' and samba_role != 'rodc' - tags: samba - - # Here we just read the actual policy. This way, on the next task, we can update only the items we need -- name: Check current password policy - shell: "samba-tool domain passwordsettings show | perl -ne 'm/^{{ samba_pwd_policy_descriptions[item] }}: (.*)/ && print $1'" - register: samba_dc_current_pwd_policy - changed_when: False - with_items: "{{ samba_pwd_policy.keys() | list }}" - when: samba_i_am_primary_dc == True - tags: samba - -- name: Set password policy - command: samba-tool domain passwordsettings set --{{ item.item }}={{ samba_pwd_policy[item.item] }} - with_items: "{{ samba_dc_current_pwd_policy.results }}" - when: - - samba_i_am_primary_dc == True - - item.stdout | string != samba_pwd_policy[item.item] | string - tags: samba - -- name: Add default zones to the list of managed ones - set_fact: samba_dns_zones={{ samba_dns_zones | default([]) + [ samba_realm | lower, '_msdcs.' + samba_realm | lower ] }} - when: samba_i_am_primary_dc == True - tags: samba - -- name: Check existing DNS zones - shell: samba-tool dns zonelist {{ ansible_all_ipv4_addresses | first }} -U Administrator --password={{ samba_dc_admin_pass | quote }} | perl -ne 'm/pszZoneName\s+:\s+(.*)/ && print "$1\n"' - register: samba_existing_zones - no_log: True - changed_when: False - when: samba_i_am_primary_dc == True - tags: samba - -- name: Create DNS zones - command: samba-tool dns zonecreate {{ ansible_all_ipv4_addresses | first }} {{ item }} -U Administrator --password={{ samba_dc_admin_pass | quote }} - no_log: True - when: samba_i_am_primary_dc == True - with_items: "{{ samba_dns_zones | difference(samba_existing_zones.stdout_lines) }}" - tags: samba - -- name: Remove DNS zones - command: samba-tool dns zonedelete {{ ansible_all_ipv4_addresses | first }} {{ item }} -U Administrator --password={{ samba_dc_admin_pass | quote }} - no_log: True - when: - - samba_i_am_primary_dc == True - - samba_remove_unmanaged_dns_zones == True - with_items: "{{ samba_existing_zones.stdout_lines | difference(samba_dns_zones) }}" - tags: samba - -- name: Create backup scripts dir - file: path=/etc/backup/{{ item }}.d state=directory - with_items: - - pre - - post - tags: samba - -- name: Deploy pre and post backup script - template: src={{ item.src }} dest={{ item.dest }} mode=755 - with_items: - - src: samba_pre_backup.sh.j2 - dest: /etc/backup/pre.d/samba.sh - - src: samba_post_backup.sh.j2 - dest: /etc/backup/post.d/samba.sh - tags: samba - -- name: Set SEbool - seboolean: name={{ item }} state=True persistent=True - when: samba_role == 'dc' or samba_role == 'rodc' - with_items: - - samba_domain_controller - tags: samba - -- name: Create samba scripts dir - file: path=/var/lib/samba/scripts state=directory - tags: samba - - include: filebeat.yml diff --git a/roles/samba/tasks/selinux.yml b/roles/samba/tasks/selinux.yml new file mode 100644 index 0000000..0bb2dca --- /dev/null +++ b/roles/samba/tasks/selinux.yml @@ -0,0 +1,22 @@ +--- + +- name: Set correct SELinux context on the ntp_signd socket dir + sefcontext: + target: "/var/lib/samba/ntp_signd(/.*)?" + setype: ntpd_var_run_t + state: present + when: samba_role == 'dc' or samba_role == 'rodc' + register: samba_ntp_selinux + tags: samba + +- name: Restore SELinux context + command: restorecon -R /var/lib/samba/ + when: samba_ntp_selinux.changed + tags: samba + +- name: Set SEbool + seboolean: name={{ item }} state=True persistent=True + when: samba_role == 'dc' or samba_role == 'rodc' + with_items: + - samba_domain_controller + tags: samba diff --git a/roles/samba/vars/CentOS-7.yml b/roles/samba/vars/CentOS-7.yml new file mode 100644 index 0000000..644f262 --- /dev/null +++ b/roles/samba/vars/CentOS-7.yml @@ -0,0 +1,16 @@ +--- + +samba_common_packages: + - samba + - samba-client + - sssd-winbind-idmap + - openldap-clients + - policycoreutils-python + - tdb-tools + +samba_dc_packages: + - samba-dc + - ldb-tools + - krb5-workstation + - python36-markdown + - patch diff --git a/roles/samba/vars/CentOS-8.yml b/roles/samba/vars/CentOS-8.yml new file mode 100644 index 0000000..756181b --- /dev/null +++ b/roles/samba/vars/CentOS-8.yml @@ -0,0 +1,16 @@ +--- + +samba_common_packages: + - samba + - samba-client + - sssd-winbind-idmap + - openldap-clients + - policycoreutils-python-utils + - tdb-tools + +samba_dc_packages: + - samba-dc + - ldb-tools + - krb5-workstation + - python3-markdown + - patch diff --git a/roles/squid/tasks/main.yml b/roles/squid/tasks/main.yml index 75c2909..139cfd8 100644 --- a/roles/squid/tasks/main.yml +++ b/roles/squid/tasks/main.yml @@ -221,7 +221,7 @@ tags: proxy - name: Deploy ufdbGuard configuration - template: src=ufdbGuard.conf.j2 dest=/etc/ufdbguard/ufdbGuard.conf group=ufdb mode=640 validate="ufdbguardd -c %s -C verify" + template: src=ufdbGuard.conf.j2 dest=/etc/ufdbguard/ufdbGuard.conf group=ufdb mode=640 notify: restart ufdb tags: proxy