Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache the fernet key in the /config volume #55

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion readme-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ available_architectures:
# container parameters
param_usage_include_ports: true
param_container_name: "{{ project_name }}"
opt_param_usage_include_vols: true
opt_param_volumes:
- { vol_path: "/config", vol_host_path: "</path/to/appdata/config>", desc: "Persistent cache for the fernet key" }
param_ports:
- { external_port: "8888", internal_port: "8888", port_desc: "the port for ldap auth daemon" }
- { external_port: "9000", internal_port: "9000", port_desc: "the port for ldap login page" }

# optional container parameters
opt_param_usage_include_env: true
opt_param_env_vars:
- { env_var: "FERNETKEY", env_value: "", desc: "Optionally define a custom valid fernet key (only needed if container is frequently recreated, or if using multi-node setups, invalidating previous authentications)" }
- { env_var: "FERNETKEY", env_value: "", desc: "Optionally define a custom valid fernet key (only needed if the /config volume is not mounted, or if using multi-node setups, invalidating previous authentications)" }
- { env_var: "CERTFILE", env_value: "", desc: "Optionally point this to a certificate file to enable HTTP over SSL (HTTPS) for the ldap auth daemon" }
- { env_var: "KEYFILE", env_value: "", desc: "Optionally point this to the private key file, matching the certificate file referred to in CERTFILE" }

Expand All @@ -33,9 +36,11 @@ app_setup_block: |
- Here's a sample config: [nginx-ldap-auth.conf](https://github.com/nginxinc/nginx-ldap-auth/blob/master/nginx-ldap-auth.conf).
- Unlike the upstream project, this image encodes the cookie information with fernet, using a randomly generated key during container creation (or optionally user defined).
- Also unlike the upstream project, this image serves the login page at `/ldaplogin` (as well as `/login`) to prevent clashes with reverse proxied apps that may also use `/login` for their internal auth.
- If the `config` volume is specified, it will be used the cache the generated fernet key across restarts.

# changelog
changelogs:
- { date: "12.11.24:", desc: "Cache the generated fernet key in /config"}
- { date: "30.06.24:", desc: "Rebase to Alpine 3.20."}
- { date: "23.12.23:", desc: "Rebase to Alpine 3.19."}
- { date: "20.06.23:", desc: "Sync upstream changes, including the ability to disable referrals with `X-Ldap-DisableReferrals`." }
Expand Down
57 changes: 45 additions & 12 deletions root/etc/s6-overlay/s6-rc.d/init-ldap-config/run
Original file line number Diff line number Diff line change
@@ -1,20 +1,53 @@
#!/usr/bin/with-contenv bash
# shellcheck shell=bash

KEY_FILE=/config/fernet.key

normalize_key () {
if [[ -z ${1} || ${1} =~ ^b\'.*\'$ ]]; then
echo "${1}"
else
echo "b'${1}'"
fi
}

test_key () {
if [[ -z ${1} ]]; then
return 1
fi
python3 -c "from cryptography.fernet import Fernet; Fernet(${1}).encrypt(b'my deep dark secret')" 2>/dev/null
}

# generate fernet key for ldap if it doesn't exist
if grep -q 'REPLACEWITHFERNETKEY' /app/ldap-backend-app.py; then
if [[ -z "${FERNETKEY}" ]]; then
KEY=$(python3 /app/fernet-key.py)
echo "generated fernet key"
elif ! python3 -c "from cryptography.fernet import Fernet; Fernet(b'${FERNETKEY}').encrypt(b'my deep dark secret')" 2>/dev/null; then
echo "FERNETKEY env var is not set to a base64 encoded 32-byte key"
KEY=$(python3 /app/fernet-key.py)
echo "generated fernet key"
else
KEY="b'${FERNETKEY}'"
echo "using FERNETKEY from env variable"
key=
# First check environment variable
if [[ -n ${FERNETKEY} ]]; then
_key=$(normalize_key "${FERNETKEY}")
if test_key "${_key}"; then
key="${_key}"
echo "using FERNETKEY from env variable"
else
echo "FERNETKEY env var is not set to a base64 encoded 32-byte key"
fi
fi
# Second, check for a cached key
if [[ -z ${key} && -f ${KEY_FILE} ]]; then
_key=$(normalize_key $(cat "${KEY_FILE}"))
if test_key "${_key}"; then
echo "using key from ${KEY_FILE}"
key="${_key}"
else
echo "${KEY_FILE} does not contain a base64 encoded 32-byte key"
fi
fi
# Finally generate (and save) a new one
if [[ -z ${key} ]]; then
key=$(python3 /app/fernet-key.py)
echo "${key}" > ${KEY_FILE}
echo "generated and saved new key"
fi

sed -i "s/REPLACEWITHFERNETKEY/${KEY}/" /app/ldap-backend-app.py
sed -i "s/REPLACEWITHFERNETKEY/${KEY}/" /app/nginx-ldap-auth-daemon.py
sed -i "s/REPLACEWITHFERNETKEY/${key}/" /app/ldap-backend-app.py
sed -i "s/REPLACEWITHFERNETKEY/${key}/" /app/nginx-ldap-auth-daemon.py
fi
Loading