Changeset - 3a03065f2240
[Not reviewed]
0 4 2
Branko Majic (branko) - 5 months ago 2023-11-30 23:07:05
branko@majic.rs
MAR-189: Refactored admin acocunt handling in the ldap_server role:

- Get rid of the admin entry from the directory, and resort to using
the directory's olcRootDN/olcRootPW attributes instead. Aligns
Buster package deployment with Bullseye one, as implemented via fix
for the following Debian bug:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821331

- Add the helper filter plugin to deal with calculating the salted
SHA1 checksum.
- Drop the architecture from Molecule instance names.
- Move the IPs around a tiny bit for Molecule instances.
6 files changed with 89 insertions and 10 deletions:
0 comments (0 inline, 0 general)
roles/ldap_server/filter_plugins/ldap_filters.py
Show inline comments
 
new file 100644
 
# (c) 2023, Branko Majic <branko@majic.rs>
 
#
 
# This file is part of Ansible
 
#
 
# Ansible is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# Ansible is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 

	
 

	
 
import hashlib
 
import os
 
import base64
 

	
 
from ansible import errors
 

	
 

	
 
def ldap_password_hash(password, salt=None):
 

	
 
    if not salt:
 
        salt = os.urandom(4)
 
    elif len(salt) != 4:
 
        raise errors.AnsibleFilterError("When passing in salt to ldap_password_hash filter, it must be exactly 4 characters long!")
 
    else:
 
        salt = salt.encode("utf-8")
 

	
 
    hashed_password = hashlib.sha1(password.encode("utf-8"))
 
    hashed_password.update(salt)
 

	
 
    return "{SSHA}" + base64.encodebytes(hashed_password.digest() + salt).strip().decode("utf-8")
 

	
 

	
 
class FilterModule(object):
 

	
 
    def filters(self):
 
        return {
 
            'ldap_password_hash': ldap_password_hash
 
        }
roles/ldap_server/molecule/default/molecule.yml
Show inline comments
 
@@ -24,7 +24,7 @@ platforms:
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-buster64
 
  - name: parameters-mandatory-buster
 
    groups:
 
      - parameters-mandatory
 
    box: debian/contrib-buster64
 
@@ -32,11 +32,11 @@ platforms:
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.12
 
        ip: 192.168.56.21
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-optional-buster64
 
  - name: parameters-optional-buster
 
    groups:
 
      - parameters-optional
 
      - backup-server
 
@@ -45,7 +45,7 @@ platforms:
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.13
 
        ip: 192.168.56.22
 
        network_name: private_network
 
        type: static
 

	
roles/ldap_server/molecule/default/prepare.yml
Show inline comments
 
@@ -23,9 +23,9 @@
 
          - "{{ item.name }}"
 
          - "{{ item.fqdn }}"
 
      with_items:
 
        - name: parameters-mandatory-buster64_ldap
 
        - name: parameters-mandatory-buster_ldap
 
          fqdn: parameters-mandatory
 
        - name: parameters-optional-buster64_ldap
 
        - name: parameters-optional-buster_ldap
 
          fqdn: parameters-optional
 

	
 
    - name: Set-up link to generated X.509 material
 
@@ -79,8 +79,8 @@
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        192.168.56.12: parameters-mandatory-buster64
 
        192.168.56.13: parameters-optional-buster64
 
        192.168.56.21: parameters-mandatory-buster
 
        192.168.56.22: parameters-optional-buster
 

	
 
- hosts: parameters-optional
 
  become: true
roles/ldap_server/molecule/default/tests/test_default_buster.py
Show inline comments
 
@@ -4,7 +4,7 @@ import testinfra.utils.ansible_runner
 

	
 

	
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*-buster64')
 
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*-buster')
 

	
 

	
 
def test_ldap_server_uses_correct_dh_parameters(host):
roles/ldap_server/molecule/default/tests/test_deprecated.py
Show inline comments
 
new file 100644
 
import os
 

	
 
import testinfra.utils.ansible_runner
 

	
 
from helpers import parse_ldif
 

	
 

	
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*')
 

	
 

	
 
def test_server_admin_entry_absent(host):
 
    """
 
    Tests if the explicit admin entry is absent from directory tree.
 
    """
 

	
 
    with host.sudo():
 
        ldapsearch = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -b dc=local cn=admin dn')
 

	
 
        assert ldapsearch.rc == 0
 
        assert ldapsearch.stdout.strip() == ''
roles/ldap_server/tasks/main.yml
Show inline comments
 
@@ -227,6 +227,11 @@
 
    filter: "(olcSuffix={{ ldap_server_int_basedn }})"
 
    rules: "{{ ldap_permissions }}"
 

	
 
- name: Drop the admin entry corresponding to olcRootDN for database from directory
 
  ldap_entry:
 
    dn: "cn=admin,{{ ldap_server_int_basedn }}"
 
    state: absent
 

	
 
- name: Create basic LDAP directory structure
 
  ldap_entry:
 
    dn: "ou={{ item }},{{ ldap_server_int_basedn }}"
 
@@ -308,6 +313,9 @@
 
  notify:
 
    - Restart ferm
 

	
 
# @TODO: This whole thing could be dropped if newer version of Ansible
 
#        was in use (where community collection has the ldap_search
 
#        module.
 
- name: Deploy temporary file with LDAP admin password
 
  template:
 
    src: "ldap_admin_password.j2"
 
@@ -324,7 +332,11 @@
 
  failed_when: false
 

	
 
- name: Update LDAP admin password
 
  command: "ldappasswd -Y EXTERNAL -H ldapi:/// 'cn=admin,{{ ldap_server_int_basedn }}' -T /root/.ldap_admin_password"
 
  ldap_attr:
 
    dn: "olcDatabase={1}mdb,cn=config"
 
    name: olcRootPW
 
    values: "{{ ldap_admin_password | ldap_password_hash }}"
 
    state: exact
 
  when: ldap_admin_password_check.rc != 0
 

	
 
- name: Remove temporary file with LDAP admin password
0 comments (0 inline, 0 general)