Secrets Manager 로컬 설정
GitLab v19.5요약
이 페이지는 GDK에서 Secrets Manager를 설정해 기능을 로컬에서 개발하고 테스트하는 과정을 안내합니다. 이 설정은 백엔드 작업용입니다. Secrets Manager UI는 재설계 중이므로, 이 페이지는 UI 단계 대신 Rails 콘솔을 사용합니다.
이 페이지는 GDK에서 Secrets Manager를 설정해 기능을 로컬에서 개발하고 테스트하는 과정을 안내합니다. 기능이 어떻게 구성되어 있는지는 Secrets Manager 개발 가이드라인을 참조합니다.
이 설정은 백엔드 작업용입니다. 프론트엔드만 작업한다면 OpenBao 없이 일반 GDK에서 프론트엔드 스펙을 실행할 수 있습니다. 자세한 내용은 Secrets Manager 프론트엔드 개발을 참조합니다.
Secrets Manager UI는 재설계 중이므로, 이 페이지는 UI 단계 대신 Rails 콘솔을 사용합니다.
콘솔 서비스는 안정적이며, UI가 가리는 오류도 확인할 수 있습니다.
진행 중인 설계는 gitlab-org/gitlab#605033을 참조합니다. 이 이슈는 비공개이며 GitLab 팀 멤버 권한이 필요합니다.
사전 요구 사항#
- 동작하는 GDK.
- Premium 또는 Ultimate 라이선스가 있는 GitLab Enterprise Edition. Secrets Manager에는
native_secrets_management라이선스 기능이 필요합니다. - 인스턴스 URL(예:
http://gdk.test:3000)에서 HTTP를 제공하는 GDK. OpenBao는 해당 URL에서 OIDC 디스커버리 문서를 가져와 GitLab JWT를 검증하므로, GitLab이 요청을 처리하지 않으면 프로비저닝이 실패합니다.
1단계: GDK에서 OpenBao 활성화#
gdk config set openbao.enabled true
gdk reconfigure
gdk start openbao
GDK는 업스트림 릴리스가 아니라 GitLab 패치가 포함된 내부 빌드로 OpenBao를 빌드합니다.
바이너리는 <gdk-root>/openbao/bin/bao에 생성됩니다.
CLI를 사용하려면 셸 프로필에 다음을 추가합니다.
export BAO_ADDR='http://gdk.test:8200'
export PATH="<gdk-root>/openbao/bin:$PATH"
감사 로그 스트리밍과 관리자 액세스를 포함한 OpenBao 전체 레퍼런스는 GDK의 OpenBao를 참조합니다.
2단계: 인스턴스 등록#
등록은 새로 합류한 개발자가 가장 자주 놓치는 단계입니다.
GDK는 GitLab Self-Managed로 동작하므로, Secrets Manager 사용 가능 여부는 인스턴스 등록에 달려 있습니다.
secrets_manager_instance_enrolled 애플리케이션 설정의 기본값은 false입니다.
OpenBao가 실행 중이어도 Secrets Manager는 사용할 수 없는 상태로 남습니다.
3단계의 시드 Rake 태스크가 등록을 대신 수행하므로, 이 단계는 프로젝트를 수동으로 프로비저닝할 때 중요합니다.
Rails 콘솔에서 등록합니다.
user = User.find_by_username('root')
SecretsManagement::InstanceEnrollmentService.new(current_user: user).enroll
GDK가 GitLab.com을 시뮬레이션한다면 대신 최상위 그룹을 등록합니다.
group = Group.find_by_full_path('your-root-group')
SecretsManagement::NamespaceEnrollmentService.new(group, current_user: user).enroll
두 서비스 모두 여러 번 실행해도 안전하며, 잘못된 배포 유형은 거부합니다. 네임스페이스 등록은 GitLab.com에서만 동작하고, 인스턴스 등록은 GitLab Self-Managed에서만 동작합니다.
3단계: 동작하는 환경 시딩#
동작하는 환경을 가장 빠르게 얻는 방법은 시드 Rake 태스크입니다. 이 태스크는 루트 네임스페이스 아래에 하위 그룹과 프로젝트를 만들고, 그룹과 프로젝트의 Secrets Manager를 프로비저닝하며, 샘플 시크릿을 추가합니다. 인스턴스 등록도 대신 수행합니다.
bundle exec rake "gitlab:secrets_management:seed[ROOT_NAMESPACE_ID]"
다음 사항에 유의합니다.
- 이 태스크는 개발 환경에서만 실행됩니다.
ROOT_NAMESPACE_ID를 기존 최상위 그룹의 ID로 바꿉니다.- 이 태스크는
root사용자를 사용하며,root가 없으면 첫 번째 관리자를 사용하고 해당 사용자를 그룹의 Owner로 추가합니다. - 프로비저닝은 동기적으로 실행되므로 Sidekiq을 기다릴 필요가 없습니다.
- 등록 방식은 GDK 모드를 따릅니다. 이 태스크는 GDK가 GitLab.com을 시뮬레이션하면 네임스페이스를, 그렇지 않으면 인스턴스를 등록합니다.
이 태스크는 루트 네임스페이스 아래에 다음 계층을 만듭니다.
subgroup-a에는project-a1과project-a2가 있고,subgroup-a1에는project-a1a가 있습니다.subgroup-b에는project-b1이 있고,subgroup-b1에는project-b1x가 있습니다.project-top1은 루트 네임스페이스 바로 아래에 있습니다.
4단계: 설정 확인#
Rails 콘솔에서 시드된 프로젝트에 대해 두 가지 사용 가능 여부 조건이 모두 통과하는지 확인합니다.
project = Project.find_by_full_path('your-root-group/subgroup-a/project-a1')
SecretsManagement::Availability.for_project?(project) # => true
project.secrets_manager.status # => "active"
for_project?가 false를 반환하면 조건을 하나씩 확인합니다.
project.licensed_feature_available?(:native_secrets_management) # license
Gitlab::CurrentSettings.secrets_manager_instance_enrolled # enrollment
그런 다음 시드된 시크릿을 나열합니다.
user = User.find_by_username('root')
result = SecretsManagement::ProjectSecrets::ListService.new(project, user).execute
result.payload[:secrets].map(&:name)
Rails 콘솔에서 수동으로 프로비저닝#
시더를 실행하지 않고 특정 프로젝트를 프로비저닝하려면 이 방법을 사용합니다.
project = Project.find_by_full_path('your-group/your-project')
user = User.find_by_username('root')
project.add_owner(user) unless project.member?(user)
result = SecretsManagement::ProjectSecretsManagers::InitializeService.new(project, user).execute
secrets_manager = result.payload[:project_secrets_manager]
# Run provisioning now instead of waiting for the background worker.
SecretsManagement::ProjectSecretsManagers::ProvisionService.new(secrets_manager, user).execute
secrets_manager.reload.status # => "active"
시크릿을 만듭니다.
result = SecretsManagement::ProjectSecrets::CreateService.new(project, user).execute(
name: 'MY_SECRET',
value: 'super-secret-value',
description: 'Test secret for local development',
environment: '*',
branch: '*'
)
result.success? # => true
그룹은 GroupSecretsManagers 및 GroupSecrets 서비스 네임스페이스로 같은 패턴을 사용합니다.
그룹 시크릿은 branch 대신 protected 파라미터를 받습니다.
독립 실행형 rails runner 스크립트에는 상관 관계 ID가 필요합니다. OpenBao 인가 프로그램이 correlation_id 클레임을 읽기 때문입니다.
호출을 다음과 같이 감쌉니다.
Labkit::Correlation::CorrelationId.use_id('local-testing') do
# your Secrets Manager calls
end
웹 서버를 거치는 요청은 상관 관계 ID가 자동으로 부여되므로, 이 내용은 스크립트와 콘솔 세션에만 적용됩니다.
OpenBao 직접 확인#
디버깅하는 동안 OpenBao 상태를 살펴보려면 관리자 로그인을 켤 수 있습니다. 이를 위해 먼저 OpenBao 데이터를 초기화해야 합니다.
gdk stop openbao
gdk reset-openbao-data
gdk config set openbao.admin_enabled true
gdk reconfigure
gdk start openbao
그런 다음 로그인합니다.
export BAO_ADDR="http://$(gdk config get openbao.__listen)"
bao login -method=userpass username=admin password=$(cat <gdk-root>/openbao/admin-password.txt)
로컬 데이터 초기화#
gdk stop openbao
gdk reset-openbao-data
gdk start openbao
이 명령은 OpenBao 상태를 지웁니다. 초기화한 뒤에는 시드 태스크를 다시 실행하는 등의 방법으로 프로젝트와 그룹을 다시 프로비저닝합니다.
문제 해결#
Secrets Manager를 사용할 수 없음#
SecretsManagement::Availability.for_project?가 false를 반환합니다.
4단계에 나온 것처럼 조건을 하나씩 확인합니다.
GDK에서는 인스턴스가 등록되지 않은 경우가 가장 흔한 원인입니다.
2단계를 참조합니다.
프로비저닝이 인증 또는 키 세트 오류로 실패함#
OpenBao가 GitLab OIDC 디스커버리 문서를 가져오지 못했습니다.
GitLab이 인스턴스 URL에서 HTTP를 제공하고 있는지 확인한 뒤 다시 시도합니다.
브라우저에서 http://gdk.test:3000/을 열어 보면 빠르게 확인할 수 있습니다.
OpenBao와 통신할 때 연결이 거부됨#
OpenBao가 실행 중이 아닙니다.
gdk start openbao를 실행하고 gdk tail openbao에서 오류를 확인합니다.
Secrets Manager가 프로비저닝 상태에서 멈춤#
백그라운드 워커가 작업을 끝내지 못했습니다. 앞에서 설명한 대로 Rails 콘솔에서 프로비저닝 서비스를 직접 실행하면 실제 오류를 확인할 수 있습니다.
다른 시크릿 작업이 진행 중임#
배타적 리스가 아직 유지되고 있습니다. 만료될 때까지 기다리거나 리스를 취소합니다.
lease_key = "project_secret_operation:project_#{project.id}"
Gitlab::ExclusiveLease.cancel(lease_key, Gitlab::ExclusiveLease.get_uuid(lease_key))
프로비저닝 중 경로가 이미 사용 중임#
이 메시지는 보통 문제가 없습니다. 시크릿 엔진 또는 인증 엔진이 이미 마운트되어 있었고, 프로비저닝 서비스가 이를 처리합니다.