mirror of
https://github.com/osixia/container-openldap.git
synced 2026-11-06 12:40:36 -04:00
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.
179 lines
6.3 KiB
Go
179 lines
6.3 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"dagger.io/dagger"
|
|
)
|
|
|
|
// replicationPassword contains characters that must be quoted or escaped in olcSyncRepl,
|
|
// double quotes are rejected.
|
|
const replicationPassword = `Repl passw0rd 'single' \ $HOME`
|
|
|
|
const defaultSchemas = "core.ldif cosine.ldif inetorgperson.ldif rfc2307bis.ldif"
|
|
|
|
//go:embed testdata/templates.sh
|
|
var templatesCheck string
|
|
|
|
// ReadOnlyTemplates checks projected-volume sources and temporary-copy cleanup.
|
|
func ReadOnlyTemplates(ctx context.Context, client *dagger.Client, image *dagger.Container) error {
|
|
_, err := expect(ctx, image, true, nil, "container", "run", "--", "bash", "-c", templatesCheck)
|
|
return err
|
|
}
|
|
|
|
// allSchemas can be loaded together. Excluded:
|
|
// - nis.ldif and virtualMail.ldif conflict with rfc2307bis.ldif and postfix-book.ldif,
|
|
// they are tested by AlternativeSchemas;
|
|
// - msuser.ldif conflicts with inetorgperson.ldif and contains duplicated attribute types
|
|
// (OpenLDAP ships it "for informational purposes only").
|
|
var allSchemas = []string{
|
|
"core.ldif", "cosine.ldif", "inetorgperson.ldif", "rfc2307bis.ldif",
|
|
// OpenLDAP
|
|
"collective.ldif", "corba.ldif", "dsee.ldif", "duaconf.ldif", "dyngroup.ldif", "java.ldif",
|
|
"misc.ldif", "namedobject.ldif", "openldap.ldif", "pmi.ldif",
|
|
// osixia/openldap
|
|
"eduperson.ldif", "kerberos.ldif", "openssh-lpk.ldif", "postfix-book.ldif", "samba.ldif",
|
|
"sudo.ldif", "totp.ldif",
|
|
}
|
|
|
|
// allModules can be loaded together. Excluded: dyngroup.so conflicts with dynlist.so and
|
|
// mqtt.so conflicts with lastbind.so.
|
|
var allModules = []string{
|
|
"back_mdb.so", "argon2.so", "ppolicy.so", "unique.so", "refint.so", "memberof.so", "syncprov.so",
|
|
"accesslog.so", "auditlog.so", "autoca.so", "back_asyncmeta.so", "back_dnssrv.so", "back_ldap.so",
|
|
"back_meta.so", "back_null.so", "back_passwd.so", "back_relay.so", "back_sock.so", "back_sql.so",
|
|
"collect.so", "constraint.so", "dds.so", "deref.so", "dynlist.so", "homedir.so", "lastbind.so",
|
|
"lloadd.so", "nestgroup.so", "otp.so", "pcache.so", "pw-pbkdf2.so", "pw-sha2.so", "remoteauth.so",
|
|
"retcode.so", "rwm.so", "seqmod.so", "sssvlv.so", "translucent.so", "valsort.so",
|
|
}
|
|
|
|
// rootPasswords sets the config and database root passwords to the test password.
|
|
func rootPasswords(ctx context.Context, image *dagger.Container) (env, error) {
|
|
|
|
hash, err := hashPassword(ctx, image)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return env{
|
|
"OPENLDAP_BOOTSTRAP_CONFIG_ROOT_PASSWORD_HASHED": hash,
|
|
"OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED": hash,
|
|
}, nil
|
|
}
|
|
|
|
// Default starts the image with its default configuration.
|
|
func Default(ctx context.Context, client *dagger.Client, image *dagger.Container) error {
|
|
|
|
passwords, err := rootPasswords(ctx, image)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
const node = "ldap"
|
|
|
|
service, err := startNode(ctx, image, node, passwords, nil, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer stopNodes(ctx, []*dagger.Service{service})
|
|
|
|
return check(ctx, image, nil, env{"TEST_NODES": node, "TEST_SCHEMAS": defaultSchemas}, defaultCheck)
|
|
}
|
|
|
|
// AlternativeSchemas bootstraps with the schemas that conflict with the default ones.
|
|
func AlternativeSchemas(ctx context.Context, client *dagger.Client, image *dagger.Container) error {
|
|
|
|
schemas := "core.ldif cosine.ldif inetorgperson.ldif nis.ldif virtualMail.ldif"
|
|
|
|
r, err := expect(ctx, withEnv(image, env{"OPENLDAP_BOOTSTRAP_SCHEMAS": schemas}), true,
|
|
[]string{"config file testing succeeded"}, "container", "--skip-process")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = expect(ctx, r.container, true, []string{"cn: {3}nis", "cn: {4}virtualMail"},
|
|
"container", "run", "--", "slapcat", "-n", "0", "-a", "(objectClass=olcSchemaConfig)")
|
|
return err
|
|
}
|
|
|
|
// AllFeatures enables every bootstrap feature, all compatible modules and schemas, on a
|
|
// 3 nodes multi-provider cluster with TLS required.
|
|
func AllFeatures(ctx context.Context, client *dagger.Client, image *dagger.Container) error {
|
|
|
|
hash, err := hashPassword(ctx, image)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
nodes := []string{"ldap1", "ldap2", "ldap3"}
|
|
certs := certificates(client, nodes)
|
|
|
|
hosts := make([]string, 0, len(nodes))
|
|
for _, n := range nodes {
|
|
hosts = append(hosts, fmt.Sprintf("ldap://%s:3890", n))
|
|
}
|
|
|
|
features := env{
|
|
"OPENLDAP_BOOTSTRAP_MODULES": strings.Join(allModules, " "),
|
|
"OPENLDAP_BOOTSTRAP_SCHEMAS": strings.Join(allSchemas, " "),
|
|
|
|
"OPENLDAP_BOOTSTRAP_CONFIG_ROOT_PASSWORD_HASHED": hash,
|
|
"OPENLDAP_BOOTSTRAP_DATA_ROOT_PASSWORD_HASHED": hash,
|
|
|
|
"OPENLDAP_BOOTSTRAP_DATA_READONLY": "true",
|
|
"OPENLDAP_BOOTSTRAP_DATA_READONLY_PASSWORD_HASHED": hash,
|
|
|
|
"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": "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, " "),
|
|
"OPENLDAP_BOOTSTRAP_REPLICATION_DATA_READONLY_PASSWORD": replicationPassword,
|
|
}
|
|
|
|
if _, err := expect(ctx, withEnv(image, merge(features, env{"OPENLDAP_BOOTSTRAP_REPLICATION_DATA_READONLY_PASSWORD": `pass"word`})), false,
|
|
[]string{"must not contain double quotes"}, "container", "--skip-process"); err != nil {
|
|
return fmt.Errorf("replication password with double quotes: %w", err)
|
|
}
|
|
|
|
services := make([]*dagger.Service, 0, len(nodes))
|
|
defer func() { stopNodes(ctx, services) }()
|
|
|
|
for _, n := range nodes {
|
|
urls := env{"OPENLDAP_URLS": fmt.Sprintf("ldap://%s:3890 ldaps://%s:6360 ldapi:///", n, n)}
|
|
|
|
service, err := startNode(ctx, image, n, merge(features, urls), certs, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
services = append(services, service)
|
|
}
|
|
|
|
return check(ctx, image, certs, env{
|
|
"TEST_NODES": strings.Join(nodes, " "),
|
|
"TEST_MODULES": strings.Join(allModules, " "),
|
|
"TEST_SCHEMAS": strings.Join(allSchemas, " "),
|
|
|
|
"TEST_REPLICATION_PASSWORD": replicationPassword,
|
|
}, fullCheck)
|
|
}
|
|
|
|
//go:embed testdata/default.sh
|
|
var defaultCheck string
|
|
|
|
//go:embed testdata/full.sh
|
|
var fullCheck string
|