diff --git a/CHANGELOG.md b/CHANGELOG.md index 7467878..c67b06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,13 @@ Project-specific changes only. See upstream [OpenLDAP release notes](https://www ### Added +- Expose management account hidden attributes through + `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES` and + `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES`. - Add optional `OPENLDAP_BOOTSTRAP_DATA_TREE` to create users, groups and services OUs, and `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT` for one scoped application account. - It reads users/groups and resets user passwords, including with ppolicy safe - modification, without hash/history reads or writes to profiles, memberships, + By default, it reads users/groups and resets user passwords, including with ppolicy + safe modification, without hash/history reads or writes to profiles, memberships, service accounts or configuration. Both features are disabled by default. - Add `openldap-ctl validate-ldif` for files and directories to check data entry LDIF syntax, values and schemas without importing entries or stopping slapd. @@ -25,7 +28,7 @@ Project-specific changes only. See upstream [OpenLDAP release notes](https://www contents change, ignoring duplicate events and unchanged projected volumes. - Default `OPENLDAP_BOOTSTRAP_MODULES` to `auto` to load base and enabled feature modules; explicit lists retain full control over module selection and order. -- Add optional file-based auditing with `OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED` +- Add optional file-based auditing with `OPENLDAP_BOOTSTRAP_AUDITLOG` and `OPENLDAP_BOOTSTRAP_AUDITLOG_FILE`. - Add `OPENLDAP_BOOTSTRAP_DATA_LAST_BIND` and `OPENLDAP_BOOTSTRAP_DATA_LAST_BIND_PRECISION` to track successful LDAP authentications in `pwdLastSuccess` (disabled by default). @@ -35,6 +38,16 @@ Project-specific changes only. See upstream [OpenLDAP release notes](https://www - Test default behavior, automatic role creation and preservation of a group after deletion of its last real member. +### Changed + +- Rename bootstrap feature flags `OPENLDAP_BOOTSTRAP_MONITOR_ENABLED` and + `OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED` to `OPENLDAP_BOOTSTRAP_MONITOR` and + `OPENLDAP_BOOTSTRAP_AUDITLOG`. Update deployment environments to the new names; + the previous names are no longer read. +- Align management bootstrap scripts, directories and LDIF filenames with the + existing `database-readonly` convention by using `database-management`. + Custom LDIF overrides must use the new filenames. + ### Fixed - Hide `pwdHistory` from the data read-only account when ppolicy is enabled diff --git a/README.md b/README.md index a7a0ce5..935e51d 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ docker exec openldap container run -- \ -b "dc=keycloakers,dc=org" "(objectClass=*)" ``` -A successful response returns the organization entry and the `cn=admin` account. +A successful response returns the organization entry. The root DN `cn=admin` authenticates without requiring a directory entry. **Passing command-line arguments to OpenLDAP** @@ -388,14 +388,16 @@ docker run --rm --user $UID -v $(pwd)/schema:/data \ | `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT` | Enable user/group reads and user password resets | `false` | | `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_DN` | Management account DN | `cn=management,${OPENLDAP_BOOTSTRAP_DATA_TREE_SERVICES_DN}` | | `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_PASSWORD_HASHED` | Hashed management password; generated if empty when enabled | `` | +| `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES` | Comma-separated attributes hidden from the management account | `userPassword,shadowLastChange` | +| `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES` | Additional hidden attributes when ppolicy is enabled | `pwdHistory` | | `OPENLDAP_BOOTSTRAP_DATA_READONLY` | Enable read-only data account creation | `false` | | `OPENLDAP_BOOTSTRAP_DATA_READONLY_DN` | DN of the read-only data account | `cn=readonly,${OPENLDAP_BOOTSTRAP_SUFFIX}` | | `OPENLDAP_BOOTSTRAP_DATA_READONLY_PASSWORD_HASHED` | Hashed password of the read-only data account; generated if empty when enabled | `` | -| `OPENLDAP_BOOTSTRAP_MONITOR_ENABLED` | Enable monitor backend | `false` | +| `OPENLDAP_BOOTSTRAP_MONITOR` | Enable monitor backend | `false` | | `OPENLDAP_BOOTSTRAP_MONITOR_READONLY` | Enable read-only monitor account creation | `false` | | `OPENLDAP_BOOTSTRAP_MONITOR_READONLY_DN` | DN of the read-only monitor account | `cn=readonly-monitor,${OPENLDAP_BOOTSTRAP_SUFFIX}` | | `OPENLDAP_BOOTSTRAP_MONITOR_READONLY_PASSWORD_HASHED` | Hashed password of the read-only monitor account; generated if empty when enabled | `` | -| `OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED` | Log successful LDAP writes | `false` | +| `OPENLDAP_BOOTSTRAP_AUDITLOG` | Log successful LDAP writes | `false` | | `OPENLDAP_BOOTSTRAP_AUDITLOG_FILE` | Audit LDIF file; requires a writable parent directory | `/var/log/openldap/audit.ldif` | | `OPENLDAP_BOOTSTRAP_LDIF_CONFIG_DIR` | Source directory for config LDIF bootstrap files | `/container/services/openldap-bootstrap/assets/ldif/config` | | `OPENLDAP_BOOTSTRAP_LDIF_DATA_DIR` | Source directory for data LDIF bootstrap files | `/container/services/openldap-bootstrap/assets/ldif/data` | diff --git a/build/README.md b/build/README.md index 71bfcfa..066ea84 100644 --- a/build/README.md +++ b/build/README.md @@ -24,7 +24,9 @@ After the shared version check, `tests/` runs integration scenarios on each buil - standard users/groups/services tree and management account: independent opt-ins, custom DNs and supplied OUs, generated passwords, user/group reads, password resets including application administrators, ppolicy-safe resets, - hidden hashes/history, and denied profile, membership, entry and service changes; + configurable hidden attributes with/without ppolicy, rejection of empty combined + lists, hidden hashes/history by default, and denied profile, membership, entry + and service changes; - global request limits: native defaults, custom values and incoming message size enforcement for anonymous and authenticated connections; - read-only bootstrap templates with projected-volume symlinks, custom overrides diff --git a/build/tests/auditlog.go b/build/tests/auditlog.go index 0f6d6c7..8e729a6 100644 --- a/build/tests/auditlog.go +++ b/build/tests/auditlog.go @@ -19,7 +19,7 @@ func AuditLog(ctx context.Context, client *dagger.Client, image *dagger.Containe settings := env{} file := "/var/log/openldap/audit.ldif" if mode != "default" { - settings["OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED"] = "true" + settings["OPENLDAP_BOOTSTRAP_AUDITLOG"] = "true" } if mode == "custom" { file = "/var/log/openldap/custom audit.ldif" diff --git a/build/tests/bootstrap.go b/build/tests/bootstrap.go index 217436b..6a475e3 100644 --- a/build/tests/bootstrap.go +++ b/build/tests/bootstrap.go @@ -126,18 +126,18 @@ func AllFeatures(ctx context.Context, client *dagger.Client, image *dagger.Conta "OPENLDAP_BOOTSTRAP_DATA_READONLY": "true", "OPENLDAP_BOOTSTRAP_DATA_READONLY_PASSWORD_HASHED": hash, - "OPENLDAP_BOOTSTRAP_MONITOR_ENABLED": "true", + "OPENLDAP_BOOTSTRAP_MONITOR": "true", "OPENLDAP_BOOTSTRAP_MONITOR_READONLY": "true", "OPENLDAP_BOOTSTRAP_MONITOR_READONLY_PASSWORD_HASHED": hash, "OPENLDAP_BOOTSTRAP_TLS": "true", "OPENLDAP_BOOTSTRAP_TLS_REQUIRED": "true", - "OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED": "true", - "OPENLDAP_BOOTSTRAP_REFINT": "true", - "OPENLDAP_BOOTSTRAP_PPOLICY": "true", - "OPENLDAP_BOOTSTRAP_UNIQUE": "true", - "OPENLDAP_BOOTSTRAP_MEMBEROF": "true", + "OPENLDAP_BOOTSTRAP_AUDITLOG": "true", + "OPENLDAP_BOOTSTRAP_REFINT": "true", + "OPENLDAP_BOOTSTRAP_PPOLICY": "true", + "OPENLDAP_BOOTSTRAP_UNIQUE": "true", + "OPENLDAP_BOOTSTRAP_MEMBEROF": "true", "OPENLDAP_BOOTSTRAP_REPLICATION": "true", "OPENLDAP_BOOTSTRAP_REPLICATION_HOSTS": strings.Join(hosts, " "), diff --git a/build/tests/data_management.go b/build/tests/data_management.go index 3f8ee7d..7f70287 100644 --- a/build/tests/data_management.go +++ b/build/tests/data_management.go @@ -21,7 +21,7 @@ func DataManagement(ctx context.Context, client *dagger.Client, image *dagger.Co "OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_PASSWORD_HASHED": passwords["OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED"], }) - for _, mode := range []string{"disabled", "tree", "plain", "policy", "custom", "supplied"} { + for _, mode := range []string{"disabled", "tree", "plain", "policy", "custom", "supplied", "hidden", "policy-hidden", "policy-only", "empty", "policy-disabled"} { if err := func() error { usersDN := "ou=users," + suffix groupsDN := "ou=groups," + suffix @@ -35,6 +35,19 @@ func DataManagement(ctx context.Context, client *dagger.Client, image *dagger.Co settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT"] = "false" case "tree": settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT"] = "false" + case "hidden": + settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES"] = "userPassword,shadowLastChange,mail" + case "policy-hidden", "policy-only", "empty": + settings["OPENLDAP_BOOTSTRAP_PPOLICY"] = "true" + settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES"] = "pwdHistory,mail" + if mode == "policy-only" || mode == "empty" { + settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES"] = "" + } + if mode == "empty" { + settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES"] = "" + } + case "policy-disabled": + settings["OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES"] = "pwdHistory,mail" case "policy": settings = merge(settings, env{ "OPENLDAP_BOOTSTRAP_PPOLICY": "true", @@ -42,7 +55,7 @@ func DataManagement(ctx context.Context, client *dagger.Client, image *dagger.Co "OPENLDAP_BOOTSTRAP_REFINT": "true", "OPENLDAP_BOOTSTRAP_REFINT_NOTHING_DN": "cn=empty-group," + servicesDN, "OPENLDAP_BOOTSTRAP_UNIQUE": "true", - "OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED": "true", + "OPENLDAP_BOOTSTRAP_AUDITLOG": "true", "OPENLDAP_BOOTSTRAP_DATA_READONLY": "true", "OPENLDAP_BOOTSTRAP_DATA_READONLY_PASSWORD_HASHED": passwords["OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED"], }) @@ -72,6 +85,11 @@ ou: services "OPENLDAP_BOOTSTRAP_DATA_TREE_SERVICES_DN": servicesDN, "OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_DN": managementDN, }) + if mode == "empty" { + _, err := expect(ctx, withEnv(nodeImage, settings), false, + []string{"Management hidden attributes must not be empty"}, "container", "--skip-process") + return err + } node := "management-" + mode service, err := startNode(ctx, nodeImage, node, settings, nil, nil) if err != nil { diff --git a/build/tests/modules.go b/build/tests/modules.go index f632405..d3e1e41 100644 --- a/build/tests/modules.go +++ b/build/tests/modules.go @@ -27,19 +27,19 @@ func AutomaticModules(ctx context.Context, client *dagger.Client, image *dagger. {"default", nil, baseModules, false}, {"custom order", env{"OPENLDAP_BOOTSTRAP_MODULES": "back_mdb.so pw-sha2.so argon2.so memberof.so"}, "back_mdb.so pw-sha2.so argon2.so memberof.so", false}, {"explicit aliases", env{ - "OPENLDAP_BOOTSTRAP_MODULES": explicitModules, - "OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED": "true", - "OPENLDAP_BOOTSTRAP_PPOLICY": "true", - "OPENLDAP_BOOTSTRAP_UNIQUE": "true", - "OPENLDAP_BOOTSTRAP_REFINT": "true", - "OPENLDAP_BOOTSTRAP_MEMBEROF": "true", + "OPENLDAP_BOOTSTRAP_MODULES": explicitModules, + "OPENLDAP_BOOTSTRAP_AUDITLOG": "true", + "OPENLDAP_BOOTSTRAP_PPOLICY": "true", + "OPENLDAP_BOOTSTRAP_UNIQUE": "true", + "OPENLDAP_BOOTSTRAP_REFINT": "true", + "OPENLDAP_BOOTSTRAP_MEMBEROF": "true", }, explicitModules, false}, {"missing explicit module", env{ "OPENLDAP_BOOTSTRAP_MODULES": baseModules, "OPENLDAP_BOOTSTRAP_UNIQUE": "true", }, "", true}, {"all automatic", env{ - "OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED": "true", + "OPENLDAP_BOOTSTRAP_AUDITLOG": "true", "OPENLDAP_BOOTSTRAP_PPOLICY": "true", "OPENLDAP_BOOTSTRAP_UNIQUE": "true", "OPENLDAP_BOOTSTRAP_REFINT": "true", @@ -49,7 +49,7 @@ func AutomaticModules(ctx context.Context, client *dagger.Client, image *dagger. }, baseModules + " ppolicy.so unique.so refint.so memberof.so auditlog.so syncprov.so", false}, } for _, feature := range []struct{ flag, module string }{ - {"AUDITLOG_ENABLED", "auditlog"}, + {"AUDITLOG", "auditlog"}, {"PPOLICY", "ppolicy"}, {"UNIQUE", "unique"}, {"REFINT", "refint"}, diff --git a/build/tests/testdata/data-management.sh b/build/tests/testdata/data-management.sh index 9ee1cf5..a9c03a4 100644 --- a/build/tests/testdata/data-management.sh +++ b/build/tests/testdata/data-management.sh @@ -77,7 +77,14 @@ expect_rc 0 bind_search "${URI}" "${TEST_MANAGEMENT_DN}" -b "${TEST_SUFFIX}" \ '(&(uid=alice)(objectClass=inetOrgPerson))' uid displayName mail userPassword expect_output "^dn: ${USER_DN}$" expect_output '^displayName: Test User$' -expect_output '^mail: alice@example.org$' +case "${TEST_MANAGEMENT_MODE}" in + hidden|policy-hidden|policy-only) + expect_no_output '^mail:' + ;; + *) + expect_output '^mail: alice@example.org$' + ;; +esac expect_no_output '^userPassword:' expect_rc 0 bind_search "${URI}" "${TEST_MANAGEMENT_DN}" -b "${TEST_GROUPS_DN}" \ "(&(member=${APP_ADMIN_DN})(objectClass=groupOfNames))" cn member @@ -96,7 +103,7 @@ for dn in "${USER_DN}" "${APP_ADMIN_DN}"; do done ok 'management resets ordinary and application-admin passwords without the old password' -if [ "${TEST_MANAGEMENT_MODE}" = "policy" ]; then +if [[ "${TEST_MANAGEMENT_MODE}" = policy* && "${TEST_MANAGEMENT_MODE}" != "policy-disabled" ]]; then # Authelia's standard LDAP Modify also needs to work with pwdSafeModify=TRUE. expect_rc 0 bind_modify "${URI}" "${TEST_MANAGEMENT_DN}" <`, to read users/groups and reset user -passwords. It cannot edit profiles or groups or read password hashes/history. +passwords. By default, it cannot edit profiles or groups or read password hashes/history. Both options are independent and disabled by default. The OU DNs, account DN and password hash are configurable through the matching `OPENLDAP_BOOTSTRAP_DATA_TREE_*_DN` and `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_*` variables. If custom LDIFs supply the OUs, leave tree creation disabled and load them before -`80-data-management-account.ldif`. Do not duplicate automatically created OUs. +`80-database-management-account.ldif`. Do not duplicate automatically created OUs. -## config/data-management +## config/database-management -`63-data-management-acl.ldif.template` limits password writes to the users branch. +`OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES` lists comma-separated +attributes hidden from the management account (default `userPassword,shadowLastChange`). +When ppolicy is enabled, `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES` +is added (default `pwdHistory`). The combined list must not be empty. + +`63-database-management-acl.ldif.template` limits password writes to the users branch. Its `=wm` privileges allow administrative resets without the old password, without hash read/compare. With ppolicy, these resets bypass quality, history-reuse and minimum-age checks: enforce password requirements in the application. @@ -155,7 +160,7 @@ docker run --name openldap \ osixia/openldap:2.6.15-beta ``` -Put `.ldif` files in these directories, or use `.ldif.template` files with `${VARIABLE}` placeholders to substitute environment variables. Leave the mounts writable so bootstrap can convert templates into `.ldif` files. +Put `.ldif` files in these directories, or use `.ldif.template` files with `${VARIABLE}` placeholders to substitute environment variables. The mounts may be read-only: bootstrap renders templates in a temporary writable copy. There are three ways to customize the bootstrap: diff --git a/services/openldap-bootstrap/assets/ldif/config/base/70-monitor.ldif.template b/services/openldap-bootstrap/assets/ldif/config/base/70-monitor.ldif.template index 6d39dbc..2aeaa93 100644 --- a/services/openldap-bootstrap/assets/ldif/config/base/70-monitor.ldif.template +++ b/services/openldap-bootstrap/assets/ldif/config/base/70-monitor.ldif.template @@ -1,4 +1,4 @@ dn: olcDatabase=monitor,cn=config objectClass: olcDatabaseConfig olcDatabase: monitor -olcMonitoring: ${OPENLDAP_BOOTSTRAP_MONITOR_ENABLED} +olcMonitoring: ${OPENLDAP_BOOTSTRAP_MONITOR} diff --git a/services/openldap-bootstrap/assets/ldif/config/data-management/63-data-management-acl.ldif.template b/services/openldap-bootstrap/assets/ldif/config/database-management/63-database-management-acl.ldif.template similarity index 100% rename from services/openldap-bootstrap/assets/ldif/config/data-management/63-data-management-acl.ldif.template rename to services/openldap-bootstrap/assets/ldif/config/database-management/63-database-management-acl.ldif.template diff --git a/services/openldap-bootstrap/assets/ldif/data/data-management/80-data-management-account.ldif.template b/services/openldap-bootstrap/assets/ldif/data/database-management/80-database-management-account.ldif.template similarity index 100% rename from services/openldap-bootstrap/assets/ldif/data/data-management/80-data-management-account.ldif.template rename to services/openldap-bootstrap/assets/ldif/data/database-management/80-database-management-account.ldif.template diff --git a/services/openldap-bootstrap/assets/scripts/00-base.sh b/services/openldap-bootstrap/assets/scripts/00-base.sh index 1e51236..7837ec2 100755 --- a/services/openldap-bootstrap/assets/scripts/00-base.sh +++ b/services/openldap-bootstrap/assets/scripts/00-base.sh @@ -33,7 +33,7 @@ if [ "${TYPE}" = "env" ]; then [unique]="${OPENLDAP_BOOTSTRAP_UNIQUE}" [refint]="${OPENLDAP_BOOTSTRAP_REFINT}" [memberof]="${OPENLDAP_BOOTSTRAP_MEMBEROF}" - [auditlog]="${OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED}" + [auditlog]="${OPENLDAP_BOOTSTRAP_AUDITLOG}" [syncprov]="${OPENLDAP_BOOTSTRAP_REPLICATION}" ) for module in ppolicy unique refint memberof auditlog syncprov; do @@ -57,7 +57,7 @@ if [ "${TYPE}" = "env" ]; then OPENLDAP_BOOTSTRAP_SCHEMAS_LDIF+="include: file://${OPENLDAP_SCHEMAS_DIR}/${schema}"$'\n' done - OPENLDAP_BOOTSTRAP_MONITOR_ENABLED=${OPENLDAP_BOOTSTRAP_MONITOR_ENABLED^^} + OPENLDAP_BOOTSTRAP_MONITOR=${OPENLDAP_BOOTSTRAP_MONITOR^^} OPENLDAP_BOOTSTRAP_DATA_LAST_BIND=${OPENLDAP_BOOTSTRAP_DATA_LAST_BIND^^} OPENLDAP_BOOTSTRAP_ORGANIZATION_DC=$(get_dn_attr dc "${OPENLDAP_BOOTSTRAP_SUFFIX}") @@ -66,7 +66,7 @@ if [ "${TYPE}" = "env" ]; then container log fatal "OPENLDAP_BOOTSTRAP_SUFFIX must start with dc= (got ${OPENLDAP_BOOTSTRAP_SUFFIX})" fi - prepare_env_file "${ENV_FILE}" OPENLDAP_GROUP_GID OPENLDAP_USER_UID OPENLDAP_BOOTSTRAP_CONFIG_ROOT_PASSWORD_HASHED OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED OPENLDAP_BOOTSTRAP_MODULES_LDIF OPENLDAP_BOOTSTRAP_SCHEMAS_LDIF OPENLDAP_BOOTSTRAP_MONITOR_ENABLED OPENLDAP_BOOTSTRAP_DATA_LAST_BIND OPENLDAP_BOOTSTRAP_ORGANIZATION_DC + prepare_env_file "${ENV_FILE}" OPENLDAP_GROUP_GID OPENLDAP_USER_UID OPENLDAP_BOOTSTRAP_CONFIG_ROOT_PASSWORD_HASHED OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED OPENLDAP_BOOTSTRAP_MODULES_LDIF OPENLDAP_BOOTSTRAP_SCHEMAS_LDIF OPENLDAP_BOOTSTRAP_MONITOR OPENLDAP_BOOTSTRAP_DATA_LAST_BIND OPENLDAP_BOOTSTRAP_ORGANIZATION_DC elif [ "${TYPE}" = "ldif" ]; then SOURCE_DIR="$2" diff --git a/services/openldap-bootstrap/assets/scripts/25-data-management.sh b/services/openldap-bootstrap/assets/scripts/25-database-management.sh similarity index 69% rename from services/openldap-bootstrap/assets/scripts/25-data-management.sh rename to services/openldap-bootstrap/assets/scripts/25-database-management.sh index 160793a..ba5d52c 100755 --- a/services/openldap-bootstrap/assets/scripts/25-data-management.sh +++ b/services/openldap-bootstrap/assets/scripts/25-database-management.sh @@ -26,9 +26,12 @@ if [ "${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT}" = "true" ]; then ensure_hashed_password OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_PASSWORD_HASHED "database management user" - OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES="userPassword,shadowLastChange" - if [ "${OPENLDAP_BOOTSTRAP_PPOLICY}" = "true" ]; then - OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES+=",pwdHistory" + if [ "${OPENLDAP_BOOTSTRAP_PPOLICY}" = "true" ] && [ -n "${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES}" ]; then + OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES+="${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES:+,}${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES}" + fi + + if [ -z "${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES}" ]; then + container log fatal "Management hidden attributes must not be empty" fi prepare_env_file "${ENV_FILE}" OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_CN OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_PASSWORD_HASHED OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES @@ -37,7 +40,7 @@ if [ "${OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT}" = "true" ]; then SOURCE_DIR="$2" OUTPUT_DIR="$3" - prepare_ldif_files "${SOURCE_DIR}/data-management" "${OUTPUT_DIR}" + prepare_ldif_files "${SOURCE_DIR}/database-management" "${OUTPUT_DIR}" fi fi diff --git a/services/openldap-bootstrap/assets/scripts/35-auditlog.sh b/services/openldap-bootstrap/assets/scripts/35-auditlog.sh index 1b0ee80..1e10376 100755 --- a/services/openldap-bootstrap/assets/scripts/35-auditlog.sh +++ b/services/openldap-bootstrap/assets/scripts/35-auditlog.sh @@ -6,7 +6,7 @@ set -euo pipefail # print commands and their arguments as they are executed container log level eq trace && set -x -if [ "${OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED}" = "true" ]; then +if [ "${OPENLDAP_BOOTSTRAP_AUDITLOG}" = "true" ]; then # shellcheck disable=SC1091 source "/container/services/openldap-bootstrap/assets/scripts/helpers/common.sh" diff --git a/services/openldap-bootstrap/assets/scripts/README.md b/services/openldap-bootstrap/assets/scripts/README.md index 3328e6e..76c57e8 100644 --- a/services/openldap-bootstrap/assets/scripts/README.md +++ b/services/openldap-bootstrap/assets/scripts/README.md @@ -16,9 +16,9 @@ Scripts are executed in numeric order. Most are feature-gated by an environment | `10-tls.sh` | `OPENLDAP_BOOTSTRAP_TLS=true` | Applies TLS certificate and protocol configuration | | `15-tls-required.sh` | `OPENLDAP_BOOTSTRAP_TLS_REQUIRED=true` | Enforces minimum 128-bit SSF (warns if TLS is not also enabled) | | `20-database-readonly.sh` | `OPENLDAP_BOOTSTRAP_DATA_READONLY=true` | Creates a read-only service account for the data database | -| `25-data-management.sh` | `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true` | Creates one account below the services branch, reading users/groups and resetting user passwords without hash/history access or other write permissions | +| `25-database-management.sh` | `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true` | Creates one account below the services branch, reading users/groups and resetting user passwords with configurable hidden attributes and no other write permissions | | `30-monitor-readonly.sh` | `OPENLDAP_BOOTSTRAP_MONITOR_READONLY=true` | Creates a read-only service account for the monitor database | -| `35-auditlog.sh` | `OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED=true` | Configures file-based auditing on the data database | +| `35-auditlog.sh` | `OPENLDAP_BOOTSTRAP_AUDITLOG=true` | Configures file-based auditing on the data database | | `40-refint.sh` | `OPENLDAP_BOOTSTRAP_REFINT=true` | Configures the referential integrity overlay and optional replacement DN | | `45-refint-nothing.sh` | `OPENLDAP_BOOTSTRAP_REFINT=true` and `OPENLDAP_BOOTSTRAP_REFINT_NOTHING_DN` non-empty | Creates the passwordless replacement role | | `50-ppolicy.sh` | `OPENLDAP_BOOTSTRAP_PPOLICY=true` | Configures password policy, hides history from the data read-only account while preserving normal ACL evaluation, and validates inactivity and progressive lockout prerequisites |