roles/samba-dc: Deploy a Samba AD DC
The *samba-dc* role installs Samba on the managed node and configures it as an Active Directory Domain controller. A custom module, `samba_domain` handles the provisioning using `samba-tool domain provision` in an idempotent way.jenkins-master
parent
ec524416c6
commit
42ce2434ad
|
@ -0,0 +1 @@
|
||||||
|
samba_dc_use_rfc2307: true
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
[libdefaults]
|
||||||
|
default_realm = {{ krb5_realm }}
|
||||||
|
dns_lookup_realm = false
|
||||||
|
dns_lookup_kdc = true
|
|
@ -0,0 +1,7 @@
|
||||||
|
samba_dc_packages:
|
||||||
|
- krb5-workstation
|
||||||
|
- openldap-clients
|
||||||
|
- samba-dc
|
||||||
|
- samba-dc-bind-dlz
|
||||||
|
- samba-winbind-clients
|
||||||
|
- tdb-tools
|
|
@ -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
|
Loading…
Reference in New Issue