Skip to content

Commit

Permalink
doc: update README (#84)
Browse files Browse the repository at this point in the history
- update README.md to include a basic case azure-kv sign & verify guide

Resolve part of #78 

Signed-off-by: Junjie Gao <[email protected]>
  • Loading branch information
JeyJeyGao authored Mar 31, 2023
1 parent 8406300 commit 45ff974
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 28 deletions.
64 changes: 42 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,58 @@

[![codecov](https://codecov.io/gh/Azure/notation-azure-kv/branch/main/graph/badge.svg)](https://codecov.io/gh/Azure/notation-azure-kv)

Azure Provider for the Notary v2 [Notation CLI](https://github.com/notaryproject/notation)
Azure Provider for the [Notation CLI](https://github.com/notaryproject/notation)

## Getting Started:
The following summarizes the steps to configure the Azure Key Vault notation plugin, configure gatekeeper, sign and verify a container image to Azure Kubernetes Service
The `notation-azure-kv` plugin allows you to sign the Notation-generated payload with a certificate in Azure Key Vault (AKV). The certificate and private key are stored in AKV and the plugin will request signing and obtain the leaf certificate from AKV.

```bash
# Sign in with Azure CLI.
# Other authorization methods are also available.
# See https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorizatio
az login
The plugin supports authentication by [Azure CLI](https://learn.microsoft.com/cli/azure/authenticate-azure-cli) or [Managed Identity](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview). Azure CLI authenticate is used by default. To enable `Managed Identity` authentication, set the `AKV_AUTH_METHOD` environment variable to `AKV_AUTH_FROM_MI`.

# Add signing and verification keys to the notation configuration policy
notation key add --name $KEY_NAME --plugin azure-kv --id $KEY_ID
notation cert add --name $KEY_NAME $CERT_PATH
## Installation the AKV plugin
Before you begin, make sure the latest version of the [Notation CLI has been installed](https://notaryproject.dev/docs/installation/cli/).

# Install ratify, with the verification key
helm install ratify ratify/charts/ratify \
--set registryCredsSecret=regcred \
--set ratifyTestCert=$PUBLIC_KEY
kubectl apply -f ./ratify/charts/ratify-gatekeeper/templates/constraint.yaml
1. Navigate to the [Releases](https://github.com/Azure/notation-azure-kv/releases) page and select the latest release of `notation-azure-kv`. Under the *Assets* section, select the `notation-azure-kv` binary for your platform.
2. Validate the checksum using the values in `checksums.txt` and then install the plugin.

# Remotely sign with Azure Key Vault
notation sign --key $KEY_NAME $IMAGE
For Linux Bash:
```sh
version=0.6.0

# Deploy the image, with Gatekeeper, Ratify and Notary v2 validation of the signed image
kubectl run net-monitor --image=$IMAGE -n demo
```
# validate checksum
cat checksums.txt | grep notation-azure-kv_${version}_linux_amd64.tar.gz | sha256sum -c

See [documentation for details on remote signing with Azure Key Vault, validating a deployment to AKS with Notation and Ratify, using a simple setup script.](docs/nv2-bicep.md).
# install the plugin
mkdir -p "$HOME/.config/notation/plugins/azure-kv"
tar zxf notation-azure-kv_${version}_linux_amd64.tar.gz -C "$HOME/.config/notation/plugins/azure-kv" notation-azure-kv
```
For macOS Zsh:
```sh
version=0.6.0

# validate checksum
cat checksums.txt | grep notation-azure-kv_${version}_darwin_amd64.tar.gz | shasum -a 256 -c

# install the plugin
mkdir -p "$HOME/Library/Application Support/notation/plugins/azure-kv"
tar zxf notation-azure-kv_${version}_darwin_amd64.tar.gz -C "$HOME/Library/Application Support/notation/plugins/azure-kv" notation-azure-kv
```
For Windows Powershell:
```powershell
$version = "0.6.0"
# validate checksum
(Get-FileHash .\notation-azure-kv_${version}_windows_amd64.zip).Hash
# install the plugin
mkdir "$env:AppData\notation\plugins\azure-kv"
Expand-Archive -Path notation-azure-kv_${version}_windows_amd64.zip -DestinationPath "$env:AppData\notation\plugins\azure-kv"
```
3. Run `notation plugin list` and confirm the `azure-kv` plugin is installed.

## Getting started
1. [Sign and verify an artifact with a self-signed Azure Key Vault certificate](docs/self-signed-workflow.md)
2. [Sign and verify an artifact with a certificate signed by a trusted CA in Azure Key Vault](docs/ca-signed-workflow.md)

> **Note** Please make sure the certificate is in PEM format. PCKS#12 will be supported in the future.
## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Expand Down
6 changes: 3 additions & 3 deletions cmd/notation-azure-kv/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ type certificateMock struct {
err error
}

func (c *certificateMock) Sign(ctx context.Context, algorithm azkeys.JSONWebKeySignatureAlgorithm, digest []byte) ([]byte, error) {
func (c *certificateMock) Sign(_ context.Context, _ azkeys.JSONWebKeySignatureAlgorithm, _ []byte) ([]byte, error) {
panic("not implemented") // TODO: Implement
}

func (c *certificateMock) CertificateChain(ctx context.Context) ([]*x509.Certificate, error) {
func (c *certificateMock) CertificateChain(_ context.Context) ([]*x509.Certificate, error) {
panic("not implemented") // TODO: Implement
}

func (c *certificateMock) Certificate(ctx context.Context) (*x509.Certificate, error) {
func (c *certificateMock) Certificate(_ context.Context) (*x509.Certificate, error) {
return c.cert, c.err
}

Expand Down
133 changes: 133 additions & 0 deletions docs/ca-signed-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Sign and verify an artifact with a certificate signed by a trusted CA in Azure Key Vault
> **Note** The following guide can be executed on Linux bash, macOS Zsh and Windows WSL
1. [Install the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
2. Log in to Azure with Azure CLI, set the subscription and make sure the `GetCertificate` and `Sign` permission have been granted to your role:
```sh
az login
az account set --subscription $subscriptionID
```
3. Create an Azure Key Vault:
```sh
resourceGroup=<your-resource-group-name>
keyVault=<your-key-vault-name>
location=westus
certName=notationLeafCert

# create a resource group
az group create -n $resourceGroup -l $location

# create a Azure Key Vault
az keyvault create -l $location -n $keyVault --resource-group $resourceGroup
```
4. Create a Certificate Signing Request (CSR):
```sh
# generate certificate policy
cat <<EOF > ./leafCert.json
{
"issuerParameters": {
"certificateTransparency": null,
"name": "Unknown"
},
"keyProperties": {
"curve": null,
"exportable": false,
"keySize": 2048,
"keyType": "RSA",
"reuseKey": true
},
"secretProperties": {
"contentType": "application/x-pem-file"
},
"x509CertificateProperties": {
"ekus": [
"1.3.6.1.5.5.7.3.3"
],
"keyUsage": [
"digitalSignature"
],
"subject": "CN=Test-Signer,C=US,ST=WA,O=notation",
"validityInMonths": 12
}
}
EOF
# create the leaf certificate
az keyvault certificate create -n $certName --vault-name $keyVault -p @leafCert.json
# get the CSR
CSR=$(az keyvault certificate pending show --vault-name $keyVault --name $certName --query 'csr' -o tsv)
CSR_PATH=${certName}.csr
printf -- "-----BEGIN CERTIFICATE REQUEST-----\n%s\n-----END CERTIFICATE REQUEST-----\n" $CSR > ${CSR_PATH}
```
5. Please take `${certName}.csr` file to a trusted CA to sign and issue your certificate, or you can use `openssl` tool to sign it locally for testing.
6. After you get the leaf certificate, you can merge the leaf certificate (`$leafCert`) to your Azure Key Vault:
```sh
az keyvault certificate pending merge --vault-name $keyVault --name $certName --file $leafCert
# get the key identifier
keyID=$(az keyvault certificate show -n $certName --vault-name $keyVault --query 'kid' -o tsv)
```
7. [Create an Azure Container Registry](https://learn.microsoft.com/azure/container-registry/container-registry-get-started-portal?tabs=azure-cli). The remaining steps use the example login server `<registry-name>.azurecr.io`, but you must substitute your own login server value.
8. Log in to container registry and push an image for signing:
```sh
registryName="<registry-name>"
server="${registryName}.azurecr.io"
az acr login --name $registryName
# notation login $server # if you don't use Azure Container Registry
# push a hello-world image for signing
docker pull hello-world:latest
docker tag hello-world:latest $server/hello-world:v1
docker push $server/hello-world:v1
```
9. Sign the image with an external certificate bundle (`$certBundlePath`) including the intermediate certificates and a root certificate in PEM format. You may fetch the certificate bundle from your CA official website.
```sh
notation key add --plugin azure-kv --id $keyID akv-key --default
notation sign $server/hello-world:v1 --plugin-config=ca_certs=$certBundlePath
```
The following example output shows the artifact is successfully signed.
```
Warning: Always sign the artifact using digest(@sha256:...) rather than a tag(:v1) because tags are mutable and a tag reference can point to a different artifact than the one signed.
Successfully signed notation.azurecr.io/hello-world@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4
```
10. Signature verification with Notation needs the root certificate of your CA in the trust store and a `trustpolicy.json` file in Notation configuration directory:
```sh
# add root certificate ($rootCertPath) to notation trust store
notation cert add --type ca --store trusted $rootCertPath
# add notation trust policy
notationConfigDir="${HOME}/.config/notation" # for Linux and WSL
# notationConfigDir="${HOME}/Library/Application Support/notation" # for macOS
mkdir -p $notationConfigDir
cat <<EOF > $notationConfigDir/trustpolicy.json
{
"version": "1.0",
"trustPolicies": [
{
"name": "trust-policy-example",
"registryScopes": [ "*" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:trusted" ],
"trustedIdentities": [
"*"
]
}
]
}
EOF
chmod 600 $notationConfigDir/trustpolicy.json
```
11. Verify the signature associated with the image:
```
notation verify $server/hello-world:v1
```
The following output shows the artifact is successfully verified.
```
Warning: Always verify the artifact using digest(@sha256:...) rather than a tag(:v1) because resolved digest may not point to the same signed artifact, as tags are mutable.
Successfully verified signature for notation.azurecr.io/hello-world@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4
```
129 changes: 129 additions & 0 deletions docs/self-signed-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Sign and verify an artifact with a self-signed Azure Key Vault certificate
> **Warning** Using self-signed certificates are intended for development and testing. Outside of development and testing, a certificate from a trusted CA is recommended.
> **Note** The following guide can be executed on Linux bash, macOS Zsh and Windows WSL
1. [Install the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
2. Log in using the Azure CLI, set the subscription, and confirm the `GetCertificate` and `Sign` permission have been granted to your role:
```sh
az login
az account set --subscription $subscriptionID
```
3. Create an Azure Key Vault:
```sh
resourceGroup=<your-resource-group-name>
keyVault=<your-key-vault-name>
location=westus
certName=notationSelfSignedCert

# create a resource group
az group create -n $resourceGroup -l $location

# create a Azure Key Vault
az keyvault create -l $location -n $keyVault --resource-group $resourceGroup
```
4. create a self-signed certificate:
```sh
# generate certificate policy
cat <<EOF > ./selfSignedPolicy.json
{
"issuerParameters": {
"certificateTransparency": null,
"name": "Self"
},
"keyProperties": {
"curve": null,
"exportable": false,
"keySize": 2048,
"keyType": "RSA",
"reuseKey": true
},
"secretProperties": {
"contentType": "application/x-pem-file"
},
"x509CertificateProperties": {
"ekus": [
"1.3.6.1.5.5.7.3.3"
],
"keyUsage": [
"digitalSignature"
],
"subject": "CN=Test-Signer,C=US,ST=WA,O=notation",
"validityInMonths": 12
}
}
EOF
# create self-signed certificate
az keyvault certificate create -n $certName --vault-name $keyVault -p @selfSignedPolicy.json
# get the key identifier
keyID=$(az keyvault certificate show -n $certName --vault-name $keyVault --query 'kid' -o tsv)
```
5. [Create an Azure Container Registry](https://learn.microsoft.com/azure/container-registry/container-registry-get-started-portal?tabs=azure-cli). The remaining steps use the example login server `<registry-name>.azurecr.io`, but you must substitute your own login server value.
6. Log in to container registry and push an image for signing:
```sh
registryName="<registry-name>"
server="${registryName}.azurecr.io"
az acr login --name $registryName
# notation login $server # if you don't use Azure Container Registry
# push a hello-world image for signing
docker pull hello-world:latest
docker tag hello-world:latest $server/hello-world:v1
docker push $server/hello-world:v1
```
7. Sign the container image with Notation:
```sh
notation key add --plugin azure-kv --id $keyID akv-key --default
notation sign $server/hello-world:v1
```
The following example output shows the artifact is successfully signed.
```
Warning: Always sign the artifact using digest(@sha256:...) rather than a tag(:v1) because tags are mutable and a tag reference can point to a different artifact than the one signed.
Successfully signed notation.azurecr.io/hello-world@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4
```
8. Add the certificate to your trust store and the `trustpolicy.json` to Notation configuration directory:
```sh
cat <<EOF > ./selfSignedCert.crt
-----BEGIN CERTIFICATE-----
$(az keyvault certificate show -n $certName --vault-name $keyVault --query 'cer' -o tsv)
-----END CERTIFICATE-----
EOF
notation cert add --type ca --store selfSigned ./selfSignedCert.crt
# add notation trust policy
notationConfigDir="${HOME}/.config/notation" # for Linux and WSL
# notationConfigDir="${HOME}/Library/Application Support/notation" # for macOS
mkdir -p $notationConfigDir
cat <<EOF > $notationConfigDir/trustpolicy.json
{
"version": "1.0",
"trustPolicies": [
{
"name": "trust-policy-example",
"registryScopes": [ "*" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:selfSigned" ],
"trustedIdentities": [
"*"
]
}
]
}
EOF
chmod 600 $notationConfigDir/trustpolicy.json
```
9. Verify the signature associated with the image:
```sh
notation verify $server/hello-world:v1
```
The following output shows the artifact is successfully verified.
```
Warning: Always verify the artifact using digest(@sha256:...) rather than a tag(:v1) because resolved digest may not point to the same signed artifact, as tags are mutable.
Successfully verified signature for notation.azurecr.io/hello-world@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4
```
6 changes: 3 additions & 3 deletions internal/keyvault/keyvault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type keyVault struct {
err error
}

func (s *keyVault) Sign(ctx context.Context, name string, version string, parameters azkeys.SignParameters, options *azkeys.SignOptions) (azkeys.SignResponse, error) {
func (s *keyVault) Sign(_ context.Context, _ string, _ string, _ azkeys.SignParameters, _ *azkeys.SignOptions) (azkeys.SignResponse, error) {
return s.resp, s.err
}

Expand Down Expand Up @@ -142,7 +142,7 @@ type certificateVault struct {
err error
}

func (s *certificateVault) GetCertificate(ctx context.Context, certificateName string, certificateVersion string, options *azcertificates.GetCertificateOptions) (azcertificates.GetCertificateResponse, error) {
func (s *certificateVault) GetCertificate(_ context.Context, _ string, _ string, _ *azcertificates.GetCertificateOptions) (azcertificates.GetCertificateResponse, error) {
return s.resp, s.err
}

Expand Down Expand Up @@ -191,7 +191,7 @@ type secretVault struct {
err error
}

func (s *secretVault) GetSecret(ctx context.Context, name string, version string, options *azsecrets.GetSecretOptions) (azsecrets.GetSecretResponse, error) {
func (s *secretVault) GetSecret(_ context.Context, _ string, _ string, _ *azsecrets.GetSecretOptions) (azsecrets.GetSecretResponse, error) {
return s.resp, s.err
}

Expand Down

0 comments on commit 45ff974

Please sign in to comment.