Azure 시크릿 엔진

Azure 시크릿 엔진 (Azure secrets engine)

Azure 서비스 주체와 역할·그룹 할당을 동적으로 생성하는 Azure 시크릿 엔진을 다룹니다.

출처: 문서

본문

Azure 시크릿 엔진은 Azure 서비스 주체(service principal)와 역할·그룹 할당을 동적으로 생성해요. Vault 역할을 하나 이상의 Azure 역할, 그리고 선택적으로 그룹 할당에 매핑할 수 있어, 생성된 서비스 주체에 부여되는 권한을 관리하는 간단하고 유연한 방법을 제공합니다.

각 서비스 주체는 Vault 리스와 연결됩니다. 리스가 만료되면(정상 폐기 또는 조기 폐기 중에) 서비스 주체가 자동으로 삭제됩니다.

역할 구성의 일부로 기존 서비스 주체가 지정되면, 새 서비스 주체 대신 새 비밀번호가 동적으로 생성됩니다. 비밀번호는 리스가 폐기될 때 삭제됩니다.

설정 (Setup)

참고: Azure 시크릿 엔진은 Vault API나 AZURE_CLIENT_ID, AZURE_CLIENT_SECRET 같은 확립된 환경 변수로 구성할 수 있어요. 두 방법을 모두 사용한다면 환경 변수가 항상 API 값보다 우선합니다.

대부분의 시크릿 엔진은 제 기능을 하기 전에 미리 구성해야 해요. 이 단계는 보통 운영자나 구성 관리 도구가 수행합니다.

CLI — Azure 시크릿 엔진 활성화:

$ vault secrets enable azure
Success! Enabled the azure secrets engine at: azure/

기본적으로 시크릿 엔진은 엔진 이름으로 마운트돼요. 다른 경로에 활성화하려면 -path 인자를 사용하면 됩니다.

설정 중 기존 워크로드 아이덴티티 연합(WIF) 아이덴티티 토큰 키를 보려면 identity/oidc/key 엔드포인트에 대한 list 권한이 있어야 해요.

GUI: 1. GUI 열기 → 2. 네임스페이스 로그인 → 3. Secrets 선택 → 4. Secrets engines 선택 → 5. Enable new engine + 클릭 → 6. Azure 선택 → 7. Next 클릭 → 8. Azure 플러그인의 마운트 경로 설정(예: azure) → 9. WIF를 사용한다면 Method Options → Identity Token Key에서 아이덴티티 토큰 키 추가 → 10. Enable engine 클릭 → 11. Save 클릭.

계정 자격 증명으로 시크릿 엔진 구성:

CLI:

$ vault write azure/config \
    subscription_id=$AZURE_SUBSCRIPTION_ID \
    tenant_id=$AZURE_TENANT_ID \
    client_id=$AZURE_CLIENT_ID \
    client_secret=$AZURE_CLIENT_SECRET

Success! Data written to: azure/config

GUI: 1. GUI 열기 → 2. 로그인 → 3. Secrets 선택 → 4. Secrets engines 선택 → 5. 업데이트할 azure 플러그인 선택 → 6. Configure 클릭 → 7. 구성 정보 입력 → 8. 접근 타입 설정 → (Enterprise) 9. 변경 사항 저장.

MSI가 활성화된 Azure VM 안에서 Vault를 실행한다면 client_id와 client_secret을 생략할 수 있어요. 인증에 대한 자세한 내용은 아래 authentication 섹션을 참고하세요.

경우에 따라 Vault 구성에 민감한 계정 자격 증명을 설정할 수 없을 수 있어요. 예를 들어 조직에서 모든 보안 자격 증명이 수명이 짧거나 머신 아이덴티티에 명시적으로 묶여야 할 수 있습니다.

Vault에 관리형 아이덴티티 보안 자격 증명을 제공하려면 아래와 같이 Vault plugin workload identity federation(WIF)을 사용할 것을 권장합니다.

또는 플러그인 워크로드 아이덴티티 연합에 대한 audience 클레임 값과 Client, Tenant, Subscription ID를 구성할 수 있어요.

CLI:

