mirror of
https://github.com/osixia/container-openldap.git
synced 2026-11-06 20:48:18 -04:00
feat(bootstrap): configure management ACLs and align feature names
Expose management hidden attribute lists through bootstrap environment defaults and keep ACL rendering in the LDIF template. Align management assets with database-readonly naming and drop the MONITOR and AUDITLOG flag suffixes. Update documentation, migration notes and integration coverage for custom hidden attributes, empty effective lists, audit logging and monitoring.
This commit is contained in:
+16
-3
@@ -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
|
||||
|
||||
@@ -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` |
|
||||
|
||||
+3
-1
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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, " "),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"},
|
||||
|
||||
+16
-6
@@ -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}" <<LDIF
|
||||
dn: ${USER_DN}
|
||||
@@ -109,13 +116,16 @@ LDIF
|
||||
expect_output '^userPassword:: '
|
||||
expect_output '^pwdHistory:'
|
||||
expect_rc 0 bind_search "${URI}" "${TEST_MANAGEMENT_DN}" -b "${USER_DN}" -s base userPassword pwdHistory
|
||||
expect_no_output '^(userPassword|pwdHistory):'
|
||||
expect_rc 0 bind_search "${URI}" "cn=readonly,${TEST_SUFFIX}" -b "${USER_DN}" -s base cn pwdHistory
|
||||
expect_no_output '^userPassword:'
|
||||
expect_no_output '^pwdHistory:'
|
||||
expect_fail ldappasswd -x -H "${URI}" -D "cn=readonly,${TEST_SUFFIX}" -w "${TEST_PASSWORD}" -s "${NEW_PASSWORD}" "${USER_DN}"
|
||||
if [ "${TEST_MANAGEMENT_MODE}" = "policy" ]; then
|
||||
expect_rc 0 bind_search "${URI}" "cn=readonly,${TEST_SUFFIX}" -b "${USER_DN}" -s base cn pwdHistory
|
||||
expect_no_output '^pwdHistory:'
|
||||
expect_fail ldappasswd -x -H "${URI}" -D "cn=readonly,${TEST_SUFFIX}" -w "${TEST_PASSWORD}" -s "${NEW_PASSWORD}" "${USER_DN}"
|
||||
fi
|
||||
expect_fail ldappasswd -x -H "${URI}" -D "${APP_ADMIN_DN}" -w "${NEW_PASSWORD}" -a "${NEW_PASSWORD}" -s short
|
||||
expect_output 'quality|too short|Constraint violation'
|
||||
ok 'policy-enabled LDAP Modify hashes passwords and keeps history private'
|
||||
ok 'policy-enabled LDAP Modify hashes passwords and honors history visibility settings'
|
||||
fi
|
||||
|
||||
# Write-only password access must not even permit comparison of stored hashes.
|
||||
|
||||
Vendored
+4
@@ -39,6 +39,10 @@ ok "authenticated users can read allowed attributes"
|
||||
expect_rc 0 bind_search "${URI}" "${CONFIG_ADMIN_DN}" -b "cn=config" -s base dn
|
||||
ok "config admin can read cn=config"
|
||||
|
||||
expect_rc 0 bind_search "${URI}" "${CONFIG_ADMIN_DN}" -b "cn=config" '(olcDatabase=monitor)' olcMonitoring
|
||||
expect_output '^olcMonitoring: FALSE$'
|
||||
ok "monitoring is disabled by default"
|
||||
|
||||
expect_rc 0 bind_search "${URI}" "${CONFIG_ADMIN_DN}" -b "cn=schema,cn=config" -s one cn
|
||||
for schema in ${TEST_SCHEMAS}; do
|
||||
expect_output "^cn: \{[0-9]+\}${schema%.ldif}$"
|
||||
|
||||
Vendored
+3
@@ -49,6 +49,9 @@ ok "anonymous users cannot read the database"
|
||||
for node in "${NODES[@]}"; do
|
||||
uri="$(ldaps_uri "${node}")"
|
||||
|
||||
expect_rc 0 bind_search "${uri}" "${CONFIG_ADMIN_DN}" -b "cn=config" '(olcDatabase=monitor)' olcMonitoring
|
||||
expect_output '^olcMonitoring: TRUE$'
|
||||
|
||||
expect_rc 0 bind_search "${uri}" "${CONFIG_ADMIN_DN}" -b "cn=module{0},cn=config" -s base olcModuleLoad
|
||||
for module in ${TEST_MODULES}; do
|
||||
expect_output "^olcModuleLoad: \{[0-9]+\}${module}$"
|
||||
|
||||
@@ -34,18 +34,20 @@ OPENLDAP_BOOTSTRAP_DATA_TREE_SERVICES_DN="ou=services,${OPENLDAP_BOOTSTRAP_SUFFI
|
||||
OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=false
|
||||
OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_DN="cn=management,${OPENLDAP_BOOTSTRAP_DATA_TREE_SERVICES_DN}"
|
||||
OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_PASSWORD_HASHED=""
|
||||
OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_ATTRIBUTES="userPassword,shadowLastChange"
|
||||
OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT_HIDDEN_PPOLICY_ATTRIBUTES="pwdHistory"
|
||||
|
||||
OPENLDAP_BOOTSTRAP_DATA_READONLY=false
|
||||
OPENLDAP_BOOTSTRAP_DATA_READONLY_DN="cn=readonly,${OPENLDAP_BOOTSTRAP_SUFFIX}"
|
||||
OPENLDAP_BOOTSTRAP_DATA_READONLY_PASSWORD_HASHED=""
|
||||
|
||||
OPENLDAP_BOOTSTRAP_MONITOR_ENABLED=false
|
||||
OPENLDAP_BOOTSTRAP_MONITOR=false
|
||||
|
||||
OPENLDAP_BOOTSTRAP_MONITOR_READONLY=false
|
||||
OPENLDAP_BOOTSTRAP_MONITOR_READONLY_DN="cn=readonly-monitor,${OPENLDAP_BOOTSTRAP_SUFFIX}"
|
||||
OPENLDAP_BOOTSTRAP_MONITOR_READONLY_PASSWORD_HASHED=""
|
||||
|
||||
OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED=false
|
||||
OPENLDAP_BOOTSTRAP_AUDITLOG=false
|
||||
OPENLDAP_BOOTSTRAP_AUDITLOG_FILE="/var/log/openldap/audit.ldif"
|
||||
|
||||
OPENLDAP_BOOTSTRAP_TLS=false
|
||||
|
||||
@@ -4,37 +4,37 @@ This directory contains LDAP Data Interchange Format (LDIF) files used to bootst
|
||||
|
||||
Files with a `.template` extension use `${VARIABLE}` placeholders that are substituted with environment variables at runtime. Static `.ldif` files are applied as-is.
|
||||
|
||||
Files are processed in lexicographic order within each directory (numerical prefixes control ordering).
|
||||
Rendered LDIF files are assembled in version-sort order (`sort -V`); numerical prefixes control ordering.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
ldif/
|
||||
├── config/ # OpenLDAP configuration database (cn=config)
|
||||
│ ├── base/ # Core configuration (always applied)
|
||||
│ ├── tls/ # TLS settings (OPENLDAP_BOOTSTRAP_TLS=true)
|
||||
│ ├── tls-required/ # Enforce TLS (OPENLDAP_BOOTSTRAP_TLS_REQUIRED=true)
|
||||
│ ├── database-readonly/ # Read-only data DB user (OPENLDAP_BOOTSTRAP_DATA_READONLY=true)
|
||||
│ ├── data-management/ # Scoped application account ACLs (OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true)
|
||||
│ ├── monitor-readonly/ # Read-only monitor user (OPENLDAP_BOOTSTRAP_MONITOR_READONLY=true)
|
||||
│ ├── auditlog/ # Audit file (OPENLDAP_BOOTSTRAP_AUDITLOG_ENABLED=true)
|
||||
│ ├── ppolicy/ # Password policy overlay (OPENLDAP_BOOTSTRAP_PPOLICY=true)
|
||||
│ ├── ppolicy-readonly/ # Hide history from the data read-only account (PPOLICY and DATA_READONLY enabled)
|
||||
│ ├── refint/ # Referential integrity overlay (OPENLDAP_BOOTSTRAP_REFINT=true)
|
||||
│ ├── unique/ # Unique attributes overlay (OPENLDAP_BOOTSTRAP_UNIQUE=true)
|
||||
│ ├── memberof/ # Memberof overlay (OPENLDAP_BOOTSTRAP_MEMBEROF=true)
|
||||
│ ├── replication/ # Replication (OPENLDAP_BOOTSTRAP_REPLICATION=true)
|
||||
│ └── custom/ # User-provided config LDIF files
|
||||
│ ├── base/ # Core configuration (always applied)
|
||||
│ ├── tls/ # TLS settings (OPENLDAP_BOOTSTRAP_TLS=true)
|
||||
│ ├── tls-required/ # Enforce TLS (OPENLDAP_BOOTSTRAP_TLS_REQUIRED=true)
|
||||
│ ├── database-readonly/ # Read-only data DB user (OPENLDAP_BOOTSTRAP_DATA_READONLY=true)
|
||||
│ ├── database-management/ # Scoped application account ACLs (OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true)
|
||||
│ ├── monitor-readonly/ # Read-only monitor user (OPENLDAP_BOOTSTRAP_MONITOR_READONLY=true)
|
||||
│ ├── auditlog/ # Audit file (OPENLDAP_BOOTSTRAP_AUDITLOG=true)
|
||||
│ ├── ppolicy/ # Password policy overlay (OPENLDAP_BOOTSTRAP_PPOLICY=true)
|
||||
│ ├── ppolicy-readonly/ # Hide history from the data read-only account (PPOLICY and DATA_READONLY enabled)
|
||||
│ ├── refint/ # Referential integrity overlay (OPENLDAP_BOOTSTRAP_REFINT=true)
|
||||
│ ├── unique/ # Unique attributes overlay (OPENLDAP_BOOTSTRAP_UNIQUE=true)
|
||||
│ ├── memberof/ # Memberof overlay (OPENLDAP_BOOTSTRAP_MEMBEROF=true)
|
||||
│ ├── replication/ # Replication (OPENLDAP_BOOTSTRAP_REPLICATION=true)
|
||||
│ └── custom/ # User-provided config LDIF files
|
||||
└── data/ # LDAP directory data (populated on first bootstrap)
|
||||
├── base/ # Root organization entry (always applied)
|
||||
├── data-tree/ # Users, groups and services OUs (OPENLDAP_BOOTSTRAP_DATA_TREE=true)
|
||||
├── data-management/ # Application account (OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true)
|
||||
├── database-readonly/ # Read-only account entry (OPENLDAP_BOOTSTRAP_DATA_READONLY=true)
|
||||
├── monitor-readonly/ # Read-only monitor account (OPENLDAP_BOOTSTRAP_MONITOR_READONLY=true)
|
||||
├── ppolicy/ # Password policy group and default policy (OPENLDAP_BOOTSTRAP_PPOLICY=true)
|
||||
├── refint-nothing/ # Passwordless replacement role (REFINT enabled and NOTHING_DN set)
|
||||
├── replication/ # Replication service accounts (OPENLDAP_BOOTSTRAP_REPLICATION=true)
|
||||
└── custom/ # User-provided data LDIF files
|
||||
├── base/ # Root organization entry (always applied)
|
||||
├── data-tree/ # Users, groups and services OUs (OPENLDAP_BOOTSTRAP_DATA_TREE=true)
|
||||
├── database-management/ # Application account (OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true)
|
||||
├── database-readonly/ # Read-only account entry (OPENLDAP_BOOTSTRAP_DATA_READONLY=true)
|
||||
├── monitor-readonly/ # Read-only monitor account (OPENLDAP_BOOTSTRAP_MONITOR_READONLY=true)
|
||||
├── ppolicy/ # Password policy group and default policy (OPENLDAP_BOOTSTRAP_PPOLICY=true)
|
||||
├── refint-nothing/ # Passwordless replacement role (REFINT enabled and NOTHING_DN set)
|
||||
├── replication/ # Replication service accounts (OPENLDAP_BOOTSTRAP_REPLICATION=true)
|
||||
└── custom/ # User-provided data LDIF files
|
||||
```
|
||||
|
||||
## Numbered prefix grouping behavior
|
||||
@@ -79,22 +79,27 @@ Core OpenLDAP configuration applied on every bootstrap. Files are numbered to co
|
||||
|
||||
ACL files ending in `-close.ldif` append a final `access to * by * none` rule to deny any unmatched access, ensuring a safe default.
|
||||
|
||||
## data/data-tree and data/data-management
|
||||
## data/data-tree and data/database-management
|
||||
|
||||
`OPENLDAP_BOOTSTRAP_DATA_TREE=true` creates `ou=users`, `ou=groups` and `ou=services`
|
||||
below the suffix. `OPENLDAP_BOOTSTRAP_DATA_MANAGEMENT=true` creates one account,
|
||||
by default `cn=management,ou=services,<suffix>`, 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:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
dn: olcDatabase=monitor,cn=config
|
||||
objectClass: olcDatabaseConfig
|
||||
olcDatabase: monitor
|
||||
olcMonitoring: ${OPENLDAP_BOOTSTRAP_MONITOR_ENABLED}
|
||||
olcMonitoring: ${OPENLDAP_BOOTSTRAP_MONITOR}
|
||||
|
||||
@@ -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"
|
||||
|
||||
+7
-4
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user