Files
keycloak-pattern/docs/guides/experiments/d3-secret-management.md
T
DongHyeonkaandClaude Opus 5 6f6ab86345 docs(guides): reproduction guides for all 26 experiments
Written by subagents running under the writing-practitioner-guides skill,
one guide per experiment, 22,566 lines. Each walks a reader from baseline
capture through injection, injection verification, observation and recovery.

Section 3 carries the weight in most of them. Injection failed silently nine
times in this lab, and a failed injection looks exactly like no effect — so
the guides verify the target is actually in the intended state before
reading any result. A-4 makes virsh list the only proof because the node
reads Ready for 40 seconds after the machine is off; A-5 makes the packet
counter the sole go/no-go because a rule on the wrong node produces an empty
result that reads like a finding; A-6 quotes the run where 적용완료 was
printed between four Cannot find device "eth0" lines.

The traps the guides are built around are ones that invert a conclusion
rather than merely annoy:

  A-0   emptying the session table without a restart leaves cache entries
        that get counted as replication arriving
  A-2   dropping -o /dev/null fuses body and status into one string
  A-3   presence of "ready to accept connections" instead of its timestamp
  B-2   row count alone reads an UPDATE as nothing having happened
  B-4   tr ',' '\n' splits ["admin","editor"] so only admin is seen
  B-7   no login screen means the cookie died and SSO re-authenticated
  C-1   counting sessions without joining realm counts your own kcadm one
  D-1   kubectl exec without -i restores nothing and still exits 0
  D-4a  "ran with error output" is what success looks like

Every quoted block is copied from docs/evidence/ and marked 실측; reshaped
commands are marked 미검증 rather than passed off as measured. Where a source
document carries a ★ correction the guides follow the corrected claim — A-7's
REVOKED_TOKEN hypothesis, C-1's session count, B-2's schema attribution.

Two hazards are stated rather than smoothed over: B-6 deletes a key that
cannot be recreated, and D-1/D-4 need host sudo, which asks for a password,
so those steps say a person must type them.

Audit over all 26: 672 interpretation pairs, 486 evidence citations, 117
undo sections, and zero occurrences of the patterns the skill forbids —
no python data processing, no deprecated kubectl get endpoints, no
placeholders, no bare kcadm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 18:29:00 +09:00

24 KiB
Raw Blame History

D-3 재현 가이드 — Secret 이 어디까지 감춰지는지 네 경로로 직접 본다

해설 문서: docs/experiment-d3-secret-management.md · 증거 원문: docs/evidence/d3-secret-management/

이 가이드가 끝나면

당신 터미널에서 이것들을 직접 본다.

보게 되는 것 어디서
describe14 bytes 만 보여주는 것 describe secret
같은 값이 한 줄로 평문이 되는 것 get -o jsonpath | base64 -d
저장소 암호화가 꺼져 있는 k3s secrets-encrypt status
노드 디스크의 저장 파일 안에 평문이 있는 grep -c on state.db
그 grep 이 0 을 돌려주는데도 안전하지 않은 같은 명령, 다른 키
파드 안에서는 그냥 환경변수인 것 env · /proc/1/environ
RBAC 은 실제로 막는 것 auth can-i

전제

  • 명령은 kc-lab-1 에서 친다. kubectlsudo 로 쓴다. k3s 서버의 저장 파일도 이 노드에 있다 — 그래서 4-2 를 여기서 칠 수 있다.
  • 게스트(kc-lab-1/kc-lab-2)의 sudo무암호다. 호스트와 다르다.
  • 네임스페이스는 keycloak-lab 이다.
  • jq 는 이 실험대 어디에도 없다. 이 가이드는 jq 를 쓰지 않는다.
  • B-6 · B-7 를 이미 했다면 이 실험의 결론이 그 key 들에도 그대로 적용된다는 것을 알고 있을 것이다.

주의 — 이건 비밀을 화면에 띄우는 실험이다

이 실험의 명령 몇 개는 비밀번호를 터미널에 그대로 찍는다. 그게 결론이기 때문에 피할 수 없지만, 그 값은 스크롤백·화면 공유·터미널 로그에 남는다.

이 가이드는 그래서 이렇게 한다.

  • 남의 진짜 비밀은 길이(wc -c)와 키 이름까지만 본다.
  • 값을 찍어 봐야 하는 곳은 이 실험용으로 직접 만든 카나리아 Secret 을 쓴다 (2절). 지워도 되는 값이므로 찍어도 된다.
  • 실측으로 실린 값들은 이 저장소의 매니페스트와 문서에 이미 적혀 있는 실험대 전용 값이다(change-me 가 이름에 들어 있는 이유가 그것이다).

