타사 ID를 증명하는 인증서 발급

이 튜토리얼에서는 ID 리플렉션워크로드 아이덴티티 풀을 사용하여 서드 파티 ID를 증명하는 인증서를 발급하는 방법을 보여줍니다.

ID 리플렉션을 사용하여 인증서 요청자의 확인된 ID와 일치하는 인증서를 만들 수 있습니다. ID 리플렉션을 사용하면 권한이 없는 인증서 요청자가 사용자 인증 정보의 ID에 해당하는 주체 대체 이름(SAN)이 있는 인증서만 요청하도록 제한할 수 있습니다.

목표

이 튜토리얼에서는 워크로드 아이덴티티 풀에서 CA Service를 사용하여 서드 파티 ID를 제휴하고 이 ID를 증명하는 인증서를 가져오는 방법에 대한 정보를 제공합니다.

시작하기 전에

시작하기 전에 다음 개념을 이해해야 합니다.

  • 워크로드 아이덴티티 풀: 워크로드 아이덴티티 풀을 사용하면 서드 파티 ID 공급업체를 관리할 수 있습니다. 자세한 내용은 워크로드 아이덴티티 풀 및 공급업체 관리를 참조하세요.
  • 워크로드 아이덴티티 제휴: 워크로드 아이덴티티 제휴는 워크로드 아이덴티티 풀을 활용하여 서드 파티 ID에 Google Cloud 서비스에 대한 액세스 권한을 부여합니다. 자세한 내용은 워크로드 아이덴티티 제휴를 참조하세요.
  • 보안 토큰 서비스(STS): 보안 토큰 서비스를 사용하면 서드 파티 사용자 인증 정보를 퍼스트 파티Google Cloud) 토큰으로 교환할 수 있습니다. 자세한 내용은 보안 토큰 서비스를 참조하세요.
  • ID 리플렉션: ID 리플렉션 기능을 사용하면 인증서 요청자의 확인된 ID를 요청된 인증서로 이동할 수 있습니다. 자세한 내용은 ID 리플렉션을 참조하세요.

다음 IAM 역할이 있는지 확인합니다.

  • 인증 기관(CA) 및 CA 풀을 관리하고 인증서를 요청하려면 CA Service 작업 관리자(privateca.caManager) 역할이 있어야 합니다. CA Service의 IAM역할에 대한 자세한 내용은 IAM으로 액세스 제어를 참조하세요.
  • 워크로드 아이덴티티 풀 및 공급업체를 관리하려면 워크로드 아이덴티티 풀 관리자(iam.workloadIdentityPoolAdmin) 역할이 있어야 합니다.
  • 서비스 계정을 만들려면 서비스 계정 관리자(iam.serviceAccountAdmin) 역할이 있어야 합니다.

IAM 역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요. Google 계정, 서비스 계정, Google 그룹, Google Workspace 계정 또는 Cloud ID 도메인에 필요한 IAM 역할을 부여할 수 있습니다.

워크로드 아이덴티티 풀 및 공급업체 설정

이 튜토리얼에서는 서비스 계정과 결합된 Google OpenID Connect(OIDC) 제공업체를 서드 파티 ID로 사용하는 방법을 설명합니다. Google 계정 OIDC 제공업체는 서드 파티 ID 공급업체(IDP) 역할을 하며 Google Cloud 서비스 계정은 이 IDP에서 어설션된 샘플 서드 파티 ID입니다.

워크로드 아이덴티티 풀은 Microsoft Azure/온프레미스 Active Directory, AWS, SAML 기반 ID 공급업체를 비롯한 다양한 ID 공급업체를 지원합니다.

워크로드 아이덴티티 풀 및 공급업체를 설정하려면 다음을 수행합니다. 1. 신뢰할 수 있는 제휴 ID 집합을 나타내기 위해 워크로드 아이덴티티 풀을 만듭니다.

```
gcloud iam workload-identity-pools create IDENTITY_POOL_ID --location global --display-name "tutorial-wip"
```

Replace the following:

- <var>IDENTITY_POOL_ID</var>: The unique identifier of the new workload
  identity pool.
  1. 서드 파티 ID 공급업체의 워크로드 아이덴티티 풀 공급업체를 만듭니다.

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID --location global --workload-identity-pool IDENTITY_POOL_ID --display-name "tutorial-oidc" --attribute-mapping "google.subject=assertion.sub" --issuer-uri="https://accounts.google.com"
    

    다음을 바꿉니다.

    • PROVIDER_ID: 워크로드 아이덴티티 풀에서 만들려는 ID 공급업체의 고유 식별자입니다.

    사용 사례에 맞게 다음 플래그를 맞춤설정할 수 있습니다.

    • attribute-mapping: 이 플래그는 서드 파티 클레임과 Google 주 구성원 클레임 google.subject 간의 매핑을 설정합니다. google.subjectCEL 표현식을 사용하여 모든 클레임 또는 클레임 조합에 설정할 수 있는 필수 매핑입니다. 자세한 내용은 속성 매핑 및 조건 정의를 참조하세요.
    • issuer-uri: OIDC 제공업체의 경우 이 플래그는 서드 파티 토큰 확인을 위해 Google에서 연결하는 공개적으로 액세스 가능한 엔드포인트입니다. 자세한 내용은 외부 ID 공급업체 준비를 참조하세요.

    워크로드 아이덴티티 공급업체 설정에 대한 자세한 내용은 워크로드 아이덴티티 제휴 구성을 참조하세요.

