고객 관리 암호화 키(CMEK) 사용 설정

이 주제에서는 Secret Manager에서 고객 관리 암호화 키(CMEK) 지원을 설명합니다.

개요

Secret Manager는 애플리케이션의 민감한 정보를 저장, 관리, 액세스할 수 있는 도구를 제공합니다.

기본적으로 Secret Manager에 저장된 보안 비밀은 Google 기본 암호화로 암호화됩니다. Google 기본 암호화를 사용하면 보안 비밀 페이로드가 영구 스토리지에 작성되기 전에 구성할 필요 없이 Google에서 관리하는 키로 암호화됩니다. Google 기본 암호화는 많은 조직에서 사용되고 있습니다.

더욱 강력한 제어를 원하는 조직의 경우 Secret Manager의 CMEK 지원을 사용하면 Secret Manager의 저장 데이터를 보호하는 Cloud KMS 키를 구성할 수 있습니다. CMEK 키를 일시적으로 중지하거나 영구 삭제하면 이 키로 암호화된 데이터를 복호화할 수 없으므로 액세스할 수 없습니다.

Secret Manager에서 CMEK 작동 방식

Secret Manager는 특정 위치에 있는 영구 스토리지에 보안 비밀 버전을 작성하기 전에 고유한 데이터 암호화 키(DEK)로 데이터를 암호화합니다. 그러면 이 DEK는 Secret Manager 서비스에서 소유한 키 암호화 키(KEK)라는 복제본별 키로 암호화됩니다.

Secret Manager에 CMEK를 사용하는 경우 KEK는 CMEK 키라고 하며 Cloud KMS 내에서 관리하는 대칭 키입니다. CMEK 키는 암호화하는 보안 비밀 버전 복제본과 동일한 GCP 위치에 있어야 합니다.

이 가이드에서는 CMEK를 사용하도록 Secret Manager를 구성하는 방법을 설명합니다. CMEK를 사용 설정하는 시기와 이유를 포함한 일반적인 CMEK에 대한 자세한 내용은 Cloud Key Management Service 문서를 참조하세요.

제한사항

Secret Manager v1 API 및 gCloud에서만 CMEK를 사용할 수 있습니다.

시작하기 전에

모든 리소스를 동일한 프로젝트에 저장하거나 보안 비밀과 키를 별도의 프로젝트에 저장할 수 있습니다. 이 결정을 더욱 잘 이해하려면 Cloud KMS 업무분장을 참조하세요.

다음 기본 요건을 완료하여 Secret Manager와 Cloud KMS를 설정합니다.

  • Secret Manager:

    • 프로젝트를 만들거나 기존 프로젝트를 사용하여 Secret Manager 리소스를 보존합니다.
    • 필요한 경우 Secret Manager 빠른 시작의 Secret Manager 구성 섹션의 단계를 완료합니다.
  • Cloud KMS:

    • 프로젝트를 만들거나 기존 프로젝트를 사용하여 Cloud KMS 리소스를 보존합니다.
    • 필요한 경우 Cloud KMS API를 사용 설정합니다.

다음 변수를 Secret Manager 및 Cloud KMS 프로젝트의 프로젝트 ID로 설정합니다.

명령줄

$ export SM_PROJECT_ID="..."
$ export KMS_PROJECT_ID="..."

Google Cloud에 인증합니다.

gcloud

$ gcloud auth login

서비스 계정 만들기

고객 관리 암호화 키가 필요한 각 프로젝트에 서비스 계정을 만들어야 합니다. 현재는 gcloud 명령줄 도구 명령어를 사용해서만 고객 관리 암호화 키에 필요한 서비스 계정 유형을 만들 수 있습니다.

gcloud 명령줄 도구로 서비스 계정을 만들려면 다음 명령어를 실행합니다.

gcloud

$ gcloud beta services identity create \
    --service "secretmanager.googleapis.com" \
    --project "${SM_PROJECT_ID}"