$ vault write azure/config \
    subscription_id=$AZURE_SUBSCRIPTION_ID \
    tenant_id=$AZURE_TENANT_ID \
    client_id=$AZURE_CLIENT_ID \
    identity_token_audience=$TOKEN_AUDIENCE

GUI: WIF 구성에 대해 "Access Type"으로 Workload Identity Federation을 선택하고 다음 정보를 입력합니다.

  • Subscription ID — Azure 구독의 ID.
  • Tenant ID — Azure Active Directory 테넌트의 ID.
  • Client ID — Azure에 연결하기 위한 OAuth2 클라이언트 id.
  • Issuer URL — Vault 플러그인 아이덴티티 토큰 발급자의 완전하고 네트워크로 접근 가능한 발급자 URL. 예: https://vault.example.com/v1/identity/oidc/plugins.
  • Identity token audience — 플러그인 아이덴티티 토큰의 audience 클레임 값. 이 값은 대상 Federated Identity Credential에 구성된 허용 audience와 일치해야 해요. client_secret과 상호 배타적입니다.

Vault 아이덴티티 토큰 제공자는 플러그인 아이덴티티 토큰 JWT를 내부적으로 서명해요. WIF를 통해 Vault와 Azure 사이에 신뢰 관계가 존재하면, 시크릿 엔진은 Vault 아이덴티티 토큰을 연합(federated) 액세스 토큰으로 교환할 수 있습니다.

Vault와 Azure 사이에 신뢰 관계를 구성하려면:

Vault와 Azure 사이의 신뢰 관계를 확립하면 Azure가 JWKS 공개 키를 가져와 플러그인 아이덴티티 토큰 서명을 검증할 수 있습니다.

역할을 구성해요. 역할은 기존 서비스 주체 또는 동적으로 생성된 서비스 주체에 할당될 Azure 역할 집합으로 설정할 수 있어요.

참고: Vault UI는 Azure Secret 엔진 구성만 지원합니다. 역할 구성과 자격 증명 회전에는 CLI/API를 사용해야 해요.

기존 서비스 주체로 "my-role"이라는 역할을 구성하려면:

$ vault write azure/roles/my-role \
    application_object_id=<OBJECT_ID> \
    ttl=1h

또는 Azure 역할이 있는 새 서비스 주체를 만들도록 역할을 구성하려면:

$ vault write azure/roles/my-role ttl=1h azure_roles=<<EOF
[
  {
    "role_name": "Contributor",
    "scope":  "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/Website"
  }
]
EOF

역할은 마운트의 TTL과 별개인 자체 TTL 구성을 가질 수도 있어요. 역할에 대한 자세한 내용은 아래 roles 섹션을 참고하세요.

사용법 (Usage)

시크릿 엔진이 구성되고 사용자/머신이 적절한 권한을 가진 Vault 토큰을 가지면 자격 증명을 생성할 수 있어요. 기존 또는 동적 서비스 주체를 사용할 때 사용 패턴은 동일합니다.

"my-role" 역할로 자격 증명을 생성하려면:

$ vault read azure/creds/my-role

Key                Value
---                -----
lease_id           azure/creds/sp_role/1afd0969-ad23-73e2-f974-962f7ac1c2b4
lease_duration     60m
lease_renewable    true
client_id          408bf248-dd4e-4be5-919a-7f6207a307ab
client_secret      ad06228a-2db9-4e0a-8a5d-e047c7f32594

이 엔드포인트는 갱신 가능한 자격 증명 집합을 생성합니다. 애플리케이션은 client_id/client_secret으로 로그인할 수 있으며, "my-role" 구성에 설정된 서비스 주체 또는 Azure 역할이 제공하는 접근 권한을 갖습니다.

루트 자격 증명 회전 (Root credential rotation)

마운트는 마운트 안에 직접 구성된 루트 자격 증명 키를 회전할 수 있어요. Vault 생성 키로 회전하면 키 값이 운영자에게 접근 불가능해지고, 오직 Vault만이 루트 사용자로 동작해 동적·정적 자격 증명을 조작할 수 있게 보장됩니다.

vault write -f azure/rotate-root

일정 기반 자격 증명 회전

