이 페이지에서는 빌드 출처 기록을 생성하고, 출력을 확인하고, 검증하는 방법에 대한 안내를 제공합니다.
빌드 출처 기록은 빌드에 대한 검증 가능한 데이터 모음입니다. 출처 메타데이터에는 빌드된 이미지의 다이제스트, 입력 소스 위치, 빌드 인수, 빌드 기간과 같은 세부정보가 포함됩니다. 이 정보를 통해 현재 사용 중인 빌드 아티팩트가 신뢰할 수 있는 소스 및 빌더에 의해 생성된 정확하고 안정적인 것인지 확인할 수 있습니다.
Cloud Build는 SLSA 버전 0.1 및 1.0의 사양을 기반으로 소프트웨어 아티팩트에 대한 공급망 등급(SLSA) 레벨 3 보장을 충족하는 빌드 출처 기록 생성을 지원합니다.
SLSA v1.0 사양에 대한 지원으로 Cloud Build는 빌드 출처 기록에 buildType
세부정보를 제공합니다. buildType
스키마를 사용하여 Cloud Build가 기록하는 값과 이러한 값의 소스를 비롯하여 빌드 프로세스에 사용되는 매개변수화된 템플릿을 파악할 수 있습니다.
자세한 내용은 Cloud Build buildType v1을 참고하세요.
제한사항
- Cloud Build는 Artifact Registry에 저장된 아티팩트에 대한 빌드 출처 기록만 생성합니다.
- SLSA v1.0 및 v0.1 출처를 모두 가져오려면 트리거를 사용하여 빌드해야 합니다. 수동으로 빌드를 시작하는 경우 gcloud CLI를 사용하여 Cloud Build는 SLSA v0.1 출처만 제공합니다.
시작하기 전에
-
Enable the Cloud Build, Container Analysis, and Artifact Registry APIs.
이 가이드에서 명령줄 예시를 사용하려면 Google Cloud SDK를 설치하고 구성하세요.
소스 코드를 준비합니다.
Artifact Registry에 저장소가 있습니다.
빌드 출처 기록 생성
다음 안내에서는 Artifact Registry에 저장하는 컨테이너 이미지에 대한 빌드 출처 기록을 생성하는 방법을 설명합니다.
빌드 구성 파일에
images
필드를 추가하여 빌드가 완료된 후 빌드된 이미지를 Artifact Registry에 저장하도록 Cloud Build를 구성합니다.명시적인
docker push
단계를 사용하여 Artifact Registry에 이미지를 푸시하는 경우 Cloud Build에서 출처를 생성할 수 없습니다.다음 스니펫은 컨테이너 이미지를 빌드하고 Artifact Registry의 Docker 저장소에 이미지를 저장하기 위한 빌드 구성을 보여줍니다.
YAML
steps: - name: 'gcr.io/cloud-builders/docker' args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE', '.' ] images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE']
각 항목의 의미는 다음과 같습니다.
LOCATION
: 저장소의 리전 또는 멀티 리전 위치입니다.PROJECT_ID
: Google Cloud 프로젝트 ID입니다.REPOSITORY
: Artifact Registry 저장소의 이름입니다.IMAGE
: 컨테이너 이미지의 이름입니다.
JSON
{ "steps": [ { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "-t", "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE", "." ] } ], "images": [ "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE" ] }
각 항목의 의미는 다음과 같습니다.
LOCATION
: 저장소의 리전 또는 멀티 리전 위치입니다.PROJECT_ID
: Google Cloud 프로젝트 ID입니다.REPOSITORY
: Artifact Registry 저장소의 이름입니다.IMAGE
: 컨테이너 이미지의 이름입니다.
빌드 구성의
options
섹션에서requestedVerifyOption
옵션을 추가하고 값을VERIFIED
로 설정합니다.이 설정을 사용하면 출처 생성을 사용 설정하고 출처 메타데이터가 있는지 확인하도록 Cloud Build를 구성할 수 있습니다. 출처가 생성된 경우에만 빌드가 성공으로 표시됩니다.
YAML
options: requestedVerifyOption: VERIFIED
JSON
{ "options": { "requestedVerifyOption": "VERIFIED" } }
빌드를 시작합니다.
빌드 출처 기록 보기
이 섹션에서는 Cloud Build에서 만든 빌드 출처 기록 메타데이터를 보는 방법을 설명합니다. 감사 목적으로 이 정보를 가져올 수 있습니다.
Google Cloud 콘솔의 보안 통계 측면 패널을 사용하거나 gcloud CLI를 사용하여 컨테이너의 빌드 출처 기록 메타데이터에 액세스할 수 있습니다.
Console
보안 통계 측면 패널에서는 Artifact Registry에 저장된 아티팩트의 보안 정보에 대한 대략적인 개요를 제공합니다.
보안 통계 패널을 보려면 다음 안내를 따르세요.
Google Cloud 콘솔에서 빌드 기록 페이지를 엽니다.
프로젝트를 선택하고 열기를 클릭합니다.
리전 드롭다운 메뉴에서 빌드를 실행한 리전을 선택합니다.
빌드가 포함된 테이블에서 보안 통계를 보려는 빌드가 있는 행을 찾습니다.
보안 통계 열에서 보기를 클릭합니다.
그러면 선택한 아티팩트의 보안 통계 패널이 표시됩니다.
빌드 카드에는 출처 세부정보와 링크가 표시됩니다. 링크 아이콘을 클릭하면 출처 스니펫을 볼 수 있습니다.
측면 패널 및 Cloud Build를 사용하여 소프트웨어 공급망을 보호하는 방법에 관한 자세한 내용은 빌드 보안 통계 보기를 참고하세요.
gcloud CLI
컨테이너 이미지의 출처 메타데이터를 보려면 다음 명령어를 실행합니다.
gcloud artifacts docker images describe \
LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH \
--show-provenance --format=FORMAT
다음을 바꿉니다.
출력 예
빌드 출처 기록은 다음과 유사합니다.
image_summary: digest: sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 fully_qualified_digest: us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 registry: us-central1-docker.pkg.dev repository: my-repo slsa_build_level: 0 provenance_summary: provenance: - build: inTotoSlsaProvenanceV1: _type: https://in-toto.io/Statement/v1 predicate: buildDefinition: buildType: https://cloud.google.com/build/gcb-buildtypes/google-worker/v1 externalParameters: buildConfigSource: path: cloudbuild.yaml ref: refs/heads/main repository: git+https://github.com/my-username/my-git-repo substitutions: {} internalParameters: systemSubstitutions: BRANCH_NAME: main BUILD_ID: e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79 COMMIT_SHA: 525c52c501739e6df0609ed1f944c1bfd83224e7 LOCATION: us-west1 PROJECT_NUMBER: '265426041527' REF_NAME: main REPO_FULL_NAME: my-username/my-git-repo REPO_NAME: my-git-repo REVISION_ID: 525c52c501739e6df0609ed1f944c1bfd83224e7 SHORT_SHA: 525c52c TRIGGER_BUILD_CONFIG_PATH: cloudbuild.yaml TRIGGER_NAME: github-trigger-staging triggerUri: projects/265426041527/locations/us-west1/triggers/a0d239a4-635e-4bd3-982b-d8b72d0b4bab resolvedDependencies: - digest: gitCommit: 525c52c501739e6df0609ed1f944c1bfd83224e7 uri: git+https://github.com/my-username/my-git-repo@refs/heads/main - digest: sha256: 154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d uri: gcr.io/cloud-builders/docker@sha256:154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d runDetails: builder: id: https://cloudbuild.googleapis.com/GoogleHostedWorker byproducts: - {} metadata: finishedOn: '2023-08-01T19:57:10.734471Z' invocationId: https://cloudbuild.googleapis.com/v1/projects/my-project/locations/us-west1/builds/e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79 startedOn: '2023-08-01T19:56:57.451553160Z' predicateType: https://slsa.dev/provenance/v1 subject: - digest: sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image - digest: sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image:latest createTime: '2023-08-01T19:57:14.810489Z' envelope: payload: eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdMWQ0LWVjNGEtNGVhNi1hY2RkLWFjOGJiMTZkY2M3OSIsICJzdGFydGVkT24iOiIyMDIzLTA4LTAxVDE5OjU2OjU3LjQ1MTU1MzE2MFoiLCAiZmluaXNoZWRPbiI6IjIwMjMtMDgtMDFUMTk6NTc6MTAuNzM0NDcxWiJ9LCAiYnlwcm9kdWN0cyI6W3t9XX19fQ==... payloadType: application/vnd.in-toto+json signatures: - keyid: projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/google-hosted-worker/cryptoKeyVersions/1 sig: MEUCIQCss8UlQL2feFePRJuKTE8VA73f85iqj4OJ9SvVPqTNwAIgYyuyuIrl1PxQC5B109thO24Y6NA4bTa0PJY34EHRSVE= kind: BUILD name: projects/my-project/occurrences/71787589-c6a6-4d6a-a030-9fd041e40468 noteName: projects/argo-qa/notes/intoto_slsa_v1_e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79 resourceUri: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 updateTime: '2023-08-01T19:57:14.810489Z'
이 예시에서 알아야 할 중요한 사항은 다음과 같습니다.
객체 참조: 이름이
digest
및fileHash
인 필드는 동일한 객체를 참조합니다. 예시 출력에 포함된digest
필드는 Base16(16진수로 인코딩)으로 인코딩됩니다. SLSA 버전 0.1 출처를 사용하는 경우 출력은 base64로 인코딩된fileHash
필드를 사용합니다.서명: SLSA 버전 0.1 출처를 사용하는 경우 출력에는
envelope
필드에 두 개의 서명이 포함됩니다. 키 이름이provenanceSigner
인 첫 번째 서명에서는 DSSE 적합 서명(사전 인증 인코딩(PAE)으로 형식 지정)을 사용하며 Binary Authorization 정책에서 이를 확인할 수 있습니다. 이 출처의 새로운 사용에 이 서명을 사용하는 것이 좋습니다. 키 이름이builtByGCB
인 두 번째 서명은 기존 사용에 제공됩니다.서비스 계정: Cloud Build 출처에 자동으로 포함된 서명은 빌드를 실행한 빌드 서비스를 확인하는 데 도움이 됩니다. 또한 빌드를 시작하는 데 사용되는 서비스 계정에 대한 검증 가능한 메타데이터를 기록하도록 Cloud Build를 구성할 수 있습니다. 자세한 내용은 cosign으로 컨테이너 이미지 서명을 참조하세요.
페이로드: 이 페이지에 표시된 출처 예시는 가독성을 위해 축약되었습니다. 페이로드는 모든 출처 메타데이터의 base-64 인코딩 버전이므로 실제 출력은 더 길어집니다.
비컨테이너 아티팩트의 출처 보기
Cloud Build는 빌드 아티팩트를 Artifact Registry에 업로드할 때 독립형 Java(Maven), Python, Node.js(npm) 애플리케이션에 대한 SLSA 출처 메타데이터를 생성합니다. 직접 API를 호출하여 출처 메타데이터를 검색할 수 있습니다.
아티팩트의 출처 메타데이터를 생성하려면 Cloud Build로 빌드를 실행합니다. 다음 가이드 중 하나를 사용하세요.
빌드가 완료되면
BuildID
를 기록합니다.터미널에서 다음 API 호출을 실행하여 출처 메타데이터를 검색합니다. 여기서 PROJECT_ID는 Google Cloud 프로젝트와 연결된 ID입니다.
alias gcurl='curl -H"Authorization: Bearer $(gcloud auth print-access-token)"' gcurl 'https://containeranalysis.googleapis.com/v1/projects/PROJECT_ID/occurrences'
이 유형의 아티팩트에 대한 출처 메타데이터에 액세스하려면 API 호출을 사용해야 합니다. 컨테이너 외 아티팩트에 대한 출처 메타데이터는 Google Cloud 콘솔에 표시되지 않으며 gcloud CLI를 통해 액세스할 수 없습니다.
프로젝트와 일치하는 항목에서
BuildID
로 검색하여 빌드 아티팩트와 연관된 출처 정보를 찾습니다.
출처 검증
이 섹션에서는 컨테이너 이미지의 빌드 출처 기록을 확인하는 방법을 설명합니다.
빌드 출처 기록을 검증하면 다음을 수행하는 데 도움이 됩니다.
- 빌드 아티팩트가 신뢰할 수 있는 소스 및 빌더에서 생성되는지 확인
- 빌드 프로세스를 설명하는 출처 메타데이터가 완전하고 진본인지 확인
자세한 내용은 빌드 보호를 참조하세요.
SLSA 인증자를 사용한 출처 검증
SLSA 인증자는 SLSA 사양을 기준으로 빌드 무결성을 검증하는 오픈소스 CLI 도구입니다.
확인자는 문제를 발견하면 빌드 프로세스를 업데이트하고 위험을 완화하는 데 도움이 되는 자세한 오류 메시지를 반환합니다.
SLSA 인증자를 사용하려면 다음 안내를 따르세요.
slsa-verifier 저장소에서 버전 2.1 이상을 설치합니다.
go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@VERSION
CLI에서 이미지 식별자의 변수를 설정합니다.
export IMAGE=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH
명령어의 자리 표시자 값을 다음으로 바꿉니다.
LOCATION
: 리전 또는 멀티 리전 위치PROJECT_ID
: Google Cloud 프로젝트 ID입니다.REPOSITORY
: 저장소 이름입니다.IMAGE
: 이미지 이름입니다.HASH
: 이미지의 sha256 해시 값입니다. 빌드 출력에서 확인할 수 있습니다.
SLSA 인증자가 출처 데이터에 액세스할 수 있도록 gcloud CLI를 승인합니다.
gcloud auth configure-docker LOCATION-docker.pkg.dev
이미지의 출처를 검색하고
JSON
으로 저장합니다.gcloud artifacts docker images describe $IMAGE --format json --show-provenance > provenance.json
출처를 확인합니다.
slsa-verifier verify-image "$IMAGE" \ --provenance-path provenance.json \ --source-uri SOURCE \ --builder-id=BUILDER_ID
각 항목의 의미는 다음과 같습니다.
SOURCE
는 이미지의 소스 저장소 URI입니다(예:github.com/my-repo/my-application
).BUILDER_ID
빌더의 고유 ID입니다(예:https://cloudbuild.googleapis.com/GoogleHostedWorker
).
정책 엔진에 사용할 수 있도록 검증된 출처를 출력하려면
--print-provenance
플래그와 함께 이전 명령어를 사용합니다.출력은
PASSED: Verified SLSA provenance
또는FAILED: SLSA verification failed: <error details>
와 비슷합니다.
선택적 플래그에 관한 자세한 내용은 옵션을 참고하세요.
gcloud CLI로 출처 메타데이터 검증
빌드 출처 기록이 조작되지 않았는지 확인하려면 다음 단계를 수행하여 출처 유효성을 검사할 수 있습니다.
새 디렉터리를 만든 후 해당 디렉터리로 이동합니다.
mkdir provenance && cd provenance
keyid
필드의 정보를 사용하여 공개 키를 가져옵니다.gcloud kms keys versions get-public-key 1 --location global --keyring attestor \ --key builtByGCB --project verified-builder --output-file my-key.pub
payload
에는 base64url로 인코딩된 출처의 JSON 표현이 포함됩니다. 데이터를 디코딩하여 파일에 저장합니다.gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \ --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
가능한 경우 SLSA 버전 0.1 및 1.0 출처 유형은 모두 저장됩니다. 버전 1.0으로 필터링하려면
predicateType
을 변경하여https://slsa.dev/provenance/v1
을 사용합니다. 예를 들면 다음과 같습니다.gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \ --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
봉투에는 출처에 대한 서명도 포함됩니다. 데이터를 디코딩하여 파일에 저장합니다.
gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \ --format=json | '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
버전 1.0으로 필터링하려면
predicateType
을 변경하여https://slsa.dev/provenance/v1
을 사용합니다. 예를 들면 다음과 같습니다.gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \ --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
위 명령어는
provenanceSigner
키로 서명된 첫 번째 출처 서명(.provenance_summary.provenance[0].envelope.signatures[0]
)을 참조합니다. 페이로드는 PAE 형식의 봉투를 통해 서명됩니다. 이를 확인하려면 다음 명령어를 실행하여 출처를"DSSEv1" + SP + LEN(type) + SP + type + SP + LEN(body) + SP + body
의 예상 PAE 형식으로 변환합니다.echo -n "DSSEv1 28 application/vnd.in-toto+json $(cat provenance.json | wc -c) $(cat provenance.json)" > provenance.json
서명 유효성을 검사합니다.
openssl dgst -sha256 -verify my-key.pub -signature signature.bin provenance.json
유효성 검사에 성공하면 출력은
Verified OK
입니다.