인생은 여행

Vault의 AppRole을 사용하는 권장 패턴 본문

Vault

Vault의 AppRole을 사용하는 권장 패턴

산떠 버하둘 2021. 7. 18. 17:29

이 글은 Hashicorp사의 Vault에 관련된 문서중 "Recommended Pattern for Vault AppRole Use"를 번역하며 약간의 의역을 더한 것입니다.

프로그램 소스 내에 존재하는 민감 정보를 소스에서 분리하여 Vault에 안전하게 보관하고 이를 CI 단계에서 안전하게 다시 주입하는 구체적인 과정을 설명하고 있습니다.

목표

하시코프 볼트는 아이덴티티 기반의 비밀, 암호화 관리 시스템입니다. 안전하고 감사 가능하며 제한된 접근을 제공하기 위해 인증(authentication) 및 권한 부여(authorization) 방법으로 제어되는 암호화 서비스를 제공합니다. UI, CLI 또는 HTTP API를 사용하여 토큰, 암호, 인증서, 비밀 보호를 위한 암호화 키 및 민감 정보에 대한 접근을 보호, 저장 및 엄격하게 제어하는 데 사용됩니다

볼트 사용의 핵심은 인증 및 권한 부여입니다. 볼트가 이를 클라이언트에 제공하는 방법을 이해하는 것이 볼트를 구성하고 관리하는 방법을 이해하기 위한 열쇠입니다.

볼트는 인증 방법(auth method)을 사용하여 클라이언트에 인증을 제공합니다.

볼트는 정책(policy)을 사용하여 클라이언트에 권한 제어를 제공합니다.

볼트는 몇 가지 내부 또는 외부 인증 방법을 제공합니다. 외부 방법을 AWS, LDAP, GitHub 등과 같은 신뢰할 수 있는 서드파티 인증자(trusted third-party authenticators)이라고 합니다. 어떤 상황에서는 신뢰할 수 있는 서드파티 인증자를 사용할 수 없으므로 볼트에서는 AppRole이라는 대체 수단을 갖습니다. 신뢰할 수 있는 서드파티 인증자가 있다면 그것을 사용하는 것이 AppRole을 사용하는 것보다는 바람직합니다.

이 가이드에서는 AppRole의 상위 수준 개념을 자세히 설명하고 상위 수준 개념에서 탐색한 권장 패턴에 따라 두 가지 세부 용도를 간략하게 설명합니다. 이 가이드는 또한 이 기능의 안전하지 않은 사용을 방지하는 데 도움이 되는 안티 패턴에 대해 자세히 설명합니다.

AppRole에 익숙하지 않은 경우 AppRole Pull 인증 자습서에서 단계별 지침을 참조하십시오. 또한 더 많은 예를 보려면 AppRole With Terraform & Chef를 참조하십시오.

볼트 모범 사례

이 가이드는 볼트의 두 가지 기본 원칙, 즉 아이덴티티의 폭발 반경과 인증 기간을 모두 제한하는 데 크게 의존합니다.

아이덴티티 폭발 반경(Blast-radius of an identity)

볼트는 아이덴티티 기반 비밀 관리 솔루션으로, 비밀에 대한 접근은 클라이언트의 알려지고 확인된 아이덴티티를 기반으로 합니다. 이 아이덴티티는 볼트에서 식별 가능해야 하고 해당 사용자가 사용하는 비밀에만 접근 가능해야 합니다. 볼트와 비밀의 최종 사용자 사이에 제 3자가 끼여서는 안 되며(never be proxied) 클라이언트는 최종 사용자가 아닌 비밀에 접근할 수 없어야 합니다.

인증 기간

볼트에서 엔터티의 아이덴티티를 확인하면, 볼트는 해당 엔터티에 토큰을 제공합니다. 클라이언트는 인증을 증명하기 위하여 볼트와의 모든 후속 상호 작용에 이 토큰을 사용하므로 이 토큰은 안전하게 처리되고 제한된 수명을 가져야 합니다. 토큰은 접근 권한을 부여한 비밀에 대한 접근이 필요한 동안에만 유효해야 합니다.

전제 조건

  • 고가용성 Vault 클러스터에 필요한 리소스를 프로비저닝하기 위해 Vault용 참조 아키텍처를 따랐습니다.
  • Vault용 배포 안내서에 따라 각 Vault 서버에 Vault를 설치 및 구성했습니다.
  • Vault 클러스터의 보안을 개선하기 위해 Vault용 프로덕션 강화 가이드를 따랐습니다.
  • 금고가 봉인되지 않았습니다. 개봉에 대한 문서를 참조하십시오.

여기에서는 Vault 버전 0.8에 도입된 응답 래핑 토큰을 참조합니다. 따라서 다음 권장 사항을 Vault v0.8 이상에 적용한다고 가정합니다.

