diff --git a/roles/samba-dc/defaults/main.yml b/roles/samba-dc/defaults/main.yml new file mode 100644 index 0000000..d788643 --- /dev/null +++ b/roles/samba-dc/defaults/main.yml @@ -0,0 +1 @@ +samba_dc_use_rfc2307: true diff --git a/roles/samba-dc/handlers/main.yml b/roles/samba-dc/handlers/main.yml new file mode 100644 index 0000000..a3fbb71 --- /dev/null +++ b/roles/samba-dc/handlers/main.yml @@ -0,0 +1,7 @@ +- name: restore samba file contexts + command: restorecon -RF /var/lib/samba +- name: display generated admin password + debug: + var=samba_dc_provision.admin_password +- name: save firewalld configuration + command: firewall-cmd --runtime-to-permanent diff --git a/roles/samba-dc/library/samba_domain b/roles/samba-dc/library/samba_domain new file mode 100644 index 0000000..78fe228 --- /dev/null +++ b/roles/samba-dc/library/samba_domain @@ -0,0 +1,124 @@ +# vim: set ft=python : +import errno +import os +import subprocess + + +def get_samba_paths(samba='samba'): + lines = [] + paths = {} + cmd = [samba, '--show-build'] + with open(os.devnull, 'r') as nul: + p = subprocess.Popen( + cmd, stdin=nul, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + out, err = p.communicate() + in_paths = False + for line in out.splitlines(): + out += line + if line.startswith(b'Paths:'): + in_paths = True + continue + if in_paths: + if line.startswith(b' '): + parts = line.decode().split(':', 1) + if len(parts) != 2: + raise ValueError( + 'Unexpected output from samba: {}'.format(line) + ) + paths[parts[0].strip()] = parts[1].strip() + else: + in_paths = False + if p.returncode != 0: + raise subprocess.CalledProcessError(p.returncode, cmd, out, err) + return paths + + +def main(): + module = AnsibleModule( + argument_spec=dict( + realm=dict( + required=True, + ), + domain=dict( + required=False, + ), + use_rfc2307=dict( + required=False, + type='bool', + default=True, + ), + dns_backend=dict( + required=False, + choices=[ + 'BIND9_DLZ', + 'SAMBA_INTERNAL', + ], + ), + ), + supports_check_mode=True, + ) + + realm = module.params['realm'] + domain = module.params['domain'] or realm.split('.')[0] + use_rfc2307 = module.params['use_rfc2307'] + dns_backend = module.params['dns_backend'] + + samba_tool = module.get_bin_path('samba-tool', required=True) + samba = module.get_bin_path('samba', required=True) + + try: + samba_paths = get_samba_paths(samba) + except OSError as e: + module.fail_json(msg='Error running samba: {}'.format(e)) + except subprocess.CalledProcessError as e: + module.fail_json( + msg='Error running samba: {}'.format(e), + stdout=e.stdout, + stderr=e.stderr, + ) + + changed = not os.path.isdir(os.path.join( + samba_paths['STATEDIR'], + 'sysvol', + realm.lower(), + )) + + if changed and not module.check_mode: + try: + os.unlink(samba_paths['CONFIGFILE']) + except OSError as e: + if e.errno != errno.ENOENT: + raise + cmd = [ + samba_tool, + 'domain', + 'provision', + '--realm={}'.format(realm), + '--domain={}'.format(domain), + ] + if use_rfc2307: + cmd.append('--use-rfc2307') + if dns_backend: + cmd += ('--dns-backend', dns_backend) + rc, out, err = module.run_command(cmd, check_rc=True) + admin_password = '' + domain_sid = '' + for line in err.splitlines(): + if line.startswith('Admin password:'): + admin_password = line.split(':', 1)[1].lstrip() + if line.startswith('DOMAIN SID:'): + domain_sid = line.split(':', 1)[1].lstrip() + module.exit_json( + changed=True, + rc=rc, + admin_password=admin_password, + domain_sid=domain_sid, + ) + + module.exit_json(changed=changed) + + +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/roles/samba-dc/tasks/main.yml b/roles/samba-dc/tasks/main.yml new file mode 100644 index 0000000..2635240 --- /dev/null +++ b/roles/samba-dc/tasks/main.yml @@ -0,0 +1,60 @@ +- name: load distribution-specific values + include_vars: '{{ item }}' + with_first_found: + - '{{ ansible_distribution }}.yml' + - defaults.yml + tags: + - always + +- name: ensure packages are installed + package: + name={{ samba_dc_packages|join(',') }} + state=present + tags: + - install + +- name: ensure selinux file contexts are correct + sefcontext: + target={{ item.path }} + setype={{ item.setype }} + state=present + with_items: '{{ samba_selinux_contexts }}' + notify: restore samba file contexts + +- name: ensure kerberos is configured + template: + src=krb5.conf.j2 + dest=/etc/krb5.conf.d/samba.conf + +- name: ensure domain is provisioned + samba_domain: + realm={{ krb5_realm }} + domain={{ netbios_domain|d(omit) }} + use_rfc2307={{ samba_dc_use_rfc2307 }} + dns_backend={{ samba_dc_dns_backend|d(omit) }} + register: samba_dc_provision + notify: + - restore samba file contexts + - display generated admin password + +- name: ensure samba starts at boot + service: + name=samba + enabled=yes +- name: ensure samba is running + service: + name=samba + state=started + +- name: ensure firewall is configured for samba + firewalld: + service={{ item if '/' not in item else omit }} + port={{ item if '/' in item else omit }} + state=enabled + permanent=no + immediate=yes + with_items: '{{ samba_firewall }}' + notify: save firewalld configuration + when: host_users_firewalld|d(true)|bool + tags: + - firewalld diff --git a/roles/samba-dc/templates/krb5.conf.j2 b/roles/samba-dc/templates/krb5.conf.j2 new file mode 100644 index 0000000..a7263b0 --- /dev/null +++ b/roles/samba-dc/templates/krb5.conf.j2 @@ -0,0 +1,4 @@ +[libdefaults] +default_realm = {{ krb5_realm }} +dns_lookup_realm = false +dns_lookup_kdc = true diff --git a/roles/samba-dc/vars/defaults.yml b/roles/samba-dc/vars/defaults.yml new file mode 100644 index 0000000..5f3f9fa --- /dev/null +++ b/roles/samba-dc/vars/defaults.yml @@ -0,0 +1,7 @@ +samba_dc_packages: +- krb5-workstation +- openldap-clients +- samba-dc +- samba-dc-bind-dlz +- samba-winbind-clients +- tdb-tools diff --git a/roles/samba-dc/vars/main.yml b/roles/samba-dc/vars/main.yml new file mode 100644 index 0000000..c19c8b5 --- /dev/null +++ b/roles/samba-dc/vars/main.yml @@ -0,0 +1,19 @@ +samba_selinux_contexts: +- path: /var/lib/samba/bind-dns/dns.keytab + setype: named_conf_t +- path: /var/lib/samba/bind-dns/named.conf.* + setype: named_conf_t +- path: /var/lib/samba/bind-dns/dns(/.*)? + setype: named_var_run_t +samba_firewall: +- dns +- kerberos +- 135/tcp +- ldap +- 389/udp +- samba +- kpasswd +- ldaps +- 3268/tcp +- 3269/tcp +- 49152-65535/tcp