docker-openldap icon indicating copy to clipboard operation
docker-openldap copied to clipboard

Bootstrapping custom LDIF

Open darth-veitcher opened this issue 5 years ago • 8 comments

I'm struggling with the --copy-service command to get a ldif file loaded by OpenLDAP with the vanilla osixia/openldap image.

Weirdly, doing the same thing with a custom image build works absolutely fine.

Obviously doing something stupid here so any help appreciated....!

--

99-add-content.ldif

# Create OUs
dn: ou=People,dc=xmansion,dc=local
objectClass: organizationalUnit
ou: People

dn: ou=Groups,dc=xmansion,dc=local
objectClass: organizationalUnit
ou: Groups

# Create Groups
dn: cn=admins,ou=Groups,dc=xmansion,dc=local
objectClass: posixGroup
cn: admins
gidNumber: 5000

# Create Users
dn: uid=bill,ou=People,dc=xmansion,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bill
sn: smith
givenName: Bill
cn: Bill Smith
displayName: Bill Smith
uidNumber: 10000
gidNumber: 5000
userPassword: password
gecos: Bill Smith
loginShell: /bin/bash
homeDirectory: /home/bsmith

Vanilla image

This does not work as expected and querying with docker exec ldap ldapsearch -x -H ldap://localhost -b dc=xmansion,dc=local -D "cn=admin,dc=xmansion,dc=local" -w mypassword gives me the following output:

# extended LDIF
#
# LDAPv3
# base <dc=xmansion,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# xmansion.local
dn: dc=xmansion,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: Mancave Inc.
dc: xmansion

# admin, xmansion.local
dn: cn=admin,dc=xmansion,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9L0tER0o1cnJHaUIxZjM4RHpuK1Q3eGhINDdoTW9nYVE=

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

It seems as though the custom ldif just isn't being found and executed?

docker-compose.yml

version: '3'

services:
  openldap:
    container_name: ldap
    image: osixia/openldap
    env_file: ./services/openldap/openldap.env
    command: --copy-service -l debug
    networks:
      - traefik_public
      - auth_internal
    volumes:
      - ./services/openldap/ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom

networks:
  # Used to expose openldap to keycloak
  traefik_public:
    external: true

  # Used to expose openldap to other apps which want to talk to LDAP
  auth_internal:
    external: true    

Custom build

This works as expected and querying with docker exec ldap ldapsearch -x -H ldap://localhost -b dc=xmansion,dc=local -D "cn=admin,dc=xmansion,dc=local" -w mypassword gives me the following output:

# extended LDIF
#
# LDAPv3
# base <dc=xmansion,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# xmansion.local
dn: dc=xmansion,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: Mancave Inc.
dc: xmansion

# admin, xmansion.local
dn: cn=admin,dc=xmansion,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9N1UyOFVFbEY5WWlZS2hIOVBwdjNoNXJsZ1ZHQ0RPUnQ=

# People, xmansion.local
dn: ou=People,dc=xmansion,dc=local
objectClass: organizationalUnit
ou: People

# Groups, xmansion.local
dn: ou=Groups,dc=xmansion,dc=local
objectClass: organizationalUnit
ou: Groups

# admins, Groups, xmansion.local
dn: cn=admins,ou=Groups,dc=xmansion,dc=local
objectClass: posixGroup
cn: admins
gidNumber: 5000

# bill, People, xmansion.local
dn: uid=bill,ou=People,dc=xmansion,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bill
sn: smith
givenName: Bill
cn: Bill Smith
displayName: Bill Smith
uidNumber: 10000
gidNumber: 5000
userPassword:: cGFzc3dvcmQ=
gecos: Bill Smith
loginShell: /bin/bash
homeDirectory: /home/bsmith

# search result
search: 2
result: 0 Success

# numResponses: 7
# numEntries: 6

docker-compose.yml

version: '3'

services:
  openldap:
    container_name: ldap
    build:
      context: ./services/openldap
      dockerfile: Dockerfile
    env_file: ./services/openldap/openldap.env
    networks:
      - traefik_public
      - auth_internal

networks:
  # Used to expose openldap to keycloak
  traefik_public:
    external: true

  # Used to expose openldap to other apps which want to talk to LDAP
  auth_internal:
    external: true    

Dockerfile

FROM osixia/openldap
# https://github.com/osixia/docker-openldap#extend-osixiaopenldap124-image

ADD ldif /container/service/slapd/assets/config/bootstrap/ldif/custom

darth-veitcher avatar May 07 '19 22:05 darth-veitcher

