a6f95cfff1
- For testing purposes, we would like to ensure that when we connect to the LDAP server we cannot accidentally avoid using TLS or StartTLS. - Also enabled the openldap `memberOf` overlay in case we want to support group search using `memberOf` in the future. - This required changes to the docker.io/bitnami/openldap container image, so we're using our own fork for now. Will submit a PR to bitnami/openldap to see if they will accept it (or something similar) upstream.
350 lines
10 KiB
YAML
350 lines
10 KiB
YAML
#! Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
|
#! SPDX-License-Identifier: Apache-2.0
|
|
|
|
#@ load("@ytt:data", "data")
|
|
#@ load("@ytt:sha256", "sha256")
|
|
#@ load("@ytt:yaml", "yaml")
|
|
|
|
#@ def ldapLIDIF():
|
|
#@yaml/text-templated-strings
|
|
ldap.ldif: |
|
|
# ** CAUTION: Blank lines separate entries in the LDIF format! Do not remove them! ***
|
|
# Here's a good explanation of LDIF:
|
|
# https://www.digitalocean.com/community/tutorials/how-to-use-ldif-files-to-make-changes-to-an-openldap-system
|
|
|
|
# pinniped.dev (organization, root)
|
|
dn: dc=pinniped,dc=dev
|
|
objectClass: dcObject
|
|
objectClass: organization
|
|
dc: pinniped
|
|
o: example
|
|
|
|
# users, pinniped.dev (organization unit)
|
|
dn: ou=users,dc=pinniped,dc=dev
|
|
objectClass: organizationalUnit
|
|
ou: users
|
|
|
|
# groups, pinniped.dev (organization unit)
|
|
dn: ou=groups,dc=pinniped,dc=dev
|
|
objectClass: organizationalUnit
|
|
ou: groups
|
|
|
|
# beach-groups, groups, pinniped.dev (organization unit)
|
|
dn: ou=beach-groups,ou=groups,dc=pinniped,dc=dev
|
|
objectClass: organizationalUnit
|
|
ou: beach-groups
|
|
|
|
# pinny, users, pinniped.dev (user)
|
|
dn: cn=pinny,ou=users,dc=pinniped,dc=dev
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: shadowAccount
|
|
cn: pinny
|
|
sn: Seal
|
|
givenName: Pinny
|
|
mail: pinny.ldap@example.com
|
|
userPassword: (@= data.values.pinny_ldap_password @)
|
|
uid: pinny
|
|
uidNumber: 1000
|
|
gidNumber: 1000
|
|
homeDirectory: /home/pinny
|
|
loginShell: /bin/bash
|
|
gecos: pinny-the-seal
|
|
|
|
# wally, users, pinniped.dev (user without password)
|
|
dn: cn=wally,ou=users,dc=pinniped,dc=dev
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: shadowAccount
|
|
cn: wally
|
|
sn: Walrus
|
|
givenName: Wally
|
|
mail: wally.ldap@example.com
|
|
mail: wally.alternate@example.com
|
|
uid: wally
|
|
uidNumber: 1001
|
|
gidNumber: 1001
|
|
homeDirectory: /home/wally
|
|
loginShell: /bin/bash
|
|
gecos: wally-the-walrus
|
|
|
|
# olive, users, pinniped.dev (user without password)
|
|
dn: cn=olive,ou=users,dc=pinniped,dc=dev
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: shadowAccount
|
|
cn: olive
|
|
sn: Boston Terrier
|
|
givenName: Olive
|
|
mail: olive.ldap@example.com
|
|
uid: olive
|
|
uidNumber: 1002
|
|
gidNumber: 1002
|
|
homeDirectory: /home/olive
|
|
loginShell: /bin/bash
|
|
gecos: olive-the-dog
|
|
|
|
# ball-game-players, beach-groups, groups, pinniped.dev (group of users)
|
|
dn: cn=ball-game-players,ou=beach-groups,ou=groups,dc=pinniped,dc=dev
|
|
cn: ball-game-players
|
|
objectClass: groupOfNames
|
|
member: cn=pinny,ou=users,dc=pinniped,dc=dev
|
|
member: cn=olive,ou=users,dc=pinniped,dc=dev
|
|
|
|
# seals, groups, pinniped.dev (group of users)
|
|
dn: cn=seals,ou=groups,dc=pinniped,dc=dev
|
|
cn: seals
|
|
objectClass: groupOfNames
|
|
member: cn=pinny,ou=users,dc=pinniped,dc=dev
|
|
|
|
# walruses, groups, pinniped.dev (group of users)
|
|
dn: cn=walruses,ou=groups,dc=pinniped,dc=dev
|
|
cn: walruses
|
|
objectClass: groupOfNames
|
|
member: cn=wally,ou=users,dc=pinniped,dc=dev
|
|
|
|
# pinnipeds, users, pinniped.dev (group of groups)
|
|
dn: cn=pinnipeds,ou=groups,dc=pinniped,dc=dev
|
|
cn: pinnipeds
|
|
objectClass: groupOfNames
|
|
member: cn=seals,ou=groups,dc=pinniped,dc=dev
|
|
member: cn=walruses,ou=groups,dc=pinniped,dc=dev
|
|
|
|
# mammals, groups, pinniped.dev (group of both groups and users)
|
|
dn: cn=mammals,ou=groups,dc=pinniped,dc=dev
|
|
cn: mammals
|
|
objectClass: groupOfNames
|
|
member: cn=pinninpeds,ou=groups,dc=pinniped,dc=dev
|
|
member: cn=olive,ou=users,dc=pinniped,dc=dev
|
|
#@ end
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: ldap-ldif-files
|
|
namespace: tools
|
|
type: Opaque
|
|
stringData: #@ ldapLIDIF()
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: ldap-server-config-before-ldif-files
|
|
namespace: tools
|
|
type: Opaque
|
|
stringData:
|
|
server-config.ldif: |
|
|
# Load the memberof module.
|
|
dn: cn=module,cn=config
|
|
cn: module
|
|
objectClass: olcModuleList
|
|
objectClass: top
|
|
olcModulePath: /opt/bitnami/openldap/lib/openldap
|
|
olcModuleLoad: memberof
|
|
|
|
dn: olcOverlay={0}memberof,olcDatabase={2}hdb,cn=config
|
|
objectClass: olcConfig
|
|
objectClass: olcMemberOf
|
|
objectClass: olcOverlayConfig
|
|
objectClass: top
|
|
olcOverlay: memberof
|
|
olcMemberOfDangling: ignore
|
|
olcMemberOfRefInt: TRUE
|
|
olcMemberOfGroupOC: groupOfNames
|
|
olcMemberOfMemberAD: member
|
|
|
|
# Load the refint module.
|
|
dn: cn=module,cn=config
|
|
cn: module
|
|
objectclass: olcModuleList
|
|
objectclass: top
|
|
olcmodulepath: /opt/bitnami/openldap/lib/openldap
|
|
olcmoduleload: refint
|
|
|
|
dn: olcOverlay={1}refint,olcDatabase={2}hdb,cn=config
|
|
objectClass: olcConfig
|
|
objectClass: olcOverlayConfig
|
|
objectClass: olcRefintConfig
|
|
objectClass: top
|
|
olcOverlay: {1}refint
|
|
olcRefintAttribute: memberof member manager owner
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: ldap-server-config-after-ldif-files
|
|
namespace: tools
|
|
type: Opaque
|
|
stringData:
|
|
server-config.ldif: |
|
|
# Reject any further connections that do not use TLS or StartTLS
|
|
dn: olcDatabase={2}hdb,cn=config
|
|
changetype: modify
|
|
add: olcSecurity
|
|
olcSecurity: tls=1
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: ldap
|
|
namespace: tools
|
|
labels:
|
|
app: ldap
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: ldap
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: ldap
|
|
annotations:
|
|
#! Cause the pod to get recreated whenever the LDIF file changes.
|
|
ldifConfigHash: #@ sha256.sum(yaml.encode(ldapLIDIF()))
|
|
spec:
|
|
containers:
|
|
- name: ldap
|
|
#! Use our own fork of docker.io/bitnami/openldap for now, because we added the
|
|
#! LDAP_SERVER_CONFIG_BEFORE_CUSTOM_LDIF_DIR and LDAP_SERVER_CONFIG_AFTER_CUSTOM_LDIF_DIR options.
|
|
#! See https://github.com/pinniped-ci-bot/bitnami-docker-openldap/tree/ldap_server_config
|
|
image: ghcr.io/pinniped-ci-bot/bitnami-openldap-forked:2.4.58-debian-10-r57
|
|
imagePullPolicy: Always
|
|
ports:
|
|
- name: ldap
|
|
containerPort: 1389
|
|
- name: ldaps
|
|
containerPort: 1636
|
|
resources:
|
|
requests:
|
|
cpu: "100m" #! one-tenth of one CPU
|
|
memory: "64Mi"
|
|
limits:
|
|
#! Do not limit CPU because it was causing issues running integration tests on AKS where openldap became very slow.
|
|
memory: "64Mi"
|
|
readinessProbe:
|
|
tcpSocket:
|
|
port: ldap
|
|
initialDelaySeconds: 2
|
|
timeoutSeconds: 90
|
|
periodSeconds: 2
|
|
failureThreshold: 9
|
|
env:
|
|
#! Example ldapsearch commands that can be run from within the container based on these env vars.
|
|
#! These will print the whole LDAP tree starting at our root.
|
|
#! Using StartTLS (-ZZ) on the ldap port...
|
|
#! LDAPTLS_CACERT=/var/certs/ca.pem ldapsearch -x -ZZ -H 'ldap://ldap.tools.svc.cluster.local' -D 'cn=admin,dc=pinniped,dc=dev' -w password -b 'dc=pinniped,dc=dev'
|
|
#! Using ldaps...
|
|
#! LDAPTLS_CACERT=/var/certs/ca.pem ldapsearch -x -H 'ldaps://ldap.tools.svc.cluster.local' -D 'cn=admin,dc=pinniped,dc=dev' -w password -b 'dc=pinniped,dc=dev'
|
|
#! Note that the memberOf attribute is special and not returned by default. It must be specified as one of attributes to return in the search, e.g.:
|
|
#! LDAPTLS_CACERT=/var/certs/ca.pem ldapsearch -x -H 'ldaps://ldap.tools.svc.cluster.local' -D 'cn=admin,dc=pinniped,dc=dev' -w password -b 'dc=pinniped,dc=dev' cn uidNumber mail member memberOf
|
|
#! This should fail and report "TLS confidentiality required" because we require TLS and this does not use TLS or StartTLS...
|
|
#! ldapsearch -x -H 'ldap://ldap.tools.svc.cluster.local' -D 'cn=admin,dc=pinniped,dc=dev' -w password -b 'dc=pinniped,dc=dev'
|
|
- name: BITNAMI_DEBUG
|
|
value: "true"
|
|
- name: LDAP_ADMIN_USERNAME
|
|
value: "admin"
|
|
- name: LDAP_ADMIN_PASSWORD
|
|
value: "password" #! ok to hardcode: the LDAP server will not be available from outside the cluster
|
|
- name: LDAP_ENABLE_TLS
|
|
value: "yes"
|
|
- name: LDAP_TLS_CERT_FILE
|
|
value: "/var/certs/ldap.pem"
|
|
- name: LDAP_TLS_KEY_FILE
|
|
value: "/var/certs/ldap-key.pem"
|
|
- name: LDAP_TLS_CA_FILE
|
|
value: "/var/certs/ca.pem"
|
|
#! Note that the custom LDIF file is only read at pod start-up time.
|
|
- name: LDAP_CUSTOM_LDIF_DIR
|
|
value: "/var/ldifs"
|
|
- name: LDAP_SERVER_CONFIG_BEFORE_CUSTOM_LDIF_DIR
|
|
value: "/var/server-config-before-ldifs"
|
|
- name: LDAP_SERVER_CONFIG_AFTER_CUSTOM_LDIF_DIR
|
|
value: "/var/server-config-after-ldifs"
|
|
#! Seems like LDAP_ROOT is still required when using LDAP_CUSTOM_LDIF_DIR because it effects the admin user.
|
|
#! Presumably this needs to match the root that we create in the LDIF file.
|
|
- name: LDAP_ROOT
|
|
value: "dc=pinniped,dc=dev"
|
|
volumeMounts:
|
|
- name: certs
|
|
mountPath: /var/certs
|
|
readOnly: true
|
|
- name: ldifs
|
|
mountPath: /var/ldifs
|
|
readOnly: true
|
|
- name: server-config-before-ldifs
|
|
mountPath: /var/server-config-before-ldifs
|
|
readOnly: true
|
|
- name: server-config-after-ldifs
|
|
mountPath: /var/server-config-after-ldifs
|
|
readOnly: true
|
|
volumes:
|
|
- name: certs
|
|
secret:
|
|
secretName: certs
|
|
- name: ldifs
|
|
secret:
|
|
secretName: ldap-ldif-files
|
|
- name: server-config-before-ldifs
|
|
secret:
|
|
secretName: ldap-server-config-before-ldif-files
|
|
- name: server-config-after-ldifs
|
|
secret:
|
|
secretName: ldap-server-config-after-ldif-files
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ldap
|
|
namespace: tools
|
|
labels:
|
|
app: ldap
|
|
spec:
|
|
type: ClusterIP
|
|
selector:
|
|
app: ldap
|
|
ports:
|
|
- protocol: TCP
|
|
port: 389
|
|
targetPort: 1389
|
|
name: ldap
|
|
- protocol: TCP
|
|
port: 636
|
|
targetPort: 1636
|
|
name: ldaps
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ldaps
|
|
namespace: tools
|
|
labels:
|
|
app: ldap
|
|
spec:
|
|
type: ClusterIP
|
|
selector:
|
|
app: ldap
|
|
ports:
|
|
- protocol: TCP
|
|
port: 636
|
|
targetPort: 1636
|
|
name: ldaps
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ldapstarttls
|
|
namespace: tools
|
|
labels:
|
|
app: ldap
|
|
spec:
|
|
type: ClusterIP
|
|
selector:
|
|
app: ldap
|
|
ports:
|
|
- protocol: TCP
|
|
port: 389
|
|
targetPort: 1389
|
|
name: ldap
|