용어 사전

  • 인증 - 본인 확인 절차입니다. 종종 AuthN으로 축약됩니다.
  • 권한 부여 - 엔터티가 어떤 수준에서 액세스할 수 있는지 확인하는 프로세스입니다. 종종 AuthZ로 축약됩니다.
  • RoleID - Vault에 인증할 역할에 대한 준 비밀 식별자입니다. 이것을 인증 쌍의 '사용자 이름' 부분으로 생각하십시오.
  • SecretID - Vault에 인증할 역할의 비밀 식별자입니다. 이것을 인증 쌍의 '비밀번호' 부분으로 생각하십시오.
  • AppRole 역할 - 인증을 위한 권한 부여 및 사용 매개변수를 포함하는 Vault에 구성된 역할입니다.

볼트 AppRole 개요

AppRole 인증 방법은 볼트에서 시스템 인증을 위해 제공합니다. AppRole은 유연하게 설계되었기 때문에 구성 방법이 다양합니다. 보안 책임은 다른 볼트 인증 방법의 경우와 같이 신뢰할 수 있는 서드파티가 아니라 구성자에게 있습니다.

AppRole은 신뢰할 수 있는 서드파티 인증자가 아니라 신뢰할 수 있는 브로커 방식입니다. 차이점은 인증에서 신뢰의 책임은 클라이언트와 볼트 간의 인증을 중개하는 안전하게 관리되는 브로커 시스템에 있다는 것입니다.

이 보안의 핵심 원칙은 볼트와의 인증 중계 중에 RoleID와 SecretID가 비밀을 소비해야하는 최종 사용자 시스템에만 항상 함께 있다는 것입니다.

AppRole 인증에는 세 명의 플레이어가 있습니다.

  • 볼트 - 볼트 서비스
  • 브로커 - 인증을 중개하는 신뢰할 수 있고 안전한 시스템
  • 비밀 소비자 - 비밀의 최종 소비자

래핑된 secretID가 있는 CI 파이프라인의 AppRole

이 시나리오에서는, CI에서 비밀로 분류되어 볼트에 저장된 데이터가 필요한 작업을 실행할 필요가 있습니다. CI에서 마스터 노드와 작업자(worker) 노드가 있습니다(예, Jenkins). 작업자 노드는 수명이 짧은 즉석 생성된 컨테이너에서 수행됩니다. 여기에서의 프로세스는 다음과 같아야 합니다.

  1. CI 작업자는 볼트에 인증합니다
  2. 볼트는 인증 토큰을 반환합니다
  3. 작업자는 토큰을 사용하여 생성할 작업의 역할(role)을 위한 래핑(wrapped)된 secretID를 볼트에 요청합니다
  4. 볼트는 래핑된 secretID를 반환합니다
  5. 작업자는 작업 실행자(runner)를 생성하고 래핑된 secretID를 작업에 변수로 전달합니다
  6. 실행자 컨테이너가 볼트에 secretID의 래핑 해제를 요청합니다
  7. 볼트는 SecretID를 반환합니다
  8. 실행자는 RoleID 및 SecretID를 사용하여 볼트에 인증합니다.
  9. 볼트는 요청 받은 비밀을 읽을 수 있는 권한이 포함된 정책의 토큰을 반환합니다
  10. 실행자는 토큰을 사용하여 볼트에서 비밀을 가져옵니다

다음은 해당 프로세스의 더 복잡한 단계에 대한 자세한 설명입니다.

CI 작업자가 볼트에 인증합니다

CI 작업자는 생성할 작업의 AppRole에 대해 래핑된 SecretID를 요청하려면 볼트에 인증해야 합니다. 작업자가 플랫폼 인증 방법을 사용할 수 있다면 작업자는 이를 사용해야 합니다. 그렇지 않다면 유일한 옵션은 다른 방법으로 작업자를 볼트에 미리 인증하는 것입니다.

볼트는 토큰을 반환합니다

작업자의 볼트 토큰은 범위가 제한되어야 하며 래핑된 SecretID 만 얻을 수 있어야 합니다. 이 때문에 작업자는 수명이 긴 볼트 토큰으로 미리 시드 하거나 하드 코딩된 RoleID 및 SecretID를 사용할 수 있습니다. 이는 경미한 위험만 제공하기 때문입니다.

작업자가 가져야 하는 정책은 다음과 같습니다.

 

path "auth/approle/role/+/secret*" {
  capabilities = [ "create", "read", "update" ]
  min_wrapping_ttl = "100s"
  max_wrapping_ttl = "300s"
}

작업자는 래핑된 SecretID를 요청하기 위하여 토큰을 사용합니다

CI 작업자는 이제 래핑된 SecretID를 검색할 수 있어야 합니다. 이 명령은 다음과 같습니다.

vault write -wrap-ttl=120s -f auth/approle/role/my-role/secret-id

작업자는 생성중인 작업의 **역할(role)**만 알고 있으면 됩니다. 위의 예에서 my-role이 그것이지만 이것이 RoleID는 아닙니다.

