From 67a2568e529b6204527c959e67420d1a587285e6 Mon Sep 17 00:00:00 2001 From: Gabriel Carneiro Date: Thu, 27 Feb 2025 10:13:40 -0300 Subject: [PATCH] initial commit --- custom/00_schemas/groupOfEntries.ldif | 6 ++ custom/00_schemas/sudo.ldif | 11 ++++ custom/10_modify/acl.ldif | 10 ++++ custom/10_modify/memberOf.ldif | 9 +++ custom/README.md | 15 +++++ custom/ou/groups.ldif | 5 ++ custom/ou/hosts.ldif | 5 ++ custom/ou/mounts.ldif | 5 ++ custom/ou/sudoers.ldif | 5 ++ custom/ou/users.ldif | 5 ++ docker-compose.yml | 77 +++++++++++++++++++++++++ templates/ldifs/acl.ldif | 9 +++ templates/ldifs/groupOfNames.ldif | 9 +++ templates/schemas/groupofentries.ldif | 6 ++ templates/schemas/groupofentries.schema | 9 +++ templates/schemas/openssh-lpk.schema | 20 +++++++ templates/schemas/sudoers.schema | 11 ++++ 17 files changed, 217 insertions(+) create mode 100755 custom/00_schemas/groupOfEntries.ldif create mode 100755 custom/00_schemas/sudo.ldif create mode 100755 custom/10_modify/acl.ldif create mode 100755 custom/10_modify/memberOf.ldif create mode 100755 custom/README.md create mode 100755 custom/ou/groups.ldif create mode 100755 custom/ou/hosts.ldif create mode 100755 custom/ou/mounts.ldif create mode 100755 custom/ou/sudoers.ldif create mode 100755 custom/ou/users.ldif create mode 100644 docker-compose.yml create mode 100755 templates/ldifs/acl.ldif create mode 100755 templates/ldifs/groupOfNames.ldif create mode 100755 templates/schemas/groupofentries.ldif create mode 100755 templates/schemas/groupofentries.schema create mode 100755 templates/schemas/openssh-lpk.schema create mode 100755 templates/schemas/sudoers.schema diff --git a/custom/00_schemas/groupOfEntries.ldif b/custom/00_schemas/groupOfEntries.ldif new file mode 100755 index 0000000..081241a --- /dev/null +++ b/custom/00_schemas/groupOfEntries.ldif @@ -0,0 +1,6 @@ +# https://tools.ietf.org/html/draft-findlay-ldap-groupofentries-00 +# +dn: cn=groupofentries,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: groupofentries +olcObjectClasses: {0}( 1.2.826.0.1.3458854.2.1.1.1 NAME 'groupOfEntries' DESC 'Replacement for groupOfNames object without required member attribute' SUP top STRUCTURAL MUST ( cn ) MAY ( member $ businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) diff --git a/custom/00_schemas/sudo.ldif b/custom/00_schemas/sudo.ldif new file mode 100755 index 0000000..8c1f4e3 --- /dev/null +++ b/custom/00_schemas/sudo.ldif @@ -0,0 +1,11 @@ +dn: cn=sudo,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: sudo +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ description ) ) diff --git a/custom/10_modify/acl.ldif b/custom/10_modify/acl.ldif new file mode 100755 index 0000000..d956935 --- /dev/null +++ b/custom/10_modify/acl.ldif @@ -0,0 +1,10 @@ +dn: olcDatabase={1}{{ LDAP_BACKEND }},cn=config +changetype: modify +delete: olcAccess +- +add: olcAccess +olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break +olcAccess: to * by dn="cn=admin,{{ LDAP_BASE_DN }}" manage by * break +olcAccess: to * by set.expand="([cn=ldap_admin,ou=groups,{{ LDAP_BASE_DN }}])/member & user" write by * break +olcAccess: to attrs=userPassword,shadowLastChange by self =w by anonymous auth by * none +olcAccess: to * by self read by dn="cn={{ LDAP_READONLY_USER_USERNAME }},{{ LDAP_BASE_DN }}" read by * none diff --git a/custom/10_modify/memberOf.ldif b/custom/10_modify/memberOf.ldif new file mode 100755 index 0000000..e78a3aa --- /dev/null +++ b/custom/10_modify/memberOf.ldif @@ -0,0 +1,9 @@ +dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config +changetype: modify +replace: olcMemberOfGroupOC +olcMemberOfGroupOC: groupOfEntries + +dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config +changetype: modify +replace: olcMemberOfMemberAD +olcMemberOfMemberAD: member diff --git a/custom/README.md b/custom/README.md new file mode 100755 index 0000000..483cfaa --- /dev/null +++ b/custom/README.md @@ -0,0 +1,15 @@ +Add your custom ldif files here if you don't want to overwrite image default boostrap ldif. +at run time you can also mount a data volume with your ldif files to /container/service/slapd/assets/config/bootstrap/ldif/custom + +The startup script provides some substitutions in bootstrap ldif files. Following substitutions are supported: + +- `{{ LDAP_BASE_DN }}` +- `{{ LDAP_BACKEND }}` +- `{{ LDAP_DOMAIN }}` +- `{{ LDAP_READONLY_USER_USERNAME }}` +- `{{ LDAP_READONLY_USER_PASSWORD_ENCRYPTED }}` + +Other `{{ * }}` substitutions are left unchanged. + +Since startup script modifies `ldif` files, +you **must** add `--copy-service` argument to entrypoint if you don't want to overwrite them. diff --git a/custom/ou/groups.ldif b/custom/ou/groups.ldif new file mode 100755 index 0000000..0566f74 --- /dev/null +++ b/custom/ou/groups.ldif @@ -0,0 +1,5 @@ +dn: ou=groups,{{ LDAP_BASE_DN }} +changetype: add +objectClass: organizationalUnit +objectClass: top +ou: groups diff --git a/custom/ou/hosts.ldif b/custom/ou/hosts.ldif new file mode 100755 index 0000000..30589e5 --- /dev/null +++ b/custom/ou/hosts.ldif @@ -0,0 +1,5 @@ +dn: ou=hosts,{{ LDAP_BASE_DN }} +changetype: add +objectClass: organizationalUnit +objectClass: top +ou: hosts diff --git a/custom/ou/mounts.ldif b/custom/ou/mounts.ldif new file mode 100755 index 0000000..f82e7d7 --- /dev/null +++ b/custom/ou/mounts.ldif @@ -0,0 +1,5 @@ +dn: ou=mounts,{{ LDAP_BASE_DN }} +changetype: add +objectClass: organizationalUnit +objectClass: top +ou: mounts diff --git a/custom/ou/sudoers.ldif b/custom/ou/sudoers.ldif new file mode 100755 index 0000000..7885837 --- /dev/null +++ b/custom/ou/sudoers.ldif @@ -0,0 +1,5 @@ +dn: ou=sudoers,{{ LDAP_BASE_DN }} +changetype: add +objectClass: organizationalUnit +objectClass: top +ou: sudoers diff --git a/custom/ou/users.ldif b/custom/ou/users.ldif new file mode 100755 index 0000000..ddc070f --- /dev/null +++ b/custom/ou/users.ldif @@ -0,0 +1,5 @@ +dn: ou=users,{{ LDAP_BASE_DN }} +changetype: add +objectClass: organizationalUnit +objectClass: top +ou: users diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..34059be --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,77 @@ +services: + openldap: + image: osixia/openldap:1.5.0 + container_name: openldap + restart: unless-stopped + command: --loglevel debug --copy-service + environment: + LDAP_LOG_LEVEL: "256" + LDAP_ORGANISATION: "Alice" + LDAP_DOMAIN: "alice.ufsj" + LDAP_BASE_DN: "dc=alice,dc=ufsj" + LDAP_ADMIN_PASSWORD_FILE: "/run/secrets/ldap-admin" + LDAP_CONFIG_PASSWORD_FILE: "/run/secrets/ldap-config" + LDAP_READONLY_USER: "true" + LDAP_READONLY_USER_USERNAME: "alice" + LDAP_READONLY_USER_PASSWORD_FILE: "/run/secrets/ldap-readonly" + LDAP_RFC2307BIS_SCHEMA: "true" + LDAP_BACKEND: "mdb" + LDAP_TLS: "false" + + # LDAP_TLS_CRT_FILENAME: "fullchain1.pem" + # LDAP_TLS_KEY_FILENAME: "privkey1.pem" + # LDAP_TLS_DH_PARAM_FILENAME: "dhparam.pem" + # LDAP_TLS_CA_CRT_FILENAME: "ca/ca-certificates.crt" + # LDAP_TLS_ENFORCE: "false" + # LDAP_TLS_VERIFY_CLIENT: "demand" + # LDAP_REPLICATION: "false" + #LDAP_REPLICATION_CONFIG_SYNCPROV: 'binddn="cn=admin,cn=config" bindmethod=simple credentials="$$LDAP_CONFIG_PASSWORD" searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1 starttls=critical' + #LDAP_REPLICATION_DB_SYNCPROV: 'binddn="cn=admin,$$LDAP_BASE_DN" bindmethod=simple credentials="$$LDAP_ADMIN_PASSWORD" searchbase="$$LDAP_BASE_DN" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1 starttls=critical' + #LDAP_REPLICATION_HOSTS: "#PYTHON2BASH:['ldap://ldap.example.org','ldap://ldap2.example.org']" + KEEP_EXISTING_CONFIG: "false" + LDAP_REMOVE_CONFIG_AFTER_SETUP: "true" + LDAP_SSL_HELPER_PREFIX: "ldap" + tty: true + stdin_open: true + secrets: + - ldap-admin + - ldap-config + - ldap-readonly + volumes: + - data:/var/lib/ldap + - config:/etc/ldap/slapd.d + - ./templates:/templates + - ./custom:/container/service/slapd/assets/config/bootstrap/ldif/custom + networks: + - traefik-public + labels: + traefik.enable: true + traefik.tcp.routers.ldaps.entrypoints: ldaps + traefik.tcp.routers.ldaps.tls: true + traefik.tcp.routers.ldaps.rule: HostSNI(`*`) + traefik.tcp.services.ldaps.loadbalancer.server.port: 389 + + # ports: + # - "389:389" + # - "636:636" + + # For replication to work correctly, domainname and hostname must be + # set correctly so that "hostname"."domainname" equates to the + # fully-qualified domain name for the host. + # domainname: "example.org" + # hostname: "ldap-server" +volumes: + data: + config: + +networks: + traefik-public: + external: true + +secrets: + ldap-admin: + file: ./secrets/ldap-admin + ldap-config: + file: ./secrets/ldap-config + ldap-readonly: + file: ./secrets/ldap-readonly diff --git a/templates/ldifs/acl.ldif b/templates/ldifs/acl.ldif new file mode 100755 index 0000000..e56b52b --- /dev/null +++ b/templates/ldifs/acl.ldif @@ -0,0 +1,9 @@ +dn: olcDatabase={1}mdb,cn=config +changetype: modify +add: olcAccess +olcAccess: to * by self read by dn="cn=admin,dc=alice,dc=ufsj" write by dn="cn=alice,dc=alice,dc=ufsj" read by users read by * none + +dn: olcDatabase={1}mdb,cn=config +changetype: modify +delete: olcAccess +olcAccess: {2} diff --git a/templates/ldifs/groupOfNames.ldif b/templates/ldifs/groupOfNames.ldif new file mode 100755 index 0000000..e78a3aa --- /dev/null +++ b/templates/ldifs/groupOfNames.ldif @@ -0,0 +1,9 @@ +dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config +changetype: modify +replace: olcMemberOfGroupOC +olcMemberOfGroupOC: groupOfEntries + +dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config +changetype: modify +replace: olcMemberOfMemberAD +olcMemberOfMemberAD: member diff --git a/templates/schemas/groupofentries.ldif b/templates/schemas/groupofentries.ldif new file mode 100755 index 0000000..081241a --- /dev/null +++ b/templates/schemas/groupofentries.ldif @@ -0,0 +1,6 @@ +# https://tools.ietf.org/html/draft-findlay-ldap-groupofentries-00 +# +dn: cn=groupofentries,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: groupofentries +olcObjectClasses: {0}( 1.2.826.0.1.3458854.2.1.1.1 NAME 'groupOfEntries' DESC 'Replacement for groupOfNames object without required member attribute' SUP top STRUCTURAL MUST ( cn ) MAY ( member $ businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) diff --git a/templates/schemas/groupofentries.schema b/templates/schemas/groupofentries.schema new file mode 100755 index 0000000..aec9aca --- /dev/null +++ b/templates/schemas/groupofentries.schema @@ -0,0 +1,9 @@ +objectclass ( 1.2.826.0.1.3458854.2.1.1.1 NAME 'groupOfEntries' SUP top STRUCTURAL + MUST ( cn ) + MAY ( member $ + businessCategory $ + seeAlso $ + owner $ + ou $ + o $ + description ) ) diff --git a/templates/schemas/openssh-lpk.schema b/templates/schemas/openssh-lpk.schema new file mode 100755 index 0000000..c4cae65 --- /dev/null +++ b/templates/schemas/openssh-lpk.schema @@ -0,0 +1,20 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey +# Author: Eric AUGE +# +# Based on the proposal of : Mark Ruijter +# + + +# octetString SYNTAX +attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' + DESC 'OpenSSH Public key' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + +# printableString SYNTAX yes|no +objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY + DESC 'OpenSSH LPK objectclass' + MUST uid + MAY sshPublicKey + ) diff --git a/templates/schemas/sudoers.schema b/templates/schemas/sudoers.schema new file mode 100755 index 0000000..8c1f4e3 --- /dev/null +++ b/templates/schemas/sudoers.schema @@ -0,0 +1,11 @@ +dn: cn=sudo,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: sudo +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ description ) )