users: Reorganize and make idempotent ldap setup

- Break down setup process into methods.

- Make sure that LDAP entity setup is idempotent.

- Peform all entry updates while slapd is running instead of using
  slapadd.

- Start slapd only when necessary.  Shutdown (only) if we have started
  slapd.
This commit is contained in:
Sunil Mohan Adapa 2016-05-18 11:51:50 +05:30 committed by James Valleroy
parent 8d9480901b
commit f68a757741
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808

View File

@ -68,57 +68,106 @@ def subcommand_pre_install(_):
check=True)
subprocess.run(
['debconf-set-selections'],
input=b'libnss-ldapd libnss-ldapd/nsswitch multiselect group, passwd, shadow',
input=b'libnss-ldapd libnss-ldapd/nsswitch multiselect '
b'group, passwd, shadow',
check=True)
def subcommand_setup(_):
"""Setup LDAP."""
# Make sure slapd isn't running when we use slapadd.
action_utils.service_stop('slapd')
subprocess.run(['slapadd'], input=b'''
dn: ou=users,dc=thisbox
objectClass: top
objectClass: organizationalUnit
ou: users
dn: ou=groups,dc=thisbox
objectClass: top
objectClass: organizationalUnit
ou: groups
''')
action_utils.service_start('slapd')
configure_access_conf()
# Update pam configs for access and mkhomedir.
subprocess.run(['pam-auth-update', '--package'], check=True)
# Restrict console login to users in admin or sudo group.
with open(ACCESS_CONF, 'r') as conffile:
lines = conffile.readlines()
configure_ldapscripts()
access_conf_completed = False
for line in lines:
if '-:ALL EXCEPT root fbx (admin) (sudo):ALL' in line:
access_conf_completed = True
configure_slapd()
if not access_conf_completed:
with open(ACCESS_CONF, 'a') as conffile:
conffile.write('-:ALL EXCEPT root fbx (admin) (sudo):ALL\n')
# Remove LDAP admin password. Allow root to modify the users directory.
subprocess.run(
['ldapmodify', '-Y', 'EXTERNAL', '-H', 'ldapi:///'],
input=b'''
def configure_slapd():
"""Configure LDAP authentication and basic structure."""
was_running = action_utils.service_is_running('slapd')
if not was_running:
action_utils.service_start('slapd')
try:
setup_admin()
create_organizational_unit('users')
create_organizational_unit('groups')
finally:
if not was_running:
action_utils.service_stop('slapd')
def create_organizational_unit(unit):
"""Create an organizational unit in LDAP."""
distinguished_name = 'ou={unit},dc=thisbox'.format(unit=unit)
try:
subprocess.run(
['ldapsearch', '-Q', '-Y', 'EXTERNAL', '-H', 'ldapi:///', '-s',
'base', '-b', distinguished_name, '(objectclass=*)'],
stdout=subprocess.DEVNULL, check=True)
return # Already exists
except subprocess.CalledProcessError:
input = '''
dn: ou={unit},dc=thisbox
objectClass: top
objectClass: organizationalUnit
ou: {unit}'''.format(unit=unit)
subprocess.run(['ldapadd', '-Q', '-Y', 'EXTERNAL', '-H', 'ldapi:///'],
input=input.encode(), stdout=subprocess.DEVNULL,
check=True)
def setup_admin():
"""Remove LDAP admin password and Allow root to modify the users."""
process = subprocess.run(
['ldapsearch', '-Q', '-L', '-L', '-L', '-Y', 'EXTERNAL', '-H',
'ldapi:///', '-s', 'base', '-b', 'olcDatabase={1}mdb,cn=config',
'(objectclass=*)', 'olcRootDN', 'olcRootPW'],
check=True, stdout=subprocess.PIPE)
ldap_object = {}
for line in process.stdout.decode().splitlines():
if line:
line = line.split(':')
ldap_object[line[0]] = line[1]
if 'olcRootPW' in ldap_object:
subprocess.run(
['ldapmodify', '-Q', '-Y', 'EXTERNAL', '-H', 'ldapi:///'],
check=True, stdout=subprocess.DEVNULL, input=b'''
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcRootPW
delete: olcRootPW''')
root_dn = 'gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth'
if ldap_object['olcRootDN'] != root_dn:
subprocess.run(
['ldapmodify', '-Q', '-Y', 'EXTERNAL', '-H', 'ldapi:///'],
check=True, stdout=subprocess.DEVNULL, input=b'''
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
''')
def configure_access_conf():
"""Restrict console login to users in admin or sudo group."""
with open(ACCESS_CONF, 'r') as conffile:
lines = conffile.readlines()
for line in lines:
if '-:ALL EXCEPT root fbx (admin) (sudo):ALL' in line:
return
with open(ACCESS_CONF, 'a') as conffile:
conffile.write('-:ALL EXCEPT root fbx (admin) (sudo):ALL\n')
def configure_ldapscripts():
"""Set the configuration used by ldapscripts for later user management."""
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')