파괴적인 단계는 없다. 만드는 것은 카나리아 Secret 하나뿐이고 5. 복구 에서 지운다. 전 구간 약 15분.

표시 규약

표시
실측 2026-09-04 15:0515:06 KST 실행 기록의 출력 원문. 증거 파일에 그대로 있다
형태 값이 매번 달라지는 출력. 모양만 보이고 숫자는 당신 것과 다르다
미검증 손으로 치기 좋게 이 가이드에서 고친 형태이거나, 이 실험이 하지 않은 확장

0. 왜 이 실험을 하는가

「비밀번호를 Secret 으로 옮겼습니다」는 리뷰에서 통과 도장을 받는 문장이다. 그 문장이 실제로 무엇을 막아 주는지를 네 경로로 나눠 판정한다.

# 경로 누가 쓰나 예측
쿠버네티스 API (get secret) 클러스터에 접근하는 사람 ?
노드 디스크의 저장 파일 디스크·백업·스냅샷을 얻은 사람 ?
파드 안의 프로세스 exec 권한이 있는 사람, 크래시 덤프 ?
RBAC 권한이 없는 주체 ?

핵심 개념부터 짚는다.

목적 되돌리기
인코딩 (base64) 바이너리를 텍스트로 안전하게 옮기기 키 없이 누구나
암호화 키 없이는 못 읽게 하기 키가 있어야

Secret 이 base64 를 쓰는 이유는 감추려는 것이 아니라 YAML 에 임의 바이트를 담기 위해서다. 그런데 kubectl describe 가 값을 가려서 보여주기 때문에 「가려져 있구나」라는 인상이 남는다 — 이 실험은 그 인상과 사실 사이의 거리를 잰다.


1. 기준선 — 무엇이 있는지부터 본다

1-1. Secret 목록

확인

sudo kubectl -n keycloak-lab get secret

실측01-base64-not-encryption.txt

  bff-secrets                Opaque       keys=1
  keycloak-lab-secrets       Opaque       keys=2
  oauth2-proxy-secrets       Opaque       keys=3

실측 줄은 원래 실행 스크립트가 정리해 찍은 것이다. 손으로 치면 NAME / TYPE / DATA / AGE 네 칸이 나오고, DATA 열이 위의 keys= 에 해당한다.

어디를 봐야 하는가 — 이름과 DATA 열(키 개수). TYPEOpaque 인 것도 본다 — 「불투명」이라는 이름이지만 그건 쿠버네티스가 내용 구조를 모른다는 뜻이지 감춘다는 뜻이 아니다.

1-2. describe 는 값을 감춘다

확인

sudo kubectl -n keycloak-lab describe secret bff-secrets

실측01-base64-not-encryption.txt

  Type:  Opaque

  Data
  ====
  KEYCLOAK_CLIENT_SECRET:  14 bytes

어디를 봐야 하는가키 이름과 바이트 수만 나온다. 값이 없다.

이 결과가 의미하는 것 — 이 화면이 「Secret 은 감춰진다」는 인상의 출처다. describe일부러 값을 안 찍는다. 그런데 그건 describe 라는 명령의 동작이지, 저장이나 전송의 성질이 아니다.

1-3. 값을 안 보고 확인하는 법 — 평소에는 이렇게 한다

남의 비밀을 다룰 때 기본 자세다. 키 이름과 길이만 본다.

확인 — 키 이름만

sudo kubectl -n keycloak-lab get secret keycloak-lab-secrets -o jsonpath='{.data}' \
  | tr ',' '\n' | grep -o '"[A-Z_]*"'

형태

"KC_BOOTSTRAP_ADMIN_PASSWORD"
"POSTGRES_PASSWORD"

확인 — 길이만

sudo kubectl -n keycloak-lab get secret keycloak-lab-secrets \
  -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c

형태

22

어디를 봐야 하는가 — 숫자 하나. 값이 화면에 없다.

이 결과가 의미하는 것 — 「Secret 이 제대로 들어갔는가」를 확인하는 데는 길이면 충분한 경우가 대부분이다. 배포가 안 될 때 진짜로 궁금한 것은 대개 **「비었는가 아닌가」**이지 값 자체가 아니다.

