Giter Site home page Giter Site logo

chrisns / cosign-keyless-demo Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 0.0 68 KB

Proof of concept that uses cosign and GitHub's in built OIDC for actions to sign container images, providing a proof that what is in the registry came from your GitHub action.

License: MIT License

Dockerfile 100.00%
oidc github github-action cosign sigstore hacktoberfest proof-of-concept container

cosign-keyless-demo's Introduction

Cosign Keyless GitHub Action Demo

Proof of concept Security Scanning GitHub issues GitHub forks GitHub stars GitHub license

Proof of concept that uses cosign and GitHub's in built OIDC for actions to sign container images, providing a proof that what is in the registry came from your GitHub action.

I ❤️ Pull Requests

Why?

Lots of people are now using OIDC from Github Actions to federate auth to AWS, GCP etc. At the same time cosign and the overall sigstore are doing great work to make signing container images and trusting the supply chain far easier.

I wanted to sign images, but it felt like an anti pattern to store the long lived private key as a secret, when cosign has some OIDC magic for keyless signing.

I've made a working example which separates the build and the build and sign process, which might be overkill for your needs.

Usage

The very short answer is you need to add the id-token: write permission and then cosign sign

To see that in action see the abridged workflow:

name: Build Push Sign
on: { push: { branches: ['main'] } }

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      id-token: write

    steps:
      - uses: actions/checkout@v1

      - name: Login to GitHub
        uses: docker/[email protected]
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: build+push
        uses: docker/[email protected]
        with:
          context: .
          push: true
          tags: ghcr.io/chrisns/cosign-keyless-demo:latest

      - uses: sigstore/cosign-installer@main

      - name: Sign the images
        run: |
          cosign sign \
            ghcr.io/chrisns/cosign-keyless-demo:latest
        env:
          COSIGN_EXPERIMENTAL: 1

      - name: Verify the pushed tags
        run: cosign verify ghcr.io/chrisns/cosign-keyless-demo:latest
        env:
          COSIGN_EXPERIMENTAL: 1

We can now do:

$ COSIGN_EXPERIMENTAL=1 cosign verify -output text ghcr.io/chrisns/cosign-keyless-demo:latest

and get back, note the subject is https://github.com/chrisns/cosign-keyless-demo/.github/workflows/ci.yml@refs/heads/main

