증명 만들기

이 페이지에서는 Binary Authorization 증명을 만드는 단계를 설명합니다.

단일 증명을 사용하면 Artifact Registry, Container Registry, 외부 컨테이너 레지스트리와 같이 여러 개의 서로 다른 위치 또는 서로 다른 레지스트리에 저장되는 동일한 이미지를 확인할 수 있습니다.

Binary Authorization은 배포 시에 증명자를 사용하여 증명을 확인합니다.

Binary Authorization 및 Google Kubernetes Engine(GKE)을 사용한 증명 기반 시행을 설명하는 엔드 투 엔드 튜토리얼은 명령줄 도구를 사용하여 시작하기 또는 Google Cloud Console을 사용하여 시작하기를 참조하세요.

다른 모든 플랫폼에 대한 엔드 투 엔드 지침은 플랫폼 설정을 참조하고 플랫폼을 선택합니다.

시작하기 전에

증명 개요는 증명을 만들기 전에 완료하는 단계를 제공합니다.

환경 설정

  1. 프로젝트 ID를 지정합니다.

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    다음을 바꿉니다.

    • ATTESTOR_PROJECT_ID: 증명자를 저장할 프로젝트의 이름입니다.
    • ATTESTATION_PROJECT_ID: 증명을 저장할 프로젝트의 이름입니다.

    증명자와 동일한 프로젝트에 증명을 만들려면 두 변수 모두 동일한 프로젝트 ID를 사용합니다. 여러 프로젝트를 사용하여 업무를 분리하는 방법을 설명하는 엔드 투 엔드 튜토리얼은 다중 프로젝트 설정을 참조하세요.

  2. 증명자 이름 및 이미지 정보를 지정합니다.

    ATTESTOR_NAME=ATTESTOR_NAME
    IMAGE_PATH=IMAGE_PATH
    IMAGE_DIGEST=IMAGE_DIGEST
    IMAGE_TO_ATTEST="${IMAGE_PATH}@${IMAGE_DIGEST}"
    

    다음을 바꿉니다.

    • ATTESTOR_NAME: build-secure 또는 prod-qa와 같은 증명자의 이름입니다.
    • IMAGE_PATH: 이미지 경로를 나타내는 URI입니다. URI가 도메인 및 이미지 이름으로 구성되어야 하지만, 실제 이미지를 참조할 필요는 없습니다. 증명을 만드는 동안에는 이미지가 액세스되지 않습니다. 이미지 경로의 예시는 다음과 같습니다.

      • us-docker.pkg.dev/google-samples/containers/gke/hello-app
      • gcr.io/example-project/quickstart-image
      • example.com/hello-app.
    • IMAGE_DIGEST: 이미지 매니페스트의 다이제스트입니다. 예를 들어 sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567us-docker.pkg.dev/google-samples/containers/gke/hello-app 이미지 경로 예시와 연관된 이미지 다이제스트입니다. Artifact Registry에서 이미지의 다이제스트를 가져오는 방법은 이미지 관리를 참조하고, Container Registry의 이미지에 대해서는 이미지 버전 나열을 참조하세요.

Identity and Access Management 역할 부여

증명을 만들려면 다음과 같이 증명자를 만드는 ID에 다음 Identity and Access Management(IAM) 역할을 부여해야 합니다.

  • 증명자와 연결된 메모 리소스에서 roles/containeranalysis.notes.attacher
  • 증명 프로젝트 리소스에서 roles/containeranalysis.occurrences.editor

증명자를 기반으로 증명을 만듭니다. 증명자는 컨테이너 분석 메모와 연결됩니다. 증명을 만들면 컨테이너 분석 일치항목이 생성되어 메모에 연결됩니다.

액세스 권한 부여에 대해 자세히 알아보세요.

Cloud Build 파이프라인에서 증명을 만드는 방법은 Kritis 서명자를 사용하여 증명 만들기를 참조하세요.

증명 만들기

로컬로 저장된 키를 사용하여 증명 만들기