wc -c 는 개행까지 세므로 base64 -d 결과에 개행이 없으면 실제 길이와 같다. 값이 비었으면 0 이 나온다 — 0 은 「Secret 은 있는데 그 키가 비었다」는 뜻이고, 배포 실패의 흔한 원인이다.


2. 주입 — 카나리아 Secret 하나를 만든다

여기부터 상태가 바뀐다. 바뀌는 것은 Secret 하나뿐이다.

되돌리기

sudo kubectl -n keycloak-lab delete secret d3-canary

2-1. 왜 카나리아를 쓰나

4절에서 저장 파일 안을 grep 해야 한다. 그러려면 찾을 문자열을 알고 있어야 하는데, 진짜 비밀번호를 grep 인자로 쓰면 그 값이 셸 히스토리와 프로세스 목록(ps 로 다른 사용자에게도 보인다)에 남는다.

그래서 「찾아도 아무 피해가 없는 값」을 하나 심는다. 실험 대상이 값 자체가 아니라 경로이기 때문에 이렇게 해도 결론은 같다.

하기

sudo kubectl -n keycloak-lab create secret generic d3-canary \
  --from-literal=CANARY=d3-canary-zq7v-do-not-use

형태

secret/d3-canary created

어디를 봐야 하는가created. 이미 있다면 AlreadyExists 가 나온다 — 그럼 지우고 다시 만든다.

이 값은 아무 데도 쓰이지 않는다. 어떤 파드도 참조하지 않으므로 지워도 아무것도 안 깨진다. 값에 do-not-use 를 넣어 둔 이유는, 나중에 저장 파일 어딘가에서 이 문자열을 다시 만났을 때 무엇인지 알아보기 위해서다.


3. 주입이 실제로 걸렸는지 확인한다

확인

sudo kubectl -n keycloak-lab get secret d3-canary
sudo kubectl -n keycloak-lab describe secret d3-canary

형태

Data
====
CANARY:  26 bytes

어디를 봐야 하는가 — 여기서도 describe 는 바이트 수만 준다. 1-2 와 같은 화면이다. 값을 아는 것은 당신뿐이고, 그래서 다음 절의 비교가 성립한다.


4. 효과를 관찰한다 — 네 경로를 하나씩 연다

4-1. ① API — 한 줄로 읽힌다

하기 — 카나리아로 먼저 해 본다. 값을 알고 있으므로 무엇이 나올지 예측된다

sudo kubectl -n keycloak-lab get secret d3-canary \
  -o jsonpath='{.data.CANARY}' | base64 -d; echo

형태

d3-canary-zq7v-do-not-use

어디를 봐야 하는가2-1 에서 심은 값이 그대로 나온다.

같은 명령이 실제 비밀에도 그대로 듣는다. 원래 실행이 네 개를 뽑은 결과가 이것이다.

실측01-base64-not-encryption.txt

  keycloak-lab-secrets/POSTGRES_PASSWORD            = lab-postgres-change-me
  keycloak-lab-secrets/KC_BOOTSTRAP_ADMIN_PASSWORD  = lab-admin-change-me
  bff-secrets/KEYCLOAK_CLIENT_SECRET                = bff-lab-secret
  oauth2-proxy-secrets/COOKIE_SECRET_A              = lab-cookie-secret-aaaaaaaaaaaaaa

어디를 봐야 하는가실험대의 모든 비밀이 명령 네 줄로 나온다. describe14 bytes 라고 했던 그 값이 bff-lab-secret (14자)이다.

이 결과가 의미하는 것 — ① 은 막지 않는다. base64 는 인코딩이고 base64 -d 는 누구나 칠 수 있다. 여기서 실질적인 방어선은 누가 이 명령을 칠 수 있는가이며, 그건 ④(RBAC)의 문제로 넘어간다.

이 네 줄을 당신 환경에서 그대로 재현할 필요는 없다. 카나리아로 한 번 확인했으면 기제는 같다. 진짜 비밀은 1-3 의 길이 확인으로 충분하다.

4-2. ② 저장소 — 노드 디스크에 평문이 있다

먼저 암호화 설정을 본다

확인

sudo k3s secrets-encrypt status

실측02-at-rest.txt

  Encryption Status: Disabled, no configuration file found

어디를 봐야 하는가Disabled, 그리고 no configuration file found. 설정 파일이 아예 없다 — 껐다기보다 켠 적이 없다는 뜻이고, 이게 기본값이다.

저장 파일이 어디 있는지 본다

확인

sudo ls -l /var/lib/rancher/k3s/server/db/