이전 명령어는 다음 형식을 사용하여 서비스 계정 이름을 반환합니다.

service-[PROJECT_NUMBER]@gcp-sa-secretmanager.iam.gserviceaccount.com

이 서비스 계정에 보안 비밀을 암호화하고 복호화하는 데 사용되는 CMEK Cloud KMS 키에 대한 액세스 권한을 부여합니다.

서비스 계정 이름을 환경 변수로 저장합니다.

명령줄

# This is from the output of the command above
$ export SM_SERVICE_ACCOUNT="service-...."

이 절차를 따를 때는 항상 Secret Manager 프로젝트, Cloud KMS 프로젝트, Secret Manager 서비스 계정의 환경 변수를 설정해야 합니다.

자동 복제 기능이 있는 CMEK

이 섹션에서는 자동 복제 정책을 통해 구성된 보안 비밀을 설명합니다.

자동 복제 정책을 사용하는 보안 비밀의 경우 CMEK 키는 전역 Cloud KMS 멀티 리전에 있어야 합니다.

전역 Cloud KMS 리전에서 대칭 Cloud KMS 키를 만들거나 기존 키를 사용합니다. 이 예시에서는 secret-manager-cmek라는 새 키링을 만든 후 my-cmek-key라는 새 키를 만듭니다.

gcloud

$ gcloud kms keyrings create "secret-manager-cmek" \
    --project "${KMS_PROJECT_ID}" \
    --location "global"

$ gcloud kms keys create "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "global" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

키의 리소스 이름을 가져와 환경 변수로 설정합니다.

명령줄

$ export KMS_KEY_NAME="projects/${KMS_PROJECT_ID}/locations/global/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key"

CMEK 키를 사용하여 서비스 계정에 암호화 및 복호화할 수 있는 Secret Manager 액세스 권한을 부여합니다. 이 명령어는 my-cmek-key Cloud KMS 키에 대한 Cloud KMS 암호화/복호화 역할(roles/cloudkms.cryptoKeyEncrypterDecrypter)을 서비스 계정에 부여합니다.

gcloud

$ gcloud kms keys add-iam-policy-binding "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "global" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

자동 복제를 사용하여 보안 비밀을 만듭니다. CMEK 키의 리소스 이름은 보안 비밀에 메타데이터로 저장됩니다.

gcloud

$ gcloud beta secrets create my-secret \
    --replication-policy "automatic" \
    --kms-key-name "${KMS_KEY_NAME}" \
    --project "${SM_PROJECT_ID}"

API

replication.automatic.customerManagedEncryption.kmsKeyName 값을 CMEK 키의 리소스 이름으로 설정합니다.

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets?secretId=my-secret" \
    --request "POST" \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @- <<EOF
{
  "replication":{
    "automatic":{
      "customerManagedEncryption":{
        "kmsKeyName": "${KMS_KEY_NAME}"
      }
    }
  }
}
EOF

이제 보안 비밀에 보안 비밀 버전이 생성될 때마다 서비스 계정에 CMEK 키에 대한 액세스 권한이 있는 한 영구 스토리지에 작성하기 전에 보안 비밀 버전의 페이로드가 키를 통해 자동으로 암호화합니다. 서비스 계정에 액세스 권한이 없거나 키를 사용할 수 없게 된 경우 새로운 보안 비밀 버전을 만들거나 기존 보안 비밀에 액세스하려고 하면 오류가 반환됩니다.

새 보안 비밀 버전을 추가합니다. Cloud KMS 키의 리소스 이름을 지정하지 않습니다. 보안 비밀의 메타데이터에서 읽습니다.

gcloud

$ echo -n "abcd1234" | gcloud beta secrets versions add "my-secret" \
    --project "${SM_PROJECT_ID}" \
    --data-file -