I use these debug steps to identify the issues I have when I am working with osixia/openldap.

  1. You could go inside the openldap container and check the contents of the /container/service/slapd/assets/config/bootstrap/ldif/custom directory to see if your ldif file is there(If it's not there, you can check if your volume mount has any problem)
  2. If it is there, you could issue your own ldapmodify command to your ldif file.
ldapadd -Z -D {{ ADMIN_DN}} -w {{ ADMIN_PW }} -f {{ ABSOLUTE_PATH_TO_LDIF_FILE }}

There are instances that if there are syntax errors in your LDIF file, it would just be ignored by the image.

Hope these helps.

cjbuckethead avatar May 09 '19 16:05 cjbuckethead

I have a similar issue and I think is not necessary to open a new issue now.

I am using docker compose format with "configs" option. It will mount every content read only, but independently from the --copy-service, the code try to apply a chown and the container is falling.

Software version: 1.2.5 and 1.3.0 (tested on both) Relevant part of the docker compose file:

Preparation (Define source) (the .ldif file is contains valid content. It was verified earlier)

configs:
  example_config:
    file: /tmp/example.ldif

Later in the compose file to apply the configuration: (configs section)

services:
  ldap:
    image: osixia/openldap:1.2.5
    networks:
      - example-ldap
    ports:
      - target: 389
        published: 6389
        protocol: tcp
        mode: ingress
      - target: 636
        published: 6636
        protocol: tcp
        mode: ingress
    environment:
      LDAP_LOG_LEVEL: "256"
      LDAP_ORGANISATION: "Example Inc."
      LDAP_DOMAIN: "example.org"
      LDAP_BASE_DN: ""
      LDAP_ADMIN_PASSWORD: "admin"
      LDAP_CONFIG_PASSWORD: "config"
      LDAP_READONLY_USER: "false"
      LDAP_READONLY_USER_USERNAME: "readonly"
      LDAP_READONLY_USER_PASSWORD: "readonly"
      LDAP_RFC2307BIS_SCHEMA: "false"
      LDAP_BACKEND: "mdb"
      LDAP_TLS: "true"
      KEEP_EXISTING_CONFIG: "false"
      LDAP_REMOVE_CONFIG_AFTER_SETUP: "false"
      LDAP_SSL_HELPER_PREFIX: "ldap"
    configs:
      - source: ldap_demo_config
        target: /container/service/slapd/assets/config/bootstrap/ldif/custom/example.ldif
        uid: '999' # openldap user in the container
        gid: '999' # openldap group in the container
    volumes:
      - ldap_config:/etc/ldap/slapd.d
      - ldap_db:/var/lib/ldap
      - ldap_certs:/container/run/service/slapd/assets/certs/
    command: ['--copy-service', '--loglevel debug']

Result during the container startup:

*** Running /container/run/startup/:ssl-tools...
 *** Running /container/run/startup/slapd...
chown: changing ownership of '/container/service/slapd/assets/config/bootstrap/ldif/custom/example.ldif': Read-only file system
*** /container/run/startup/slapd failed with status 1
*** Killing all processes...

I tried to and , then remove the --copy service flag, but it didn't affect the problem. I changed the path to /container/**run/**service/slapd/assets/config/bootstrap/ldif/custom/example.ldif. Result: the container will started, but ldif file will not applied.

So in this case not possible to add quickly LDIF files to these folders, because these configs will be writable and not possible to change the rights on the file.

From docker compose reference:

Configs cannot be writable because they are mounted in a temporary filesystem, so if you set the writable bit, it is ignored.

Source: Docker compose reference

Probably, the "configs" parameter is the best way to add our custom configs. Currently the code try to override the ownership on the "/container/service/slapd/assets/config/bootstrap/ldif/custom/" folder recursively, but it will not be applied anymore (reason above in docker compose reference).

Possible solutions for the issue:

  • Prepared directories with prepared right ownership and access rights and not change the ownership on the directory during the start.

  • Add a special environment variable to avoid the ownership changing the folder and its contents.

Many thanks for help and any idea.

kallaics avatar Dec 05 '19 07:12 kallaics

I found the "DISABLE_CHOWN" variable, but it generate other issue during the start process:

*** Running /container/run/startup/:ssl-tools...
*** Running /container/run/startup/slapd...
Start OpenLDAP...
Waiting for OpenLDAP to start...
Add TLS config...
No certificate file and certificate key provided, generate:
/container/service/slapd/assets/certs/ldap.crt and /container/service/slapd/assets/certs/ldap.key
2019/12/05 08:39:47 [INFO] generate received request
2019/12/05 08:39:47 [INFO] received CSR
2019/12/05 08:39:47 [INFO] generating key: ecdsa-384
2019/12/05 08:39:47 [INFO] encoded CSR
2019/12/05 08:39:47 [INFO] signed certificate with serial number 146118095191485821425214368443093861167456094075
Link /container/service/:ssl-tools/assets/default-ca/default-ca.pem to /container/service/slapd/assets/certs/ca.crt
*** /container/run/startup/slapd failed with status 80

*** Killing all processes...

The certs are generated by the image itself and I would like to add a custom LDIF file and unfortunately these combination is failing as well.

kallaics avatar Dec 05 '19 08:12 kallaics

I found the solution for my issue!

When I configure a volume under /container/run/ any subdirectory the container will be broken!

kallaics avatar Dec 06 '19 07:12 kallaics

Might be unrelated, but I get this when I try to mount custom ldifs:

Remove config files...
rm: cannot remove '/container/service/slapd/assets/config/bootstrap/ldif/custom': Device or resource busy
*** /container/run/startup/slapd failed with status 1```

sokoow avatar Dec 10 '19 15:12 sokoow

anyone has any progress with seeding the ldap db using osixia's image ?

sokoow avatar Dec 10 '19 15:12 sokoow

I use these debug steps to identify the issues I have when I am working with osixia/openldap.

  1. You could go inside the openldap container and check the contents of the /container/service/slapd/assets/config/bootstrap/ldif/custom directory to see if your ldif file is there(If it's not there, you can check if your volume mount has any problem)
  2. If it is there, you could issue your own ldapmodify command to your ldif file.
ldapadd -Z -D {{ ADMIN_DN}} -w {{ ADMIN_PW }} -f {{ ABSOLUTE_PATH_TO_LDIF_FILE }}

There are instances that if there are syntax errors in your LDIF file, it would just be ignored by the image.

Hope these helps.

I would like to add that i have used this command line with switch -n to just display in terminal what happening during an ldapadd function. It will show syntax errors within your LDIF file.

ludurr avatar Jan 14 '20 14:01 ludurr

I have a similar issue and I think is not necessary to open a new issue now.

I am using docker compose format with "configs" option. It will mount every content read only, but independently from the --copy-service, the code try to apply a chown and the container is falling.

Software version: 1.2.5 and 1.3.0 (tested on both) Relevant part of the docker compose file:

Preparation (Define source) (the .ldif file is contains valid content. It was verified earlier)

configs:
  example_config:
    file: /tmp/example.ldif

Later in the compose file to apply the configuration: (configs section)

services:
  ldap:
    image: osixia/openldap:1.2.5
    networks:
      - example-ldap
    ports:
      - target: 389
        published: 6389
        protocol: tcp
        mode: ingress
      - target: 636
        published: 6636
        protocol: tcp
        mode: ingress
    environment:
      LDAP_LOG_LEVEL: "256"
      LDAP_ORGANISATION: "Example Inc."
      LDAP_DOMAIN: "example.org"
      LDAP_BASE_DN: ""
      LDAP_ADMIN_PASSWORD: "admin"
      LDAP_CONFIG_PASSWORD: "config"
      LDAP_READONLY_USER: "false"
      LDAP_READONLY_USER_USERNAME: "readonly"
      LDAP_READONLY_USER_PASSWORD: "readonly"
      LDAP_RFC2307BIS_SCHEMA: "false"
      LDAP_BACKEND: "mdb"
      LDAP_TLS: "true"
      KEEP_EXISTING_CONFIG: "false"
      LDAP_REMOVE_CONFIG_AFTER_SETUP: "false"
      LDAP_SSL_HELPER_PREFIX: "ldap"
    configs:
      - source: ldap_demo_config
        target: /container/service/slapd/assets/config/bootstrap/ldif/custom/example.ldif
        uid: '999' # openldap user in the container
        gid: '999' # openldap group in the container
    volumes:
      - ldap_config:/etc/ldap/slapd.d
      - ldap_db:/var/lib/ldap
      - ldap_certs:/container/run/service/slapd/assets/certs/
    command: ['--copy-service', '--loglevel debug']

Result during the container startup:

*** Running /container/run/startup/:ssl-tools...
 *** Running /container/run/startup/slapd...
chown: changing ownership of '/container/service/slapd/assets/config/bootstrap/ldif/custom/example.ldif': Read-only file system
*** /container/run/startup/slapd failed with status 1
*** Killing all processes...

I tried to and , then remove the --copy service flag, but it didn't affect the problem. I changed the path to /container/**run/**service/slapd/assets/config/bootstrap/ldif/custom/example.ldif. Result: the container will started, but ldif file will not applied.

So in this case not possible to add quickly LDIF files to these folders, because these configs will be writable and not possible to change the rights on the file.

From docker compose reference:

Configs cannot be writable because they are mounted in a temporary filesystem, so if you set the writable bit, it is ignored.

Source: Docker compose reference

Probably, the "configs" parameter is the best way to add our custom configs. Currently the code try to override the ownership on the "/container/service/slapd/assets/config/bootstrap/ldif/custom/" folder recursively, but it will not be applied anymore (reason above in docker compose reference).

Possible solutions for the issue:

  • Prepared directories with prepared right ownership and access rights and not change the ownership on the directory during the start.
  • Add a special environment variable to avoid the ownership changing the folder and its contents.

Many thanks for help and any idea.

Thanks for giving solutions. Use LDAP_SEED_INTERNAL_LDIF_PATH work

env:
  - name: LDAP_SEED_INTERNAL_LDIF_PATH
    value: "/home/ldif"

hitchao avatar Mar 01 '22 04:03 hitchao