실측02-at-rest.txt

  total 23336
  drwx------ 2 root root     4096 Sep  2 09:12 .
  drwx------ 8 root root     4096 Sep  4 03:23 ..
  -rw-r--r-- 1 root root 13078528 Sep  4 06:05 state.db
  -rw-r--r-- 1 root root    32768 Sep  4 06:06 state.db-shm
  -rw-r--r-- 1 root root 10769712 Sep  4 06:06 state.db-wal

어디를 봐야 하는가 — 파일이 이다.

파일 무엇인가
state.db 본체
state.db-wal 아직 본체에 합쳐지지 않은 최근 쓰기
state.db-shm 공유 메모리 인덱스

k3s 는 etcd 대신 SQLite 를 쓴다. 「저장소(at rest)」의 자리는 같다 — etcd 를 쓰는 클러스터라면 이 자리가 etcd 의 데이터 디렉터리다.

-wal 이 10MB 나 되는 것을 봐 둔다. 방금 만든 카나리아는 아직 본체에 없을 가능성이 높다. 아래에서 이게 함정이 된다.

★ 파일 안을 찾아본다

하기 — 카나리아부터

sudo grep -c 'd3-canary-zq7v-do-not-use' /var/lib/rancher/k3s/server/db/state.db
sudo grep -c 'd3-canary-zq7v-do-not-use' /var/lib/rancher/k3s/server/db/state.db-wal

미검증 — 이 실험대는 카나리아 대신 실제 값으로 쟀다. 그 결과가 아래다.

실측02-at-rest.txt

=== ★ 저장 파일에서 비밀번호가 그대로 보이는가 ===
  state.db 안의 평문 일치: 2
=== 평문이 저장 파일에 있다는 것을 눈으로 ===
  client secret 평문 등장 횟수: 0

어디를 봐야 하는가두 줄의 값이 다르다. 20.

같은 파일, 같은 명령, 다른 키인데 하나는 두 번 나오고 하나는 안 나온다.

이 결과가 의미하는 것 — 이 절에서 제일 중요한 문장이다.

grep0 을 돌려준 것은 「평문이 없다」가 아니라 「이 파일의 이 시점에 이 형태로는 못 찾았다」이다.

2 가 나온 순간 ②의 답은 이미 정해졌다 — 저장 파일에 평문이 있다. 0 이 나온 키에 대해 「그건 안전한가 보다」라고 읽으면, 같은 파일에 평문이 들어 있는 것을 이미 본 뒤에 그러는 것이다.

0 이 나왔을 때 다음에 볼 곳미검증. 이 실험은 원인을 가리지 않았다.

sudo grep -c 'bff-lab-secret' /var/lib/rancher/k3s/server/db/state.db-wal
sudo strings /var/lib/rancher/k3s/server/db/state.db | grep -c 'bff-lab-secret'
왜 안 나올 수 있나 확인
아직 -wal 에만 있다 -wal 을 같이 grep
값이 페이지 경계를 넘어 잘렸다 strings 로 한 번 더
그 키가 그 시점에 없었다 get secret 으로 존재 확인

grep -c 는 바이너리 파일에도 듣는다. 평소의 grep 은 바이너리를 만나면 Binary file ... matches 한 줄만 찍고 내용을 안 보여주는데, -c 는 개수만 세므로 그대로 숫자가 나온다. 값 자체를 화면에 안 띄운다는 점에서도 이 형태가 맞다 — 여기서 궁금한 것은 「있는가」이지 「무엇인가」가 아니다.

그래서 무엇이 위험한가

노드 디스크를 얻으면 전 클러스터의 비밀
노드 백업/스냅샷 같은 것을 복사한다
A-4 에서 본 local-path PVC 같은 디스크에 있다
D-1 의 덤프 같은 기계에 뒀다면 거기도 같이

D-1 에서 「덤프를 같은 장애 도메인에 두면 백업이 아니다」라고 했는데, 여기서는 「노드 디스크 하나가 모든 비밀」이다. 백업을 잘 챙길수록 비밀도 잘 복사된다.

k3s 는 --secrets-encryption 플래그로 켤 수 있다. 지금은 안 켜져 있고, 이 가이드는 켜지 않는다 — 켜는 것은 서버 재시작과 기존 Secret 재암호화를 수반하고, 이 실험대에서 시험하지 않았다(미검증).

4-3. ③ 파드 안 — 평범한 환경변수다

확인 — 어느 파드를 볼지 먼저 정한다