호출자에게 CMEK 키를 사용할 수 있는 직접 액세스 권한이 없더라도 보안 비밀 버전이 생성됩니다. 호출자가 아닌 Secret Manager의 서비스 계정은 보안 비밀을 읽거나 쓸 때 암호화하고 복호화해야 합니다.

마찬가지로 보안 비밀에 액세스하기 위해 CMEK 키에 직접 액세스할 필요는 없습니다. 서비스 계정은 키에 액세스하고 개발자를 대신하여 보안 비밀을 암호화하거나 복호화합니다.

방금 만든 보안 비밀 버전에 액세스합니다.

gcloud

$ gcloud beta secrets versions access latest \
    --project "${SM_PROJECT_ID}" \
    --secret "my-secret"

CMEK 구성 업데이트

global Cloud KMS 멀티 리전에서 새 대칭 KMS 키를 만듭니다.

gcloud

$ gcloud kms keys create "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "global" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

새 CMEK 키를 사용하여 서비스 계정에 암호화 및 복호화할 수 있는 Secret Manager 액세스 권한을 부여합니다. 이 명령어는 my-other-key Cloud KMS 키에 대한 Cloud KMS 암호화/복호화 역할(roles/cloudkms.cryptoKeyEncrypterDecrypter)을 서비스 계정에 부여합니다.

gcloud

$ gcloud kms keys add-iam-policy-binding "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "global" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

새 Cloud KMS 키 리소스 이름으로 보안 비밀의 복제를 업데이트하여 보안 비밀의 CMEK 구성을 수정합니다.

gcloud

$ gcloud beta secrets replication update my-secret \
    --set-kms-key="projects/${KMS_PROJECT_ID}/locations/global/keyRings/secret-manager-cmek/cryptoKeys/my-other-key" \
    --project "${SM_PROJECT_ID}"

API

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets/my-secret?updateMask=replication" \
    --request "PATCH" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --header "Content-Type: application/json" \
    --data-binary @- <<EOF
{
  "replication": {
    "automatic":{
      "customerManagedEncryption":{
        "kmsKeyName": "projects/${KMS_PROJECT_ID}/locations/global/keyRings/secret-manager-cmek/cryptoKeys/my-other-key"
      }
    }
  }
}
EOF

사용자 관리 복제 기능이 있는 CMEK

이 섹션에서는 사용자 관리 복제 정책으로 구성된 보안 비밀을 설명합니다. 사용자 관리 복제 정책으로 보안 비밀이 저장되는 GCP 위치를 제어합니다. 모든 GCP 위치에서는 항상 보안 비밀에 액세스할 수 있습니다.

사용자 관리 복제 정책이 적용된 보안 비밀에서는 보안 비밀 버전이 저장되는 위치에 정확히 매핑되는 Cloud KMS 키를 사용해야 합니다. 이 가이드에서는 us-east1, us-central1 등 두 위치에 보안 비밀을 저장합니다. 보안 비밀 액세스 요청은 다음 위치 중 하나로 라우팅됩니다.

두 리전 각각에서 암호화를 위해 키링과 Cloud KMS 키를 만들거나 기존 키를 사용합니다. 이 예시에서는 secret-manager-cmek라는 새 키링을 만든 후 각 리전에 my-cmek-key라는 키를 만듭니다.

gcloud

# us-east1
$ gcloud kms keyrings create "secret-manager-cmek" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-east1"

$ gcloud kms keys create "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-east1" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

# us-central1
$ gcloud kms keyrings create "secret-manager-cmek" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-central1"

$ gcloud kms keys create "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-central1" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

개별적으로 CMEK 키 각각에 또는 프로젝트의 모든 키에 Cloud KMS 암호화/복호화 역할(roles/cloudkms.cryptoKeyEncrypterDecrypter)을 부여하여 서비스 계정에 CMEK 키를 사용해 암호화 및 복호화할 수 있는 Secret Manager 권한을 부여합니다.

gcloud

# us-east1
$ gcloud kms keys add-iam-policy-binding "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-east1" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