Enterprise에요. 적절한 Vault Enterprise 라이선스가 필요합니다.

rotation_schedule 필드로 Azure 시크릿 엔진의 루트 자격 증명에 대한 일정 기반 자동 회전을 구성해요. 예를 들어 다음 명령은 회전이 매주 토요일 자정(00:00)에 일어나게 설정합니다.

$ vault write azure/config \
    ...
    rotation_schedule="0 * * * SAT"
    ...

예약된 루트 자격 증명 회전은 회전이 발생하도록 허용되는 창인 rotation_window도 설정할 수 있어요. Vault는 창이 만료되면 자격 증명 회전 시도를 중지합니다. 예를 들어 다음 명령은 토요일 자정에 회전하되 1시간 안에만 회전하도록 합니다. 실패 등으로 1시까지 회전하지 못하면 다음 예약 회전까지 회전 시도를 중지합니다.

$ vault write azure/config \
    ...
    rotation_window="1h" \
    rotation_schedule="0 * * * SAT"
    ...

disable_automated_rotation을 true로 설정해 루트 회전을 임시로 비활성화할 수 있어요. 이 필드는 false로 재설정될 때까지 루트 자격 증명의 회전을 방지합니다. rotation_period를 사용한다면 disable_automated_rotation을 설정하면 자격 증명 TTL도 초기화됩니다.

Azure 플러그인의 루트 자격 증명 회전에 대한 자세한 내용은 Root credential rotation API 문서를 참고하세요.

역할 (Roles)

Vault 역할로 기존 서비스 주체 또는 Azure 역할 집합을 구성하고, 역할별 TTL 파라미터도 설정할 수 있어요. 기존 서비스 주체가 제공되지 않으면 구성된 Azure 역할이 새로 생성된 서비스 주체에 할당됩니다. Vault 역할은 선택적으로 역할별 ttl 및/또는 max_ttl 값을 지정할 수 있어요. 리스가 생성될 때 마운트 또는 역할 TTL 값 중 더 제한적인 값이 사용됩니다.

애플리케이션 객체 ID

기존 서비스 주체를 사용하려면 Application Object ID를 Vault 역할에 설정해야 해요. 이 ID는 az CLI 도구나 Azure Portal로 원하는 Application을 검사해 찾을 수 있습니다. Application ID가 아니라 Application Object ID를 제공해야 한다는 점에 주의하세요.

Azure 역할

동적 서비스 주체를 사용한다면 Azure 역할을 Vault 역할에 구성해야 해요. Azure 역할은 JSON 목록으로 제공되며, 각 요소는 할당될 Azure 역할과 범위를 설명합니다. Azure 역할은 role_name 파라미터("Owner") 또는 role_id("/subscriptions/.../roleDefinitions/...")로 지정할 수 있어요. role_id는 Vault 작업 중 사용되는 결정적인 ID이고, role_name은 역할 관리 작업 중의 편의를 위한 것입니다. 구성이 기록될 때 모든 역할이 존재해야 하며, 그렇지 않으면 작업이 실패합니다. 역할 조회 우선순위는:

  1. role_id가 제공되면 검증되고 해당 role_name이 업데이트됩니다.
  2. role_name만 제공되면 대소문자 구분 없는 이름 검색이 수행되며, 정확히 하나 의 일치 역할이 있을 때만 성공합니다. role_id 필드는 일치하는 역할 ID로 업데이트됩니다.

모든 역할 할당에 범위를 제공해야 해요.

Azure 그룹

동적 서비스 주체를 사용한다면 Azure 그룹 목록을 Vault 역할에 구성할 수 있어요. 서비스 주체가 만들어지면 이 그룹들에 할당됩니다. Azure 역할을 지정하는 형식과 비슷하게, Azure 그룹은 group_name 또는 object_id로 참조할 수 있어요. 이름으로 그룹을 지정하면 단일 일치 그룹이 나와야 합니다.

역할 구성 예제:

$ vault write azure/roles/my-role \
    ttl=1h \
    max_ttl=24h \
    azure_roles=@az_roles.json \
    azure_groups=@az_groups.json

