Skip to content

Commit f348deb

Browse files
authored
Merge pull request #248675 from yizha1/cssc/update_experience
doc: update signing using a self-signed certificate
2 parents e23756b + c18c64e commit f348deb

File tree

1 file changed

+118
-84
lines changed

1 file changed

+118
-84
lines changed
Lines changed: 118 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,64 @@
11
---
2-
title: Build, Sign and Verify a container image using notation and certificate in Azure Key Vault
3-
description: In this tutorial you'll learn to create a signing certificate, build a container image, remote sign image with notation and Azure Key Vault, and then verify the container image using the Azure Container Registry.
4-
author: feynmanzhou
5-
ms.author: davete
2+
title: Sign container images with Notation and Azure Key Vault using a self-signed certificate (Preview)
3+
description: In this tutorial you'll learn to create a self-signed certificate in Azure Key Vault (AKV), build and sign a container image stored in Azure Container Registry (ACR) with notation and AKV, and then verify the container image with notation.
4+
author: yizha1
5+
ms.author: yizha1
66
ms.service: container-registry
77
ms.custom: devx-track-azurecli
88
ms.topic: how-to
99
ms.date: 4/23/2023
1010
---
1111

12-
# Build, sign, and verify container images using Notary and Azure Key Vault (Preview)
12+
# Sign container images with Notation and Azure Key Vault using a self-signed certificate (Preview)
1313

