fix(k8s): ensure-secrets keeps secret values off command lines
Values were passed as kubectl -p argument and via environment variables, both visible to other processes. Node now generates the values and writes the patch into a private temp file (umask 077, removed on exit); kubectl reads it with --patch-file. Only key names and modes are on the command line. Also fixes the first key being dropped (node -e argv offset). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
6e3e9aee9b
commit
46991a0815
1 file changed
+26
-12
@@ -21,9 +21,14 @@ NS="${NAMESPACE:-apicore}"
|
|||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
||||||
|
|
||||||
random_key() {
|
# Secret values never appear on a command line or in the environment (both
|
||||||
node -e "process.stdout.write(require('crypto').randomBytes(48).toString('base64url'))"
|
# are visible to other processes): node writes the patch straight into a
|
||||||
}
|
# private temp file, kubectl reads it with --patch-file.
|
||||||
|
umask 077
|
||||||
|
PATCH_FILE="$(mktemp)"
|
||||||
|
trap 'rm -f "$PATCH_FILE"' EXIT
|
||||||
|
# Windows tools (node, kubectl) in Git Bash need the native path.
|
||||||
|
PATCH_FILE_NATIVE="$(cygpath -w "$PATCH_FILE" 2>/dev/null || echo "$PATCH_FILE")"
|
||||||
|
|
||||||
existing_keys() {
|
existing_keys() {
|
||||||
kubectl get secret "$1" -n "$NS" -o jsonpath='{.data}' 2>/dev/null \
|
kubectl get secret "$1" -n "$NS" -o jsonpath='{.data}' 2>/dev/null \
|
||||||
@@ -35,19 +40,13 @@ ensure_keys() {
|
|||||||
local secret="$1"; shift
|
local secret="$1"; shift
|
||||||
local have
|
local have
|
||||||
have="$(existing_keys "$secret")"
|
have="$(existing_keys "$secret")"
|
||||||
local patch="{}" added=()
|
local spec=() added=()
|
||||||
while (($#)); do
|
while (($#)); do
|
||||||
local key="$1" mode="$2"; shift 2
|
local key="$1" mode="$2"; shift 2
|
||||||
if grep -qx "$key" <<<"$have"; then
|
if grep -qx "$key" <<<"$have"; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
local value
|
spec+=("$key=$mode")
|
||||||
case "$mode" in
|
|
||||||
random) value="$(random_key)" ;;
|
|
||||||
empty) value="" ;;
|
|
||||||
dummy) value="dummy" ;;
|
|
||||||
esac
|
|
||||||
patch="$(KEY="$key" VALUE="$value" PATCH="$patch" node -e "const p=JSON.parse(process.env.PATCH);p.stringData=p.stringData||{};p.stringData[process.env.KEY]=process.env.VALUE;process.stdout.write(JSON.stringify(p))")"
|
|
||||||
added+=("$key")
|
added+=("$key")
|
||||||
done
|
done
|
||||||
if ((${#added[@]} == 0)); then
|
if ((${#added[@]} == 0)); then
|
||||||
@@ -58,10 +57,25 @@ ensure_keys() {
|
|||||||
echo "$secret: wuerde ergaenzen: ${added[*]}"
|
echo "$secret: wuerde ergaenzen: ${added[*]}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
# Only key names and modes go on the command line; values are created here.
|
||||||
|
PATCH_FILE_PATH="$PATCH_FILE_NATIVE" node -e "
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const value = (mode) =>
|
||||||
|
mode === 'random' ? crypto.randomBytes(48).toString('base64url')
|
||||||
|
: mode === 'dummy' ? 'dummy'
|
||||||
|
: '';
|
||||||
|
const stringData = {};
|
||||||
|
for (const entry of process.argv.slice(1)) {
|
||||||
|
const [key, mode] = entry.split('=');
|
||||||
|
stringData[key] = value(mode);
|
||||||
|
}
|
||||||
|
require('fs').writeFileSync(process.env.PATCH_FILE_PATH, JSON.stringify({ stringData }), { mode: 0o600 });
|
||||||
|
" "${spec[@]}"
|
||||||
if ! kubectl get secret "$secret" -n "$NS" >/dev/null 2>&1; then
|
if ! kubectl get secret "$secret" -n "$NS" >/dev/null 2>&1; then
|
||||||
kubectl create secret generic "$secret" -n "$NS" >/dev/null
|
kubectl create secret generic "$secret" -n "$NS" >/dev/null
|
||||||
fi
|
fi
|
||||||
kubectl patch secret "$secret" -n "$NS" --type merge -p "$patch" >/dev/null
|
kubectl patch secret "$secret" -n "$NS" --type merge --patch-file "$PATCH_FILE_NATIVE" >/dev/null
|
||||||
|
: >"$PATCH_FILE"
|
||||||
echo "$secret: ergaenzt: ${added[*]}"
|
echo "$secret: ergaenzt: ${added[*]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user