Secrets Manager 개발 가이드라인
GitLab v19.5요약
GitLab Secrets Manager는 오픈 소스 시크릿 관리 엔진인 OpenBao에 시크릿을 저장합니다. 페이지가 설명하는 동작을 변경한다면 같은 머지 리퀘스트에서 해당 페이지를 업데이트합니다. GitLab은 시크릿 값을 PostgreSQL에 저장하지 않습니다.
GitLab Secrets Manager는 오픈 소스 시크릿 관리 엔진인 OpenBao에 시크릿을 저장합니다.
GitLab은 OpenBao를 백킹 서비스로 실행하고 Rails 서비스 계층을 통해 관리합니다.
모든 Secrets Manager 코드는 GitLab Enterprise Edition(EE) 전용이며 ee/ 아래에 있습니다.
기능 카테고리는 secrets_management입니다.
작업에 맞는 페이지를 읽습니다.
- 동작하는 GitLab Development Kit(GDK) 환경을 만들려면 Secrets Manager 로컬 설정을 참조합니다.
- 데이터 모델, OpenBao 네임스페이스 구성, GitLab이 러너에 보내는 내용은 Secrets Manager 아키텍처를 참조합니다.
- Secrets Manager 변경을 작성하거나 검토하기 전에 Secrets Manager 변경 가이드라인을 참조합니다.
- 프로비저닝, 프로비저닝 해제, 시크릿 쓰기, 등록, 권한을 변경하기 전에 Secrets Manager 상태 및 부수 효과를 참조합니다.
- 체험판, 청구, 권한 확인, 읽기 전용 동작을 변경하기 전에 Secrets Manager 이행 및 권한을 참조합니다.
- 네임스페이스 및 인스턴스 등록과 사용 가능 여부가 이를 사용하는 방식은 Secrets Manager 등록을 참조합니다.
- 서비스를 추가하거나 변경하려면 Secrets Manager 서비스를 참조합니다.
- 타입, 뮤테이션, 리졸버를 추가하거나 변경하려면 Secrets Manager GraphQL API를 참조합니다.
- 클라이언트, JWT, Common Expression Language(CEL) 프로그램, 액세스 제어 목록(ACL) 정책은 Secrets Manager OpenBao 클라이언트 및 인증을 참조합니다.
- 백그라운드 워커, cron job, 인가 정책, 감사 로그는 Secrets Manager 워커 및 정책을 참조합니다.
- CI job 가져오기, 시크릿 쓰기, OpenBao 호출과 같은 핫 패스를 변경하기 전에 Secrets Manager 성능을 참조합니다.
- 스펙 헬퍼, 팩토리, 공유 예시, Kubernetes 테스트는 Secrets Manager 테스트를 참조합니다.
- Vue 애플리케이션과 그 스펙을 작업하려면 Secrets Manager 프론트엔드 개발을 참조합니다.
페이지가 설명하는 동작을 변경한다면 같은 머지 리퀘스트에서 해당 페이지를 업데이트합니다.
전체 구성#
GitLab은 시크릿 값을 PostgreSQL에 저장하지 않습니다.
값은 OpenBao에 있습니다.
PostgreSQL에는 프로비저닝 상태와 OpenBao 마운트 구성을 추적하는 ProjectSecretsManager 및 GroupSecretsManager 레코드가 있습니다.
Secrets Manager가 활성화된 각 프로젝트나 그룹은 자체 OpenBao 네임스페이스를 갖습니다.
예를 들어 네임스페이스 경로는 org_1/group_2/project_1과 같은 형태일 수 있습니다.
OpenBao 네임스페이스 사이에는 상속이 없습니다.
한 네임스페이스의 토큰은 해당 네임스페이스만 읽을 수 있습니다.
프로젝트가 그룹의 시크릿을 읽는 것과 같은 CI의 수준 간 접근은 OpenBao가 아니라 GitLab이 명시적으로 처리합니다.
GitLab은 JWT로 OpenBao에 인증합니다. OpenBao는 GitLab OpenID Connect(OIDC) 디스커버리 문서를 가져와 이 JWT를 검증합니다. 따라서 OpenBao 작업이 동작하려면 GitLab에 HTTP로 접근할 수 있어야 합니다.
사용 가능 여부 조건#
Secrets Manager를 사용하려면 두 조건이 모두 참이어야 합니다.
모든 확인은 ee/lib/secrets_management/availability.rb의 SecretsManagement::Availability를 거칩니다.
- 라이선스. Premium 이상에서 사용할 수 있는
native_secrets_management라이선스 기능입니다. - 등록. GitLab.com에서는 최상위 그룹별로 등록합니다(
SecretsManagement::NamespaceEnrollment). GDK를 포함한 GitLab Self-Managed에서는 등록이 인스턴스 전체 애플리케이션 설정secrets_manager_instance_enrolled이며, 기본값은false입니다.
두 조건은 AND로 결합됩니다. 등록을 끄면 Secrets Manager를 즉시 사용할 수 없게 됩니다. 그 이후에 가져온 CI job은 시크릿을 받지 못하며, 이미 실행 중인 job은 받은 시크릿을 유지합니다.
권한(entitlement)은 체험판 및 청구 상태에 기반한 별도의 추가 조건입니다. 자세한 내용은 권한 상태를 참조합니다.
코드 맵#
특정 종류의 Secrets Manager 코드가 어디에 있는지 찾으려면 이 표를 사용합니다.
| 항목 | 위치 |
|---|---|
| 모델 | ee/app/models/secrets_management/ |
| 서비스 | ee/app/services/secrets_management/ |
| 서비스 concern | ee/app/services/concerns/secrets_management/ |
| GraphQL 타입, 뮤테이션, 리졸버 | ee/app/graphql/{types,mutations,resolvers}/secrets_management/ |
| 워커 | ee/app/workers/secrets_management/ |
| 정책 | ee/app/policies/secrets_management/ |
| OpenBao 클라이언트, JWT, 사용 가능 여부 | ee/lib/secrets_management/ |
| Rake 태스크 | ee/lib/tasks/gitlab/secrets_management/ |
| 헬퍼 | ee/app/helpers/secrets_management/ |
| 프론트엔드 | ee/app/assets/javascripts/ci/secrets/ |
| 백엔드 테스트 | ee/spec/{services,models,workers,requests,lib,helpers}/secrets_management/ |
| 프론트엔드 테스트 | ee/spec/frontend/ci/secrets/ |
코드를 작성하기 전에 알아야 할 패턴#
이러한 패턴은 Secrets Manager 코드베이스 전반에서 반복됩니다. 코드를 작성하기 전에 알아 두면 가장 흔한 버그를 피하는 데 도움이 됩니다.
시크릿은 ActiveRecord가 아님#
시크릿 객체는 OpenBao를 기반으로 하는 ActiveModel::Model 인스턴스입니다.
find_by, 스코프, 데이터베이스 조인이 동작하리라고 기대하지 않습니다.
두 개의 인가 계층#
요청은 Rails 정책 확인과 OpenBao ACL 정책을 모두 통과해야 합니다. 둘 중 하나만 통과해서는 충분하지 않습니다.
읽거나 쓰기 전에 프로비저닝#
Secrets Manager 레코드는 active 상태여야 합니다.
아직 provisioning 상태이면 서비스가 실패합니다.
쓰기의 배타적 리스#
쓰기 작업은 배타적 리스를 획득하며, 재시도하지 않고 즉시 실패합니다. 같은 프로젝트에 대한 동시 쓰기는 오류를 반환합니다.
메타데이터 check-and-set#
업데이트는 현재 메타데이터 버전과 일치해야 하는 metadata_cas 값을 전달합니다.
이렇게 하면 두 업데이트가 서로를 조용히 덮어쓰는 일을 막으며, 이러한 패턴을 낙관적 동시성 제어라고 합니다.
두 단계 쓰기#
쓰기는 시작 단계와 완료 단계로 나뉘므로, 실패해도 시크릿이 반쯤 기록된 상태가 아니라 닫힌 상태로 남습니다.
오류 정리#
원시 OpenBao 오류를 사용자에게 그대로 전달하지 않습니다. 대신 안전한 메시지로 매핑합니다.
그룹은 프로젝트가 아님#
프로젝트 시크릿은 branch 파라미터를, 그룹 시크릿은 protected 파라미터를 받습니다.
기본 역할 부여와 이전 방식도 두 쪽이 서로 다릅니다.
프로젝트 코드를 변경할 때는 그룹 코드 경로를 따로 확인합니다.
전체 목록은 프로젝트와 그룹의 차이를 참조합니다.
프로비저닝 해제는 태스크 기반의 비동기 방식#
Secrets Manager 행을 삭제하면 데이터베이스 트리거가 실행되어 프로비저닝 해제 태스크를 기록합니다. 워커가 이 태스크를 읽고 OpenBao 정리를 실행합니다. 그러면 상위 프로젝트나 그룹이 이미 사라진 뒤에 정리가 끝날 수 있습니다.