diff --git a/cli/utils/manager/inventory.py b/cli/utils/manager/inventory.py index ec74b5ba..acc96781 100644 --- a/cli/utils/manager/inventory.py +++ b/cli/utils/manager/inventory.py @@ -49,7 +49,7 @@ class InventoryManager: target.setdefault("credentials", {})["database_password"] = self.generate_value("alphanumeric") if "oauth2" in data["features"] and \ data["features"]["oauth2"]: - target.setdefault("credentials", {})["oauth2"] = self.generate_value("random_hex_16") + target.setdefault("credentials", {})["oauth2_proxy_cookie_secret"] = self.generate_value("random_hex_16") # Apply recursion only for the `credentials` section self.recurse_credentials(self.schema, target) @@ -148,8 +148,13 @@ class InventoryManager: if algorithm == "sha1": return hashlib.sha1(secrets.token_bytes(20)).hexdigest() if algorithm == "bcrypt": + # Generate a random password and hash it with bcrypt pw = secrets.token_urlsafe(16).encode() - return bcrypt.hashpw(pw, bcrypt.gensalt()).decode() + raw_hash = bcrypt.hashpw(pw, bcrypt.gensalt()).decode() + # Replace every '$' with a random lowercase alphanumeric character + alnum = string.digits + string.ascii_lowercase + escaped = "".join(secrets.choice(alnum) if ch == '$' else ch for ch in raw_hash) + return escaped if algorithm == "alphanumeric": return self.generate_secure_alphanumeric(64) if algorithm == "base64_prefixed_32": diff --git a/group_vars/all/12_oidc.yml b/group_vars/all/12_oidc.yml index 1e310cae..2516da19 100644 --- a/group_vars/all/12_oidc.yml +++ b/group_vars/all/12_oidc.yml @@ -8,12 +8,13 @@ # @see https://en.wikipedia.org/wiki/OpenID_Connect ## Helper Variables: -_oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and oidc.client.realm is defined else primary_domain }}" -_oidc_client_issuer_url: "{{ web_protocol }}://{{domains | get_domain('keycloak')}}/realms/{{_oidc_client_realm}}" +_oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and oidc.client.realm is defined else primary_domain }}" +_oidc_client_issuer_url: "{{ web_protocol }}://{{domains | get_domain('keycloak')}}/realms/{{_oidc_client_realm}}" +_oidc_client_id: "{{ oidc.client.id if oidc.client is defined and oidc.client.id is defined else primary_domain }}" defaults_oidc: client: - id: "{{primary_domain}}" # Client identifier, typically matching your primary domain + id: "{{ _oidc_client_id }}" # Client identifier, typically matching your primary domain # secret: # Client secret for authenticating with the OIDC provider (set in the inventory file). Recommend greater then 32 characters realm: "{{_oidc_client_realm}}" # The realm to which the client belongs in the OIDC provider issuer_url: "{{_oidc_client_issuer_url}}" # Base URL of the OIDC provider (issuer) @@ -24,6 +25,7 @@ defaults_oidc: logout_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/logout" # Endpoint to log out the user change_credentials: "{{_oidc_client_issuer_url}}account/account-security/signing-in" # URL for managing or changing user credentials certs: "{{_oidc_client_issuer_url}}/protocol/openid-connect/certs" # JSON Web Key Set (JWKS) + reset_credentials: "{{_oidc_client_issuer_url}}/login-actions/reset-credentials?client_id={{ _oidc_client_id }}" # Password reset url button_text: "SSO Login ({{primary_domain | upper}})" # Default button text attributes: # Attribut to identify the user diff --git a/roles/docker-ldap/tasks/main.yml b/roles/docker-ldap/tasks/main.yml index 6832ca8f..3d930274 100644 --- a/roles/docker-ldap/tasks/main.yml +++ b/roles/docker-ldap/tasks/main.yml @@ -25,6 +25,10 @@ - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml" +- name: "Reset LDAP admin passwords" + include_tasks: reset_admin_passwords.yml + when: applications[application_id].network.local + - name: "create directory {{ldif_host_path}}{{item}}" file: path: "{{ldif_host_path}}{{item}}" @@ -59,13 +63,13 @@ ############################################################################### - name: Ensure LDAP users exist community.general.ldap_entry: - dn: "{{ ldap.attributes.user_id }}={{ item.key }},{{ ldap.dn.users }}" - server_uri: "{{ ldap_server_uri }}" - bind_dn: "{{ ldap.dn.administrator.data }}" - bind_pw: "{{ ldap.bind_credential }}" - objectClass: "{{ ldap.user_objects.structural }}" + dn: "{{ ldap.attributes.user_id }}={{ item.key }},{{ ldap.dn.users }}" + server_uri: "{{ ldap_server_uri }}" + bind_dn: "{{ ldap.dn.administrator.data }}" + bind_pw: "{{ ldap.bind_credential }}" + objectClass: "{{ ldap.user_objects.structural }}" attributes: - uid: "{{ item.key }}" # {{ ldap.attributes.user_id }} can't be used as key here, dynamic key generation isn't possible + uid: "{{ item.value.username }}" sn: "{{ item.value.sn | default(item.key) }}" cn: "{{ item.value.cn | default(item.key) }}" userPassword: "{SSHA}{{ item.value.password }}" diff --git a/roles/docker-ldap/tasks/reset_admin_passwords.yml b/roles/docker-ldap/tasks/reset_admin_passwords.yml new file mode 100644 index 00000000..744657f9 --- /dev/null +++ b/roles/docker-ldap/tasks/reset_admin_passwords.yml @@ -0,0 +1,57 @@ +--- +# Reset both Database and Configuration Admin passwords in LDAP via LDAPI +# roles/docker-ldap/tasks/reset_admin_passwords.yml + +- name: "Query available LDAP databases" + shell: | + docker exec {{ applications[application_id].hostname }} \ + ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b cn=config "(olcDatabase=*)" dn + register: ldap_databases + +- name: "Determine data backend DN (mdb)" + set_fact: + data_backend_dn: >- + {{ ldap_databases.stdout_lines + | select('search','^dn: olcDatabase=.*mdb') + | map('regex_replace','^dn: ','') + | list + | first }} + +- name: "Determine config backend DN" + set_fact: + config_backend_dn: >- + {{ ldap_databases.stdout_lines + | select('search','^dn: olcDatabase=\{[0-9]+\}config,cn=config$') + | map('regex_replace','^dn: ','') + | list + | first }} + +- name: "Generate hash for Database Admin password" + shell: | + docker exec {{ applications[application_id].hostname }} \ + slappasswd -s "{{ ldap.bind_credential }}" + register: database_admin_pw_hash + +- name: "Reset Database Admin password in LDAP (olcRootPW)" + shell: | + docker exec -i {{ applications[application_id].hostname }} ldapmodify -Y EXTERNAL -H ldapi:/// <