✨ Commits existing images to git

- Implemented sync-roles.sh to synchronize Active Directory group memberships as MariaDB roles and user accounts.
- Created Containerfile for building a custom ldap2pg image with patched YAML decoding.
- Added provision-user-db.sh for provisioning user databases and roles based on LDAP synchronization.
- Introduced a new Containerfile for MariaDB with PAM authentication via pam_ldap.
- Configured PAM service for MariaDB logins and added necessary plugins for LDAP authentication.
- Implemented health checks and entrypoint scripts for MariaDB and pgpool containers.
- Enhanced PostgreSQL image with additional extensions and custom pg_hba.conf for improved security and functionality.
This commit is contained in:
akritikos committed 2026-08-15 19:57:25 +03:00
commit 5744f4b7db
20 files changed
+1023

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
# syntax=docker/dockerfile:1.7
ARG MARIADB_VERSION=latest
FROM mariadb:${MARIADB_VERSION}
# ── AD/LDAP authentication via PAM ──────────────────────────────────────────
# MariaDB Community has no native LDAP auth plugin, so AD logins go through the
# auth_pam plugin -> a PAM "mariadb" service -> daemonless pam_ldap doing an
# LDAP search+bind against Active Directory. This is the analogue of the pgpool
# `ldap` method in pool_hba.conf; deliberately NO SSSD/nslcd daemon is added.
#
# libpam-ldap is the daemonless PAM/LDAP module. The auth_pam plugin ships with
# recent MariaDB; the separate plugin package (older layouts) is installed
# best-effort and also fixes the setuid auth_pam_tool helper permissions.
# Either source must leave auth_pam.so in place: 10-plugins.cnf loads it
# unconditionally, so a missing .so would only surface as a server that refuses
# to start.
RUN set -eu; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
libpam-ldap \
ca-certificates \
gettext-base; \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
mariadb-plugin-auth-pam || true; \
rm -rf /var/lib/apt/lists/*; \
plugin=/usr/lib/mysql/plugin/auth_pam.so; \
[ -e "$plugin" ] || { echo "auth_pam: missing $plugin" >&2; exit 1; }
# ── Layered configuration ───────────────────────────────────────────────────
# Mirror the postgres image: image-owned defaults load first, user overrides
# last (last-wins). The stock image already reads /etc/mysql/conf.d and
# /etc/mysql/mariadb.conf.d; we append two include dirs AFTER those so:
# image.conf.d -> our defaults (override the base image's 50-server.cnf)
# site.conf.d -> a clean "mount your *.cnf here" area (wins over everything)
RUN set -eu; \
mkdir -p /etc/mysql/image.conf.d /etc/mysql/site.conf.d; \
{ \
echo '!includedir /etc/mysql/image.conf.d/'; \
echo '!includedir /etc/mysql/site.conf.d/'; \
} >> /etc/mysql/mariadb.cnf
COPY conf.d/ /etc/mysql/image.conf.d/
# PAM service definition for MariaDB logins (auth_pam calls service "mariadb").
COPY pam.d/mariadb /etc/pam.d/mariadb
# Entrypoint wrapper: renders /etc/pam_ldap.conf from env (keeps the AD bind
# secret out of the image), then hands off to the stock mariadb entrypoint.
COPY --chmod=0755 docker-entrypoint.sh /usr/local/bin/ldap-entrypoint.sh
# Report health via the image's bundled healthcheck helper.
HEALTHCHECK --interval=10s --timeout=5s --retries=5 --start-period=15s \
CMD healthcheck.sh --connect --innodb_initialized || exit 1
ENTRYPOINT ["ldap-entrypoint.sh"]
CMD ["mariadbd"]
+11
View File
@@ -0,0 +1,11 @@
# Image-owned plugin preload (analogue of the postgres image's
# shared_preload_libraries in 10-extensions.conf). auth_pam provides Active
# Directory logins via PAM -> pam_ldap.
[mariadb]
plugin_load_add = auth_pam
# Make auth_pam use the mysql_clear_password protocol instead of the interactive
# "dialog" one. Required for MaxScale: its clear_pw_passthrough only speaks
# mysql_native_password / mysql_clear_password to backends, never dialog. The
# password is sent in cleartext, so TLS must be on (99-tls.cnf) — it is.
pam_use_cleartext_plugin = 1
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euo pipefail
# Render pam_ldap's config from the environment so the AD bind credentials are
# never baked into the image. pam_ldap performs a search+bind against AD: bind
# as the service account, find the user by ${LDAP_LOGIN_ATTR}, then re-bind as
# that DN with the supplied password to verify it — the same shape as pgpool's
# `ldap` method (see pool_hba.conf).
: "${LDAPURI:?LDAPURI is required (e.g. ldaps://hecate.ad.kritikos.io)}"
: "${LDAP_BASE:?LDAP_BASE is required (e.g. DC=ad,DC=kritikos,DC=io)}"
: "${LDAPBINDDN:?LDAPBINDDN is required (AD service/bind account)}"
: "${LDAPPASSWORD:?LDAPPASSWORD is required}"
: "${LDAP_LOGIN_ATTR:?LDAP_LOGIN_ATTR is required (e.g. sAMAccountName)}"
# demand = validate the AD cert against the trust store; relax to 'allow' only
# for testing, or add your internal CA to the image and keep 'demand'.
: "${LDAP_TLS_REQCERT:?LDAP_TLS_REQCERT is required (demand|allow|never)}"
umask 077
# pam_ldap.so on this image reads /etc/ldap.conf (the PADL default path), and
# libpam-ldap ships a placeholder there (base dc=example,dc=net) that otherwise
# shadows our config and makes every login fail. Render both paths.
for conf in /etc/ldap.conf /etc/pam_ldap.conf; do
cat > "$conf" <<EOF
uri ${LDAPURI}
base ${LDAP_BASE}
binddn ${LDAPBINDDN}
bindpw ${LDAPPASSWORD}
scope sub
referrals no
pam_login_attribute ${LDAP_LOGIN_ATTR}
pam_filter objectclass=User
tls_cacertdir /etc/ssl/certs
tls_reqcert ${LDAP_TLS_REQCERT}
EOF
chmod 600 "$conf"
done
# Grant mysql read access to the host TLS key (mode 0640, owned by GID
# ${CERTS_GID}). compose exposes that GID via `group_add`, but the stock
# entrypoint drops root -> mysql with gosu, which rebuilds mysql's groups from
# /etc/group and discards the compose-added GID — mysql then can't read ssl_key
# and MariaDB aborts with "Unable to get private key". While still root, put
# mysql in a group with that GID so it survives the privilege drop.
: "${CERTS_GID:?CERTS_GID is required (GID owning the host TLS key)}"
if [ "$(id -u)" = '0' ]; then
if getent group "${CERTS_GID}" >/dev/null; then
certgroup="$(getent group "${CERTS_GID}" | cut -d: -f1)"
else
groupadd -g "${CERTS_GID}" hostcerts
certgroup=hostcerts
fi
usermod -aG "$certgroup" mysql
else
echo "ldap-entrypoint: not root (uid $(id -u)); left group membership unchanged (CERTS_GID=${CERTS_GID})" >&2
fi
exec docker-entrypoint.sh "$@"
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -euo pipefail
# Runs once on first cluster init (empty datadir), the analogue of
# init_pgpool_user.sql. Creates the infrastructure accounts (MaxScale monitor +
# service, and the replication user) on the backend. All use native password
# auth (NOT pam) — they are service accounts, not human AD logins. Passwords
# come from the environment so nothing secret is committed to a .sql file, and
# the root password goes via MYSQL_PWD (read by the client) rather than -p so it
# never appears in the process list.
: "${MARIADB_ROOT_PASSWORD:?}"
: "${MAXSCALE_MONITOR_PASSWORD:?}"
: "${MAXSCALE_SERVICE_PASSWORD:?}"
: "${MARIADB_REPL_PASSWORD:?}"
MYSQL_PWD="${MARIADB_ROOT_PASSWORD}" mariadb --protocol=socket -uroot <<SQL
-- Monitor account: mariadbmon health checks, replication state, and failover.
CREATE USER IF NOT EXISTS 'maxscale_monitor'@'%' IDENTIFIED BY '${MAXSCALE_MONITOR_PASSWORD}';
GRANT BINLOG MONITOR, SLAVE MONITOR, REPLICATION SLAVE, REPLICATION MASTER ADMIN,
REPLICATION SLAVE ADMIN, READ_ONLY ADMIN, RELOAD, PROCESS,
SHOW DATABASES, EVENT
ON *.* TO 'maxscale_monitor'@'%';
-- Service account: reads the user tables so MaxScale can authenticate clients
-- and route them (pass-through auth defers the real check to the backend PAM).
CREATE USER IF NOT EXISTS 'maxscale_service'@'%' IDENTIFIED BY '${MAXSCALE_SERVICE_PASSWORD}';
GRANT SELECT ON mysql.* TO 'maxscale_service'@'%';
GRANT SHOW DATABASES ON *.* TO 'maxscale_service'@'%';
-- Replication account: the replica's IO thread uses this to stream the binlog.
CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED BY '${MARIADB_REPL_PASSWORD}';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
SQL
+6
View File
@@ -0,0 +1,6 @@
# PAM service for MariaDB auth_pam logins (accounts created IDENTIFIED VIA pam
# USING 'mariadb'). Authenticate + authorize against Active Directory through
# the daemonless pam_ldap module; its connection settings live in
# /etc/pam_ldap.conf, rendered at container start from the environment.
auth required pam_ldap.so
account required pam_ldap.so