
cosign v3.1.3
컨테이너 및 바이너리를 위한 코드 서명 및 투명성
cosign
Sigstore를 사용하여 OCI 컨테이너(및 기타 아티팩트)에 서명하세요!
Cosign은 서명을 보이지 않는 인프라로 만드는 것을 목표로 합니다.
Cosign이 지원하는 기능:
- Sigstore 공공재 Fulcio 인증 기관과 Rekor 투명성 로그를 사용한 "키리스 서명" (기본값)
- 하드웨어 및 KMS 서명
- cosign으로 생성된 암호화된 개인/공개 키페어로 서명
- OCI 레지스트리에서 컨테이너 서명, 검증 및 저장
- 자체 PKI 사용(Bring-your-own PKI)
정보
Cosign은 sigstore 프로젝트의 일부로 개발되고 있습니다.
또한 slack 채널도 사용합니다!
초대 링크는 여기를 클릭하세요.
설치
Homebrew, Arch, Nix, GitHub Action 및 Kubernetes 설치에 대한 자세한 내용은 설치 문서를 참조하세요.
Linux 및 macOS 바이너리는 GitHub 릴리스 자산을 참조하세요.
🚨 GCS 버킷에서 cosign 릴리스를 다운로드하는 경우 2023년 7월 31일 지원 중단 공지에서 자세한 정보를 확인하세요. 🚨
개발자 설치
Go 1.22+가 있다면 개발 환경을 설정할 수 있습니다:```shell $ git clone https://github.com/sigstore/cosign $ cd cosign $ go install ./cmd/cosign $ $(go env GOPATH)/bin/cosign
## 기여
`cosign`에 기여하는 데 관심이 있으시면 [기여 문서](https://github.com/sigstore/cosign/blob/HEAD/CONTRIBUTING.md)를 읽어 주세요.
향후 Cosign 개발은 [sigstore-go](https://github.com/sigstore/sigstore-go)를 기반으로 하는 다음 주요 릴리스에
집중될 것입니다. 유지 관리자는 sigstore-go 내의 기능 개발에 집중할 것입니다.
sigstore-go에 대한 기여, 특히 자체 키(bring-your-own keys) 및 서명과 관련된 기여를 환영합니다.
좋은 첫 이슈는 [이슈 트래커](https://github.com/sigstore/sigstore-go/issues)를 참조하세요.
Cosign 2.x는 안정적인 릴리스이며 계속해서 주기적인 기능 업데이트와 버그 수정을 받게 됩니다. 범위와 크기가 작은
PR은 가장 빠르게 검토될 가능성이 높습니다.
API를 크게 수정하거나 중단시키는 PR은 수락되지 않습니다. 크기는 크지만 호환성을 깨뜨리지 않는 PR은
수락될 수 있지만, sigstore-go의 PR보다 낮은 우선순위로 간주됩니다.
## Dockerfile
다음은 ghcr.io/sigstore/cosign/cosign 이미지를 통해 Dockerfile 내부에 cosign을 설치하고 사용하는 방법입니다:```shell
FROM ghcr.io/sigstore/cosign/cosign:v2.4.1 as cosign-bin
# Source: https://github.com/chainguard-images/static
FROM cgr.dev/chainguard/static:latest
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
ENTRYPOINT [ "cosign" ]
빠른 시작
다음 방법을 보여줍니다:
- 기본 ID 기반 "키리스 서명" 방식으로 컨테이너 이미지 서명 (자세한 내용은 문서 참조)
- 컨테이너 이미지 검증
- Sigstore Cosign 빠른 시작에서 더 광범위한 키리스 blob 서명/검증 흐름 탐색
컨테이너 서명 및 레지스트리에 서명 저장
이미지는 태그(:latest)보다는 다이제스트(@sha256:...)를 기준으로 항상 서명해야 합니다. 그렇지 않으면 의도하지 않은 것을 서명할 수 있기 때문입니다!```shell
cosign sign $IMAGE
Generating ephemeral keys... Retrieving signed certificate...
Note that there may be personally identifiable information associated with this signed artifact.
This may include the email address associated with the account with which you authenticate.
This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs. Are you sure you would like to continue? [y/N] y Your browser will now be opened to: https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=OrXitVKUZm2lEWHVt1oQWR4HZvn0rSlKhLcltglYxCY&code_challenge_method=S256&nonce=2KvOWeTFxYfxyzHtssvlIXmY6Jk&redirect_uri=http%3A%2F%2Flocalhost%3A57102%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2KvOWfbQJ1caqScgjwibzK2qJmb Successfully verified SCT... tlog entry created with index: 12086900 Pushing signature to: $IMAGE
Cosign은 OIDC를 통해 인증을 요청하며, 이메일 주소로 로그인하게 됩니다.
내부적으로 cosign은 Fulcio 인증 기관에서 코드 서명 인증서를 요청합니다.
인증서의 주체는 로그인한 이메일 주소와 일치합니다.
그런 다음 cosign은 서명과 인증서를 Rekor 투명성 로그에 저장하고, 서명하는 이미지와 함께 OCI 레지스트리에 서명을 업로드합니다.
### 컨테이너 검증
이미지를 검증하려면 `--certificate-identity` 및 `--certificate-oidc-issuer` 플래그를 통해 예상 인증서 주체와 인증서 발급자를 전달해야 합니다.```
cosign verify $IMAGE --certificate-identity=$IDENTITY --certificate-oidc-issuer=$OIDC_ISSUER
또한 인증서 ID 및 발급자 플래그에 대한 정규식을 전달할 수 있습니다, --certificate-identity-regexp 및 --certificate-oidc-issuer-regexp.
공개 키로 컨테이너 검증
이 명령은 이미지에 대해 공개 키와 일치하는 하나 이상의 cosign 형식 서명이 발견되면
0을 반환합니다.
다른 서명 형식에 대한 정보와 주의 사항은 아래의 자세한 사용법을 참조하십시오.
유효한 페이로드는 json 형식으로 stdout에 출력됩니다. 이 서명된 페이로드에는 컨테이너 이미지의 다이제스트가 포함되어 있으며, 이를 통해 이러한 "분리된" 서명이 올바른 이미지를 다루고 있음을 확신할 수 있습니다.```shell $ cosign verify --key cosign.pub $IMAGE_URI:1h The following checks were performed on these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8"},"Type":"cosign container image signature"},"Optional":null}
### 에어갭 환경에서 컨테이너 검증
**참고:** 이 섹션은 최신 상태가 아닙니다.
**참고:** 대부분의 검증 워크플로는 TUF 저장소에서 서비스 키를 주기적으로 요청해야 합니다.
public-good 인스턴스를 사용하여 서명을 에어갭 검증하려면 프로덕션 TUF 저장소에서
[trusted root](https://github.com/sigstore/root-signing/blob/main/targets/trusted_root.json) 파일을 검색해야 합니다.
이 파일의 내용은 통지 없이 변경될 수 있습니다. TUF를 사용하지 않는 경우, 이 파일의 에어갭 사본을
최신 상태로 유지하는 자체 메커니즘을 구축해야 합니다.
Cosign은 일반적으로 이미지 매니페스트의 주석으로 배포되는 [bundle](https://github.com/sigstore/cosign/blob/HEAD/specs/SIGNATURE_SPEC.md#properties)을 검증하여 완전히 오프라인 검증을 수행할 수 있습니다.
이 주석이 존재하는 한 오프라인 검증을 수행할 수 있습니다.
이 번들 주석은 키리스 서명에 기본적으로 항상 포함되므로 기본 `cosign sign` 기능에는 오프라인 검증에 필요한 모든 자료가 포함됩니다.
에어갭 환경에서 이미지를 검증하려면 이미지와 서명이 로컬 파일 시스템에 있어야 합니다.
이미지는 `cosign save`를 사용하여 로컬에 저장할 수 있습니다 (참고: 이 단계는 네트워크 연결이 있는 상태에서 수행해야 합니다):```
cosign initialize # This will pull in the latest TUF root
cosign save $IMAGE_NAME --dir ./path/to/dir
이제 에어갭(air-gapped) 환경에서는 이 로컬 이미지를 검증할 수 있습니다:```shell
cosign verify
--certificate-identity $CERT_IDENTITY
--certificate-oidc-issuer $CERT_OIDC_ISSUER
--offline=true
--new-bundle-format=false \ # for artifacts signed without the new protobuf bundle format
--trusted-root ~/.sigstore/root/tuf-repo-cdn.sigstore.dev/targets/trusted_root.json \ # default location of trusted root
--local-image ./path/to/dir
이 이미지를 올바르게 검증하려면 `$CERT_IDENTITY` 및 `$CERT_OIDC_ISSUER`에 대한 예상 값을 전달해야 합니다.
키페어로 서명한 경우, 공개 키 자료가 로컬에 존재한다면 동일한 명령이 작동합니다:```
cosign verify --key cosign.pub --offline --local-image ./path/to/dir
신원 기반 블롭 서명 및 검증
키 없는 블롭 서명(cosign sign-blob에서 --key 없이)을 사용하고 예상 서명자 신원을 기준으로 검증하세요:```shell
$ cosign sign-blob artifact --bundle artifact.sigstore.json --yes
$ cosign verify-blob artifact
--bundle artifact.sigstore.json
--certificate-identity "https://github.com/ORG/REPO/.github/workflows/release.yml@refs/heads/main"
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
### 문제 해결
Cosign에 문제가 발생하면 먼저 최신 릴리스를 사용 중인지 확인하세요. Cosign 프로젝트는 가장 최신 릴리스와 v2 시리즈의 마지막 릴리스를 적극적으로 지원합니다.
#### 일반적인 문제 및 해결 방법
1. 다음 오류로 인해 검증이 실패하는 경우: `failed to verify timestamps: threshold not met for verified log entry integrated timestamps: 0 < 1`: RFC3161 타임스탬프 지원이 필요한 서명을 검증하고 있을 수 있습니다.
* 최신 Cosign으로 업그레이드하거나
* Cosign 2.6.x를 사용하는 경우 `--use-signed-timestamps` 사용
1. 다음 오류로 인해 검증이 실패하는 경우: `no signatures found`: Rekor v2 투명성 로그 지원이 필요한 이미지 서명을 검증하고 있을 수 있습니다.
* 최신 Cosign으로 업그레이드
1. HTTP 오류로 서명이 실패하는 경우: Cosign으로 서명하려면 여러 Sigstore 서비스가 필요합니다. 이러한 서비스 중 하나라도 실패하면 재시도가 유용한 해결 방법이 될 수 있습니다. 특정 실패에 대한 이슈를 제기해 주시는 것도 감사하겠습니다.
#### 다른 문제인 경우
[이슈](https://github.com/sigstore/cosign/issues/new/choose)를 열거나 [슬랙 채널](#info)에 문의하세요.
## 다른 아티팩트 작업
OCI 레지스트리는 컨테이너 이미지뿐만 아니라 더 많은 것을 저장하는 데 유용합니다!
`Cosign`에는 바이너리, 스크립트, 구성 파일을 포함한 일반 아티팩트를 OCI 프로토콜로 게시하기 위한 몇 가지 유틸리티도 포함되어 있습니다.
이 섹션에서는 이를 활용하여 Sigstore의 나머지 부분과 잘 통합되는 사용하기 쉬운 역호환 아티팩트 배포 시스템을 구축하는 방법을 보여줍니다.
자세한 내용은 [문서](https://docs.sigstore.dev/cosign/signing/other_types/)를 참조하세요.
### Blobs
`cosign upload blob`로 아티팩트를 게시할 수 있습니다:```shell
$ echo "my first artifact" > artifact
$ BLOB_SUM=$(shasum -a 256 artifact | cut -d' ' -f 1) && echo "$BLOB_SUM"
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626
$ BLOB_NAME=my-artifact-$(uuidgen | head -c 8 | tr 'A-Z' 'a-z')
$ BLOB_URI=ttl.sh/$BLOB_NAME:1h
$ BLOB_URI_DIGEST=$(cosign upload blob -f artifact $BLOB_URI) && echo "$BLOB_URI_DIGEST"
Uploading file from [artifact] to [ttl.sh/my-artifact-f42c22e0:5m] with media type [text/plain]
File [artifact] is available directly at [ttl.sh/v2/my-artifact-f42c22e0/blobs/sha256:c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626]
Uploaded image to:
ttl.sh/my-artifact-f42c22e0@sha256:790d47850411e902aabebc3a684eeb78fcae853d4dd6e1cc554d70db7f05f99f
사용자들은 "direct" URL에서 curl이나 wget과 같은 표준 도구로 다운로드할 수 있습니다:```shell $ curl -L ttl.sh/v2/$BLOB_NAME/blobs/sha256:$BLOB_SUM > artifact-fetched
다이제스트가 URL에 그대로 포함되어 있으므로, 그것도 확인할 수 있습니다:```shell
$ cat artifact-fetched | shasum -a 256
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626 -
일반적인 cosign sign 명령과 플래그로 서명할 수 있습니다:```shell
$ cosign sign --key cosign.key $BLOB_URI_DIGEST
Enter password for private key:
Pushing signature to: ttl.sh/my-artifact-f42c22e0
평소와 같이, 서명하는 모든 이미지를 해당 다이제스트로 참조하여 잘못된 것에 서명하지 않도록 하세요!
#### Tekton 번들
[Tekton](https://tekton.dev) 번들은 OCI 레지스트리 내에서 업로드하고 관리할 수 있습니다.
명세는 [여기](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/)에 있습니다.
즉, `cosign`으로 서명하고 검증할 수도 있습니다.
Tekton 번들은 현재 [tkn cli](https://github.com/tektoncd/cli)로 업로드할 수 있지만, 향후 이 지원을
`cosign`에 추가할 수도 있습니다.```shell
$ tkn bundle push us.gcr.io/dlorenc-vmtest2/pipeline:latest -f task-output-image.yaml
Creating Tekton Bundle:
- Added TaskRun: to image
Pushed Tekton Bundle to us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
Enter password for private key:
tlog entry created with index: 5086
Pushing signature to: us.gcr.io/dlorenc-vmtest2/demo:sha256-124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155.sig
WASM
Web Assembly 모듈은 이 명세를 사용하여 OCI 레지스트리에 저장될 수도 있습니다.
Cosign은 cosign wasm upload 명령을 사용하여 이를 업로드할 수 있습니다:```shell
$ cosign upload wasm -f hello.wasm us.gcr.io/dlorenc-vmtest2/wasm
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/wasm@sha256:9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812
Enter password for private key:
tlog entry created with index: 5198
Pushing signature to: us.gcr.io/dlorenc-vmtest2/wasm:sha256-9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812.sig
#### eBPF
[eBPF](https://ebpf.io) 모듈은 이 [명세](https://github.com/solo-io/bumblebee/tree/main/spec)를 사용하여 OCI 레지스트리에 저장할 수도 있습니다.
아래 이미지는 `bee` 도구를 사용하여 빌드되었습니다. 더 많은 정보는 [여기](https://github.com/solo-io/bumblebee/)에서 확인할 수 있습니다.
Cosign은 다른 OCI 이미지에 서명하는 것과 마찬가지로 이러한 이미지에도 서명할 수 있습니다.```shell
$ bee build ./examples/tcpconnect/tcpconnect.c localhost:5000/tcpconnect:test
$ bee push localhost:5000/tcpconnect:test
$ cosign sign --key cosign.key localhost:5000/tcpconnect@sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6
Enter password for private key:
Pushing signature to: localhost:5000/tcpconnect
$ cosign verify --key cosign.pub localhost:5000/tcpconnect:test
Verification for localhost:5000/tcpconnect:test --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
[{"critical":{"identity":{"docker-reference":"localhost:5000/tcpconnect"},"image":{"docker-manifest-digest":"sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6"},"type":"cosign container image signature"},"optional":null}]
In-Toto 증명
Cosign에는 in-toto 증명에 대한 내장 지원도 있습니다. 이에 대한 사양은 여기에 정의되어 있습니다.
다음 명령을 사용하여 로컬 predicate 파일에서 하나를 생성하고 서명할 수 있습니다:```shell $ cosign attest --predicate --key cosign.key $IMAGE_URI_DIGEST
모든 표준 키 관리 시스템이 지원됩니다.
Payloads는 [여기](https://github.com/secure-systems-lab/dsse)에 정의된 DSSE 서명 스펙을 사용하여 서명됩니다.
확인하려면:```shell
$ cosign verify-attestation --key cosign.pub $IMAGE_URI
Detailed Usage
자세한 내용은 사용 문서를 참조하세요.
Hardware-based Tokens
하드웨어와 함께 cosign을 사용하는 방법에 대한 정보는 하드웨어 토큰 문서를 참조하세요.
Registry Support
cosign은 레지스트리 상호 작용을 위해 go-containerregistry를 사용합니다. 일반적으로 매우 우수한 호환성을 제공하지만 일부 레지스트리에는 문제가 있을 수 있습니다.
현재 cosign은 다음 레지스트리에서 테스트되었으며 작동합니다:
- AWS Elastic Container Registry
- GCP's Artifact Registry and Container Registry
- Docker Hub
- Azure Container Registry
- JFrog Artifactory Container Registry
- The CNCF distribution/distribution Registry
- GitLab Container Registry
- GitHub Container Registry
- The CNCF Harbor Registry
- Digital Ocean Container Registry
- Sonatype Nexus Container Registry
- Alibaba Cloud Container Registry
- Red Hat Quay Container Registry 3.6+ / Red Hat quay.io
- Elastic Container Registry
- IBM Cloud Container Registry
- Cloudsmith Container Registry
- The CNCF zot Registry
- OVHcloud Managed Private Registry
우리는 광범위한 레지스트리 지원을 목표로 합니다. 아직 OCI 미디어 유형을 완전히 지원하지 않는 레지스트리의 이미지를 sign하려면 레거시 등가물로 대체하기 위해 COSIGN_DOCKER_MEDIA_TYPES를 사용해야 할 수 있습니다. 예를 들어:```shell
COSIGN_DOCKER_MEDIA_TYPES=1 cosign sign --key cosign.key legacy-registry.example.com/my/image@$DIGEST
문제가 보이면 테스트에 참여하여 버그를 신고해 주세요!
지침은 [추적 이슈](https://github.com/sigstore/cosign/issues/40)에서 확인할 수 있습니다.
## 주의사항
### 의도적으로 빠진 기능
`cosign`은 일시적인 키리스 서명과 관리형 키 서명 모두에 대해 ECDSA-P256 키만 생성하고 SHA256 해시를 사용합니다.
키는 PEM 인코딩된 PKCS8 형식으로 저장됩니다.
하지만 `cosign`을 사용하여 어떤 알고리즘의 어떤 형식으로든 서명을 저장하고 검색할 수 있습니다.
### 아마 변경되어야 할 사항들
#### 페이로드 형식
`cosign`은 페이로드에 대해 Red Hat의 [simple signing](https://www.redhat.com/en/blog/container-image-signing)
형식만 지원합니다.
형식은 다음과 같습니다:```json
{
"critical": {
"identity": {
"docker-reference": "testing/manifest"
},
"image": {
"Docker-manifest-digest": "sha256:20be...fe55"
},
"type": "cosign container image signature"
},
"optional": {
"creator": "Bob the Builder",
"timestamp": 1458239713
}
}
참고: 이는 cosign generate $IMAGE_URI_DIGEST를 사용하여 이미지 참조에 대해 생성할 수 있습니다.
이 형식을 다른 것으로 바꾸는 것도 괜찮습니다. 한 가지 옵션은 https://github.com/notaryproject/nv2/issues/40 를 참조하세요.
레지스트리 세부 사항
cosign 서명은 OCI 레지스트리에서 별도의 객체로 저장되며, 서명 대상 객체에 대한 약한
참조(weak reference)만 가집니다.
즉, 이 관계는 레지스트리에 불투명하므로 서명은 이미지가 삭제되어도 삭제되거나 가비지 컬렉션되지 않습니다.
마찬가지로, 한 환경에서 다른 환경으로 쉽게 복사할 수 있지만, 이는 자동으로
이루어지지 않습니다.
여러 서명은 리스트에 저장되는데, 현재는 아쉽게도 경쟁 조건(race condition)이 있습니다. 서명을 추가하기 위해 클라이언트는 "읽기-추가-쓰기" 작업을 조정하므로, 경합이 발생하면 마지막 쓰기가 승리합니다.
레지스트리 지정
cosign은 기본적으로 서명 중인 이미지와 동일한 저장소에 서명을 저장합니다.
서명을 위한 다른 저장소를 지정하려면 COSIGN_REPOSITORY 환경 변수를 설정할 수 있습니다.
그러면 제공된 이미지의 저장소가 다음과 같이 대체됩니다:```shell $ export COSIGN_REPOSITORY=gcr.io/my-new-repo $ cosign sign --key cosign.key $IMAGE_URI_DIGEST
따라서 `gcr.io/dlorenc-vmtest2/demo`에 대한 서명은 `gcr.io/my-new-repo/demo:sha256-DIGEST.sig`에 저장됩니다.
참고: 레지스트리에 따라 "저장소"에 대해 서로 다른 형식을 기대할 수 있습니다.
* [GCR](https://cloud.google.com/container-registry)을 사용하려면 위 예시와 같이
`gcr.io/$REPO`와 같은 레지스트리 이름이면 충분합니다.
* [Artifact Registry](https://cloud.google.com/artifact-registry)을 사용하려면
저장소만이 아니라
`$LOCATION-docker.pkg.dev/$PROJECT/$REPO/$STORAGE_IMAGE`와 같은 전체 이미지
이름을 지정하세요. 예를 들어, ```shell
$ export COSIGN_REPOSITORY=us-docker.pkg.dev/my-new-repo/demo
$ cosign sign --key cosign.key $IMAGE_URI_DIGEST
where the sha256-DIGEST는 gcr.io/dlorenc-vmtest2/demo에 대한 다이제스트와 일치합니다.
Artifact Registry에서는 $LOCATION-docker.pkg.dev/$PROJECT/$REPO처럼 저장소(repo)만 지정하는 것으로는 작동하지 않습니다.
서명 사양
cosign은 minisign 및
signify와 같은 도구에서 영감을 받았습니다.
생성된 개인 키는 PEM 형식으로 저장됩니다. 키는 scrypt를 KDF로 사용하고 nacl/secretbox를 암호화에 사용하여 비밀번호로 암호화됩니다.
PEM 헤더는 ENCRYPTED SIGSTORE PRIVATE KEY입니다:```shell
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
...
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----
공개 키는 PEM 인코딩 표준 PKIX 형식으로 디스크에 저장되며 헤더는 `PUBLIC KEY`입니다.```
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELigCnlLNKgOglRTx1D7JhI7eRw99
QolE9Jo4QUxnbMy5nUuBL+UZF9qqfm/Dg1BNeHRThHzWh2ki9vAEgWEDOw==
-----END PUBLIC KEY-----
Storage Specification
cosign은 서명을 OCI 레지스트리에 저장하며, 서명 인덱스를 찾기 위해 명명 규칙(서명 대상의 sha256 기반 태그)을 사용합니다.
reg.example.com/ubuntu@sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715의 서명은 reg.example.com/ubuntu:sha256-703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sig에 있습니다.
대략적으로(호스트 이름의 포트는 무시): 서명 인덱스를 찾으려면 s/:/-/g 및 s/@/:/g를 적용합니다.
이 전략과 관련된 몇 가지 주의 사항은 Race conditions를 참조하세요.
대체 구현으로는 투명성 로그, 로컬 파일 시스템, 별도 저장소 레지스트리, 서명 인덱스에 대한 명시적 참조, 새로운 레지스트리 API, grafeas 등을 사용할 수 있습니다.
서명 대상 (Signing subjects)
cosign은 현재 레지스트리에 "manifest"로 저장된 아티팩트에 대해서만 작동합니다.
제안된 메커니즘은 임의의 대상을 서명할 수 있을 만큼 유연합니다.
KMS 지원
cosign은 KMS 제공자를 사용하여 키를 생성하고 서명하는 것을 지원합니다.
현재 cosign은 Hashicorp Vault, AWS KMS, GCP KMS, Azure Key Vault를 지원하며, 향후 더 많은 제공자를 지원할 예정입니다!
추가 KMS 제공자는 OVHcloud KMS와 같은 외부 플러그인으로 제공됩니다.
자세한 내용은 KMS 문서를 참조하세요.
OCI Artifacts
oras를 사용하여 레지스트리에 아티팩트를 푸시합니다(이 경우에는 cosign 자체입니다!):```shell
$ oras push us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact ./cosign
Uploading f53604826795 cosign
Pushed us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact
Digest: sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
이제 서명하세요! 물론 `cosign`을 사용해서:```shell
$ cosign sign --key cosign.key us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
Enter password for private key:
Pushing signature to: us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact:sha256-551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef.sig
마지막으로, cosign을 cosign으로 다시 확인하세요:```shell
$ cosign verify --key cosign.pub us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The claims were present in the transparency log
- The signatures were integrated into the transparency log when the certificate was valid
- The signatures were verified against the specified public key
- The code-signing certificate was verified using trusted certificate authority certificates
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef"},"Type":"cosign container image signature"},"Optional":null}
## FAQ
### Notary v2를 사용하지 않는 이유
이 질문에 간단히 답하기는 어렵습니다.
이 게시물에는 몇 가지 비교가 포함되어 있습니다:
[Notary V2 and Cosign](https://medium.com/@dlorenc/notary-v2-and-cosign-b816658f044d)
다른 비교 게시물을 찾으면 여기에 PR을 보내 주시면 모두 링크하겠습니다.
### containers/image 서명을 사용하지 않는 이유
`containers/image` 서명은 `cosign`과 유사하며, 페이로드 형식을 재사용합니다.
`cosign`은 PGP 대신 ECDSA-P256 키로 서명하고, 서명을 레지스트리에 저장한다는 점에서
다릅니다.
### TUF를 사용하지 않는 이유?
이 도구는 TUF와 상호 보완적이며 함께 사용할 수 있다고 생각합니다.
아직 시도해 보지는 않았지만 TUF 저장에도 레지스트리를 재사용할 수 있다고 생각합니다.
## 설계 요구 사항
* 서명 저장, 조회, 검색을 위한 외부 서비스 없음
* 가능한 한 많은 레지스트리를 지원하는 것을 목표로 함
* 모든 것이 레지스트리 API를 통해 동작해야 함
* PGP가 전혀 필요하지 않아야 함.
* 사용자는 이미지에 대한 모든 서명을 찾을 수 있어야 함
* 서명자는 푸시 후 이미지에 서명할 수 있음
* 여러 주체가 이미지에 서명할 수 있음
* 이미지에 서명해도 이미지가 변경되지 않음
* 순수 Go 구현
## 향후 아이디어
### 레지스트리 API 변경
레지스트리에 데이터를 저장하는 데 사용하는 명명 규칙과 읽기-수정-쓰기 업데이트 패턴은
약간, 음, "hacky"합니다.
오늘날 사용 가능한 최선의(유일한) 실제 옵션이라고 생각하지만, 레지스트리 API가
변경된다면 이를 개선할 수 있습니다.
### 기타 유형
`cosign`은 레지스트리의 모든 것에 서명할 수 있습니다.
이 예시들은 단일 이미지 서명을 보여주지만, 다중 플랫폼 `Index`나
다른 모든 유형의 아티팩트에도 서명할 수 있습니다.
여기에는 Helm Charts, Tekton Pipelines, 그리고 현재 배포를 위해 OCI 레지스트리를 사용하는
모든 것이 포함됩니다.
또한 새로운 아티팩트 유형을 레지스트리에 업로드하고 서명할 수 있다는 의미이기도 합니다.
저장하고 서명하기에 흥미로운 유형 중 하나는 TUF 저장소입니다.
아직 시도해 보지는 않았지만, TUF가 이를 기반으로 구현될 수 있다고 확신합니다.
### 태그 서명
`cosign` 서명은 레지스트리에 저장된 객체의 다이제스트를 보호합니다.
선택적 `annotations` 지원(`cosign sign`의 `-a` 플래그를 통해)을 사용하여 서명 및 서명으로 보호되는
페이로드에 추가 데이터를 넣을 수 있습니다.
이에 대한 한 가지 사용 사례는 태그->다이제스트 매핑에 서명하는 것입니다.
특정 태그(또는 태그 집합)가 특정 다이제스트를 가리켜야 한다고 증명하려면 다음과 같이
실행하면 됩니다:```shell
$ docker push $IMAGE_URI
The push refers to repository [dlorenc/demo]
994393dc58e7: Pushed
5m: digest: sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870 size: 528
$ TAG=sign-me
$ cosign sign --key cosign.key -a tag=$TAG $IMAGE_URI_DIGEST
Enter password for private key:
Pushing signature to: dlorenc/demo:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870.sig
그런 다음 cosign verify의 -a 플래그를 사용하여 태그->다이제스트 매핑이 서명에도 포함되어 있는지 확인할 수 있습니다.
이 예제는 (sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870)을 가리키는 다이제스트 $TAG가 서명되었는지, 또한 tag 어노테이션의 값이 sign-me인지 확인합니다:```shell
$ cosign verify --key cosign.pub -a tag=$TAG $IMAGE_URI | jq .
{
"Critical": {
"Identity": {
"docker-reference": ""
},
"Image": {
"Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
},
"Type": "cosign container image signature"
},
"Optional": {
"tag": "sign-me"
}
}
Timestamps could also be added here, to implement TUF-style freeze-attack prevention.
### Base Image/Layer Signing
Again, `cosign` can sign anything in a registry.
You could use `cosign` to sign an image that is intended to be used as a base image,
and include that provenance metadata in resulting derived images.
This could be used to enforce that an image was built from an authorized base image.
Rough Idea:
* OCI manifests have an ordered list of `layer` `Descriptors`, which can contain annotations.
See [here](https://github.com/opencontainers/image-spec/blob/master/manifest.md) for the
specification.
* A base image is an ordered list of layers to which other layers are appended, as well as an
initial configuration object that is mutated.
* A derived image is free to completely delete/destroy/recreate the config from its base image,
so signing the config would provided limited value.
* We can sign the full set of ordered base layers, and attach that signature as an annotation to
the **last** layer in the resulting child image.
This example manifest manifest represents an image that has been built from a base image with two
layers.
One additional layer is added, forming the final image.```json
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
"annotations": {
"dev.cosign.signature.baseimage": "Ejy6ipGJjUzMDoQFePWixqPBYF0iSnIvpMWps3mlcYNSEcRRZelL7GzimKXaMjxfhy5bshNGvDT5QoUJ0tqUAg=="
}
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
}
],
}
참고로 이는 여러 중간 기본 이미지에 대해 재귀적으로 적용될 수 있습니다.
카운터 서명
Cosign 서명(및 보호된 페이로드)은 레지스트리에 아티팩트로 저장됩니다. 이러한 서명 객체도 서명될 수 있으며, 그 결과 새로운 "카운터 서명" 아티팩트가 생성됩니다. 이 "카운터 서명"은 서명(또는 서명 집합) 및 참조된 아티팩트를 보호하므로, 서명(들) 자체에 대한 증명(attestation) 역할을 할 수 있습니다.
서명 아티팩트에 서명하기 전에, 나중에 찾을 수 있도록 기억하기 쉬운 이름을 먼저 지정합니다.```shell $ cosign sign --key cosign.key -a sig=original $IMAGE_URI_DIGEST Enter password for private key: Pushing signature to: dlorenc/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig $ cosign verify --key cosign.pub dlorenc/demo | jq . { "Critical": { "Identity": { "docker-reference": "" }, "Image": { "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36" }, "Type": "cosign container image signature" }, "Optional": { "sig": "original" } }
<!-- TODO: https://github.com/sigstore/cosign/issues/2333 -->
이제 해당 서명에 기억하기 쉬운 이름을 지정한 다음, 서명하세요:```shell
$ crane tag $(cosign triangulate $IMAGE_URI) mysignature
2021/02/15 20:22:55 dlorenc/demo:mysignature: digest: sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e size: 556
$ cosign sign --key cosign.key -a sig=counter dlorenc/demo:mysignature
Enter password for private key:
Pushing signature to: dlorenc/demo:sha256-71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e.sig
$ cosign verify --key cosign.pub dlorenc/demo:mysignature
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e"},"Type":"cosign container image signature"},"Optional":{"sig":"counter"}}
마지막으로, 원본 서명을 확인하세요:```shell $ crane manifest dlorenc/demo@sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e { "schemaVersion": 2, "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "size": 233, "digest": "sha256:3b25a088710d03f39be26629d22eb68cd277a01673b9cb461c4c24fbf8c81c89" }, "layers": [ { "mediaType": "application/vnd.oci.descriptor.v1+json", "size": 217, "digest": "sha256:0e79a356609f038089088ec46fd95f4649d04de989487220b1a0adbcc63fadae", "annotations": { "dev.sigstore.cosign/signature": "5uNZKEP9rm8zxAL0VVX7McMmyArzLqtxMTNPjPO2ns+5GJpBeXg+i9ILU+WjmGAKBCqiexTxzLC1/nkOzD4cDA==" } } ] }
## 릴리스 주기
필요에 따라 릴리스를 배포합니다. 패치 릴리스는 사소한 버그를 수정하기 위해 배포됩니다. 마이너 릴리스는 여러 버그가 수정되거나 기능이 추가되었을 때 주기적으로 배포됩니다. 메이저 릴리스는 호환성이 깨지는 기능이 있을 때 출시됩니다.
## 보안
보안 문제를 발견하신 경우 sigstore의 [보안
프로세스](https://github.com/sigstore/.github/blob/main/SECURITY.md)를 참조하세요.
## GitHub 릴리스 자산의 번들 파일
`cosign`에 대한 GitHub 릴리스 자산에는 릴리스 바이너리의 무결성을 검증하는 데 사용되는 cosign blob에 서명하면서 [GoReleaser](https://github.com/sigstore/cosign/blob/ac999344eb381ae91455b0a9c5c267e747608d76/.goreleaser.yml#L166)가 생성한 Sigstore 번들 파일이 포함되어 있습니다. 이 파일은 cosign 자체에서 사용되지는 않지만, [릴리스 바이너리의 무결성을 검증](https://docs.sigstore.dev/cosign/system_config/installation/#verifying-cosign-with-artifact-key)하려는 사용자를 위해 제공됩니다.