$ cat az_roles.json
[
  {
    "role_name": "Contributor",
    "scope":  "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/Website"
  },
  {
    "role_id": "/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Authorization/roleDefinitions/<ROLE_DEF_ID>",
    "scope":  "/subscriptions/<SUBSCRIPTION_ID>"
  },
  {
    "role_name": "This won't matter as it will be overwritten",
    "role_id": "/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Authorization/roleDefinitions/<ROLE_DEF_ID>",
    "scope":  "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/Database"
  }
]

$ cat az_groups.json
[
  {
    "group_name": "foo"
  },
  {
    "group_name": "This won't matter as it will be overwritten",
    "object_id": "a6a834a6-36c3-4575-8e2b-05095963d603"
  }
]

Azure 객체 영구 삭제

동적 서비스 주체를 사용한다면 Vault가 만든 애플리케이션·서비스 주체를 영구 삭제하는 옵션을 Vault 역할에 구성할 수 있어요. 이 옵션 활성화 시 리스가 만료·폐기되면, 리스와 연결된 애플리케이션과 서비스 주체가 Azure Active Directory에서 영구 삭제됩니다. 그 결과 이 객체들은 Azure 테넌트의 총 리소스 quota에 계산되지 않습니다. 이 옵션이 활성화되지 않으면 리스가 만료·폐기되어도 애플리케이션과 서비스 주체는 삭제되지만 영구적이지 않습니다. 이 객체들은 삭제 후 30일 동안 복원할 수 있습니다.

역할 구성 예제:

$ vault write azure/roles/my-role permanently_delete=true ttl=1h azure_roles=<<EOF
[
  {
    "role_name": "Contributor",
    "scope":  "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/Website"
  }
]
EOF

인증 (Authentication)

Azure 시크릿 백엔드는 Azure 역할 정보를 읽고 서비스 주체를 관리할 충분한 권한이 있어야 해요. 인증 파라미터는 백엔드 구성 또는 환경 변수로 설정할 수 있습니다. 환경 변수가 우선합니다. 개별 파라미터는 API 문서의 configuration 섹션에 설명되어 있습니다.

클라이언트 ID나 시크릿이 없고 Vault가 Azure VM에서 실행 중이라면, Vault는 Azure에 접근하기 위해 Managed Service Identity (MSI)를 사용하려 시도합니다. MSI를 사용할 때는 테넌트·구독 ID를 여전히 구성이나 환경 변수에 명시적으로 제공해야 한다는 점에 주의하세요.

MS Graph API 권한

Azure를 관리하기 위해 Vault에 제공된 서비스 주체에 다음 MS Graph API 권한을 할당해야 해요. 동적 또는 기존 서비스 주체를 사용하느냐에 따라 권한이 다릅니다.

동적 서비스 주체:

권한 이름 타입
Application.ReadWrite.OwnedBy Application
GroupMember.ReadWrite.All Application

참고: rotate root 자격 증명 API를 사용할 계획이라면 Application.ReadWrite.OwnedBy를 Application.ReadWrite.All로 바꿔야 해요.

기존 서비스 주체:

권한 이름 타입
Application.ReadWrite.All Application
GroupMember.ReadWrite.All Application

역할 할당 (Role assignments)

시크릿 엔진이 자신이 만든 서비스 주체에 대한 역할 할당을 관리할 수 있도록 다음 Azure 역할 할당이 부여되어야 해요.

역할 범위 보안 주체
User Access Administrator Subscription 구성에 주어진 Service Principal ID

플러그인 워크로드 아이덴티티 연합 (Plugin Workload Identity Federation / WIF)

Enterprise에요. 이 기능은 Vault Enterprise가 필요합니다.

Azure 시크릿 엔진은 플러그인 WIF 워크플로를 지원하며, 플러그인 아이덴티티 토큰이라는 신원 소스를 가집니다. 플러그인 아이덴티티 토큰은 Vault의 plugin identity token issuer가 내부적으로 서명하는 JWT입니다.

워크로드 아이덴티티 연합을 통해 Vault와 Azure 사이에 신뢰 관계가 구성되어 있다면, 시크릿 엔진은 자신의 아이덴티티 토큰을 작업을 수행하는 데 필요한 단기 액세스 토큰으로 교환할 수 있어요.