작업자는 작업 실행자를 생성하고 래핑된 SecretID를 전달합니다

이는 래핑된 토큰을 환경 변수로 전달하여 달성할 수 있습니다. 다음은 Jenkins에서 이 작업을 수행하는 방법의 예입니다.

environment {
   WRAPPED_SID = """$s{sh(
                    returnStdout: true,
                    Script: ‘curl --header "X-Vault-Token: $VAULT_TOKEN"
       --header "X-Vault-Namespace: ${PROJ_NAME}_namespace"
       --header "X-Vault-Wrap-Ttl: 300s"
         $VAULT_ADDR/v1/auth/approle/role/$JOB_NAME/secret-id’
         | jq '.data.secret_id'
                 )}"""
}

실행자는 RoleID와 SecretID를 사용하여 볼트에 인증합니다

실행자는 볼트에 인증하고 정확히 필요한 비밀만 읽을 수 있는 정책을 수신합니다. 정책의 예는 다음과 같습니다.

path "kv/my-role_secrets/*" {
  capabilities = [ "read" ]
}

구현 세부사항

추가 보안 조치로 다음 사항을 염두에 두고 App에 필요한 역할을 생성하십시오.

권장 사항: 최상의 보안을 위해 secret_id_num_uses를 1로 설정하십시오. 또한 접속할 장치의 소스 IP 범위를 제한하기 위해 secret_id_bound_cidrs를 변경하는 것을 고려하십시오.

안티 패턴

볼트의 AppRole 인증 방법을 사용할 때 이러한 안티 패턴을 피하는 것이 좋습니다.

CI 작업자가 비밀을 검색합니다

CI 작업자는 볼트에 인증하고 작업에 대한 비밀을 직접 검색하여 이를 실행자에게 전달할 수 있지만 이는 위에 나열된 모범 사례 중 첫 번째를 위반한 것입니다.

CI 작업자는 많은 다른 유형의 작업을 실행해야 할 수 있으며 그 중 상당수는 비밀이 필요합니다. 이 방법을 사용하는 경우 작업자는 비밀의 소비자가 아니면서도 많은 비밀을 검색할 수 있는 권한(정책)을 가지고 있어야 합니다. 또한 하나의 비밀이 노출된다면, 노출된 비밀과 아이덴티티를 연결 지어서 해당 아이덴티티에 대한 유리 깨기 절차(break-glass procedure)를 시작할 수 없을 것입니다. 그래서 모든 비밀을 노출된 것으로 간주해야 합니다.

CI 작업자가 실행자에게 볼트 토큰을 전달합니다

작업자는 권한을 받아서 볼트에서 RoleID와 SecretID를 검색하고 둘 다 사용하도록 실행자에게 전달할 수도 있습니다. 이렇게 하면 작업자가 모든 비밀을 검색할 수 있는 볼트 권한이 부여되지 않지만 RoleID와 SecretID를 모두 가지고 있으므로 그런 권한이 있는 것과 마찬가지입니다. 이는 모범 사례에 위배됩니다.

CI 작업자가 실행자에게 볼트 토큰을 전달합니다

작업자에게 비밀을 검색할 권한이 있는 하위 토큰을 생성할 수 있는 권한이 부여될 수 있습니다. 이 토큰을 실행자에게 전달하면 실행자는 이 토큰 만으로 비밀을 검색할 수 있습니다. 작업자에게 비밀에 직접적으로 접근할 수 있는 권한이 부여되지는 않았지만 작업자는 이 비밀에 접근할 수 있는 토큰을 알고 있기 때문에 권한이 이미 있는 것과 같습니다. 따라서 모범 사례에 위배됩니다.

보안 고려 사항

신뢰할 수 있는 브로커 상황에서, 브로커(이 경우 Jenkins 작업자)에 대한 보안을 유지해야 하고 브로커는 위험한 시스템으로 취급되어야 합니다. 이는 사용자가 최소한의 권한을 가져야 하고 접근 행위에 대해 면밀히 모니터링하고 감사해야 함을 의미합니다.

또한 볼트 감사 로그는 타임스탬프 이벤트를 제공하므로 다음 두 이벤트에 대한 알림으로 전체 프로세스를 모니터링합니다.

  • AppRole에 대해 래핑된 SecretID가 요청되고 실행 중인 Jenkins 작업이 없는 경우
  • Jenkins 슬레이브가 토큰의 래핑을 풀려고 시도하였지만 토큰이 이미 사용되었기 때문에 볼트가 거부하는 경우

두 경우 모두 신뢰할 수 있는 브로커 워크플로가 손상되었을 가능성이 있으며 이벤트를 조사해야 함을 나타냅니다.

볼트 AppRole 참조

'Vault' 카테고리의 다른 글

Vault HA 구성 with Consul  (0) 2021.08.09
Vault KV Secrets Engine  (0) 2021.07.22
Vault Seal/Unseal  (0) 2021.07.20
Comments