# us-central1
$ gcloud kms keys add-iam-policy-binding "my-cmek-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-central1" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

사용자 관리 복제로 보안 비밀을 사용 설정한 CMEK를 만듭니다. CMEK 키의 리소스 이름은 보안 비밀에 메타데이터로 저장됩니다.

gcloud

$ cat <<EOF > replication-policy.json
{
  "userManaged":{
    "replicas":[
      {
        "location":"us-east1",
        "customerManagedEncryption":{
          "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-east1/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key"
        }
      },
      {
        "location":"us-central1",
        "customerManagedEncryption":{
          "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-central1/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key"
        }
      }
    ]
  }
}
EOF

$ gcloud beta secrets create my-ummr-secret \
    --replication-policy-file replication-policy.json \
    --project "${SM_PROJECT_ID}"

API

replication.userManaged.replicas.customerManagedEncryption.kmsKeyName 값을 CMEK 키의 리소스 이름으로 설정합니다.

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets?secretId=my-ummr-secret" \
--request "POST" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @- <<EOF
{
  "replication":{
    "userManaged":{
      "replicas":[
        {
          "location":"us-east1",
          "customerManagedEncryption":{
            "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-east1/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key"
          }
        },
        {
          "location":"us-central1",
          "customerManagedEncryption":{
            "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-central1/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key"
          }
        }
      ]
    }
  }
}
EOF

이제 보안 비밀에 보안 비밀 버전이 생성될 때마다 서비스 계정에 CMEK 키에 대한 액세스 권한이 있는 한 영구 스토리지에 작성하기 전에 보안 비밀 버전의 페이로드가 키를 통해 자동으로 암호화합니다. 서비스 계정에 액세스 권한이 없거나 키를 사용할 수 없게 된 경우 새로운 보안 비밀 버전을 만들거나 기존 보안 비밀에 액세스하려고 하면 오류가 반환됩니다.

새 보안 비밀 버전을 추가합니다. Cloud KMS 키의 리소스 이름을 지정하지 않습니다. 보안 비밀의 메타데이터에서 읽습니다.

gcloud

$ echo -n "abcd1234" | gcloud beta secrets versions add "my-ummr-secret" \
    --project "${SM_PROJECT_ID}" \
    --data-file -

호출자에게 CMEK 키를 사용할 수 있는 직접 액세스 권한이 없더라도 보안 비밀 버전이 생성됩니다. 호출자가 아닌 Secret Manager의 서비스 계정은 보안 비밀을 읽거나 쓸 때 암호화하고 복호화해야 합니다.

마찬가지로 보안 비밀에 액세스하기 위해 CMEK 키에 직접 액세스할 필요는 없습니다. 서비스 계정은 키에 액세스하고 개발자를 대신하여 보안 비밀을 암호화하거나 복호화합니다.

방금 만든 보안 비밀 버전에 액세스합니다.

gcloud

$ gcloud beta secrets versions access latest \
    --project "${SM_PROJECT_ID}" \
    --secret "my-ummr-secret"

CMEK 구성 업데이트

보안 비밀과 동일한 리전에 새 대칭 KMS 키 두 개를 만듭니다.

gcloud

# us-east1
$ gcloud kms keys create "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-east1" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

# us-central1
$ gcloud kms keys create "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-central1" \
    --keyring "secret-manager-cmek" \
    --purpose "encryption"

새 CMEK 키를 사용하여 서비스 계정에 암호화 및 복호화할 수 있는 Secret Manager 액세스 권한을 부여합니다. 이 명령어는 my-other-key Cloud KMS 키에 대한 Cloud KMS 암호화/복호화 역할(roles/cloudkms.cryptoKeyEncrypterDecrypter)을 서비스 계정에 부여합니다.

gcloud

# us-east1
$ gcloud kms keys add-iam-policy-binding "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-east1" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