아이덴티티 토큰을 액세스 토큰으로 교환하면 Azure 시크릿 엔진이 민감한 클라이언트 자격 증명에 대한 명시적 접근을 구성하지 않고도 동작할 수 있습니다.

시크릿 엔진을 플러그인 WIF로 구성하려면:

  1. Vault openid-configuration과 public JWKS API가 Azure에서 네트워크로 접근 가능한지 확인해요. Vault API 노출을 제한해야 한다면 API 프록시나 게이트웨이 사용을 권장합니다.
  2. Azure의 전용 애플리케이션 등록에 Vault와의 신뢰 관계를 확립하는 federated identity credential을 구성해요.
    1. 발급자 URL은 반드시 /.well-known/openid-configuration 접미사를 뺀 Vault plugin identity token issuer를 가리켜야 해요. 예: https://host:port/v1/identity/oidc/plugins.
    2. 주체 식별자(subject identifier)는 플러그인 아이덴티티 토큰이 발급하는 고유 sub 클레임과 일치해야 해요. 주체 식별자는 plugin-identity:<NAMESPACE_ID>:secret:<AZURE_MOUNT_ACCESSOR> 형식이어야 합니다.
    3. audience는 600자 미만이어야 해요. Azure에서 기본값은 api://AzureADTokenExchange입니다.
  3. Azure 시크릿 엔진을 subscription, client, tenant ID와 OIDC audience 값으로 구성해요.
$ vault write azure/config \
  subscription_id=$AZURE_SUBSCRIPTION_ID \
  tenant_id=$AZURE_TENANT_ID \
  client_id=$AZURE_CLIENT_ID \
  identity_token_audience="api://AzureADTokenExchange"

이제 시크릿 엔진은 구성 자격 증명에 플러그인 WIF를 사용할 수 있습니다. 기본적으로 WIF 자격 증명은 수명이 1시간이며 만료되면 자동으로 새로 고쳐집니다.

플러그인 WIF와 관련된 필드에 대한 자세한 내용은 API documentation을 참고하세요.

정적 역할 (Static roles)

Enterprise에요. 적절한 Vault Enterprise 라이선스가 필요합니다.

Azure 시크릿 엔진은 동적·정적 역할을 지원합니다.

Vault는 정적 역할로 Azure 애플리케이션의 장기(long-lived) 클라이언트 시크릿을 관리합니다. 매 요청마다 새 자격 증명을 생성하는 동적 역할과 달리, 정적 역할은 값을 명시적으로 회전할 때까지 항상 같은 클라이언트 시크릿을 반환합니다. 시크릿이 회전되면 Vault가 애플리케이션에 새 클라이언트 시크릿을 생성하고 이전 시크릿을 폐기합니다.

rotate-role 엔드포인트로 수동으로 시크릿을 회전할 수 있어요.

새 시크릿을 생성하는 것 외에도 정적 역할은 기존 Azure 자격 증명 가져오기를 지원합니다. 이를 통해 Vault가 Vault 밖에서 만들어진 자격 증명의 관리를 인수해 Vault의 라이프사이클 통제 하에 둘 수 있어요.

자격 증명을 가져오는 방법:

  • 메타데이터 가져오기 — secret_id, skip_import_rotation=true, 선택적 만료를 제공. Vault는 메타데이터를 기록하지만, 역할을 명시적으로 회전해 유효한 시크릿을 생성하기 전까지 읽기를 차단합니다.
  • 전체 가져오기 — secret_id, client_secret, 선택적 만료를 제공. 가져온 자격 증명을 Vault에서 즉시 사용할 수 있어요.
  • 가져오기 시 회전 — secret_id를 제공하고 skip_import_rotation을 설정하지 않음. Vault가 가져오기 중 자격 증명을 회전해 신선하고 유효한 시크릿을 보장합니다.

자세한 내용은 Azure plugin API documentation을 참고하세요.

동적 또는 기존 서비스 주체 선택

