Rotate a Secret
DiracX requires various secrets to operate securely. This guide explains how to rotate these secrets for maintenance or security purposes.
Throughout this page you'll need the release name you used when installing with helm (typically diracx
).
To find which releases are installed in your cluster you can use:
Note
Many kubernetes distributions (e.g. openshift) provide a web interface for managing secrets which may be simpler than the raw kubernetes commands listed below.
Database Secrets
SQL Database Connection URLs
You can get the current connection URLs with:
$ kubectl get secret/diracx-sql-connection-urls -o jsonpath='{.data}' | jq -r 'to_entries[] | "\(.key): \(.value | @base64d)"'
DIRACX_DB_URL_AUTHDB: mysql+aiomysql://username:password@hostname.invalid:1234/DiracXAuthDB
DIRACX_DB_URL_JOBDB: mysql+aiomysql://username:password@hostname.invalid:1234/JobDB
You can then update the connection URLs using:
# One-liner to update
kubectl patch secret diracx-sql-connection-urls -p '{
"data": {
"DIRACX_DB_URL_AUTHDB": "'$(echo -n "mysql+aiomysql://username:newpassword@hostname.invalid:1234/DiracXAuthDB" | base64 -w0)'",
"DIRACX_DB_URL_JOBDB": "'$(echo -n "mysql+aiomysql://username:newpassword@hostname.invalid:1234/JobDB" | base64 -w0)'"
}
}'
# Restart services to use new connections
kubectl rollout restart deployment <release-name>
Admin SQL Database Connection URLs
Similar to above, the root connection URLs can be found with:
$ kubectl get secret/diracx-sql-root-connection-urls -o jsonpath='{.data}' | jq -r 'to_entries[] | "\(.key): \(.value | @base64d)"'
DIRACX_DB_URL_AUTHDB: mysql+aiomysql://root:password@hostname.invalid:1234/DiracXAuthDB
DIRACX_DB_URL_JOBDB: mysql+aiomysql://root:password@hostname.invalid:1234/JobDB
And updated with:
# One-liner to update
kubectl patch secret diracx-sql-root-connection-urls -p '{
"data": {
"DIRACX_DB_URL_AUTHDB": "'$(echo -n "mysql+aiomysql://root:newpassword@hostname.invalid:1234/DiracXAuthDB" | base64 -w0)'",
"DIRACX_DB_URL_JOBDB": "'$(echo -n "mysql+aiomysql://root:newpassword@hostname.invalid:1234/JobDB" | base64 -w0)'"
}
}'
# No need to restart services as these URLs are only used during upgrades
OpenSearch Connection Configuration
You can get the current connection configuration with:
$ kubectl get secret/diracx-os-connection-urls -o jsonpath='{.data}' | jq -r 'to_entries[] | "\(.key): \(.value | @base64d)"'
DIRACX_OS_DB_JOBPARAMETERSDB: {"hosts": "username:password@hostname.invalid:443/os", "use_ssl": true, "verify_certs": true}
You can then update the connection configuration using:
# One-liner to update
kubectl patch secret diracx-os-connection-urls -p '{
"data": {
"DIRACX_OS_DB_JOBPARAMETERSDB": "'$(echo -n '{"hosts": "username:newpassword@hostname.invalid:443/os", "use_ssl": true, "verify_certs": true}' | base64 -w0)'"
}
}'
# Restart services to use new connections
kubectl rollout restart deployment <release-name>
Object storage
Sandbox store
Warning
DiracX makes extensive use of pre-signed URLs for exposing access S3 to clients (e.g. when uploading/downloading sandboxes). These are explicitly tied to the access key and secret used by DiracX and revoking the credentials will cause errors for clients which have already been given pre-signed URLs. If the need is not urgent, we recommend waiting a few hours before revoking the previous credentials.
To check the current credentials:
$ kubectl get secret/diracx-secrets -o jsonpath='{.data.DIRACX_SANDBOX_STORE_S3_CLIENT_KWARGS}' | base64 -d
{"endpoint_url": "https://s3.invalid", "aws_access_key_id": "abcedfg", "aws_secret_access_key": "hijklmnop"}
To set new S3 credentials:
kubectl patch secret diracx-secrets -p '{
"data": {
"DIRACX_SANDBOX_STORE_S3_CLIENT_KWARGS": "'$(echo -n '{"endpoint_url": "https://s3.invalid", "aws_access_key_id": "123456", "aws_secret_access_key": "78910"}' | base64 -w0)'"
}
}'
kubectl rollout restart deployment <release-name>
Authentication Secrets
DiracX Service Auth State Key
Warning
Any currently in progress login sessions will fail as a result of changing the auth state key!
Update the authentication state key in-place (this will cause a brief service restart):
# Generate new key and update the existing secret
new_key=$(head -c 32 /dev/urandom | base64)
kubectl patch secret diracx-dynamic-secrets -p "{\"data\":{\"DIRACX_SERVICE_AUTH_STATE_KEY\":\"$new_key\"}}"
# Restart DiracX services to pick up the new key
kubectl rollout restart deployment <release-name>
JWT Signing Keys (JWK)
DiracX supports having multiple JWT signing keys available at the same time, with only the latest one being used for signing new keys.
Before proceeding you likely want to know the key IDs that you currently have in use, you can find these by running:
$ curl --silent -L https://<your-installation-hostname>/.well-known/jwks.json | jq -r '.keys[]|.kid'
0196af4d311579728287cb89c24514e9
0196af4d0ab27b1299dff55b8617991d
To add a new JWK into rotation run:
# Get the current keystore
kubectl get secret/diracx-jwks -o jsonpath='{.data.jwks\.json}' | base64 -d > keystore.json
# Modify the keystore
python -m diracx.logic rotate-jwk --jwks-path keystore.json
# Update the secret in the cluster
kubectl patch secret/diracx-jwks --type='json' -p='[{"op": "replace", "path": "/data/jwks.json", "value":"'$(base64 -w 0 keystore.json)'"}]'
rm keystore.json
# Restart DiracX services to pick up the new key
kubectl rollout restart deployment <release-name>
After your satisfied the previous key is no longer used (or if you wish to immediately revoke all currently active credentials) you can run:
# Get the current keystore
kubectl get secret/diracx-jwks -o jsonpath='{.data.jwks\.json}' | base64 -d > keystore.json
# Modify the keystore
python -m diracx.logic delete-jwk --jwks-path keystore.json --kid 0196af4d0ab27b1299dff55b8617991d
# Update the secret in the cluster
kubectl patch secret/diracx-jwks --type='json' -p='[{"op": "replace", "path": "/data/jwks.json", "value":"'$(base64 -w 0 keystore.json)'"}]'
rm keystore.json
# Restart DiracX services to pick up the new key
kubectl rollout restart deployment <release-name>
Legacy exchange secret
Warning
Rotating the legacy exchange secret will cause a brief service interruption. In principle clients should automatically retry but good luck!
To rotate the secret which is used by your legacy DIRAC installation to communicate with DiracX first generate a new pair of secrets:
import secrets
import base64
import hashlib
token = secrets.token_bytes()
# This is the secret to include in the request by setting the
# /DiracX/LegacyExchangeApiKey CS option in your legacy DIRAC installation
print(f"API key is diracx:legacy:{base64.urlsafe_b64encode(token).decode()}")
# This is the environment variable to set on the DiracX server
print(
f"DIRACX_LEGACY_EXCHANGE_HASHED_API_KEY={hashlib.sha256(token).hexdigest()}"
)
Update the hashed secret in your DiracX installation:
kubectl patch secret diracx-secrets -p '{
"data": {
"DIRACX_LEGACY_EXCHANGE_HASHED_API_KEY": "'$(echo -n "0123456789abcef0123456789abcef0123456789abcef0123456789abcef0123" | base64 -w0)'"
}
}'
Then update /DiracX/LegacyExchangeApiKey
in your legacy DIRAC installation's dirac.cfg
and restart:
# Trigger a rollout of DiracX to pick up the new key
kubectl rollout restart deployment <release-name>
# Restart your legacy DIRAC services (e.g. with "runsvctrl t ...")
TLS Certificates
TLS certificates are automatically managed by cert-manager and shouldn't require intervention. To force certificate renewal see the upstream documentation.