diff --git a/images/base/Dockerfile b/images/base/Dockerfile index 76c54704..ed307a3b 100644 --- a/images/base/Dockerfile +++ b/images/base/Dockerfile @@ -12,14 +12,18 @@ RUN mkdir /rootfs && curl "$URL" | tar --zstd -x -C /rootfs FROM scratch COPY --from=builder /rootfs / -# Install and setup sssd autoconfiguration +# Install and setup sssd autoconfiguration. +# ldap-utils provides ldapsearch, used by the git-identity profile script to +# fetch a user's email from the internal LDAP server on first interactive login. RUN apt-get update && \ - apt-get install -y sssd sudo tmux curl gnupg git jq unattended-upgrades && \ + apt-get install -y sssd sudo tmux curl gnupg git jq ldap-utils unattended-upgrades && \ pam-auth-update --enable mkhomedir && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* COPY --chmod=0440 sssd.conf /etc/sssd/sssd.conf COPY --chmod=0440 ldapusers /etc/sudoers.d/ldapusers +COPY --chmod=0644 ldap.conf /etc/ldap/ldap.conf +COPY --chmod=0755 git-identity.sh /etc/profile.d/git-identity.sh # The following service ensures environment variables set in the OCI metadata # or container configuration are passed to programs executed by systemd which diff --git a/images/base/git-identity.sh b/images/base/git-identity.sh new file mode 100644 index 00000000..2f80e516 --- /dev/null +++ b/images/base/git-identity.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Automatically configures git user.name and user.email from the user's LDAP +# profile on first interactive login to a container. Subsequent logins skip +# this entirely once git config is set. +# +# The name is read from the NSS gecos field (mapped from LDAP cn via sssd.conf). +# The email is read from LDAP via an anonymous ldapsearch (REQUIRE_AUTH_FOR_SEARCH +# is disabled on the internal ldap-gateway, so no bind credentials are needed). + +# Only run for interactive shells +[[ $- != *i* ]] && return + +# Only if git is available +command -v git >/dev/null 2>&1 || return +command -v ldapsearch >/dev/null 2>&1 || return + +# Skip if already configured — user-set values always take precedence +[ -n "$(git config --global user.email 2>/dev/null)" ] && [ -n "$(git config --global user.name 2>/dev/null)" ] && return + +_GIT_SETUP_USER="${USER:-$(id -un 2>/dev/null)}" +[ -z "$_GIT_SETUP_USER" ] && return +[ "$_GIT_SETUP_USER" = "root" ] && return + +# Full name from NSS (SSSD reads the LDAP gecos attribute by default via ldap_user_gecos) +_GIT_SETUP_NAME=$(getent passwd "$_GIT_SETUP_USER" 2>/dev/null | cut -d: -f5) + +# Email from LDAP anonymous query +_GIT_SETUP_LDAP_HOST="${LDAP_URI:-ldaps://ldap1:636}" + +# Resolve baseDN the same way SSSD does: rootDSE namingContexts autodiscovery. +# Use LDAP_BASE_DN if explicitly set; otherwise query rootDSE. +# - Single namingContexts entry -> use it directly +# - Multiple namingContexts -> use defaultNamingContext +# - Neither resolvable -> abort +if [ -n "${LDAP_BASE_DN:-}" ]; then + _GIT_SETUP_LDAP_BASE="$LDAP_BASE_DN" +else + _GIT_SETUP_ROOTDSE=$(ldapsearch -x -H "$_GIT_SETUP_LDAP_HOST" -b "" -s base namingContexts defaultNamingContext 2>/dev/null) + _GIT_SETUP_NC_COUNT=$(echo "$_GIT_SETUP_ROOTDSE" | grep -c '^namingContexts:') + if [ "$_GIT_SETUP_NC_COUNT" -eq 1 ]; then + _GIT_SETUP_LDAP_BASE=$(echo "$_GIT_SETUP_ROOTDSE" | awk '/^namingContexts:/{print $2; exit}') + elif [ "$_GIT_SETUP_NC_COUNT" -gt 1 ]; then + _GIT_SETUP_LDAP_BASE=$(echo "$_GIT_SETUP_ROOTDSE" | awk '/^defaultNamingContext:/{print $2; exit}') + fi + unset _GIT_SETUP_ROOTDSE _GIT_SETUP_NC_COUNT +fi +[ -z "${_GIT_SETUP_LDAP_BASE:-}" ] && return + +_GIT_SETUP_EMAIL=$(ldapsearch -x \ + -H "$_GIT_SETUP_LDAP_HOST" \ + -b "$_GIT_SETUP_LDAP_BASE" \ + "(uid=${_GIT_SETUP_USER})" mail 2>/dev/null \ + | awk '/^mail:/{print $2; exit}') + +if [ -n "$_GIT_SETUP_NAME" ]; then + git config --global user.name "$_GIT_SETUP_NAME" +fi + +if [ -n "$_GIT_SETUP_EMAIL" ]; then + git config --global user.email "$_GIT_SETUP_EMAIL" +fi + +unset _GIT_SETUP_USER _GIT_SETUP_NAME _GIT_SETUP_EMAIL _GIT_SETUP_LDAP_HOST _GIT_SETUP_LDAP_BASE _GIT_SETUP_ROOTDSE _GIT_SETUP_NC_COUNT diff --git a/images/base/ldap.conf b/images/base/ldap.conf new file mode 100644 index 00000000..ba75df65 --- /dev/null +++ b/images/base/ldap.conf @@ -0,0 +1,5 @@ +# OpenLDAP client configuration for containers. +# Mirrors the TLS check level used by SSSD (ldap_tls_reqcert = allow) so that +# ldapsearch and other ldap-utils tools accept the internal certificate without +# additional flags. +TLS_REQCERT allow diff --git a/images/base/sssd.conf b/images/base/sssd.conf index 3086ee24..73d486cf 100644 --- a/images/base/sssd.conf +++ b/images/base/sssd.conf @@ -7,5 +7,9 @@ auth_provider = ldap ldap_uri = ldaps://ldap1:636, ldaps://ldap2:636 ldap_tls_reqcert = allow +# Map LDAP cn attribute to the NSS gecos field so that tools like getent, +# finger, and the git-identity profile script can read the user's full name. +ldap_user_gecos = cn + # set a timeout long enough for a push notification to be responded to ldap_opt_timeout = 60