로컬 키로 서명된 증명을 만들려면 다음을 수행합니다.

  1. 서명 페이로드 파일을 만듭니다.

    gcloud

    서명 페이로드 파일을 만들려면 다음 명령어를 입력합니다.

    gcloud container binauthz create-signature-payload \
        --artifact-url="${IMAGE_TO_ATTEST}" > /tmp/generated_payload.json
    

    JSON 형식의 페이로드 파일은 다음 출력과 비슷합니다.

    {
      "critical": {
        "identity": {
          "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    

    REST API

    이 문서의 앞 부분에서 설정한 환경 변수를 사용하여 /tmp/generated_payload.json이라는 페이로드 파일을 만듭니다.

    cat > /tmp/generated_payload.json << EOM
    {
      "critical": {
        "identity": {
          "docker-reference": "${IMAGE_PATH}"
        },
        "image": {
          "docker-manifest-digest": "${IMAGE_DIGEST}"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    EOM
    
  2. 비공개 키로 페이로드를 서명하여 서명 파일을 생성합니다.

    이 가이드에서는 서명을 위해 권장되는 타원 곡선 디지털 서명 알고리즘(ECDSA)을 사용합니다. RSA 알고리즘을 사용할 수도 있습니다. 서명 알고리즘에 대한 자세한 내용은 주요 목적 및 알고리즘을 참조하세요. 또한 이 가이드에서는 공개 키 인프라(X.509)(PKIX) 서명 형식이 사용됩니다. PGP를 사용할 수도 있습니다.

    PRIVATE_KEY_FILE=PRIVATE_KEY_FILE
    openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
    

    PRIVATE_KEY_FILE을 증명자를 만들었을 때 생성한 비공개 키의 경로로 바꿉니다.

  3. 공개 키 ID를 가져옵니다.

    다음 명령어를 입력하여 증명자에서 공개 키 ID를 검색할 수 있습니다.

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    
  4. 증명을 만듭니다.

    gcloud

    증명을 만들고 검증하려면 다음을 입력합니다.

    gcloud container binauthz attestations create \
        --project="${ATTESTATION_PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}" \
        --validate
    

    validate 플래그는 정책에 구성된 증명자로 증명을 확인할 수 있는지 검사합니다.

    참고: 키 ID는 문자열일 수 있습니다.

    REST API

    증명을 만들려면 다음을 수행하세요.

    1. 증명과 연결된 증명자를 검색하고 저장된 공개 키 ID를 추출합니다.

      curl \
          -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
          -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
          "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
      

      Binary Authorization은 다음과 비슷한 JSON 객체를 반환합니다.

      {
        "name": "projects/example-project/attestors/test-attestor",
        "userOwnedGrafeasNote": {
          "noteReference": "projects/example-project/notes/test-attestor",
          "publicKeys": [
            {
              "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70",
              "pkixPublicKey": {
                "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n",
                "signatureAlgorithm": "ECDSA_P256_SHA256"
              }
            }
          ],
          "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
        },
        "updateTime": "2019-06-26T16:58:33.977438Z"
      }
      

      공개 키는 id 필드에서 찾을 수 있습니다.

    2. /tmp/attestation.json에 증명을 기술하는 JSON 파일을 만듭니다.

      cat > /tmp/attestation.json << EOM
      {
        "resourceUri": "${IMAGE_TO_ATTEST}",
        "note_name": "${NOTE_URI}",
        "attestation": {
           "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)",
           "signatures": [
              {
               "public_key_id": "${PUBLIC_KEY_ID}",
               "signature": "$(base64 --wrap=0 /tmp/ec_signature)"
              }
           ]
        }
       }
      EOM
      
    3. 증명을 만듭니다.

      curl -X POST \
          -H "Content-Type: application/json" \
          -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \
          -H "Authorization: Bearer $(gcloud auth print-access-token)" \
          --data-binary @/tmp/attestation.json \
          "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
      

Cloud KMS를 사용하여 증명 만들기

Cloud Key Management Service를 사용하여 증명을 만들려면 다음 안내를 따르세요.

  1. 환경 변수를 만듭니다.

    KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID
    KMS_KEY_LOCATION=KMS_KEY_LOCATION
    KMS_KEYRING_NAME=KMS_KEYRING_NAME
    KMS_KEY_NAME=KMS_KEY_NAME
    KMS_KEY_VERSION=KMS_KEY_VERSION
    

    다음을 바꿉니다.

    • KMS_KEY_PROJECT_ID: Cloud Key Management Service 키가 저장된 프로젝트의 ID입니다.
    • KMS_KEY_LOCATION: 키의 위치입니다(기본값 global).
    • KMS_KEYRING_NAME: 키링의 이름입니다.
    • KMS_KEY_NAME: 키의 이름입니다.
    • KMS_KEY_VERSION: 키 버전입니다.
  2. 서명하고 증명을 만듭니다.

    gcloud

    다음 명령어를 입력합니다.

    gcloud beta container binauthz attestations sign-and-create \
        --project="${ATTESTATION_PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="${ATTESTOR_NAME}" \
        --attestor-project="${ATTESTOR_PROJECT_ID}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    

    REST API

    1. 위에서 설정한 환경 변수를 사용하여 /tmp/generated_payload.json이라는 페이로드 파일을 만듭니다.

      cat > /tmp/generated_payload.json << EOM
      {
        "critical": {
          "identity": {
            "docker-reference": "${IMAGE_PATH}"
          },
          "image": {
            "docker-manifest-digest": "${IMAGE_DIGEST}"
          },
          "type": "Google cloud binauthz container signature"
        }
      }
      EOM
      
    2. 페이로드 파일에 서명합니다.

      curl \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $(gcloud auth print-access-token)" \
        --header "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
        --data '{"digest":  {"DIGEST_ALGORITHM": "'$(openssl dgst -sha256 -binary /tmp/generated_payload.json | openssl base64)'" }}' \
      https://cloudkms.googleapis.com/v1/projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}/cryptoKeyVersions/${KMS_KEY_VERSION}:asymmetricSign?alt=json
      

      DIGEST_ALGORITHM을 입력 다이제스트 알고리즘으로 바꿉니다. 이 가이드의 예시에서는 sha256 다이제스트가 사용됩니다. sha256, sha384, sha512를 사용할 수 있습니다.

      이 예시에서 출력은 다음과 비슷합니다.

      {
        "signature": "<var>SIGNATURE</var>": "996305066",
        "name": "projects/<var>KMS_KEY_PROJECT_ID</var>/locations/<var>KMS_KEY_LOCATION</var>/keyRings/<var>KMS_KEYRING_NAME</var>/cryptoKeys/<var>KMS_KEY_NAME</var>/cryptoKeyVersions/<var>KMS_KEY_VERSION</var>"
      }
      

      이 출력에서 SIGNATURE는 페이로드 파일의 base64로 인코딩된 서명입니다.

    3. 서명을 환경 변수에 저장합니다.

      PAYLOAD_SIGNATURE=PAYLOAD_SIGNATURE
      
    4. 사용자를 대신하여 증명에 서명하는 증명자를 검색하고 저장된 공개 키 ID와 메모 ID를 추출합니다.

      curl \
          -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
          -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
          "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
      

      Binary Authorization은 다음과 비슷한 JSON 객체를 반환합니다.

      {
        "name": "projects/example-project/attestors/test-attestor",
        "userOwnedGrafeasNote": {
          "noteReference": "projects/example-project/notes/test-attestor",
          "publicKeys": [
            {
              "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70",
              "pkixPublicKey": {
                "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n",
                "signatureAlgorithm": "ECDSA_P256_SHA256"
              }
            }
          ],
          "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
        },
        "updateTime": "2019-06-26T16:58:33.977438Z"
      }
      

      공개 키 ID는 id 필드에서, 메모 ID는 noteReference 필드에서 찾을 수 있습니다.

    5. 공개 키 ID를 환경 변수에 저장합니다.

      PUBLIC_KEY_ID="PUBLIC_KEY_ID"
      NOTE_URI="NOTE_URI"
      

      다음을 바꿉니다.

      • PUBLIC_KEY_ID: 증명자의 공개 키 ID입니다.
      • NOTE_URI: 증명자와 연결된 컨테이너 분석 메모의 URI입니다.
    6. /tmp/attestation.json에 증명을 기술하는 JSON 파일을 만듭니다.

      cat > /tmp/attestation.json << EOM
      {
        "resourceUri": "${IMAGE_TO_ATTEST}",
        "note_name": "${NOTE_URI}",
        "attestation": {
           "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)",
           "signatures": [
               {
                   "public_key_id": "${PUBLIC_KEY_ID}",
                   "signature": "${PAYLOAD_SIGNATURE}"
               }
           ]
        }
      }
      EOM
      
    7. 증명을 만듭니다.

      curl -X POST \
          -H "Content-Type: application/json" \
          -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \
          -H "Authorization: Bearer $(gcloud auth print-access-token)" \
          --data-binary @/tmp/attestation.json \
      "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
      

증명을 만들었습니다.

증명이 생성되었는지 확인

증명이 생성되었는지 확인하려면 이미지와 연관된 증명을 나열할 수 있습니다.

gcloud

증명 목록을 검색하려면 다음 명령어를 입력합니다.

gcloud container binauthz attestations list\
    --project="${ATTESTATION_PROJECT_ID}"\
    --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}"\
    --artifact-url="${IMAGE_TO_ATTEST}"

REST API

증명 목록을 요청하려면 다음 명령어를 입력합니다.

curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22

증명이 여러 개 있으면 응답에 nextPageToken 값이 포함될 수 있습니다. 이 경우 다음과 같이 요청을 반복하고, pageToken 쿼리 매개변수를 추가하여 결과의 다음 페이지를 검색할 수 있습니다.

NEXT_PAGE_TOKEN=NEXT_PAGE_TOKEN
curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22&pageToken=${NEXT_PAGE_TOKEN}

NEXT_PAGE_TOKEN을 이전 요청의 응답에 있는 nextPageToken 값으로 바꿉니다.

nextPageToken이 비어 있으면 더 이상 결과가 없음을 나타냅니다.

증명 삭제

증명을 삭제하려면 먼저 다음을 수행해야 합니다.

  1. 삭제로 인한 영향이 무엇인지 확인합니다. 증명을 삭제하면 결국 증명과 연관된 컨테이너 이미지가 배포되지 않습니다.

  2. 삭제하려는 증명과 연관된 모든 실행 중인 컨테이너를 중지합니다.

  3. Artifact Registry 및 컨테이너 분석 저장소 등 위치에 관계없이 증명의 모든 복사본을 삭제합니다.

  4. 영향을 받는 이미지를 다시 배포하려고 시도하여 실제로 배포되지 않도록 차단되는지 확인합니다.

증명을 삭제하려면 다음 명령어를 실행합니다.

  1. 증명을 나열합니다.

    gcloud container binauthz attestations list \
      --attestor-project=${ATTESTOR_PROJECT_ID} \
      --attestor=${ATTESTOR_NAME}
    

    증명에는 어커런스 ID가 포함됩니다. 출력은 다음과 비슷합니다.

    projects/ATTESTOR_PROJECT_ID/occurrences/OCCURRENCE_ID
    
  2. 어커런스 ID를 저장합니다.

    삭제하려는 증명의 어커런스 ID를 저장합니다.

    OCCURRENCE_ID=OCCURRENCE_ID
    
  3. 증명을 삭제합니다.

    curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -X DELETE \
      https://containeranalysis.googleapis.com/v1beta1/projects/${ATTESTATION_PROJECT_ID}/occurrences/${OCCURRENCE_ID}
    

    증명을 다시 나열하여 증명이 삭제되었는지 확인합니다.

다음 단계