Verify an image with Notation using GitHub Actions
In this article, you'll learn how to create a GitHub Actions workflow to achieve the following goals:
- Verify an image's signatures with Notation trust store and trust policy.
Prerequisites
- You've created an Azure Key Vault (AKV) and a self-signed signing key and certificate. To learn how to create these resources for testing purposes, see Create a self-signed certificate in AKV.
- You've created an Azure Container Registry (ACR).
- You have a GitHub repository to store the sample workflow file and GitHub Secrets.
Authenticate from Azure to GitHub
Follow the instructions in the Authenticate from Azure to GitHub section in order to connect GitHub Actions to your ACR and AKV.
Create the GitHub Actions workflow
Once you've configured authentication, you're ready to create the GitHub Actions workflow.
Create a
.github/workflows
directory in your repository on GitHub if this directory does not already exist.In the
.github/workflows
directory, create a file named<your-workflow>.yml
, filling in your own name for the placeholder.Copy the verify template workflow from the collapsed section below into your own
<your-workflow>.yml
file.
Click here to see the verify workflow template.
# setup notation and verify an OCI artifact stored in ACR
name: notation-github-actions-verify-template
on:
push:
env:
ACR_REGISTRY_NAME: <registry_name_of_your_ACR> # example: myRegistry.azurecr.io
ACR_REPO_NAME: <repository_name_of_your_ACR> # example: myRepo
target_artifact_reference: <ACR_REGISTRY_NAME/ACR_REPO_NAME@digest> # example: myRegistry.azurecr.io/myRepo@sha256:abcdef
NOTATION_EXPERIMENTAL: 1 # [Optional] when set, can use Referrers API in the workflow
jobs:
notation-verify:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
# Log in to Azure with your service principal secret
- name: Azure login
uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# If you are using OIDC and federated credential, make sure to replace the above step with below:
# - name: Azure login
# uses: Azure/login@v1
# with:
# client-id: ${{ secrets.AZURE_CLIENT_ID }}
# tenant-id: ${{ secrets.AZURE_TENANT_ID }}
# subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
# Log in to your ACR registry
- name: ACR login
run: |
az acr login --name ${{ env.ACR_REGISTRY_NAME }}
# Install Notation CLI, the default version is "1.1.0"
- name: setup notation
uses: notaryproject/notation-action/setup@v1
# Verify the OCI artifact
- name: verify OCI artifact
uses: notaryproject/notation-action/verify@v1
with:
target_artifact_reference: ${{ env.target_artifact_reference }}
trust_policy: .github/trustpolicy/trustpolicy.json
trust_store: .github/truststore
allow_referrers_api: 'true'
- Finally, update the environment variables based on your own environment and your chosen authentication method by following the comments in the template. Save and commit the file to your repository.
Important
.github/trustpolicy/trustpolicy.json
must follow the Notation trust policy specs.
.github/truststore
must follow the Notation trust store specs. For example:
.github/truststore
└── x509
├── ca
│ └── <my_trust_store1>
│ ├── <my_certificate1>
│ └── <my_certificate2>
└── signingAuthority
└── <my_trust_store2>
├── <my_certificate3>
└── <my_certificate4>
Trigger the GitHub Actions workflow
The trigger logic in the sample workflow is set to the
on: push
event. Committing the workflow file to a branch in your repository triggers the push event and runs your workflow.On success, you'll be able to see the image's signatures have been verified. Your output will look similar to the following:
Run notaryproject/notation-action/verify@v1
/home/runner/work/_temp/3d9e3a7c-3cb0-459f-81c4-36b3e0c95f8b/notation policy import --force .github/trustpolicy/trustpolicy.json
Warning: existing trust policy configuration file will be overwritten
Trust policy configuration imported successfully.
/home/runner/work/_temp/3d9e3a7c-3cb0-459f-81c4-36b3e0c95f8b/notation policy show
***
"version": "1.0",
"trustPolicies": [
***
"name": "wabbit-networks-images",
"registryScopes": [ "*" ],
"signatureVerification": ***
"level" : "audit"
***,
"trustStores": ["ca:acme-rockets"],
"trustedIdentities": [
"x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder",
"x509.subject: CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
]
***
]
***
/home/runner/work/_temp/3d9e3a7c-3cb0-459f-81c4-36b3e0c95f8b/notation cert add -t ca -s acme-rockets .github/truststore/x509/ca/acme-rockets/cert2.pem
Successfully added following certificates to named store acme-rockets of type ca:
.github/truststore/x509/ca/acme-rockets/cert2.pem
/home/runner/work/_temp/3d9e3a7c-3cb0-459f-81c4-36b3e0c95f8b/notation cert ls
STORE TYPE STORE NAME CERTIFICATE
ca acme-rockets cert2.pem
/home/runner/work/_temp/3d9e3a7c-3cb0-459f-81c4-36b3e0c95f8b/notation verify -v --allow-referrers-api ******
Warning: This feature is experimental and may not be fully tested or completed and may be deprecated. Report any issues to "https://github/notaryproject/notation"
level=info msg="Trying to use the referrers API"
level=info msg="Reference sha256:0e3642f0659bed3d5264e8445f38392ab9952b86730204ab9a19d1c5559e6b6e resolved to manifest descriptor: ***MediaType:application/vnd.docker.distribution.manifest.v2+json Digest:sha256:0e3642f0659bed3d5264e8445f38392ab9952b86730204ab9a19d1c5559e6b6e Size:2004 URLs:[] Annotations:map[] Data:[] Platform:<nil> ArtifactType:***"
level=info msg="Checking whether signature verification should be skipped or not"
level=info msg="Trust policy configuration: &***Name:wabbit-networks-images RegistryScopes:[*] SignatureVerification:***VerificationLevel:audit Override:map[]*** TrustStores:[ca:acme-rockets] TrustedIdentities:[x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder x509.subject: CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US]***"
level=info msg="Check over. Trust policy is not configured to skip signature verification"
level=info msg="Processing signature with manifest mediaType: application/vnd.oci.image.manifest.v1+json and digest: sha256:6a038e955464b882cd964954687152f6f115b2c0e77ac328b0bbdaf8ce869e61"
level=info msg="Trust policy configuration: &***Name:wabbit-networks-images RegistryScopes:[*] SignatureVerification:***VerificationLevel:audit Override:map[]*** TrustStores:[ca:acme-rockets] TrustedIdentities:[x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder x509.subject: CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US]***"
Successfully verified signature for ******
- Alternatively, you can configure your workflow file to trigger when a new tag is pushed to the Github repository. See Triggering a workflow for more details. This is a common practice that's done in order to secure a software release process while using GitHub Actions.
View your GitHub Actions workflow results
Under your GitHub repository name, click the Actions tab of your GitHub repository to see the workflow logs.