# us-central1
$ gcloud kms keys add-iam-policy-binding "my-other-key" \
    --project "${KMS_PROJECT_ID}" \
    --location "us-central1" \
    --keyring "secret-manager-cmek" \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"

새 Cloud KMS 키 리소스 이름으로 보안 비밀의 복제를 업데이트하여 보안 비밀의 CMEK 구성을 수정합니다.

gcloud

$ gcloud beta secrets replication update my-ummr-secret \
    --set-kms-key="projects/${KMS_PROJECT_ID}/locations/us-east1/keyRings/secret-manager-cmek/cryptoKeys/my-other-key" \
    --location=us-east1 \
    --project "${SM_PROJECT_ID}"

$ gcloud beta secrets replication update my-ummr-secret \
    --set-kms-key="projects/${KMS_PROJECT_ID}/locations/us-central1/keyRings/secret-manager-cmek/cryptoKeys/my-other-key" \
    --location=us-central1 \
    --project "${SM_PROJECT_ID}"

보안 비밀의 키 여러 개를 동시에 업데이트하려면 파일을 통해 복제 정책을 가져오고 설정하면 됩니다.

gcloud

$ gcloud beta secrets replication get my-ummr-secret --project "${SM_PROJECT_ID}" --format=json > replication-policy.json

# update the file to reflect desired CMEK configuration
$ edit replication-policy json

$ gcloud beta secrets replication set my-ummr-secret \
    --replication-policy-file=replication-policy.json \
    --project "${SM_PROJECT_ID}"

API

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets/my-ummr-secret?updateMask=replication" \
    --request "PATCH" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --header "Content-Type: application/json" \
    --data-binary @- <<EOF
{
  "replication":{
    "userManaged":{
      "replicas":[
        {
          "location":"us-east1",
          "customerManagedEncryption":{
            "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-east1/keyRings/secret-manager-cmek/cryptoKeys/my-other-key"
          }
        },
        {
          "location":"us-central1",
          "customerManagedEncryption":{
            "kmsKeyName":"projects/${KMS_PROJECT_ID}/locations/us-central1/keyRings/secret-manager-cmek/cryptoKeys/my-other-key"
          }
        }]
      }
    }
  }
EOF

보안 비밀 버전 CMEK 구성 보기

보안 비밀 버전이 사용 설정된 CMEK이고 CMEK 키 버전의 리소스 이름인지 여부를 비롯한 보안 비밀 버전의 메타데이터를 검사하려면 메타데이터를 봅니다.

gcloud

$ gcloud beta secrets versions describe latest --secret my-secret --project "${SM_PROJECT_ID}"

API

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets/my-secret/versions/latest" \
    --request "GET" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --header "Content-Type: application/json"

그러면 보안 비밀 버전을 암호화하는 데 사용되는 키 버전의 전체 Cloud KMS 리소스 이름이 반환됩니다.

{
  "name": "projects/[PROJECT_NUMBER]/secrets/my-secret/versions/1",
  "createTime": "2020-07-...",
  "state": "ENABLED",
  "replicationStatus": {
    "automatic": {
      "customerManagedEncryption": {
        "kmsKeyVersionName": "projects/[KMS_PROJECT]/locations/global/keyRings/secret-manager-cmek/cryptoKeys/my-cmek-key/cryptoKeyVersions/1"
      }
    }
  }
}

CMEK 중지

복제 정책을 업데이트하여 보안 비밀에서 CMEK 구성을 삭제합니다.

gcloud

$ gcloud beta secrets replication update my-secret --remove-cmek --project "${SM_PROJECT_ID}"

API

$ curl "https://secretmanager.googleapis.com/v1/projects/${SM_PROJECT_ID}/secrets/my-secret?updateMask=replication" \
    --request "PATCH" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --header "Content-Type: application/json" \
    --data-binary @- <<EOF
{
  "replication":{
    "automatic":{}
  }
}
EOF

다음 단계

  • CMEK 자세히 알아보기