feat(S15P11A705-96): AI 소유 값을 SealedSecret으로 봉인해 전달한다 - #34
Merged
Conversation
GitHub Actions Secret 은 Kubernetes Pod 에 자동 전달되지 않는다. Infra 가 "값을 열람하지 않은 채 암호화 Secret 만 배포"하는 경계를 세웠으므로(ai#32), 공개키로 봉인한 manifest 만 넘기는 경로를 만든다. kubeseal --raw 로 값 하나씩 봉인한다. 흔히 쓰는 kubectl create secret --dry-run | kubeseal 경로는 중간 산출물이 평문 base64 Secret YAML 이라, 한 단계 실수로 파일이 될 수 있다. --raw 는 평문이 셸 변수와 파이프에만 존재한다. 앱이 기동 시 fail-fast 로 거르는 검사(/gmsapi/ 형식, profile 정합)를 봉인 시점으로 앞당긴다. profile 이 어긋난 채 배포되면 기존 임베딩이 조회 대상에서 전부 빠지는데, 조용히 결과만 비므로 배포 후에는 알아채기 어렵다. controller 인증서는 SHA-256 지문으로 고정한다. 엉뚱한 공개키로 봉인하면 복호화 실패가 배포 시점에야 드러난다. EMBEDDING 넷은 비밀이 아니다(정본 P32). Infra 가 주입 경로를 하나로 요구해 같은 경로로 다루며, 그 판단 근거는 리포트에 남겼다. 검증: 인증서 지문 Infra 제공값과 일치 · 유효기간 확인 · kubeseal 릴리스 실재 확인 · workflow YAML 파싱 · 셸 블록 bash -n 5개 통과. 실제 봉인은 미실행 — Actions Secret 등록 후에만 가능하다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
ai#32에서 Infra가 요청한 ① GitHub Secret → 암호화 Secret handoff를 구현한다. 수동 트리거 workflow 하나와 controller 공개 인증서가 전부이며, 앱 코드·DB·API 변경은 없다.이 handoff의 ②
/ready·③smoke는ai#33으로 이미 전달했다. ①만 남아 있었고 그동안 배포가 여기서 막혀 있었다.Jira
S15P11A705-96— [AI] dev 배포용 GMS·모델·bootstrap·관측 계약 확정왜 필요한가
GitHub Actions Secret은 Kubernetes Pod에 자동으로 전달되지 않는다. 값을 클러스터까지 보내려면 누군가 평문을 한 번은 만져야 하는데, Infra는 *"key/token 값을 AI owner 소유로 두고, 값을 열람하지 않은 채 암호화 Secret과 컨테이너만 배포하겠다"*는 경계를 세웠다. SealedSecret이 그 경계를 성립시킨다 — 복호화는 클러스터 안의 controller만 할 수 있다.
변경 사항
.github/workflows/seal-ai-secrets.ymlworkflow_dispatch수동 트리거 — Secret 회전은 사람이 결정하는 사건이고 push마다 돌 이유가 없다deploy/sealed-secrets/pinlog-dev-cert.pemkube-system/sealed-secrets-controller에서 가져다 준 공개 인증서. 공개키라 커밋해도 안전하다docs/implements/2026-07-29-sealed-secret-handoff.mddocs/implements/README.md·docs/WORKLOG.md설계 결정
kubeseal --raw— 평문 YAML을 만들지 않는다흔한 경로는
kubectl create secret generic --dry-run=client -o yaml | kubeseal인데, 이 파이프의 중간 산출물이 평문 base64 Secret YAML이다. 파이프 안에만 있다 해도 한 단계 실수(리다이렉트·tee·디버깅용cat)로 파일이 된다.--raw는 값 하나를 받아 암호문 한 줄을 돌려준다. 평문은 셸 변수와 파이프에만 존재하고, 변수 확장은 셸 내부에서 끝나므로ps로도 보이지 않는다.기각한 대안:
kubectl경로가 manifest를 손으로 조립하지 않아도 되어 간단하지만, 위 이유로 택하지 않았다. 조립 비용은echo몇 줄이다.배포 전에 실패시킬 수 있는 것은 배포 전에
앱이 기동 시 fail-fast로 거르는 검사를 봉인 시점에 미리 돌린다.
profile이 어긋난 채 배포되면 기존 임베딩이 전부 조회 대상에서 빠진다. 조용히 검색 결과만 비므로 배포 후에 알아채기 가장 어려운 종류다.
EMBEDDING 넷은 비밀이 아닌데 왜 같은 경로인가
모델명·차원·거리함수·프로필 식별자이고 정본은 공개 문서
P32에 있다.ai#32에서 Infra도 이 넷을 *"non-secret ConfigMap 명시 주입"*으로 분류했다.그럼에도 Secret 경로로 다루는 것은 Infra가 주입 경로를 하나로 요구했기 때문이다. 값이 공개라는 사실과 "어디서 주입되는가"는 별개이고, 앱이 이 넷에 기본값을 두지 않으므로 누락 시 Pod이 아예 뜨지 않는다 — 경로를 나누면 그 실패가 두 곳에서 날 수 있다.
테스트 / 검증
openssl x509 -noout -fingerprint -sha256이 Infra 제공 값(4A:C5:…:A2)과 일치-checkend 0통과 (2026-07-20 ~ 2036-07-17)v0.27.1및 asset 이름 두 개를 GitHub API로 조회bash -n5개 전부 통과리뷰 포인트
encryptedData검증을 두 방향으로 건다. ⑴ 모든 값이Ag로 시작하는 100자 이상 base64인가 ⑵ 평문이 새지 않았는가 — 단 12자 이상만 본다.1536·cosine같은 짧은 값은 base64 암호문에 우연히 포함돼 거짓 양성을 만들고, 그 길이대는 ⑴이 덮는다echo조립으로 바꿨다pinlog-dev/ai-owner-secrets조합에 묶인다. 유출된 manifest가 다른 네임스페이스에서 복호화되는 경로가 없다미결 / 후속
PINLOG_AI_INFRA_PR_TOKEN— Infra 요구 목록에 있으나 이 앱이 읽지 않는다(레포 전체 참조 0건). GitOps 레포에 PR을 여는 용도로 보이며, 그렇다면 전달이 artifact가 아니라 PR이 된다. 대상 레포·권한 범위·만료·커밋 경로를 확인한 뒤 workflow를 그쪽으로 바꾼다pinlog-dev전용이다. prod는 별도 controller·인증서가 필요하다🤖 Generated with Claude Code