원하는 Azure 리소스를 RBAC 시스템과 Vault 역할에 정의된 Azure 역할로 제공할 수 있다면 동적 서비스 주체가 선호됩니다. 이 형태의 자격 증명은 다른 클라이언트와 완전히 분리되고, 발급 후 권한 변경의 대상이 아니며, 최고의 감사 세분성을 제공합니다.

하지만 일부 Azure 서비스에 대한 접근은 RBAC 시스템으로 제공할 수 없어요. 이런 경우 기존 서비스 주체를 필요한 접근 권한으로 설정하고, Vault가 이 서비스 주체에 대해 새 비밀번호를 만들 수 있습니다. 서비스 주체 권한의 어떤 변경도 모든 클라이언트에 영향을 줍니다. 게다가 Azure는 어떤 자격 증명이 작업에 사용됐는지에 대한 로깅을 제공하지 않아요.

기존 서비스 주체를 사용할 때 중요한 제한은 Azure가 단일 Application에 대해 비밀번호 수를 제한한다는 것입니다. 이 제한은 Application 객체 크기에 기반하며 확정적으로 지정되지는 않지만, 실제로 Application당 수백 개의 비밀번호를 발급할 수 있습니다. 객체 크기에 도달하면 오류가 반환됩니다. 이 제한은 역할 TTL을 줄이거나, 같은 권한으로 구성된 다른 Azure 서비스 주체에 대해 또 다른 Vault 역할을 만들어 관리할 수 있어요.

추가 참고 사항

  • 참조된 Azure 역할이 존재하지 않으면 자격 증명이 생성되지 않습니다. 모든 역할 할당이 성공해야만 서비스 주체가 생성됩니다. 이는 언젠가 삭제될 수 있는 커스텀 Azure 역할 정의를 사용할 때 중요해요.
  • Azure 역할은 서비스 주체가 생성될 때 한 번만 할당됩니다. Vault 역할이 Azure 역할 목록을 바꾸어도, 토큰 갱신 후에도 그 변경은 기존 서비스 주체에 반영되지 않습니다.
  • 자격 증명 발급에 걸리는 시간은 할당해야 하는 Azure 역할 수에 대략 비례합니다. 이 작업은 시간이 걸릴 수 있어요(십수 초는 흔하며, 1분을 넘는 것도 본 적이 있습니다).
  • 서비스 주체 자격 증명 타임아웃은 사용되지 않습니다. Vault는 서비스 주체를 삭제해 접근을 폐기합니다.
  • 동적 서비스 주체의 애플리케이션 이름에는 vault- 접두사가 붙습니다. 마찬가지로 기존 서비스 주체에 추가된 비밀번호의 keyId는 ffffff로 시작합니다. az 도구나 Portal에서 Vault 생성 자격 증명을 검색하는 데 사용할 수 있어요.

Azure 디버그 로그

Azure 시크릿 엔진 플러그인은 Azure API로부터의 요청·응답에 대한 추가 정보를 포함하는 디버그 로깅을 지원합니다.

Azure 디버그 로그를 활성화하려면 Vault 서버에서 AZURE_SDK_GO_LOGGING 환경 변수를 all로 설정해요.

AZURE_SDK_GO_LOGGING=all

도움말·지원

Azure 시크릿 엔진은 외부 Vault 플러그인으로 작성되어 메인 Vault 레포지토리 밖에 있습니다. Vault 릴리스와 자동으로 번들되지만 코드는 별도로 관리됩니다.

문제 보고, 기능 요청, 기여는 GitHub의 vault-plugin-secrets-azure repo에 제출하세요.

튜토리얼

Azure 시크릿 엔진으로 Azure 자격 증명을 동적으로 생성하는 방법을 배우려면 Azure Secrets Engine 튜토리얼을 참고하세요.

API

Azure 시크릿 엔진은 완전한 HTTP API를 제공해요. 자세한 내용은 Azure secrets engine API docs를 참고하세요.

Terraform

Vault Terraform 제공자로 Azure 시크릿 리소스를 프로그래밍 방식으로 관리할 수 있어요. Terraform Registry 문서에서 자세한 내용을 확인하세요.

더 알아보기 (Learn more)