sudo kubectl -n keycloak-lab get pods -l app=bff

하기미검증(원래 실행은 파드 이름을 직접 지정했다)

sudo kubectl -n keycloak-lab exec deploy/bff -- sh -c 'env | grep -iE "secret|password"'

실측02-at-rest.txt

  KEYCLOAK_CLIENT_SECRET=bff-lab-secret
  BFF_DB_PASSWORD=lab-postgres-change-me

어디를 봐야 하는가env 한 번이면 나온다. 그리고 bff-lab-secret 은 4-1 에서 API 로 뽑은 값과 같다 — 두 경로가 같은 평문에 닿는다.

execdeploy/bff 로 안 되면(파드가 종료 중이거나 여럿이면) 이름을 골라 친다.

sudo kubectl -n keycloak-lab get pod -l app=bff \
  --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}'; echo

같은 파드 안의 다른 프로세스도 본다. 이게 「환경변수」의 진짜 성질이다.

하기미검증

sudo kubectl -n keycloak-lab exec deploy/bff -- \
  sh -c 'tr "\0" "\n" < /proc/1/environ | grep -i secret'

어디를 봐야 하는가 — 같은 값이 나오는가. /proc/<pid>/environ 은 그 프로세스의 환경변수를 그대로 담고 있고, 같은 UID 의 아무 프로세스나 읽는다.

새는 경로
kubectl exec 권한이 있는 사람 바로 본다
같은 파드의 다른 프로세스 /proc/<pid>/environ
크래시 덤프 · 오류 리포트 환경변수를 함께 담는 도구가 많다
자식 프로세스 상속된다

볼륨으로 마운트하면 이 중 몇 가지가 줄어든다 — 파일 권한으로 제한할 수 있고, 환경변수 덤프에 안 들어간다.

volumeMounts:
  - name: secrets
    mountPath: /etc/secrets
    readOnly: true

줄어드는 것이지 없어지는 것이 아니다. exec 권한이 있으면 파일도 읽는다.

4-4. ④ RBAC — 유일하게 막는다

확인

sudo kubectl auth can-i get secrets -n keycloak-lab \
  --as=system:serviceaccount:keycloak-lab:default

실측02-at-rest.txt

  default SA: no

어디를 봐야 하는가no 한 단어.

어떤 권한이 있는지 통째로 보려면미검증

sudo kubectl auth can-i --list -n keycloak-lab \
  --as=system:serviceaccount:keycloak-lab:default
sudo kubectl -n keycloak-lab get role,rolebinding

이 결과가 의미하는 것 — 기본 서비스계정은 Secret 을 못 읽는다. 명시적으로 거부해서가 아니라 아무 권한도 주지 않았기 때문이다. RBAC 은 기본이 거부이고, Role 을 붙여야 할 수 있게 된다.

네 가지 중 유일하게 제 역할을 하는 것이 RBAC 다. 그러므로 실질적인 방어선은 「누가 get secrets 를 할 수 있는가」이며, 관리자 권한을 가진 사람에게는 아무 방어가 없다.

A-0 의 관측 스택에서 nodes/proxy 서브리소스를 따로 줘야 했던 것처럼, Secret 접근도 리소스 단위로 나눌 수 있다.

4-5. 네 경로 정리

# 경로 감춰지는가 무엇이 뚫나
get -o jsonpath | base64 -d 아니다 클러스터 접근 권한
describe secret 값을 숨긴다 그래서 안전하다고 착각한다
저장 파일(state.db) 아니다. 암호화 꺼짐 노드 디스크·백업·스냅샷
파드 안 아니다. 평범한 환경변수 exec · /proc · 크래시 덤프
RBAC 막는다 관리자 권한

「Secret 이니까 안전하다」는 네 가지 중 하나(RBAC)만 맞다. 그리고 ②·③ 은 쿠버네티스 API 를 한 번도 거치지 않고 평문에 닿는다.


5. 복구

5-1. 카나리아를 지운다

하기

sudo kubectl -n keycloak-lab delete secret d3-canary
sudo kubectl -n keycloak-lab get secret

형태

secret "d3-canary" deleted

어디를 봐야 하는가 — 1-1 의 목록으로 돌아왔는가. 세 개다.

5-2. ★ 지웠다고 파일에서 없어지지는 않는다

확인미검증. 이 실험은 삭제 후를 재지 않았다

sudo grep -c 'd3-canary-zq7v-do-not-use' /var/lib/rancher/k3s/server/db/state.db
sudo grep -c 'd3-canary-zq7v-do-not-use' /var/lib/rancher/k3s/server/db/state.db-wal