CA 풀 및 발급 CA 만들기

이 섹션에서는 CA 풀을 만들고 루트 CA를 추가하는 방법을 설명합니다. 이 CA 풀을 사용하여 ID가 리플렉션된 인증서를 발급할 수 있습니다. 기존 CA 풀과 CA를 사용하려는 경우에는 이 섹션을 건너뛰면 됩니다.

루트 CA 대신 하위 CA를 만들 수도 있습니다. 루트 CA를 만들면 절차를 줄일 수 있습니다.

  1. DevOps 등급에서 CA 풀을 만듭니다.

    gcloud privateca pools create CA_POOL_ID --location LOCATION --tier devops
    

    다음을 바꿉니다.

    • CA_POOL_ID - 인증서를 발급하는 CA Service CA 풀의 ID입니다.
    • LOCATION - CA 풀의 위치입니다.

    CA 풀을 만드는 방법에 대한 자세한 내용은 CA 풀 만들기를 참조하세요.

  2. 루트 CA를 만듭니다.

    gcloud privateca roots create CA_ID --pool CA_POOL_ID  --location LOCATION --subject "CN=test,O=test-org"
    

    다음을 바꿉니다.

    • CA_ID - 인증서를 발급하는 인증 기관의 ID입니다.
    • CA_POOL_ID - 인증서를 발급하는 CA Service CA 풀의 ID입니다.
    • LOCATION - CA 풀의 위치입니다.

    루트 CA를 만드는 방법에 대한 자세한 내용은 루트 CA 만들기를 참조하세요.

  3. 워크로드 아이덴티티 풀에서 제휴한 ID를 사용 설정하여 CA 풀에서 인증서를 발급합니다. ID 리플렉션을 위해서는 CreateCertificate 요청자에 CA Service 워크로드 인증서 요청자(roles/privateca.workloadCertificateRequester) IAM 역할이 필요합니다.

    워크로드 아이덴티티 풀 주 구성원을 단일 주체부터 여러 공급업체의 풀에 있는 모든 ID에 이르기까지 세분화하여 나타낼 수 있습니다. 자세한 내용은 사용 사례에 가장 적합한 사용 가능한 주 구성원 또는 주 구성원 집합(Google Cloud CLI 탭 사용)을 참조하세요.

    gcloud privateca pools add-iam-policy-binding CA_POOL_ID --location LOCATION --role roles/privateca.workloadCertificateRequester --member "principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/*"
    

    다음을 바꿉니다.

    • PROJECT_NUMBER: 워크로드 아이덴티티 풀을 만든 프로젝트의 프로젝트 번호입니다.

서드 파티 ID를 나타내는 서비스 계정 만들기

다음 절차에서는 서비스 계정이 서드 파티를 나타낸다고 가정합니다. 이 섹션에서는 GenerateIdToken IAM 엔드포인트를 사용하여 OIDC 토큰 형식으로 서드 파티 ID를 가져오는 방법을 보여줍니다. 사용 사례에 따라 선택한 서드 파티 ID 토큰을 가져오는 데 다른 단계가 필요할 수도 있습니다.

gcloud iam service-accounts create SERVICE_ACCOUNT

다음을 바꿉니다.

  • SERVICE_ACCOUNT - 서드 파티 ID를 나타내는 서비스 계정의 ID입니다.

서드 파티 ID를 증명하는 인증서 발급

시작하기 전 서비스 계정 토큰 생성자(roles/iam.serviceAccountTokenCreator) IAM 역할이 있는지 확인합니다. GenerateIdToken API를 호출하려면 이 IAM 역할이 필요합니다.