[
  {
    "critical": {
      "identity": {
        "docker-reference": "ghcr.io/chrisns/cosign-keyless-demo"
      },
      "image": {
        "docker-manifest-digest": "sha256:25884cd45107dd8d9b1b1e187c32ac8b97a0277fe506ac83da0cab27cf1d4c0d"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "Bundle": {
        "SignedEntryTimestamp": "MEQCID9dyEFKuXUNa7Ug5JKohmsOgb8kqtCLjB/KWZtMGcsnAiAEjOrcxs/WUVsEZOvdl0lbK6nGIlYi0Ld2McLq229VFg==",
        "Payload": {
          "body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJkMTExNTRhMDEyOGI0MzNiYTRmZGRkNzQzOTM4M2M0OTI3NmVmNGUxNTNiNjFjNGFiNmYyN2ZjNjQwNDIwMTI1In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUQrOU13QXRrRk9lN29mWGZQa0VRQVMvc0J2NHdjdG0xQktmeGRMRTU3amd3SWhBSlRPcHRxc2xIKzNhK0tCVW1ycVpnTnRKVmliRWFnd1dQRjFYTHBiallPeCIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVU4yUkVORFFXdEhaMEYzU1VKQlowbFVXRnBWUWtoWlNUaHJUVUZGU0ZKQ2RTOXZaRWwwYTNGVE0ycEJTMEpuWjNGb2EycFBVRkZSUkVGNlFYRUtUVkpWZDBWM1dVUldVVkZMUlhkNGVtRlhaSHBrUnpsNVdsTTFhMXBZV1hoRlZFRlFRbWRPVmtKQlRWUkRTRTV3V2pOT01HSXpTbXhOUWpSWVJGUkplQXBOVkVGNVRVUkZkMDFVVVhoT1JtOVlSRlJKZUUxVVFYbE5SRVYzVFhwUmVFMHhiM2RCUkVKYVRVSk5SMEo1Y1VkVFRUUTVRV2RGUjBORGNVZFRUVFE1Q2tGM1JVaEJNRWxCUWxCbVdUaDRibGhoY1Rob2JWUklPR3RhYkd0T2RHRlZRek40VHpaSllVSnlaeXR2UldKTFJURndWWHBFTWtSUGRHbHpha1ZzU3pnS1dHTkpVSFptUkdJMVRXTjNjU3RXYW5ablVEQldiMlJKZW1reWIwWTVlV3BuWjBaMVRVbEpRbUZxUVU5Q1owNVdTRkU0UWtGbU9FVkNRVTFEUWpSQmR3cEZkMWxFVmxJd2JFSkJkM2REWjFsSlMzZFpRa0pSVlVoQmQwMTNSRUZaUkZaU01GUkJVVWd2UWtGSmQwRkVRV1JDWjA1V1NGRTBSVVpuVVZWTWJqTnFDaXRTZG5ocmJDc3JNRGx6V1d0R2FFbzRRazB6TmxVd2QwaDNXVVJXVWpCcVFrSm5kMFp2UVZWNVRWVmtRVVZIWVVwRGEzbFZVMVJ5UkdFMVN6ZFZiMGNLTUN0M2QyZFpNRWREUTNOSFFWRlZSa0ozUlVKQ1NVZEJUVWcwZDJaQldVbExkMWxDUWxGVlNFMUJTMGRqUjJnd1pFaEJOa3g1T1hkamJXd3lXVmhTYkFwWk1rVjBXVEk1ZFdSSFZuVmtRekF5VFVST2JWcFVaR3hPZVRCM1RVUkJkMHhVU1hsTmFtTjBXVzFaTTA1VE1XMU9SMWt4V2xSbmQxcEVTVFZPVkZGMUNtTXpVblpqYlVadVdsTTFibUl5T1c1aVIxWm9ZMGRzZWt4dFRuWmlVemxxV1ZSTk1sbFVSbXhQVkZsNVRrUkthVTlYV21wWmFrVXdUbWs1YWxsVE5Xb0tZMjVSZDFwUldVUldVakJTUVZGSUwwSkdjM2RYV1ZwWVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKT2IyTnRiSHBpYmsxMldUSTVlZ3BoVjJSMVRGZDBiR1ZYZUd4ak0wMTBXa2RXZEdKNU9IVmFNbXd3WVVoV2FVd3paSFpqYlhSdFlrYzVNMk41T1dwaFV6VTFZbGQ0UVdOdFZtMWplVGx2Q2xwWFJtdGplVGwwV1Zkc2RVMUJiMGREUTNGSFUwMDBPVUpCVFVSQk1tdEJUVWRaUTAxUlEybG5ZMFIwVXpOaE15OW1hVk4xWkRWbk0wRTNLM1ZaTVNzS2VtOVlZM00zTkc4elFVd3djRmxPZVN0cU5FaHNWaTlLTTFCcWMxWjBXRGt4TVRWYWFYRnpRMDFSUTBScEsxaGhObXhIV1ZKNUsxTlJWMjR5UTI1aFl3cDNWM0V3Ykc0NU9HcDRObkp4UWxSVU1VOHdRamxhVTBsMFdXcG9jbVpyYnpSeFNFZDRlWGQ2YUVOelBRb3RMUzB0TFVWT1JDQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENnPT0ifX19fQ==",
          "integratedTime": 1634724863,
          "logIndex": 783661,
          "logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
        }
      },
      "Subject": "https://github.com/chrisns/cosign-keyless-demo/.github/workflows/ci.yml@refs/heads/main"
    }
  },
  {
    "critical": {
      "identity": {
        "docker-reference": "ghcr.io/chrisns/cosign-keyless-demo"
      },
      "image": {
        "docker-manifest-digest": "sha256:25884cd45107dd8d9b1b1e187c32ac8b97a0277fe506ac83da0cab27cf1d4c0d"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "Bundle": {
        "SignedEntryTimestamp": "MEYCIQDqC+9t68eV92HIpNbGLw/mmb831CwMKlTciw+U5dmU6AIhANB+DCpJSuSg66cz8Y+5YszFiE8ZVCuQDfTqrZ68yrGW",
        "Payload": {
          "body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJkMTExNTRhMDEyOGI0MzNiYTRmZGRkNzQzOTM4M2M0OTI3NmVmNGUxNTNiNjFjNGFiNmYyN2ZjNjQwNDIwMTI1In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNKQ0hibm5hejFZZVR4bXAyQjJrTWVjNmw1ZHAxSHFBeHNyR2RYOVY3VFFnSWdCZWJsNGFpd1V4R3hlZFpNVXRWK3E2ZzVac0t1bC8yZTZsa0JmeVlrWHNzPSIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVU4yUkVORFFXdEhaMEYzU1VKQlowbFVXRnBWUWtoWlNUaHJUVUZGU0ZKQ2RTOXZaRWwwYTNGVE0ycEJTMEpuWjNGb2EycFBVRkZSUkVGNlFYRUtUVkpWZDBWM1dVUldVVkZMUlhkNGVtRlhaSHBrUnpsNVdsTTFhMXBZV1hoRlZFRlFRbWRPVmtKQlRWUkRTRTV3V2pOT01HSXpTbXhOUWpSWVJGUkplQXBOVkVGNVRVUkZkMDFVVVhoT1JtOVlSRlJKZUUxVVFYbE5SRVYzVFhwUmVFMHhiM2RCUkVKYVRVSk5SMEo1Y1VkVFRUUTVRV2RGUjBORGNVZFRUVFE1Q2tGM1JVaEJNRWxCUWxCbVdUaDRibGhoY1Rob2JWUklPR3RhYkd0T2RHRlZRek40VHpaSllVSnlaeXR2UldKTFJURndWWHBFTWtSUGRHbHpha1ZzU3pnS1dHTkpVSFptUkdJMVRXTjNjU3RXYW5ablVEQldiMlJKZW1reWIwWTVlV3BuWjBaMVRVbEpRbUZxUVU5Q1owNVdTRkU0UWtGbU9FVkNRVTFEUWpSQmR3cEZkMWxFVmxJd2JFSkJkM2REWjFsSlMzZFpRa0pSVlVoQmQwMTNSRUZaUkZaU01GUkJVVWd2UWtGSmQwRkVRV1JDWjA1V1NGRTBSVVpuVVZWTWJqTnFDaXRTZG5ocmJDc3JNRGx6V1d0R2FFbzRRazB6TmxVd2QwaDNXVVJXVWpCcVFrSm5kMFp2UVZWNVRWVmtRVVZIWVVwRGEzbFZVMVJ5UkdFMVN6ZFZiMGNLTUN0M2QyZFpNRWREUTNOSFFWRlZSa0ozUlVKQ1NVZEJUVWcwZDJaQldVbExkMWxDUWxGVlNFMUJTMGRqUjJnd1pFaEJOa3g1T1hkamJXd3lXVmhTYkFwWk1rVjBXVEk1ZFdSSFZuVmtRekF5VFVST2JWcFVaR3hPZVRCM1RVUkJkMHhVU1hsTmFtTjBXVzFaTTA1VE1XMU9SMWt4V2xSbmQxcEVTVFZPVkZGMUNtTXpVblpqYlVadVdsTTFibUl5T1c1aVIxWm9ZMGRzZWt4dFRuWmlVemxxV1ZSTk1sbFVSbXhQVkZsNVRrUkthVTlYV21wWmFrVXdUbWs1YWxsVE5Xb0tZMjVSZDFwUldVUldVakJTUVZGSUwwSkdjM2RYV1ZwWVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKT2IyTnRiSHBpYmsxMldUSTVlZ3BoVjJSMVRGZDBiR1ZYZUd4ak0wMTBXa2RXZEdKNU9IVmFNbXd3WVVoV2FVd3paSFpqYlhSdFlrYzVNMk41T1dwaFV6VTFZbGQ0UVdOdFZtMWplVGx2Q2xwWFJtdGplVGwwV1Zkc2RVMUJiMGREUTNGSFUwMDBPVUpCVFVSQk1tdEJUVWRaUTAxUlEybG5ZMFIwVXpOaE15OW1hVk4xWkRWbk0wRTNLM1ZaTVNzS2VtOVlZM00zTkc4elFVd3djRmxPZVN0cU5FaHNWaTlLTTFCcWMxWjBXRGt4TVRWYWFYRnpRMDFSUTBScEsxaGhObXhIV1ZKNUsxTlJWMjR5UTI1aFl3cDNWM0V3Ykc0NU9HcDRObkp4UWxSVU1VOHdRamxhVTBsMFdXcG9jbVpyYnpSeFNFZDRlWGQ2YUVOelBRb3RMUzB0TFVWT1JDQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENnPT0ifX19fQ==",
          "integratedTime": 1634724867,
          "logIndex": 783662,
          "logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
        }
      },
      "Subject": "https://github.com/chrisns/cosign-keyless-demo/.github/workflows/ci.yml@refs/heads/main"
    }
  }
]

And we can inspect the certificate to check it

    Data:
        Version: 3 (0x2)
        Serial Number:
            5d:95:01:1d:82:3c:90:c0:04:1d:10:6e:fe:87:48:b6:4a:92:de
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: O=sigstore.dev, CN=sigstore
        Validity
            Not Before: Oct 20 10:14:14 2021 GMT
            Not After : Oct 20 10:34:13 2021 GMT
        Subject:
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:f7:d8:f3:19:d7:6a:af:21:99:31:fc:91:99:64:
                    36:d6:94:0b:7c:4e:e8:86:81:ae:0f:a8:11:b2:84:
                    d6:95:33:0f:60:ce:b6:2b:23:12:52:bc:5d:c2:0f:
                    bd:f0:db:e4:c7:30:ab:e5:63:be:03:f4:56:87:48:
                    ce:2d:a8:17:dc
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage:
                Code Signing
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                2E:7D:E3:F9:1B:F1:92:5F:BE:D3:DB:18:90:58:49:F0:13:37:E9:4D
            X509v3 Authority Key Identifier:
                keyid:C8:C5:1D:00:41:9A:24:29:32:51:24:EB:0D:AE:4A:ED:4A:06:D3:EC

            Authority Information Access:
                CA Issuers - URI:http://privateca-content-603fe7e7-0000-2227-bf75-f4f5e80d2954.storage.googleapis.com/ca36a1e96242b9fcb146/ca.crt

            X509v3 Subject Alternative Name: critical
                URI:https://github.com/chrisns/cosign-keyless-demo/.github/workflows/ci.yml@refs/heads/main
    Signature Algorithm: ecdsa-with-SHA384
         30:66:02:31:00:a2:81:c0:ed:4b:76:b7:fd:f8:92:b9:de:60:
         dc:0e:fe:b9:8d:7e:ce:85:dc:b3:be:28:dc:02:f4:a5:83:72:
         fa:3e:07:95:5f:c9:dc:f8:ec:56:d5:fd:d7:5e:59:8a:ab:02:
         31:00:83:8b:e5:da:ea:51:98:47:2f:92:41:69:f6:0a:76:9c:
         c1:6a:b4:96:7f:7c:8f:1e:ab:a8:14:d3:d4:ed:01:f5:94:88:
         b5:88:e1:ad:f9:28:e2:a1:c6:c7:2c:33:84:2b

A shorthand for extracting the public certificate is:

$ COSIGN_EXPERIMENTAL=1 cosign verify \
  -output json \
  ghcr.io/chrisns/cosign-keyless-demo:latest \
  | jq -r '.[0].optional.Bundle.Payload.body' \
  | base64 -d \
  | jq -r .spec.signature.publicKey.content \
  | base64 -d

References

cosign-keyless-demo's People

Contributors

chrisns avatar dependabot[bot] avatar jetersen avatar renovate-bot avatar renovate[bot] avatar the-repository-manager[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.