어디를 봐야 하는가 — 0 이 나오면 「이 시점에 이 형태로는 안 보인다」이고, 0 이 아니면 지운 Secret 의 평문이 아직 파일에 남아 있는 것이다. 어느 쪽이든 4-2 의 결론은 안 바뀐다 — 판정은 이미 2 에서 났다.

이 결과가 의미하는 것 — 데이터베이스 파일은 지운 행의 자리를 즉시 0으로 덮어쓰지 않는다. 「Secret 을 지웠다」와 「그 값이 디스크에서 사라졌다」는 다른 사건이며, 비밀이 유출됐을 때 실제로 해야 하는 일은 삭제가 아니라 **회전(rotation)**인 이유가 여기 있다 — B-6·B-7 의 주제다.

5-3. 원상복구 확인표

항목 명령 돌아왔을 때
카나리아 sudo kubectl -n keycloak-lab get secret d3-canary NotFound
Secret 목록 sudo kubectl -n keycloak-lab get secret 세 개
파드 sudo kubectl -n keycloak-lab get pods 전부 Running (아무것도 안 건드렸다)
터미널 history | tail -40 비밀번호가 찍힌 줄이 어디까지 남았는지 본다

이 실험의 진짜 뒷정리는 스크롤백이다. 4-1 을 실제 비밀로 쳤다면 그 값이 터미널 버퍼와 셸 히스토리에 남아 있다. 실험대 값이라 지금은 상관없지만, 같은 절차를 운영에서 하면 그게 유출 경로가 된다.


6. 그래서 무엇을 해야 하는가

   지금:  매니페스트에 stringData 평문  →  git 에 커밋되면 끝
          k3s 저장소 암호화 꺼짐
          파드 환경변수
단계 얻는 것 이 실험대
① 매니페스트에서 값을 빼고 .example 만 커밋 git 유출을 막는다 안 함
k3s --secrets-encryption 활성화 노드 디스크 유출을 막는다 안 함 (미검증)
③ 환경변수 대신 볼륨 마운트 프로세스·덤프 유출을 줄인다 안 함
SealedSecret / 외부 KMS 매니페스트에 암호문만 남는다 안 함
RBAC 최소화 유일하게 이미 동작하는 방어선을 좁힌다 기본값 그대로

이 실험대는 ①~④ 중 아무것도 안 하고 있다. 실험 목적으로는 의도적이지만, 그 사실을 기록해두지 않으면 그대로 운영에 옮겨간다. 값 이름에 change-me 를 넣어 둔 것이 그 최소한의 표시다.


막히면

증상 원인 확인
grep0 인데 안전하다고 읽힌다 0 은 「이 파일의 이 시점에 이 형태로는 못 찾았다」 -walstrings 로 한 번 더 — 4-2
grepBinary file matches 만 찍는다 바이너리 파일이다 -c 를 쓴다(개수만). 값을 안 띄우는 이점도 있다
k3s secrets-encrypt 가 없다 서버 노드가 아니다 kc-lab-1(control-plane)에서 친다
state.dbPermission denied root 전용 디렉터리 게스트 sudo 는 무암호다. sudo 를 붙인다
exec deploy/bff 가 실패한다 파드가 종료 중이거나 여럿이다 --field-selector=status.phase=Running 으로 이름을 고른다 — 4-3
auth can-iyes 라고 한다 그 SA 에 Role 이 붙어 있다 get rolebinding -o wide 로 누가 줬는지 본다
값이 0 bytes 로 나온다 Secret 은 있는데 키가 비었다 describe 의 바이트 수를 본다 — 배포 실패의 흔한 원인
비밀번호를 화면에 찍어 버렸다 4-1 을 실제 값으로 쳤다 스크롤백·히스토리를 지우고, 운영이면 회전한다

다음

실험 D-3 이 남긴 것
B-6 key 회전 key 를 Secret 에 두면 이 실험의 결론이 그대로 적용된다
B-7 쿠키 비밀 회전 유출 대응은 삭제가 아니라 회전이다 — 5-2
D-1 백업 덤프에도 같은 문제가 있다. 백업을 잘 챙길수록 비밀도 잘 복사된다
D-4 인증서 개인키(privkey.pem)도 같은 비밀 관리 문제다
운영 RBAC 이 유일하게 동작하는 방어선이다. 관리자에게는 아무 방어가 없다