diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ae0c3be2..df463a95f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,13 +14,16 @@ # limitations under the License. version: 2 + updates: - package-ecosystem: gomod directory: "/" schedule: interval: daily open-pull-requests-limit: 10 + - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" + interval: daily + open-pull-requests-limit: 10 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 52f6881a3..691bebed5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,8 +45,7 @@ jobs: # will use the latest release available for ko - uses: imjasonh/setup-ko@2c3450ca27f6e6f2b02e72a40f2163c281a1f675 # v0.4 - - name: Install goimports - run: go get golang.org/x/tools/cmd/goimports + - uses: chainguard-dev/actions/goimports@84c993eaf02da1c325854fb272a4df9184bd80fc # main - name: Set up Cloud SDK uses: google-github-actions/auth@ceee102ec2387dd9e844e01b530ccd4ec87ce955 # v0.8.0 @@ -58,4 +57,6 @@ jobs: run: gcloud auth configure-docker --quiet - name: policy-controller - run: echo -n "${{secrets.COSIGN_PASSWORD}}" | KO_PREFIX=gcr.io/projectsigstore/cosign/ci make sign-policy-controller + env: + COSIGN_EXPERIMENTAL: true + run: KO_PREFIX=gcr.io/projectsigstore/policy-controller/ci make build-sign-containers diff --git a/.github/workflows/cosign-test.key b/.github/workflows/cosign-test.key deleted file mode 100644 index 611e46431..000000000 --- a/.github/workflows/cosign-test.key +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN ENCRYPTED COSIGN PRIVATE KEY----- -eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6 -OCwicCI6MX0sInNhbHQiOiJYcDVZWW5nRVBWNkR1Kzh0Qmdsbll1OEc2YTZOWGVJ -L1M3bXo0VUYvWk1FPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94 -Iiwibm9uY2UiOiIyT0YvUFJBQ09sKzRTVTJXVHpycTFHalFML2JlQzQvQiJ9LCJj -aXBoZXJ0ZXh0IjoiMDV6eTlxaWVZWlVjZ0pCZHNndWhSNmd6ZmEvc1RrbnBCZTN0 -Z3VsdDlXK0g0bnE3UE9sODFvdUttT0xhY3g5bzhKekhLNDg5SFR5NnNBYnhiWUVX -R3Ewam85RUtSS0x0SU9NTWJ3cVluc2Z3YnVHQzNSNm1CR29CZncwV1pUOEdlMDM1 -NEQ2MzlTR1NLSytLMW9IM0xCSVdDWFgxYkllWFFkaFRWQTR4UDExVDFIZzFLM0RY -WXVsUGpydFB0Yk5BVk44YmZUY3VSbHoxTlE9PSJ9 ------END ENCRYPTED COSIGN PRIVATE KEY----- diff --git a/.github/workflows/cosign-test.pub b/.github/workflows/cosign-test.pub deleted file mode 100644 index 385e6eef5..000000000 --- a/.github/workflows/cosign-test.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZxAfzrQG1EbWyCI8LiSB7YgSFXoI -FNGTyQGKHFc6/H8TQumT9VLS78pUwtv3w7EfKoyFZoP32KrO7nzUy2q6Cw== ------END PUBLIC KEY----- diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index fd7225918..a61e9d28f 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -96,5 +96,5 @@ jobs: uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc # v3 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.46.0 + version: v1.46.2 args: --timeout=5m diff --git a/.gitignore b/.gitignore index 5ef31f9f5..2ea313818 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,6 @@ /cosign* .vscode .idea -/sget* # fuzzing artifacts *.libfuzzer @@ -27,9 +26,7 @@ bin* dist/ -cosignImagerefs policyControllerImagerefs -sgetImagerefs policyImagerefs **verify-experimental* diff --git a/EXAMPLES.md b/EXAMPLES.md deleted file mode 100644 index 03056677c..000000000 --- a/EXAMPLES.md +++ /dev/null @@ -1,92 +0,0 @@ -# Other cosign examples - -## GCP KMS with `gcloud` - -Use `cosign` to generate the payload, sign it with `gcloud kms`, then use `cosign` to upload it. - -```shell -$ cosign generate us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun > payload.json -$ gcloud kms asymmetric-sign --digest-algorithm=sha256 --input-file=payload.json --signature-file=gcpkms.sig --key=foo --keyring=foo --version=1 --location=us-central -# We have to base64 encode the signature -$ cat gcpkms.sig | base64 | cosign attach signature --signature - us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun -``` - -Now (on another machine) download the public key, payload, signatures and verify it! - -```shell -$ cosign download signature us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun > signatures.json -# There could be multiple signatures, let's pretend it's the last one. -# Extract the payload and signature, base64 decoding them. -$ cat signatures.json | tail -1 | jq -r .Payload | base64 -D > payload -$ cat signatures.json | tail -1 | jq -r .Base64Signature | base64 -D > signature -# Now download the public key -$ gcloud kms keys versions get-public-key 1 --key=foo --keyring=foo --location=us-central1 > pubkey.pem -# Verify in openssl -$ openssl dgst -sha256 -verify pubkey.pem -signature gcpkms.sig payload -``` - -## Sign With OpenSSL, Verify With Cosign - -```shell -# Generate a keypair -$ openssl ecparam -name prime256v1 -genkey -noout -out openssl.key -$ openssl ec -in openssl.key -pubout -out openssl.pub -# Generate the payload to be signed -$ cosign generate us.gcr.io/dlorenc-vmtest2/demo > payload.json -# Sign it and convert to base64 -$ openssl dgst -sha256 -sign openssl.key -out payload.sig payload.json -$ cat payload.sig | base64 > payloadbase64.sig -# Upload the signature -$ cosign attach signature --payload payload.json --signature payloadbase64.sig us.gcr.io/dlorenc-vmtest2/demo -# Verify! -$ cosign verify --key openssl.pub us.gcr.io/dlorenc-vmtest2/demo -Verification for us.gcr.io/dlorenc-vmtest2/demo -- -The following checks were performed on each of these signatures: - - The cosign claims were validated - - The signatures were verified against the specified public key - - Any certificates were verified against the Fulcio roots. -{"critical":{"identity":{"docker-reference":"us.gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155"},"type":"cosign container image signature"},"optional":null} -``` - -## AWS KMS with `aws` - -Use `aws` (CLI version 2) to create a CMK for sign and verification (just need this once): - -```shell -$ export AWS_CMK_ID=$(aws kms create-key --customer-master-key-spec RSA_4096 \ - --key-usage SIGN_VERIFY \ - --description "Cosign Signature Key Pair" \ - --query KeyMetadata.KeyId --output text) -``` - -Use `cosign` to generate the payload, sign it with `aws kms`, then use `cosign` to upload it. - -```shell -$ cosign generate docker.io/davivcgarcia/hello-world:latest > payload.json - -$ aws kms sign --key-id $AWS_CMK_ID \ - --message file://payload.json \ - --message-type RAW \ - --signing-algorithm RSASSA_PKCS1_V1_5_SHA_256 \ - --output text \ - --query Signature > payload.sig - -$ cosign attach signature docker.io/davivcgarcia/hello-world:latest --signature $(< payload.sig) -``` - -Now (on another machine) use the `cosign` to download signature bundle, extract payload and signature value, and verify it with `aws kms`! - -```shell -$ cosign download signature docker.io/davivcgarcia/hello-world:latest > signatures.json - -$ cat signatures.json | tail -1 | jq -r .Base64Signature | base64 -D > remote_payload.sig -$ cat signatures.json | tail -1 | jq -r .Payload | base64 -D > remote_payload.json - -$ aws kms verify --key-id $AWS_CMK_ID \ - --message file://remote_payload.json \ - --message-type RAW \ - --signing-algorithm RSASSA_PKCS1_V1_5_SHA_256 \ - --signature fileb://remote_payload.sig \ - --output text \ - --query SignatureValid -``` \ No newline at end of file diff --git a/KMS.md b/KMS.md deleted file mode 100644 index a17a8db37..000000000 --- a/KMS.md +++ /dev/null @@ -1,208 +0,0 @@ -# KMS Integrations - -This page contains detailed instructions on how to configure `cosign` to work with KMS providers. -Right now `cosign` supports Hashicorp Vault, AWS KMS, and GCP KMS, and we are hoping to support more in the future! - -## Basic Usage - -When referring to a key managed by a KMS provider, `cosign` takes a [go-cloud](https://gocloud.dev) style URI to refer to the specific provider. -For example: - -`gcpkms://`, `awskms://`, or `hashivault://` - -The URI path syntax is provider specific and explained in the section for each provider. - -### Key Generation and Management - -To generate keys using a KMS provider, you can use the `cosign generate-key-pair` command with the `--kms` flag. -For example: - -```shell -$ cosign generate-key-pair --kms :// -``` - -The public key can be retrieved with: - -```shell -$ cosign public-key --key :// ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXc+DQU8Pb7Xo2RWCjFG/f6qbdABN -jnVtSyKZxNzBfNMLLtVxdu8q+AigrGCS2KPmejda9bICTcHQCRUrD5OLGQ== ------END PUBLIC KEY----- -``` - -### Signing and Verification - -To sign and verify using a key managed by a KMS provider, you can pass a provider-specific URI to the `--key` command: - -```shell -$ cosign sign --key :// gcr.io/dlorenc-vmtest2/demo -Pushing signature to: gcr.io/dlorenc-vmtest2/demo:sha256-410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd.cosign - -$ cosign verify --key :// gcr.io/dlorenc-vmtest2/demo - -Verification for gcr.io/dlorenc-vmtest2/demo -- -The following checks were performed on each of these signatures: - - The cosign claims were validated - - The signatures were verified against the specified public key - - Any certificates were verified against the Fulcio roots. - -[{"critical":{"identity":{"docker-reference":"gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd"},"type":"cosign container image signature"},"optional":null}] -``` - -You can also export the public key and verify against that file: - -```shell -$ cosign public-key --key :// > kms.pub -$ cosign verify --key kms.pub gcr.io/dlorenc-vmtest2/demo -``` - -### Providers - -This section contains the provider-specific documentation. - - -### AWS - -AWS KMS keys can be used in `cosign` for signing and verification. -The URI format for AWS KMS is: - -`awskms://$ENDPOINT/$KEYID` - -where ENDPOINT and KEYID are replaced with the correct values. - -The ENDPOINT value is left blank in most scenerios, but can be set for testing with KMS-compatible servers such as [localstack](https://localstack.cloud/). -If omitting a custom endpoint, it is mandatory to prefix the URI with `awskms:///` (with three slashes). - -If a custom endpoint is used, you may disable TLS verification by setting an environment variable: `AWS_TLS_INSECURE_SKIP_VERIFY=1`. - -AWS credentials are provided using standard configuration as [described in AWS docs](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials). - -The KEYID value must conform to any [AWS KMS key identifier](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id) -format as described in the linked document (Key ARN, Key ID, Alias ARN, or Alias ID). - -Note that key creation is not supported by cosign if using the Key ARN or Key ID formats, so it is recommended to use [Key Aliases](https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html) -for most situations. - -The following URIs are valid: - -- Key ID: `awskms:///1234abcd-12ab-34cd-56ef-1234567890ab` -- Key ID with endpoint: `awskms://localhost:4566/1234abcd-12ab-34cd-56ef-1234567890ab` -- Key ARN: `awskms:///arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab` -- Key ARN with endpoint: `awskms://localhost:4566/arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab` -- Alias name: `awskms:///alias/ExampleAlias` -- Alias name with endpoint: `awskms://localhost:4566/alias/ExampleAlias` -- Alias ARN: `awskms:///arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias` -- Alias ARN with endpoint: `awskms://localhost:4566/arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias` - -Example: - -```shell -$ export AWS_REGION=us-east-1 -$ export AWS_CMK_ID=$(aws kms create-key --customer-master-key-spec RSA_4096 \ - --key-usage SIGN_VERIFY \ - --description "Cosign Signature Key Pair" \ - --query KeyMetadata.KeyId --output text) - -$ cosign sign --key awskms:///${AWS_CMK_ID} docker.io/davivcgarcia/hello-world:latest -$ cosign verify --key awskms:///${AWS_CMK_ID} docker.io/davivcgarcia/hello-world:latest | jq . -``` - -### GCP - -GCP KMS keys can be used in `cosign` for signing and verification. -The URI format for GCP KMS is: - -`gcpkms://projects/$PROJECT/locations/$LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY/versions/$KEY_VERSION` - -where PROJECT, LOCATION, KEYRING, KEY and KEY_VERSION are replaced with the correct values. - -Cosign automatically uses GCP Application Default Credentials for authentication. -See the GCP [API documentation](https://cloud.google.com/docs/authentication/production) for information on how to authenticate in different environments. - -The user must have the following IAM roles: -* Safer KMS Viewer Role -* Cloud KMS CryptoKey Signer/Verifier (`roles/cloudkms.signerVerifier`) - -### Azure Key Vault - -Azure Key Vault keys can be used in `cosign` for signing and verification. - -The URI format for Azure Key Vault is: -`azurekms://[VAULT_NAME][VAULT_URI]/[KEY]` - -where VAULT_NAME, VAULT_URI, and KEY are replaced with the correct values. - -The following environment variables must be set to let cosign authenticate to Azure Key Vault. (see this [reference](https://devblogs.microsoft.com/azure-sdk/authentication-and-the-azure-sdk/#environment-variables) for more details about Azure SDK Authentication) -- AZURE_TENANT_ID -- AZURE_CLIENT_ID -- AZURE_CLIENT_SECRET - -To create a key using `cosign generate-key-pair -kms azurekms://[VAULT_NAME][VAULT_URI]/[KEY]` you will need a user which has permissions to create keys in Key Vault. For example `Key Vault Crypto Officer` role. - -To sign images using `cosign sign -key azurekms://[VAULT_NAME][VAULT_URI]/[KEY] [IMAGE]` you will need a user which has permissions to the sign action such as the `Key Vault Crypto User` role. - -### Hashicorp Vault - -Hashicorp Vault keys can be used in `cosign` for signing and verification. -The URI format for Hashicorp Vault KMS is: - -`hashivault://$keyname` - -This provider requires that the standard Vault environment variables (VAULT_ADDR, VAULT_TOKEN) are set correctly. -This provider also requires that the `transit` secret engine is enabled - -### Kubernetes Secret - -Cosign can use keys stored in Kubernetes Secrets to so sign and verify signatures. In -order to generate a secret you have to pass `cosign generate-key-pair` a -`k8s://[NAMESPACE]/[NAME]` URI specifying the namespace and secret name: - -``` -cosign generate-key-pair k8s://default/testsecret -Enter password for private key: **** -Enter again: **** -Successfully created secret testsecret in namespace default -Public key written to cosign.pub -``` - -After generating the key pair, cosign will store it in a Kubernetes secret using -your current context. The secret will contain the private and public keys, as -well as the password to decrypt the private key. - -The secret has the following structure: - -``` -apiVersion: v1 -kind: Secret -metadata: - name: testsecret - namespace: default -type: Opaque -data: - cosign.key: LS0tLS1CRUdJTiBFTkNSWVBURUQgQ09TSUdOIFBSSVZBVEUgS0VZLS0tLS[...]== - cosign.password: YWJjMTIz - cosign.pub: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQo[...]== -``` - -When verifying an image signature using `cosign verify`, the key will be automatically -decrypted using the password stored in the kubernetes secret under the `cosign.password` -field. - -#### Local Setup - -For a local setup, you can run Vault yourself or use the `docker-compose` file from [sigstore/sigstore](https://github.com/sigstore/sigstore/blob/main/test/e2e/docker-compose.yml) as an example. - -After running it: - -```shell -$ export VAULT_ADDR=http://localhost:8200 -$ export VAULT_TOKEN=testtoken -$ vault secrets enable transit -``` - -If you enabled `transit` secret engine at different path with the use of `-path` flag (i.e., `$ vault secrets enable -path="someotherpath" transit`), you can use `TRANSIT_SECRET_ENGINE_PATH` environment variable to specify this path while generating a key pair like the following: - -```shell -$ TRANSIT_SECRET_ENGINE_PATH="someotherpath" cosign generate-key-pair --kms hashivault://testkey -``` diff --git a/test/ci.mk b/test/ci.mk index 030cedd03..df45f23e9 100644 --- a/test/ci.mk +++ b/test/ci.mk @@ -2,15 +2,10 @@ # signing ci ############ -.PHONY: sign-policy-controller -sign-policy-controller: - cosign sign --key .github/workflows/cosign-test.key -a GIT_HASH=$(GIT_HASH) ${KO_PREFIX}/policy-controller:$(GIT_HASH) +.PHONY: sign-policy-images +sign-policy-images: + cosign sign -a GIT_HASH=$(GIT_HASH) ${KO_PREFIX}/policy-controller:$(GIT_HASH) + cosign sign -a GIT_HASH=$(GIT_HASH) ${KO_PREFIX}/policy-webhook:$(GIT_HASH) -.PHONY: sign-keyless-policy-controller -sign-keyless-policy-controller: - cosign sign -a sha=$(GIT_HASH) -a run_id=${GITHUB_RUN_ID} -a run_attempt=${GITHUB_RUN_ATTEMPT} ${KO_PREFIX}/policy-controller:$(GIT_HASH) - cosign sign -a sha=$(GIT_HASH) -a run_id=${GITHUB_RUN_ID} -a run_attempt=${GITHUB_RUN_ATTEMPT} ${KO_PREFIX}/policy-controller:$(GIT_VERSION) - - -.PHONY: sign-keyless-container -sign-keyless-container: ko sign-keyless-policy-controller +.PHONY: build-sign-containers +build-sign-containers: ko sign-policy-images