Sikker håndtering af hemmeligheder og rent miljø
Hold legitimationsoplysninger ude af proceslister og logs ved hjælp af stdin, filer og rensede miljøer.
Sikker håndtering af hemmeligheder og rent miljø er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvorfor god håndtering af hemmeligheder er vigtig
Hemmeligheder — API-nøgler, adgangskoder og tokens — er de mest følsomme data i ethvert system. Forkert håndtering af dem i Bash-scripts er en af de mest almindelige og skadelige sikkerhedsfejl.
- Proceslister: Argumenter, der sendes til kommandoer, vises i
ps aux,/proc/<pid>/cmdlineog systemets revisionslogge — synlige for alle brugere på værten. - Shell-historik: Kommandoer, der indtastes interaktivt (og nogle gange scripts), gemmes i
~/.bash_history. - Logfiler: Spor fra
set -x, applikationslogge og CI/CD-output kan opfange variableværdier. - Lækage gennem miljøet: Underprocesser arver hele deres overordnede proces' miljø, herunder alle eksporterede hemmeligheder.
Et hærdet script behandler hemmeligheder som radioaktivt materiale — minimér eksponeringstiden, begræns overfladen, og rens alt på vej ud.
Angrebsfladen i proceslister
Når du sender en hemmelighed som et kommandolinjeargument, kan alle brugere på systemet straks læse den via ps. Det er ikke teoretisk — det udnyttes jævnligt i delte hostingmiljøer og container-miljøer.
Uddraget nedenfor viser problemet og løsningen side om side.
#!/usr/bin/env bash
# DANGEROUS: password visible in 'ps aux' output
# curl -u "admin:SuperSecret123" https://api.example.com/data
# SAFE: pass credentials via stdin or a flag that reads from a file
# Many tools support reading secrets from stdin with '-' or dedicated flags:
# Option 1 — pipe the secret so it never appears in argv
echo 'SuperSecret123' | curl -u 'admin' --password-stdin \
https://api.example.com/data 2>/dev/null || true
# Option 2 — write a temporary netrc and point curl at it
# (covered in a later scene)
echo 'Secret never touches the command line this way'Læsning af hemmeligheder fra stdin
Det sikreste interaktive mønster er at læse en hemmelighed under kørsel med read -rs. Flaget -s undertrykker ekko, så tegnene aldrig vises, og -r forhindrer fortolkning af omvendte skråstreger.
Vigtige punkter:
- Variablen eksporteres aldrig, så underprocesser ikke kan se den via
/proc/<pid>/environ. - Efter brug skal du straks unset variablen for at forkorte eksponeringsvinduet.
- Undgå
echo "$SECRET"— brugprintf '%s'for at forhindre, at et afsluttende linjeskift ødelægger værdien, og for at forblive usynlig i sporingsoutput.
#!/usr/bin/env bash
set -euo pipefail
# Prompt on stderr so stdout stays clean for piping
read -rsp 'Enter API token: ' API_TOKEN <&2
printf '\n' >&2
# Use the secret — printf keeps it out of argv
response=$(printf '%s' "$API_TOKEN" | curl -sS -X POST \
-H 'Content-Type: application/json' \
--data-binary @- \
https://httpbin.org/post 2>/dev/null) || true
echo "Request sent."
# Scrub immediately — unset removes it from shell memory
unset API_TOKENHemmeligheder i filer: Tilladelser og ejerskab
Når en hemmelighed skal gemmes på disken (f.eks. en nøgle til en servicekonto), er filens tilladelser dit primære forsvar.
- Tilstand 0600 — kan kun læses og skrives af ejeren. Ingen adgang for gruppen eller andre.
- Tilstand 0400 — skrivebeskyttet for ejeren. Foretræk dette til nøgler, som du aldrig ved et uheld bør overskrive.
- Gem hemmelighedsfiler i en dedikeret mappe som
~/.secrets/eller/run/secrets/(sidstnævnte er et RAM-baseret tmpfs på mange Linux-systemer og findes kun indtil næste genstart). - Placér aldrig hemmelighedsfiler i en git-sporet mappe uden en helt solid
.gitignore.
#!/usr/bin/env bash
set -euo pipefail
SECRETS_DIR="${HOME}/.secrets"
mkdir -p "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR" # directory: only owner can list contents
KEY_FILE="${SECRETS_DIR}/api_token"
# Write secret — atomically restrict permissions before writing content
install -m 0600 /dev/null "$KEY_FILE"
printf '%s' 'my-super-secret-token' > "$KEY_FILE"
echo "Permissions:"
ls -la "$KEY_FILE"
# Read back safely — no subshell, no echo
API_TOKEN=$(< "$KEY_FILE")
echo "Token length: ${#API_TOKEN} chars (value not printed)"
unset API_TOKENBrug af en .netrc-fil med curl
curl understøtter en ~/.netrc-fil (eller en vilkårlig sti via --netrc-file), der knytter værtsnavne til legitimationsoplysninger. Det holder godkendelsesdata helt væk fra kommandolinjen og scriptets brødtekst.
Filformatet er enkelt:
machine api.example.com
login admin
password s3cr3tBedste praksis:
- Sæt altid
chmod 0600 ~/.netrc— curl afviser filen, hvis den kan læses af alle, på nogle systemer. - Brug
--netrc-file /run/secrets/netrctil at pege på en hemmelighed i et tmpfs eller en hemmelighed, der er tilført containeren. - Ryd midlertidige netrc-filer op med en
trapved EXIT.
#!/usr/bin/env bash
set -euo pipefail
TMP_NETRC=$(mktemp)
chmod 0600 "$TMP_NETRC"
# Trap ensures cleanup even on error or signal
trap 'rm -f "$TMP_NETRC"' EXIT
# Write credentials to the temp netrc
cat > "$TMP_NETRC" <<'EOF'
machine httpbin.org
login myuser
password mypassword
EOF
curl -fsS --netrc-file "$TMP_NETRC" \
https://httpbin.org/basic-auth/myuser/mypassword \
-o /dev/null -w 'HTTP %{http_code}\n' || true
# trap fires here: $TMP_NETRC is deleted
echo 'Temp netrc cleaned up by trap.'Hygiejne for miljøvariabler
Miljøvariabler er en populær måde at tilføre hemmeligheder til scripts på (12-factor-apps, CI/CD-pipelines). De lækkes dog til hver underproces og findes i /proc/<pid>/environ i hele processens levetid.
Beskyttende mønstre:
- Indlæs straks hemmeligheden i en lokal variabel, og fjern miljøvariablen med
unset, så underprocesser ikke kan arve den. - Send hemmeligheder til bestemte kommandoer med
env -ieller en tildeling på samme linje i stedet for at bruge hele det nedarvede miljø. - Brug aldrig
exportmed en hemmelighedsvariabel — brug om muligt kun en tildeling (udenexport).
#!/usr/bin/env bash
set -euo pipefail
# Simulate a secret arriving via environment (e.g., from CI system)
export DB_PASSWORD='hunter2' # set by CI — we did not choose this
# Capture locally, then strip from environment immediately
db_password="$DB_PASSWORD"
unset DB_PASSWORD
# Verify the env var is gone before spawning any child process
if printenv DB_PASSWORD 2>/dev/null; then
echo 'ERROR: DB_PASSWORD still in environment!' >&2
exit 1
fi
echo 'Secret captured and env var scrubbed.'
echo "Password length: ${#db_password}"
unset db_passwordForhindring af, at hemmeligheder vises i spor fra set -x
set -x (xtrace) er uvurderlig til fejlfinding, men udskriver værdien af hver variabel, den udvider — også hemmeligheder — til stderr. Disse spor ender ofte i CI-logfiler eller syslog.
Strategier til at beskytte hemmeligheder og samtidig bevare nyttig sporing:
- Deaktivér sporing midlertidigt omkring følsomme handlinger med
{ set +x; } 2>/dev/null. - Aktivér den igen bagefter med
set -x. - Omdirigér xtrace-outputtet til en separat fildeskriptor, der skriver til en beskyttet logfil i stedet for den offentlige logstrøm.
#!/usr/bin/env bash
set -euo pipefail
set -x # tracing ON — safe for non-sensitive sections
echo 'Building application...'
SRC_DIR='/tmp/build'
mkdir -p "$SRC_DIR"
# Disable xtrace around secret handling (suppress the set +x line itself)
{ set +x; } 2>/dev/null
read -rsp 'Token (hidden from trace): ' SECRET_TOKEN <&2
printf '\n' >&2
token_len=${#SECRET_TOKEN}
unset SECRET_TOKEN
set -x # tracing back ON
echo "Token captured (length=$token_len). Continuing build..."
ls "$SRC_DIR"Fjernelse af hemmeligheder fra logfiler
Selv når du er forsigtig, finder hemmeligheder nogle gange vej til logoutputtet — især i udførlige eller ældre scripts. En wrapperfunktion til logning, der slører kendte mønstre, giver et ekstra sikkerhedsnet.
Dette mønster bruger en regex-baseret erstatning på alt logoutput. Det er et sidste forsvarslag og ikke en erstatning for de øvrige hygiejnepraksisser, der allerede er gennemgået.
#!/usr/bin/env bash
set -euo pipefail
# A logging function that scrubs common secret patterns before writing
log() {
local line
# Replace anything that looks like key=VALUE or password=VALUE
line=$(printf '%s\n' "$*" \
| sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***REDACTED***/gi')
printf '[%s] %s\n' "$(date -u '+%T')" "$line"
}
# Usage:
log 'Connecting to database with password=hunter2'
log 'Loaded API token=sk-abc123xyz secret'
log 'Build step completed successfully' # unchangedIsolerede miljøer med env -i
env -i starter en kommando med et helt tomt miljø, så ingen nedarvede variabler — herunder utilsigtede hemmeligheder — når frem til underprocessen. Derefter sender du eksplicit kun det, der er nødvendigt.
Det er især nyttigt, når du kører scripts, buildværktøjer eller tredjepartsværktøjer, som ikke er pålidelige og kan forsøge at hente data ud af miljøet.
#!/usr/bin/env bash
set -euo pipefail
# Polluted parent environment (simulating a CI runner)
export AWS_SECRET_ACCESS_KEY='AKIAIOSFODNN7EXAMPLE'
export GITHUB_TOKEN='ghp_faketoken123'
export HOME="$HOME"
export PATH="$PATH"
echo '--- Child sees full environment:'
env | grep -E 'AWS|GITHUB' | head -5
echo '--- Sanitised child (env -i) sees nothing secret:'
env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-dumb}" \
bash -c 'env | grep -E "AWS|GITHUB" || echo "No secrets visible"'
unset AWS_SECRET_ACCESS_KEY GITHUB_TOKENMidlertidige hemmelighedsfiler på tmpfs
tmpfs er et RAM-baseret filsystem. Filer, der skrives dertil, tømmes aldrig til disken, hvilket fjerner risikoen for, at hemmeligheder overlever i swap, diskcache eller snapshots.
- På Linux er
/dev/shmog/run/user/<uid>typisk tmpfs-monteringer. - Kombinér altid brug af tmpfs med en
trap EXITfor at slette filer, når scriptet afsluttes. - I containere (Docker, Kubernetes) kan hemmeligheder monteres som tmpfs-diskenheder direkte i
/run/secrets.
#!/usr/bin/env bash
set -euo pipefail
# Prefer /run/user/$UID (user-owned tmpfs) or /dev/shm (world-readable dir!)
if [[ -d "/run/user/$UID" ]]; then
TMPFS_DIR="/run/user/$UID"
elif [[ -d '/dev/shm' ]]; then
TMPFS_DIR='/dev/shm'
else
# Fallback: warn that disk will be used
echo 'WARNING: No tmpfs available; using /tmp (disk-backed)' >&2
TMPFS_DIR='/tmp'
fi
SECRET_FILE=$(mktemp "${TMPFS_DIR}/secret.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'shred -u "$SECRET_FILE" 2>/dev/null || rm -f "$SECRET_FILE"' EXIT
printf '%s' 'my-runtime-token' > "$SECRET_FILE"
echo "Secret stored in: $SECRET_FILE"
df -T "$SECRET_FILE" | awk 'NR==2 {print "Filesystem type:", $2}'
# Use the secret...
token=$(< "$SECRET_FILE")
echo "Token length: ${#token}"
unset token
# trap fires on exit: file shreddedSådan samles det hele: Et hærdet deploymentscript
Det følgende script kombinerer alle teknikkerne fra denne lektion i en realistisk hjælper til deployment. Læg mærke til, hvordan hvert forsvarslag styrker de andre:
- Læsning fra stdin med
-s— ingen ekko på terminalen - Hemmelighedsfil på tmpfs med oprydning via
trap - Rensning af miljøet — hemmeligheden fjernes med
unsetfør enhver underproces - xtrace-vagt — sporing sættes på pause omkring følsom kode
- Sløring i loggen — sikkerhedsnet med regex før skrivning til loggen
#!/usr/bin/env bash
set -euo pipefail
### 1. Redacting logger
log() {
local msg
msg=$(printf '%s' "$*" \
| sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***/gi')
printf '[%s] %s\n' "$(date -u +%T)" "$msg"
}
### 2. tmpfs secret store
TMPFS_DIR="${XDG_RUNTIME_DIR:-/tmp}"
SECRET_FILE=$(mktemp "${TMPFS_DIR}/deploy_token.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'rm -f "$SECRET_FILE"; log "Secret file cleaned up."' EXIT
### 3. Read secret without trace
{ set +x; } 2>/dev/null
read -rsp 'Deploy token: ' _tok <&2; printf '\n' >&2
printf '%s' "$_tok" > "$SECRET_FILE"
unset _tok
set -x
### 4. Scrub inherited env vars before subprocess
unset DEPLOY_TOKEN 2>/dev/null || true
log 'Starting deployment...'
# Simulate deploy using secret from file (token never in argv)
# curl -H "Authorization: Bearer $(< $SECRET_FILE)" https://api.example.com/deploy
log 'Deployment complete. token=hidden_by_redactor'
echo 'Done.'Videnstjek: Eksponering af hemmeligheder via procesliste
Test din forståelse af, hvordan hemmeligheder lækkes gennem proceslister, og hvordan du kan forhindre det.
Opsummering af lektionen: Sikker håndtering af hemmeligheder
Du har gennemført Sikker håndtering af hemmeligheder og miljøhygiejne. Her er en kort oversigt over alt det, der blev gennemgået:
- Proceslister: Send aldrig hemmeligheder som kommandolinjeargumenter — de vises i
ps auxog/proc/<pid>/cmdline. Brug i stedet piping via stdin eller--netrc-file. - Læsning fra stdin: Brug
read -rstil interaktivt at indsamle hemmeligheder uden ekko på terminalen eller eksponering i shellhistorikken. - Filtilladelser: Hemmelighedsfiler skal have
chmod 0600(eller0400). Bruginstall -m 0600til atomisk oprettelse. - netrc-filer: Overlad legitimationsoplysninger til en midlertidig fil, som der peges på med
--netrc-file; ryd op medtrap EXIT. - Miljøhygiejne: Fjern straks hemmelige miljøvariabler med
unset, efter at du har gemt dem lokalt; brug aldrigexportunødvendigt; brugenv -itil isolering af underprocesser. - xtrace-vagt: Omslut følsom kode med
{ set +x; } 2>/dev/null ... set -xfor at forhindre, at fejlfindingsspor lækker værdier. - Sløring i loggen: Brug en logger baseret på
sedsom sidste sikkerhedsnet. - tmpfs: Gem runtime-hemmeligheder i
/run/user/$UIDeller/dev/shm, så de aldrig rammer disken; makulér dem ved afslutning.
Forsvar i dybden er den afgørende tankegang: Ingen enkelt foranstaltning er tilstrækkelig, men når du kombinerer dem i lag, bliver lækage af hemmeligheder ekstremt vanskelig.
Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 142
- Lektioner
- 568
Ofte stillede spørgsmål
Er lektionen “Sikker håndtering af hemmeligheder og rent miljø” gratis?
Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Sikker håndtering af hemmeligheder og rent miljø”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Sikker håndtering af hemmeligheder og rent miljø”?
Hold legitimationsoplysninger ude af proceslister og logs ved hjælp af stdin, filer og rensede miljøer. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?
Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Sikker håndtering af hemmeligheder og rent miljø”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?
Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Forebyggelse af kommando- og argumentinjektion
- Sikker håndtering af hemmeligheder og rent miljø
- Kørsel med færrest mulige rettigheder og disciplineret brug af sudo
- Statisk analyse og audit med ShellCheck