서드 파티 ID를 증명하는 인증서를 받으려면 다음을 수행하세요.

  1. 서드 파티 ID 공급업체에서 서드 파티 ID 토큰을 가져옵니다.

    curl

    export ID_TOKEN=`curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;print(json.load(sys.stdin)['token'])"`
    

    다음을 바꿉니다.

    • PROJECT_ID - 리소스를 만들 프로젝트의 Google Cloud 프로젝트 ID입니다.

    클라이언트 라이브러리

    프로그래매틱 방식으로 서드 파티 토큰에 액세스하려면 파일 소스 사용자 인증 정보 또는 URL 소스 사용자 인증 정보에서 토큰을 가져오면 됩니다. 자세한 내용은 클라이언트 라이브러리, gcloud CLI 또는 Terraform을 사용하여 인증을 참조하세요. 이 튜토리얼에서는 파일 소스 사용자 인증 정보 워크플로를 따릅니다.

    인증서 요청자가 읽을 수 있는 경로에 사용자 인증 정보를 로드합니다.

    curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;       print(json.load(sys.stdin)['token']) > /tmp/oidc_token.txt
    

    다음을 바꿉니다.

    • PROJECT_ID: 리소스를 만들 프로젝트의 프로젝트 ID입니다.
  2. STS token 엔드포인트를 사용하여 서드 파티 토큰을 제휴 OAuth 토큰으로 교환합니다.

    curl

    export STS_TOKEN=`curl -L -X POST 'https://sts.googleapis.com/v1/token' -H 'Content-Type: application/json' \
    -d '{
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
        "scope": "https://www.googleapis.com/auth/cloud-platform",
        "subject_token": "'$ID_TOKEN'",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt"
    }' | python3 -c "import sys;import json; print(json.load(sys.stdin)['access_token'])"`
    

    클라이언트 라이브러리

    1. 인증서 요청 코드가 토큰 교환을 수행하기 위해 읽을 수 있는 oidc_token.txt라는 사용자 인증 정보 구성 파일을 만듭니다.
    gcloud iam workload-identity-pools create-cred-config projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID --output-file=/tmp/cred_config.json --credential-source-file=/tmp/oidc_token.txt
    
    1. oidc_token.txt 파일을 읽고 클라이언트 라이브러리에서 승인 메커니즘을 설정합니다.

    python

    import json
    
    from google.auth import identity_pool
    
    with open('/tmp/cred_config.json', 'r') as f:
      json_config_info = json.loads(f.read())
    credentials = identity_pool.Credentials.from_info(json_config_info)
    scoped_credentials = credentials.with_scopes(
        ['https://www.googleapis.com/auth/cloud-platform'])
    
  3. REFLECTED_SPIFFE 주체 요청 모드를 사용하여 CA Service에 요청을 수행합니다.

    curl

    1. 선택사항: CSR이 없으면 다음 명령어를 실행하여 CSR을 만듭니다.

      export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
      
    2. CSR, 수명, 리플렉션된 주체 요청 모드로 인증서를 요청합니다.

      curl -H "Authorization: Bearer $(echo $STS_TOKEN)" https://privateca.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/caPools/CA_POOL_ID/certificates\?alt\=json  -X POST -H "Content-Type: application/json" -H 'Accept: application/json' --data '{"lifetime": "100s", "pemCsr": "'$TUTORIAL_CSR'", "subjectMode": "REFLECTED_SPIFFE"}'
      

    클라이언트 라이브러리

    퍼스트 파티 토큰을 CA Service로 전달하려면 사용자 인증 정보 클라이언트를 만들어야 합니다. 그런 다음 이 사용자 인증 정보 클라이언트를 사용하여 인증서를 요청하면 됩니다.

    1. 사용자 인증 정보 CA Service 클라이언트를 시작합니다.

      python

      caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
      
    2. 인증서를 요청합니다.

      Python

      CA Service에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

      import google.cloud.security.privateca_v1 as privateca_v1
      from google.protobuf import duration_pb2
      
      def create_certificate(
          project_id: str,
          location: str,
          ca_pool_name: str,
          ca_name: str,
          certificate_name: str,
          common_name: str,
          domain_name: str,
          certificate_lifetime: int,
          public_key_bytes: bytes,
      ) -> None:
          """
          Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
          The key used to sign the certificate is created by the Cloud KMS.
      
          Args:
              project_id: project ID or project number of the Cloud project you want to use.
              location: location you want to use. For a list of locations, see: https://cloud.google.com/certificate-authority-service/docs/locations.
              ca_pool_name: set a unique name for the CA pool.
              ca_name: the name of the certificate authority which issues the certificate.
              certificate_name: set a unique name for the certificate.
              common_name: a title for your certificate.
              domain_name: fully qualified domain name for your certificate.
              certificate_lifetime: the validity of the certificate in seconds.
              public_key_bytes: public key used in signing the certificates.
          """
      
          caServiceClient = privateca_v1.CertificateAuthorityServiceClient()
      
          # The public key used to sign the certificate can be generated using any crypto library/framework.
          # Also you can use Cloud KMS to retrieve an already created public key.
          # For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key.
      
          # Set the Public Key and its format.
          public_key = privateca_v1.PublicKey(
              key=public_key_bytes,
              format_=privateca_v1.PublicKey.KeyFormat.PEM,
          )
      
          subject_config = privateca_v1.CertificateConfig.SubjectConfig(
              subject=privateca_v1.Subject(common_name=common_name),
              subject_alt_name=privateca_v1.SubjectAltNames(dns_names=[domain_name]),
          )
      
          # Set the X.509 fields required for the certificate.
          x509_parameters = privateca_v1.X509Parameters(
              key_usage=privateca_v1.KeyUsage(
                  base_key_usage=privateca_v1.KeyUsage.KeyUsageOptions(
                      digital_signature=True,
                      key_encipherment=True,
                  ),
                  extended_key_usage=privateca_v1.KeyUsage.ExtendedKeyUsageOptions(
                      server_auth=True,
                      client_auth=True,
                  ),
              ),
          )
      
          # Create certificate.
          certificate = privateca_v1.Certificate(
              config=privateca_v1.CertificateConfig(
                  public_key=public_key,
                  subject_config=subject_config,
                  x509_config=x509_parameters,
              ),
              lifetime=duration_pb2.Duration(seconds=certificate_lifetime),
          )
      
          # Create the Certificate Request.
          request = privateca_v1.CreateCertificateRequest(
              parent=caServiceClient.ca_pool_path(project_id, location, ca_pool_name),
              certificate_id=certificate_name,
              certificate=certificate,
              issuing_certificate_authority_id=ca_name,
          )
          result = caServiceClient.create_certificate(request=request)
      
          print("Certificate creation result:", result)
      
      

    3. 인증서를 확인합니다. 인증서에 단일 URI SAN이 포함된 주체가 있어야 합니다. ID를 증명하는 SAN은 다음과 같은 형식입니다.

      spiffe://IDENTITY_POOL_ID.PROJECT_NUMBER.global.workload.id.goog/subject/<oidc_subject_number>
      

      다음과 같이 바꿉니다.

      • IDENTITY_POOL_ID: 워크로드 아이덴티티 풀의 고유 식별자입니다.
      • PROJECT_NUMBER: 워크로드 아이덴티티 풀을 만든 프로젝트의 프로젝트 번호입니다.

