Git GnuPG 서명 검증
Git GnuPG 서명 검증 (Git GnuPG signature verification)
소스 저장소의 커밋이 신뢰하는 GnuPG 키로 올바르게 서명되었는지 검증하는 방법을 설명해요. 승인된 기여자만 커밋할 수 있도록 소스 무결성을 강제할 수 있습니다.
출처: 문서
본문
개요 (Overview)
소스 저장소의 커밋이 신뢰하는 GnuPG 키 중 하나로 올바르게 서명되었는지 검증합니다.
Note
신뢰에 대한 몇 마디
ArgoCD는 임포트한 키에 대해 매우 단순한 신뢰 모델을 사용합니다. 키가 임포트되면 ArgoCD는 그 키를 신뢰합니다. ArgoCD는 더 복잡한 신뢰 모델을 지원하지 않으며, ArgoCD에 임포트할 공개 키에 서명할 필요도 없고(가능하지도 않습니다).
Note
호환성 공지
GnuPG 검증은 v1.7에서 signatureKeys로 구성되는 프로젝트 전역 제약으로 처음 도입되었습니다. Argo CD 3.5부터 이는 소스 무결성 검증의 방법 중 하나로 지원되지만 다른 선언 형식을 사용합니다. signatureKeys에 구성된 키는 계속 지원되지만, sourceIntegrity와 함께 사용할 수는 없습니다. 레거시 signatureKeys 구성을 sourceIntegrity로 변환하는 방법은 아래를 참조하세요.
GnuPG 서명 검증은 Git 저장소에서만 지원됩니다. Helm이나 OCI 애플리케이션 소스를 사용할 때는 불가능합니다.
GnuPG 검증은 Argo CD GnuPG 키링을 채우고 저장소에 대한 소스 무결성 정책을 구성해야 합니다.
Argo CD GnuPG 키링 관리 (Managing Argo CD GnuPG keyring)
Argo CD가 신뢰할 모든 GnuPG 키는 먼저 키링에 추가되어야 합니다.
키링 RBAC 규칙 (Keyring RBAC rules)
Argo CD의 RBAC 구현에서 GnuPG 키 관리를 허용하는 적절한 리소스 표기법은 gpgkeys입니다.
role:myrole이라는 역할에 대해 키 목록 조회를 허용하려면:
p, role:myrole, gpgkeys, get, *, allow
role:myrole이라는 역할에 대해 키 추가를 허용하려면:
p, role:myrole, gpgkeys, create, *, allow
마지막으로 role:myrole이라는 역할에 대해 키 삭제를 허용하려면:
p, role:myrole, gpgkeys, delete, *, allow
키링 관리 (Keyring management)
ArgoCD가 커밋 서명 검증에 사용할 GnuPG 공개 키는 CLI, 웹 UI 또는 선언적 설정(declarative setup)으로 구성할 수 있습니다.
Note
GnuPG 키를 임포트한 후, 키가 구성된 것으로 표시되더라도 클러스터 내에서 키가 전파되는 데 시간이 걸릴 수 있습니다. 이미 임포트된 키로 서명된 커밋에 여전히 동기화할 수 없다면 아래 문제 해결 섹션을 참조하세요.
CLI를 사용한 공개 키 관리
CLI로 GnuPG 공개 키를 구성하려면 argocd gpg 명령을 사용하세요.
구성된 모든 키 목록
ArgoCD가 알고 있는 구성된 모든 키를 나열하려면 argocd gpg list 하위 명령을 사용하세요:
argocd gpg list
특정 키 정보 표시
특정 키에 대한 정보를 얻으려면 argocd gpg get 하위 명령을 사용하세요:
argocd gpg get
키 임포트
ArgoCD에 새 공개 키를 임포트하려면 argocd gpg add 하위 명령을 사용하세요:
argocd gpg add --from
임포트할 키는 바이너리 또는 ASCII-armored 형식일 수 있습니다.
구성에서 키 제거
이전에 구성된 키를 구성에서 제거하려면 argocd gpg rm 하위 명령을 사용하세요:
argocd gpg rm
웹 UI를 사용한 공개 키 관리
GnuPG 공개 키의 목록, 임포트, 제거를 위한 기본 키 관리 기능은 웹 UI에 구현되어 있습니다. Settings 페이지의 GnuPG keys 모듈에서 구성 모듈을 찾을 수 있습니다.
웹 UI로 키를 구성할 때는 현재 ASCII armored 형식으로 임포트해야 한다는 점을 유의하세요.
선언적 설정으로 공개 키 관리
ArgoCD는 공개 키를 내부적으로 argocd-gpg-keys-cm ConfigMap 리소스에 저장합니다. 공개 GnuPG 키의 ID를 이름으로, ASCII armored 키 데이터를 문자열 값으로 저장합니다. 즉, GitHub의 web-flow 서명 키에 대한 항목은 다음과 같습니다:
4AEE18F83AFDEB23: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFmUaEEBCACzXTDt6ZnyaVtueZASBzgnAmK13q9Urgch+sKYeIhdymjuMQta
x15OklctmrZtqre5kwPUosG3/B2/ikuPYElcHgGPL4uL5Em6S5C/oozfkYzhwRrT
SQzvYjsE4I34To4UdE9KA97wrQjGoz2Bx72WDLyWwctD3DKQtYeHXswXXtXwKfjQ
7Fy4+Bf5IPh76dA8NJ6UtjjLIDlKqdxLW4atHe6xWFaJ+XdLUtsAroZcXBeWDCPa
buXCDscJcLJRKZVc62gOZXXtPfoHqvUPp3nuLA4YjH9bphbrMWMf810Wxz9JTd3v
yWgGqNY0zbBqeZoGv+TuExlRHT8ASGFS9SVDABEBAAG0NUdpdEh1YiAod2ViLWZs
b3cgY29tbWl0IHNpZ25pbmcpIDxub3JlcGx5QGdpdGh1Yi5jb20+iQEiBBMBCAAW
BQJZlGhBCRBK7hj4Ov3rIwIbAwIZAQAAmQEH/iATWFmi2oxlBh3wAsySNCNV4IPf
DDMeh6j80WT7cgoX7V7xqJOxrfrqPEthQ3hgHIm7b5MPQlUr2q+UPL22t/I+ESF6
9b0QWLFSMJbMSk+BXkvSjH9q8jAO0986/pShPV5DU2sMxnx4LfLfHNhTzjXKokws
+8ptJ8uhMNIDXfXuzkZHIxoXk3rNcjDN5c5X+sK8UBRH092BIJWCOfaQt7v7wig5
4Ra28pM9GbHKXVNxmdLpCFyzvyMuCmINYYADsC848QQFFwnd4EQnupo6QvhEVx1O
j7wDwvuH5dCrLuLwtwXaQh0onG4583p0LGms2Mf5F+Ick6o/4peOlBoZz48=
=Bvzs
-----END PGP PUBLIC KEY BLOCK-----
GnuPG 서명 검증 정책 (Policies for GnuPG signature verification)
GnuPG 커밋 서명 검증은 하나 또는 여러 개의 Git gpg 정책을 통해 구성됩니다.
정책은 다음과 같이 구성합니다:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
spec:
sourceIntegrity:
git:
policies:
- repos:
- url: "https://github.com/my-group/*"
- url: "!https://github.com/my-group/ignored.git"
gpg:
mode: "none|head|strict"
keys:
- "D56C4FCA57A46444"
repos 키는 검증할 소스의 URL과 대조되는 glob 스타일 패턴 목록을 포함합니다. 양수 glob 중 하나와 일치하면서 !로 시작하는 음수 glob 중 어느 것과도 일치하지 않으면 주어진 전략이 사용됩니다.
소스 저장소당 정책 하나만 적용되며, 어떤 정책과도 일치하지 않는 소스는 무결성이 검증되지 않습니다.
멀티 소스 애플리케이션은 각 소스 저장소를 서로 다른 정책으로 검증할 수 있다는 점을 유의하세요.
gpg 검증 정책
Git 커밋 서명 검증은 구성된 키링으로 git verify-commit/git verify-tag를 호출하고 서명에 사용된 키 ID가 소스 무결성 정책에 구성된 키 ID에 포함되어 있는지 확인하는 것의 대안입니다. 대상 리비전이 해당 기준을 충족하지 않는 커밋이나 태그를 가리키면 동기화되지 않습니다.
keys 키는 서명된 커밋에 신뢰할 키 ID 집합을 나열합니다. 저장소의 커밋이 신뢰하는 서명자 목록에 없는 ID로 서명된 경우 검증이 실패합니다.
mode는 GnuPG 검증이 얼마나 철저한지 정의합니다:
검증 모드 none
이 전략에 대해서는 검증이 수행되지 않으며, 다음 전략도 시도되지 않습니다.
이 모드는 서명되지 않은 커밋뿐 아니라 어떤 의미에서 유효하지 않은 서명(만료됨, 검증 불가 등)이 있는 커밋도 허용한다는 점을 유의하세요.
검증 모드 head
소스의 대상 리비전이 가리키는 커밋/태그만 검증합니다. 리비전이 annotated 태그라면 커밋의 서명이 아니라 태그의 서명이 검증됩니다(즉 태그 자체가 git tag -s로 서명되어야 함). 그 외에 대상 리비전이 브랜치 이름, 참조 이름(예: HEAD) 또는 커밋 SHA라면 Argo CD는 커밋의 GnuPG 서명을 검증합니다.
검증 모드 strict
대상 리비전과 모든 조상(ancestor)을 검증합니다. 이는 기록에 서명되지 않은 변경이 없도록 보장합니다. 리비전이 annotated 태그라면 태그가 가리키는 커밋을 포함한 커밋 기록과 함께 태그의 서명이 검증됩니다.
전체 기록을 검증하는 것이 실용적이지 않은 상황이 있습니다 - 일반적으로 기록에 서명되지 않은 커밋이나 더 이상 신뢰되지 않는 키로 서명된 커밋이 포함된 경우입니다. 이는 GnuPG 검증이 git 저장소에 나중에 도입되거나, 예전에 승인된 키가 제거·취소·교체될 때 발생합니다. git rebase로 다시 서명해 해결할 수 있지만, Git 기록을 다시 쓰지 않아도 되는 더 나은 방법이 있습니다.
strict 모드와 커밋 씰 서명 (Commit seal-signing with strict mode)
씰 커밋(sealing commit)은 GnuPG로 서명된 커밋으로, 그 모든 조상 커밋이 신뢰하는 키로 서명되었거나 씰 커밋의 작성자에 의해 검토되고 신뢰되었음을 증명하는 "승인 도장(seal of approval)" 역할을 합니다. 그러면 Argo CD의 GnuPG 서명 검증은 각 조상 브랜치에서 가장 최근 "씰" 커밋까지만 기록을 거슬러 진행합니다.
실제로 committer는 이전 "씰 커밋" 이후 서명되지 않았거나 신뢰되지 않는 키로 서명된 모든 커밋을 먼저 검토하고, 메시지에 커스텀 Git trailer가 있는 새 커밋(비어 있을 수 있음)을 생성합니다. 이러한 커밋은 조직 수준의 의미를 가질 수 있습니다:
- "지금부터 이 저장소의 모든 커밋에 GnuPG 서명을 하겠습니다. 이전에 서명되지 않은 커밋을 검증할 필요는 없습니다."
- "신뢰하지 않는 외부 기여자의 변경을 병합하며, 이를 승인합니다."
- "Bob의 GnuPG 키를 제거합니다. 그의 이전 커밋은 모두 신뢰하지만 새 커밋은 신뢰하지 않습니다. 은퇴를 축하합니다, Bob!"
- "내 이전 키를 새 키로 교체합니다. 이 씰 커밋 이전에 이전 키로 서명된 커밋은 신뢰하지만, 이 씰 커밋 이후에는 새 키만 신뢰합니다."
씰 커밋을 만들려면 git commit --signoff --gpg-sign --trailer="Argocd-gpg-seal: "을 실행하고 Argo CD가 가져오는 브랜치로 push하세요. 씰 커밋을 사용하는 것은 git 기록을 다시 쓰는 것보다 좋습니다. 이는 소스 무결성이나 저장소 데이터의 정확성을 위협할 수 있는 경우가 많은 rebase 실수의 여지를 없애기 때문입니다.
Source Integrity Verification으로 업그레이드 (Upgrade to Source Integrity Verification)
레거시 선언에서 새 소스 검증 정책으로 마이그레이션하려면 .spec.signatureKeys를 제거한 다음 .spec.sourceIntegrity.git.policies에서 원하는 정책을 정의하세요.
프로젝트에서 레거시 Argo CD 검증 동작을 달성하려면 다음 구성을 사용하세요:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
spec:
sourceIntegrity:
git:
policies:
- repos:
- url: "*" # For any repository in the project
gpg:
mode: "head" # Verify only the HEAD of the target revision
keys:
- "..." # Keys from .spec.signatureKeys
.spec.sourceIntegrity가 정의되지 않고 .spec.signatureKeys가 정의되어 있을 때 Argo CD는 백그라운드에서 유사한 변환을 수행합니다. 하지만 소스 무결성 구성이 더 큰 유연성을 제공하고 .spec.signatureKeys는 향후 릴리스에서 제거될 예정이므로 마이그레이션을 수행하는 것이 좋습니다.
Source Integrity Verification에서 다운그레이드 (Downgrade from Source Integrity Verification)
다운그레이드 시 어떤 AppProject에 .spec.signatureKeys를 다시 도입하고, .spec.sourceIntegrity.git.policies의 모든 키로 채운 다음 .spec.sourceIntegrity 섹션을 삭제하세요. 레거시 기능은 새 기능 중 상당수가 없음을 유의하세요—모든 프로젝트 저장소에 대해 모두 "head" 모드일 것입니다.
다운그레이드의 대안으로 여기의 문제 해결 섹션을 참조하세요.
레거시 서명 키 관리 (DEPRECATED)
프로젝트 전역 서명 키는 UI와 CLI로 관리할 수 있습니다. 이들은 소스 무결성 정책으로 대체되고 있으므로 사용자는 이를 마이그레이션하는 것이 좋습니다.
CLI로 구성 (DEPRECATED)
허용 키 목록에 키 ID 추가
프로젝트에 허용된 GnuPG 키 목록에 키 ID를 추가하려면 argocd proj add-signature-key 명령을 사용할 수 있습니다. 즉, 다음 명령은 myproj라는 프로젝트에 키 ID 4AEE18F83AFDEB23을 추가합니다:
# DEPRECATED
argocd proj add-signature-key myproj 4AEE18F83AFDEB23
허용 키 목록에서 키 ID 제거
마찬가지로 argocd proj remove-signature-key 명령으로 프로젝트의 허용된 GnuPG 키 목록에서 키 ID를 제거할 수 있습니다. 즉, 위에서 추가한 키를 myproj 프로젝트에서 제거하려면:
# DEPRECATED
argocd proj remove-signature-key myproj 4AEE18F83AFDEB23
프로젝트의 허용 키 ID 표시
주어진 프로젝트에 어떤 키 ID가 허용되는지 확인하려면 argocd proj get 명령의 출력을 검사할 수 있습니다. 예를 들어 gpg라는 프로젝트의 경우:
# DEPRECATED
$ argocd proj get gpg
Name: gpg
Description: GnuPG verification
Destinations: *,*
Repositories: *
Allowed Cluster Resources: */*
Denied Namespaced Resources:
Signature keys: 4AEE18F83AFDEB23, 07E34825A909B250
Orphaned Resources: disabled
키 ID 목록 재정의
--signature-keys 플래그와 함께 argocd proj set 명령을 사용해 현재 허용된 키를 하나 이상의 새 키로 명시적으로 설정할 수도 있습니다. 이 플래그로 허용된 키 ID의 쉼표 구분 목록을 지정할 수 있습니다:
# DEPRECATED
argocd proj set myproj --signature-keys 4AEE18F83AFDEB23,07E34825A909B250
--signature-keys 플래그는 프로젝트 생성 시, 즉 argocd proj create 명령에서도 사용할 수 있습니다.
웹 UI로 구성 (DEPRECATED)
웹 UI의 프로젝트 구성에서 서명 검증에 필요한 GnuPG 키 ID를 구성할 수 있습니다. Settings 페이지로 이동해 Projects 모듈을 선택한 다음 구성하려는 프로젝트를 클릭하세요.
프로젝트 상세 페이지에서 Edit을 클릭하고 Required signature keys 섹션을 찾아 서명 검증에 사용할 키 ID를 추가하거나 제거하세요. 프로젝트를 수정한 후 Update를 클릭해 변경 사항을 저장하세요.
문제 해결 (Troubleshooting)
기능 비활성화
원한다면 GnuPG 기능을 완전히 비활성화할 수 있습니다. 비활성화하려면 argocd-server, argocd-repo-server, argocd-application-controller 및 argocd-applicationset-controller 배포 매니페스트의 pod 템플릿에 대해 환경 변수 ARGOCD_GPG_ENABLED를 false로 설정하세요.
pod가 재시작된 후 GnuPG 기능은 비활성화됩니다.
GnuPG 키링 검사
서명 검증에 사용되는 GnuPG 키링은 argocd-repo-server의 pod 내에서 유지됩니다. 키링의 키는 argocd-gpg-keys-cm ConfigMap 리소스에 저장된 구성으로 동기화되며, 이는 argocd-repo-server pod에 volume-mount 됩니다.
Note
pod의 GnuPG 키링은 일시적이며 pod가 재시작될 때마다 구성에서 다시 생성됩니다. 변경 사항이 손실되므로 pod의 키링에 키를 수동으로 추가하거나 제거해서는 안 됩니다. 또한 키링에서 발견되는 개인 키는 불안정하며 재시작마다 다시 생성됩니다. 개인 키는 실행 중인 pod의 신뢰 DB를 구축하는 데만 사용됩니다.
키가 실제로 동기화되었는지 확인하려면 저장소 서버의 pod에 kubectl exec로 접속해 /app/config/gpg/keys 경로에 있는 키링을 검사할 수 있습니다.
$ kubectl exec -it argocd-repo-server-7d6bdfdf6d-hzqkg bash
argocd@argocd-repo-server-7d6bdfdf6d-hzqkg:~$ GNUPGHOME=/app/config/gpg/keys gpg --list-keys
/app/config/gpg/keys/pubring.kbx
--------------------------------
pub rsa2048 2020-06-15 [SC] [expires: 2020-12-12]
D48F075D818A813C436914BC9324F0D2144753B1
uid [ultimate] Anon Ymous (ArgoCD key signing key)
pub rsa2048 2017-08-16 [SC]
5DE3E0509C47EA3CF04A42D34AEE18F83AFDEB23
uid [ultimate] GitHub (web-flow commit signing)
argocd@argocd-repo-server-7d6bdfdf6d-hzqkg:~$
키를 추가하거나 제거한 후에도 키링이 오랫동안 구성과 동기화되지 않으면 argocd-repo-server pod를 재시작하고 싶을 수 있습니다. 그러한 문제가 지속되면 버그 리포트를 제출하는 것을 고려하세요.