14-
The Azure Key Vault (AKV) is used to store a signing key that can be utilized by [notation](http://notaryproject.dev/) with the notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures using the **az** or **oras** CLI commands.
15-
16-
The signed image enables users to assure deployments are built from a trusted entity and verify artifact hasn't been tampered with since their creation. The signed artifact ensures integrity and authenticity before the user pulls an artifact into any environment and avoid attacks.
14+
Signing container images is a process that ensures their authenticity and integrity. This is achieved by adding a digital signature to the container image, which can be validated during deployment. The signature helps to verify that the image is from a trusted publisher and has not been modified. [Notation](https://github.com/notaryproject/notation) is an open source supply chain tool developed by the [Notary Project](https://notaryproject.dev/), which supports signing and verifying container images and other artifacts. The Azure Key Vault (AKV) is used to store certificates with signing keys that can be used by Notation with the Notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach signatures to container images and other artifacts as well as view those signatures.
1715

16+
> [!IMPORTANT]
17+
> 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).
1818
1919
In this tutorial:
2020

2121
> [!div class="checklist"]
22-
> * Store a signing certificate in Azure Key Vault
23-
> * Sign a container image with notation
24-
> * Verify a container image signature with notation
22+
> * Install Notation CLI and AKV plugin
23+
> * Create a self-signed certificate in AKV
24+
> * Build and push a container image with [ACR Tasks](container-registry-tasks-overview.md)
25+
> * Sign a container image with Notation CLI and AKV plugin
26+
> * Validate a container image against the signature with Notation CLI
2527
2628
## Prerequisites
2729

28-
> * Create and sign in ACR with OCI artifact enabled
29-
> * Create or use an [Azure Key Vault](../key-vault/general/quick-create-cli.md)
30-
>* This tutorial can be run in the [Azure Cloud Shell](https://portal.azure.com/#cloudshell/)
30+
* Create or use an [Azure Container Registry](../container-registry/container-registry-get-started-azure-cli.md) for storing container images and signatures
31+
* Create or use an [Azure Key Vault](../key-vault/general/quick-create-cli.md) for managing certificates
32+
* 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/)
3133

32-
## Install the notation CLI and AKV plugin
34+
## Install Notation CLI and AKV plugin
3335

34-
1. Install notation v1.0.0-rc.7 on a Linux environment. You can also download the package for other environments by following the [Notation installation guide](https://notaryproject.dev/docs/installation/cli/).
36+
1. Install Notation v1.0.0 on a Linux amd64 environment. You can also download the package for other environments by following the [Notation installation guide](https://notaryproject.dev/docs/user-guides/installation/).
3537

3638
```bash
3739
# Download, extract and install
38-
curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.0.0-rc.7/notation_1.0.0-rc.7_linux_amd64.tar.gz
40+
curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.0.0/notation_1.0.0_linux_amd64.tar.gz
3941
tar xvzf notation.tar.gz
4042

41-
# Copy the notation cli to the desired bin directory in your PATH
43+
# Copy the Notation binary to the desired bin directory in your $PATH, for example
4244
cp ./notation /usr/local/bin
4345
```
4446

45-
2. Install the notation Azure Key Vault plugin on a Linux environment for remote signing and verification. 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).
47+
2. Install the Notation Azure Key Vault plugin on a Linux amd64 environment. 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).
4648

4749
> [!NOTE]
48-
> The plugin directory varies depending upon the operating system being used. The directory path below assumes Ubuntu. Please read the [Notation directory structure for system configuration](https://notaryproject.dev/docs/concepts/directory-structure/) for more information.
50+
> The plugin directory varies depending upon the operating system being used. The directory path below assumes Ubuntu. Please read the [Notation directory structure for system configuration](https://notaryproject.dev/docs/user-guides/how-to/directory-structure/) for more information.
4951

5052
```bash
5153
# Create a directory for the plugin
5254
mkdir -p ~/.config/notation/plugins/azure-kv
5355
5456
# Download the plugin
5557
curl -Lo notation-azure-kv.tar.gz \
56-
https://github.com/Azure/notation-azure-kv/releases/download/v1.0.0-rc.2/notation-azure-kv_1.0.0-rc.2_linux_amd64.tar.gz
58+
https://github.com/Azure/notation-azure-kv/releases/download/v1.0.1/notation-azure-kv_1.0.1_linux_amd64.tar.gz
5759
5860
# Extract to the plugin directory
59-
tar xvzf notation-azure-kv.tar.gz -C ~/.config/notation/plugins/azure-kv notation-azure-kv
61+
tar xvzf notation-azure-kv.tar.gz -C ~/.config/notation/plugins/azure-kv
6062
```
6163

6264
3. List the available plugins.
@@ -73,12 +75,12 @@ In this tutorial:
7375
1. Configure AKV resource names.
7476

7577
```bash
76-
# Name of the existing Azure Key Vault used to store the signing keys
77-
AKV_NAME=<your-unique-keyvault-name>
78-
# New desired key name used to sign and verify
79-
KEY_NAME=wabbit-networks-io
80-
CERT_SUBJECT="CN=wabbit-networks.io,O=Notary,L=Seattle,ST=WA,C=US"
81-
CERT_PATH=./${KEY_NAME}.pem
78+
# Name of the existing AKV used to store the signing keys
79+
AKV_NAME=myakv
80+
# Name of the certificate created in AKV
81+
CERT_NAME=wabbit-networks-io
82+
CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
83+
CERT_PATH=./${CERT_NAME}.pem
8284
```
8385

8486
2. Configure ACR and image resource names.
@@ -96,16 +98,47 @@ In this tutorial:
9698
IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
9799
```
98100

99-
## Store the signing certificate in AKV
101+
## Sign in with Azure CLI
102+
103+
```bash
104+
az login
105+
```
106+
107+
To learn more about Azure CLI and how to sign in with it, see [Sign in with Azure CLI](/cli/azure/authenticate-azure-cli).
108+
109+
## Assign access policy in AKV (Azure CLI)
110+
111+
A user principal with the correct access policy permissions is needed to create a self-signed certificate and sign artifacts. This principal can be a user principal, service principal, or managed identity. At a minimum, this principal needs the following permissions:
112+
113+
- `Create` permissions for certificates
114+
- `Get` permissions for certificates
115+
- `Sign` permissions for keys
116+
117+
In this tutorial, the access policy is assigned to a signed-in Azure user. To learn more about assigning policy to a principal, see [Assign Access Policy](/azure/key-vault/general/assign-access-policy).
100118

101-
If you have an existing certificate, upload it to AKV. For more information on how to use your own signing key, see the [signing certificate requirements.](https://github.com/Azure/notation-azure-kv/blob/release-0.6/docs/ca-signed-workflow.md)
102-
Otherwise create an x509 self-signed certificate storing it in AKV for remote signing using the steps below.
119+
### Set the subscription that contains the AKV resource
103120

104-
### Create a self-signed certificate (Azure CLI)
121+
```bash
122+
az account set --subscription <your_subscription_id>
123+
```
124+
125+
### Set the access policy in AKV
126+
127+
```bash
128+
USER_ID=$(az ad signed-in-user show --query id -o tsv)
129+
az keyvault set-policy -n $AKV_NAME --certificate-permissions create get --key-permissions sign --object-id $USER_ID
130+
```
131+
132+
> [!IMPORTANT]
133+
> This example shows the minimum permissions needed for creating a certificate and signing a container image. Depending on your requirements, you may need to grant additional permissions.
134+
135+
## Create a self-signed certificate in AKV (Azure CLI)
136+
137+
The following steps show how to create a self-signed certificate for testing purpose.
105138

106139
1. Create a certificate policy file.
107140

108-
Once the certificate policy file is executed as below, it creates a valid signing certificate compatible with **notation** in AKV. The EKU listed is for code-signing, but isn't required for notation to sign artifacts. The subject is used later as trust identity that user trust during verification.
141+
Once the certificate policy file is executed as below, it creates a valid certificate compatible with [Notary Project certificate requirement](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signature-specification.md#certificate-requirements) in AKV. The value for `ekus` is for code-signing, but isn't required for notation to sign artifacts. The subject is used later as trust identity that user trust during verification.
109142
110143
```bash
111144
cat <<EOF > ./my_policy.json
@@ -114,6 +147,12 @@ Otherwise create an x509 self-signed certificate storing it in AKV for remote si
114147
"certificateTransparency": null,
115148
"name": "Self"
116149
},
150+
"keyProperties": {
151+
"exportable": false,
152+
"keySize": 2048,
153+
"keyType": "RSA",
154+
"reuseKey": true
155+
},
117156
"x509CertificateProperties": {
118157
"ekus": [
119158
"1.3.6.1.5.5.7.3.3"
@@ -130,87 +169,79 @@ Otherwise create an x509 self-signed certificate storing it in AKV for remote si
130169
131170
2. Create the certificate.
132171
133-
```azure-cli
134-
az keyvault certificate create -n $KEY_NAME --vault-name $AKV_NAME -p @my_policy.json
172+
```bash
173+
az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
135174
```
136175
137-
3. Get the Key ID for the certificate.
176+
## Sign a container image with Notation CLI and AKV plugin
177+
178+
1. Authenticate to your ACR by using your individual Azure identity.
138179
139180
```bash
140-
KEY_ID=$(az keyvault certificate show -n $KEY_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
181+
az acr login --name $ACR_NAME
141182
```
142-
143-
4. Download public certificate.
183+
184+
> [!IMPORTANT]
185+
> 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/).
186+
187+
2. Build and push a new image with ACR Tasks. Always use the digest value to identify the image for signing since tags are mutable and can be overwritten.
144188
145189
```bash
146-
CERT_ID=$(az keyvault certificate show -n $KEY_NAME --vault-name $AKV_NAME --query 'id' -o tsv)
147-
az keyvault certificate download --file $CERT_PATH --id $CERT_ID --encoding PEM
190+
DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv)
191+
IMAGE=$REGISTRY/${REPO}@$DIGEST
148192
```
149193
150-
5. Add a signing key referencing the key ID.
194+
In this tutorial, if the image has already been built and is stored in the registry, the tag serves as an identifier for that image for convenience.
151195
152196
```bash
153-
notation key add $KEY_NAME --plugin azure-kv --id $KEY_ID
197+
IMAGE=$REGISTRY/${REPO}@$TAG
154198
```
155199
156-
6. List the keys to confirm.
200+
3. Get the Key ID of the signing key. A certificate in AKV can have multiple versions, the following command gets the Key ID of the latest version.
157201
158-
```bash
159-
notation key ls
160-
```
202+
```bash
203+
KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
204+
```
161205
162-
7. Add the downloaded public certificate to named trust store for signature verification.
206+
4. Sign the container image with the [COSE](https://datatracker.ietf.org/doc/html/rfc9052) signature format using the signing key ID. To sign with a self-signed certificate, you need to set the plugin configuration value `self_signed=true`.
163207
164-
```bash
165-
STORE_TYPE="ca"
166-
STORE_NAME="wabbit-networks.io"
167-
notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
168-
```
208+
```bash
209+
notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
210+
```
169211
170-
8. List the certificate to confirm.
212+
5. View the graph of signed images and associated signatures.
171213
172214
```bash
173-
notation cert ls
215+
notation ls $IMAGE
174216
```
175217
176-
## Build and sign a container image
177-
178-
1. Build and push a new image with ACR Tasks.
218+
## Verify a container image with Notation CLI
179219
180-
```azure-cli
181-
az acr build -r $ACR_NAME -t $IMAGE $IMAGE_SOURCE
182-
```
220+
To verify the container image, add the root certificate that signs the leaf certificate to the trust store and create trust policies for verification. For the self-signed certificate used in this tutorial, the root certificate is the self-signed certificate itself.
183221
184-
2. Authenticate with your individual Azure AD identity to use an ACR token.
222+
1. Download public certificate.
185223
186-
```azure-cli
187-
export USER_NAME="00000000-0000-0000-0000-000000000000"
188-
export PASSWORD=$(az acr login --name $ACR_NAME --expose-token --output tsv --query accessToken)
189-
notation login -u $USER_NAME -p $PASSWORD $REGISTRY
224+
```bash
225+
az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
190226
```
191227
192-
> [!NOTE]
193-
> Currently, `notation` relies on [Docker Credential Store](https://docs.docker.com/engine/reference/commandline/login/#credentials-store) for authentication. Notation requires additional configuration on Linux. If `notation login` is failing, you can configure the Docker Credential Store or Notation environment variables by following the guide [Authenticate with OCI-compliant registries](https://notaryproject.dev/docs/how-to/registry-authentication/).
228+
2. Add the downloaded public certificate to named trust store for signature verification.
194229
195-
3. Sign the container image with the [COSE](https://datatracker.ietf.org/doc/html/rfc8152) signature format using the signing key added in previous step.
196-
197-
```bash
198-
notation sign --signature-format cose --key $KEY_NAME $IMAGE
199-
```
230+
```bash
231+
STORE_TYPE="ca"
232+
STORE_NAME="wabbit-networks.io"
233+
notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
234+
```
200235
201-
4. View the graph of signed images and associated signatures.
236+
3. List the certificate to confirm.
202237
203238
```bash
204-
notation ls $IMAGE
239+
notation cert ls
205240
```
241+
242+
4. Configure trust policy before verification.
206243
207-
## Verify the container image
208-
209-
1. Configure trust policy before verification.
210-
211-
The trust policy is a JSON document named `trustpolicy.json`, which is stored under the notation configuration directory. Users who verify signed artifacts from a registry use the trust policy to specify trusted identities that sign the artifacts, and the level of signature verification to use.
212-
213-
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`. The trust identity that user trusts has the x509 subject `$CERT_SUBJECT` from previous step, and stored under trust store named `$STORE_NAME` of type `$STORE_TYPE`. See [Trust store and trust policy specification](https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md) for details.
244+
Trust policies allow users to specify fine-tuned verification policies. The following example configures a trust policy named `wabbit-networks-images`, which applies to all artifacts in `$REGISTRY/$REPO` and uses the named trust store `$STORE_NAME` of type `$STORE_TYPE`. It also assumes that the user trusts a specific identity with the X.509 subject `$CERT_SUBJECT`. For more details, see [Trust store and trust policy specification](https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md).
214245
215246
```bash
216247
cat <<EOF > ./trustpolicy.json
@@ -233,20 +264,23 @@ Otherwise create an x509 self-signed certificate storing it in AKV for remote si
233264
EOF
234265
```
235266
236-
3. Use `notation policy` to import the trust policy configuration from a JSON file that we created previously.
267+
5. Use `notation policy` to import the trust policy configuration from a JSON file that we created previously.
237268
238269
```bash
239270
notation policy import ./trustpolicy.json
240271
notation policy show
241272
```
242273
243-
4. 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.
274+
6. Use `notation verify` to verify the container image hasn't been altered since build time.
244275

245276
```bash
246277
notation verify $IMAGE
247278
```
279+
248280
Upon successful verification of the image using the trust policy, the sha256 digest of the verified image is returned in a successful output message.
249281

250282
## Next steps
251283

252284
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).
285+
286+
[terms-of-use]: https://azure.microsoft.com/support/legal/preview-supplemental-terms/

0 commit comments

Comments
 (0)