삭제

이 문서에서 만든 CA Service 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 Google Cloud CLI를 사용하여 다음 작업을 수행합니다.

  1. 생성한 CA를 삭제합니다.

    1. CA를 중지합니다.

      gcloud privateca roots disable CA_ID --pool CA_POOL_ID  --location LOCATION
      

      다음과 같이 바꿉니다.

      • CA_ID: CA의 고유 식별자입니다.
      • CA_POOL_ID: CA 풀의 고유 식별자입니다.
      • LOCATION: CA 풀의 위치입니다.
    2. CA를 삭제합니다.

      gcloud privateca roots delete CA_ID --pool CA_POOL_ID  --location LOCATION --ignore-active-certificates
      

      다음과 같이 바꿉니다.

      • CA_ID: CA의 고유 식별자입니다.
      • CA_POOL_ID: CA 풀의 고유 식별자입니다.
      • LOCATION: CA 풀의 위치입니다.
  2. 생성한 CA 풀을 삭제합니다.

    gcloud privateca pools delete CA_POOL_ID --location LOCATION
    

    다음과 같이 바꿉니다.

    • CA_POOL_ID: CA 풀의 고유 식별자입니다.
    • LOCATION: CA 풀의 위치입니다.

    gcloud privateca pools delete 명령어에 대한 자세한 내용은 gcloud privateca pools delete를 참조하세요.

  3. 자신이 만든 워크로드 아이덴티티 풀을 삭제합니다.

    gcloud iam workload-identity-pools delete IDENTITY_POOL_ID --location global
    

    다음과 같이 바꿉니다.

    • IDENTITY_POOL_ID: 워크로드 아이덴티티 풀의 고유 식별자입니다.
  4. 생성한 서비스 계정을 삭제합니다.

    gcloud iam service-accounts delete SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
    

    다음과 같이 바꿉니다.

    • SERVICE_ACCOUNT: 워크로드 아이덴티티 풀의 고유 식별자입니다.
    • PROJECT_ID: 서비스 계정을 소유하는 프로젝트입니다.

CA Service 워크로드 인증서 요청자(privateca.workloadCertificateRequester) IAM 역할은 발급된 인증서의 주체를 요청자의 ID로만 제한합니다. ID 리플렉션 기능을 사용하는 사용자 또는 워크로드에 CA Service 워크로드 인증서 요청자(privateca.workloadCertificateRequester) IAM 역할만 부여되었는지 확인합니다. 최소 권한의 원칙을 따르려면 CA Service 인증서 요청자(privateca.certificateRequester) IAM 역할을 부여하지 말아야 합니다.

다음 단계