Skip to content

Commit 8296138

Browse files
committed
update notary project links
Signed-off-by: Yi Zha <[email protected]>
1 parent 80cd4b1 commit 8296138

File tree

1 file changed

+295
-0
lines changed

1 file changed

+295
-0
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
---
2+
title: Sign container images with Notation and Azure Key vault using a CA-issued certificate (Preview)
3+
description: In this tutorial learn to create a CA-issued certificate in Azure Key Vault, build and sign a container image stored in Azure Container Registry (ACR) with notation and AKV, and then verify the container image using notation.
4+
author: yizha1
5+
ms.author: yizha1
6+
ms.service: container-registry
7+
ms.custom: devx-track-azurecli
8+
ms.topic: how-to
9+
ms.date: 6/9/2023
10+
---
11+
12+
# Sign container images with Notation and Azure Key Vault using a CA-issued certificate (Preview)
13+
14+
Signing and verifying the container images with a certificate issued by a trusted Certificate Authority (CA) ensure authorizing and validating the identity responsibly with approved CA without any compromise. The trusted CA entities (for example, GlobalSign or DigiCert) ensure to validate the user's and organization's identity and also have the authority to revoke the certificate immediately upon any risk or misuse.
15+
16+
[Notation](https://github.com/notaryproject/notation) is an open source supply chain tool developed by [Notary Project](https://notaryproject.dev/), which supports signing and verifying container images and other artifacts. The Azure Key Vault (AKV) is used to store a certificate with a signing key that can be utilized by Notation with the [Notation AKV plugin (azure-kv)](https://github.com/Azure/notation-azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures to the signed image.
17+
18+
> [!IMPORTANT]
19+
> This feature is currently in preview. Previews are made available to you on the condition that you agree to the [supplemental terms of use][terms-of-use]. Some aspects of this feature may change prior to general availability (GA).
20+
21+
In this article:
22+
23+
> [!div class="checklist"]
24+
> * Install the notation CLI and AKV plugin
25+
> * Create or import a certificate issued by a CA in AKV
26+
> * Build and push a container image with ACR task
27+
> * Sign a container image with Notation CLI and AKV plugin
28+
> * Verify a container image signature with Notation CLI
29+
30+
## Prerequisites
31+
32+
> * Create or use an [Azure Container Registry](../container-registry/container-registry-get-started-azure-cli.md) for storing container images and signatures
33+
> * Create or use an [Azure Key Vault.](../key-vault/general/quick-create-cli.md)
34+
> * Install and configure the latest [Azure CLI](/cli/azure/install-azure-cli), or run commands in the [Azure Cloud Shell](https://portal.azure.com/#cloudshell/)
35+
36+
> [!NOTE]
37+
> We recommend creating a new Azure Key Vault for storing certificates only.
38+
39+
## Install the notation CLI and AKV plugin
40+
41+
1. Install `Notation v1.0.0` on a Linux amd64 environment. Follow the [Notation installation guide](https://notaryproject.dev/docs/user-guides/installation/) to download the package for other environments.
42+
43+
```bash
44+
# Download, extract and install
45+
curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.0.0/notation_1.0.0_linux_amd64.tar.gz
46+
tar xvzf notation.tar.gz
47+
48+
# Copy the notation cli to the desired bin directory in your PATH, for example
49+
cp ./notation /usr/local/bin
50+
```
51+
52+
2. Install the notation Azure Key Vault plugin on a Linux environment for remote signing. You can also download the package for other environments by following the [Notation AKV plugin installation guide](https://github.com/Azure/notation-azure-kv#installation-the-akv-plugin).
53+
54+
```bash
55+
# Create a directory for the plugin
56+
mkdir -p ~/.config/notation/plugins/azure-kv
57+
58+
# Download the plugin
59+
curl -Lo notation-azure-kv.tar.gz https://github.com/Azure/notation-azure-kv/releases/download/v1.0.1/notation-azure-kv_1.0.1_linux_amd64.tar.gz
60+
61+
# Extract to the plugin directory
62+
tar xvzf notation-azure-kv.tar.gz -C ~/.config/notation/plugins/azure-kv
63+
```
64+
65+
> [!NOTE]
66+
> The plugin directory varies depending upon the operating system in use. The directory path assumes Ubuntu. For more information, see [Notation directory structure for system configuration.](https://notaryproject.dev/docs/user-guides/how-to/notary-project-concepts/)
67+
68+
3. List the available plugins.
69+
70+
```bash
71+
notation plugin ls
72+
```
73+
74+
## Configure environment variables
75+
76+
> [!NOTE]
77+
> We recommend to provide values for the Azure resources to match the existing AKV and ACR resources for easy execution of commands in the tutorial.
78+
79+
1. Configure AKV resource names.
80+
81+
```bash
82+
# Name of the existing Azure Key Vault used to store the signing keys
83+
AKV_NAME=myakv
84+
85+
# Name of the certificate created or imported in AKV
86+
CERT_NAME=wabbit-networks-io
87+
88+
# X.509 certificate subject
89+
CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
90+
```
91+
92+
2. Configure ACR and image resource names.
93+
94+
```bash
95+
# Name of the existing registry example: myregistry.azurecr.io
96+
ACR_NAME=myregistry
97+
# Existing full domain of the ACR
98+
REGISTRY=$ACR_NAME.azurecr.io
99+
# Container name inside ACR where image will be stored
100+
REPO=net-monitor
101+
TAG=v1
102+
# Source code directory containing Dockerfile to build
103+
IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
104+
```
105+
106+
## Sign in with Azure CLI
107+
108+
```bash
109+
az login
110+
```
111+
112+
To learn more about Azure CLI and how to sign in with it, see [Sign in with Azure CLI](/cli/azure/authenticate-azure-cli).
113+
114+
115+
## Create or import a certificate issued by a CA in AKV
116+
117+
### Certificate requirements
118+
119+
When creating certificates for signing and verification, it is important to ensure that they meet the [Notary Project certificate requirement](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signature-specification.md#certificate-requirements).
120+
121+
The requirements for root and intermediate certificates are as follows:
122+
- The `basicConstraints` extension MUST be present and MUST be marked as critical. The `cA` field MUST be set `true`.
123+
- The `keyUsage` extension MUST be present and MUST be marked `critical`. Bit positions for `keyCertSign` MUST be set.
124+
125+
The requirements for certificates issued by a CA are as follows:
126+
- X.509 certificate properties:
127+
- Subject MUST contain common name (`CN`), country (`C`), state or province (`ST`), and organization (`O`). In this tutorial, `$CERT_SUBJECT` is used as the subject.
128+
- X.509 key usage flag must be `DigitalSignature` only.
129+
- Extended Key Usages (EKUs) must be empty or `1.3.6.1.5.5.7.3.3` (for Codesigning).
130+
- Key properties:
131+
- The property "exportable" should be set to `false`
132+
- Select [supported key type and size](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signature-specification.md#algorithm-selection)
133+
134+
> [!NOTE]
135+
> Version v1.0.0 of the Notation AKV plugin requires a specific certificate order in a certificate chain. However, this limitation has been removed in version v1.0.1. We recommend using the latest version of the plugin.
136+
137+
### Create a certificate issued by a CA
138+
139+
To create a certificate issued by a CA, follow these steps:
140+
141+
1. Create a certificate signing request (CSR) by following the instructions in [create certificate signing request](../key-vault/certificates/create-certificate-signing-request.md).
142+
2. When merging the CSR, make sure you merge the entire chain that brought back from the CA vendor.
143+
144+
### Import a certificate in AKV
145+
146+
To import a certificate, follow these steps:
147+
148+
1. Get the certificate file from CA vendor with entire certificate chain.
149+
2. Import the certificate into Azure Key Vault by following the instructions in [import a certificate](../key-vault/certificates/tutorial-import-certificate.md).
150+
151+
> [!NOTE]
152+
> If the certificate does not contain a certificate chain after creation or importing, you can obtain the intermediate and root certificates from your CA vendor. You can ask your vendor to provide you with a PEM file that contains the intermediate certificates (if any) and root certificate. This file can then be used at step 5 of [signing container images](#sign-a-container-image-with-notation-cli-and-akv-plugin).
153+
154+
## Sign a container image with Notation CLI and AKV plugin
155+
156+
1. Authenticate to your ACR by using your individual Azure identity.
157+
158+
```bash
159+
az acr login --name $ACR_NAME
160+
```
161+
162+
> [!IMPORTANT]
163+
> If you have Docker installed on your system and used `az acr login` or `docker login` to authenticate to your ACR, your credentials are already stored and available to notation. In this case, you don’t need to run `notation login` again to authenticate to your ACR. To learn more about authentication options for notation, see [Authenticate with OCI-compliant registries](https://notaryproject.dev/docs/user-guides/how-to/registry-authentication/).
164+
165+
2. Build and push a new image with ACR Tasks. Always use `digest` to identify the image for signing, because tags are mutable and and can be overwritten.
166+
167+
```bash
168+
DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv)
169+
IMAGE=$REGISTRY/${REPO}@$DIGEST
170+
```
171+
172+
3. Assign access policy in AKV (Azure CLI)
173+
174+
To sign a container image with a certificate in AKV, a principal must have authorized access to AKV. The principal can be a user principal, service principal, or managed identity. In this tutorial, we assign access policy to a signed-in user. To learn more about assigning policy to a principal, see [Assign Access Policy](/azure/key-vault/general/assign-access-policy).
175+
176+
To set the subscription that contains the AKV resources, run the following command:
177+
178+
```bash
179+
az account set --subscription <your_subscription_id>
180+
```
181+
182+
If the certificate contains the entire certificate chain, the principal must be granted key permission `Sign`, secret permission `Get`, and certificate permissions `Get`. To grant these permissions to the principal, run the following command:
183+
184+
```bash
185+
USER_ID=$(az ad signed-in-user show --query id -o tsv)
186+
az keyvault set-policy -n $AKV_NAME --key-permissions sign --secret-permissions get --certificate-permissions get --object-id $USER_ID
187+
```
188+
189+
If the certificate doesn't contain the chain, the principal must be granted key permission `Sign`, and certificate permissions `Get`. To grant these permissions to the principal, run the following command:
190+
191+
```bash
192+
USER_ID=$(az ad signed-in-user show --query id -o tsv)
193+
az keyvault set-policy -n $AKV_NAME --key-permissions sign --certificate-permissions get --object-id $USER_ID
194+
```
195+
196+
4. Get the Key ID for a certificate, assuming the certificate name is $CERT_NAME. A certificate in AKV can have multiple versions, the following command get the Key Id for the latest version.
197+
198+
```bash
199+
KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
200+
```
201+
202+
5. Sign the container image with the COSE signature format using the key ID.
203+
204+
If the certificate contains the entire certificate chain, run the following command:
205+
206+
```bash
207+
notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv
208+
```
209+
210+
If the certificate does not contain the chain, you need to use an additional plugin parameter `--plugin-config ca_certs=<ca_bundle_file>` to pass the CA certificates in a PEM file to AKV plugin, run the following command:
211+
212+
```bash
213+
notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv --plugin-config ca_certs=<ca_bundle_file>
214+
```
215+
216+
6. View the graph of signed images and associated signatures.
217+
218+
```bash
219+
notation ls $IMAGE
220+
```
221+
222+
## Verify a container image with Notation CLI
223+
224+
1. Add root certificate to a named trust store for signature verification. Users need to obtain the root certificate from the CA vendor, and assuming the root certificate file is stored in $ROOT_CERT.
225+
226+
```bash
227+
STORE_TYPE="ca"
228+
STORE_NAME="wabbit-networks.io"
229+
notation cert add --type $STORE_TYPE --store $STORE_NAME $ROOT_CERT
230+
```
231+
232+
2. List the root certificate to confirm.
233+
234+
```bash
235+
notation cert ls
236+
```
237+
238+
3. Configure trust policy before verification.
239+
240+
Trust policies allow users to specify fine-tuned verification policies. Use the following command to configure trust policy. Upon successful execution of the command, one trust policy named `wabbit-networks-images` is created. This trust policy applies to all the artifacts stored in repositories defined in `$REGISTRY/$REPO`. Assuming that the user trusts a specific identity with the X.509 subject `$CERT_SUBJECT`, which is used for the signing certificate. The named trust store `$STORE_NAME` of type `$STORE_TYPE` contains the root certificates. See [Trust store and trust policy specification](https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md) for details.
241+
242+
```bash
243+
cat <<EOF > ./trustpolicy.json
244+
{
245+
"version": "1.0",
246+
"trustPolicies": [
247+
{
248+
"name": "wabbit-networks-images",
249+
"registryScopes": [ "$REGISTRY/$REPO" ],
250+
"signatureVerification": {
251+
"level" : "strict"
252+
},
253+
"trustStores": [ "$STORE_TYPE:$STORE_NAME" ],
254+
"trustedIdentities": [
255+
"x509.subject: $CERT_SUBJECT"
256+
]
257+
}
258+
]
259+
}
260+
EOF
261+
```
262+
263+
4. Use `notation policy` to import the trust policy configuration from a JSON file that we created previously.
264+
265+
```bash
266+
notation policy import ./trustpolicy.json
267+
notation policy show
268+
```
269+
270+
5. The notation command can also help to ensure the container image hasn't been tampered with since build time by comparing the `sha` with what is in the registry.
271+
272+
```bash
273+
notation verify $IMAGE
274+
```
275+
Upon successful verification of the image using the trust policy, the sha256 digest of the verified image is returned in a successful output message.
276+
277+
## FAQ
278+
279+
- What should I do if the certificate is expired?
280+
281+
If the certificate has expired, it invalidates the signature. To resolve this issue, you should renew the certificate and sign container images again. Learn more about [Renew your Azure Key Vault certificates](../key-vault/certificates/overview-renew-certificate.md).
282+
283+
- What should I do if the root certificate is expired?
284+
285+
If the root certificate has expired, it invalidates the signature. To resolve this issue, you should obtain a new certificate from a trusted CA vendor and sign container images again. Replace the expired root certificate with the new one from the CA vendor.
286+
287+
- What should I do if the certificate is revoked?
288+
289+
If the certificate is revoked, it invalidates the signature. The most common reason for revoking a certificate is when the certificate’s private key has been compromised. To resolve this issue, you should obtain a new certificate from a trusted CA vendor and sign container images again.
290+
291+
## Next steps
292+
293+
See [Ratify on Azure: Allow only signed images to be deployed on AKS with Notation and Ratify](https://github.com/deislabs/ratify/blob/main/docs/quickstarts/ratify-on-azure.md).
294+
295+
[terms-of-use]: https://azure.microsoft.com/support/legal/preview-supplemental-terms/

0 commit comments

Comments
 (0)