Skip to content

Commit

Permalink
update docs for gov cloud region
Browse files Browse the repository at this point in the history
Signed-off-by: Jim Bugwadia <[email protected]>
  • Loading branch information
JimBugwadia committed Mar 17, 2024
1 parent 8aaa30d commit 5eb72ef
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 120 deletions.
275 changes: 156 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,122 +8,6 @@ A [Kyverno](https://kyverno.io) extension service that executes the [AWS Signer]

![logo](img/kyverno-notation-aws.png)

# Features

## Image Signature Verification

The Nirmata extension service is invoked from a Kyverno policy which passes it a list of images to be verified. The service then verifies [notation](https://notaryproject.dev/) format signatures for container images using the [AWS Signer](https://docs.aws.amazon.com/signer/index.html) notation plugin and returns responses back to Kyverno.

The service manages Notation [trust policies](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-policy) and [trust stores](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-store) as Kubernetes resources.

## Image Digest Mutation

To ensure image integrity and prevent tampering, the service replaces image tags, which are mutable and can be spoofed, with digests.

The Kyverno policy passes the `images` variable to the services' `/checkimages` endpoint. The result returns a list of images with their JSON path and digests so Kyverno can mutate each image in the admission payload.

Here is an example:

**Response object structure**

```json
{
"verified": true,
"message": "...",
"results": [
{
"op": "replace",
"path": "/spec/containers/0/image",
"value": "<ACCOUNT>.dkr.ecr.<REGION>.amazonaws.com/<REPO>@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108"
}
]
}
```

**Kyverno policy fragment**

```yaml
mutate:
foreach:
- list: "response.results"
patchesJson6902: |-
- path: '{{ element.path }}'
op: '{{ element.op }}'
value: '{{ element.value }}'
```
## Attestation Verification
In addition to verifying signatures, the extension service can verify signed metadata i.e. [attestations](https://nirmata.com/2022/03/15/a-map-for-kubernetes-supply-chain-security/).
To verify attestations, the Kyverno policy can optionally pass a variable called `attestations` in the request:

```yaml
- key: attestations
value:
- imageReference: "*"
type:
- name: sbom/cyclone-dx
conditions:
all:
- key: \{{creationInfo.licenseListVersion}}
operator: Equals
value: "3.17"
message: invalid license version
- name: application/sarif+json
conditions:
all:
- key: \{{ element.components[].licenses[].expression }}
operator: AllNotIn
value: ["GPL-2.0", "GPL-3.0"]
- imageReference: "844333597536.dkr.ecr.us-west-2.amazonaws.com/kyverno-demo*" # this is just an example
type:
- name: application/vnd.cyclonedx
conditions:
all:
- key: \{{ element.components[].licenses[].expression }}
operator: AllNotIn
value: ["GPL-2.0", "GPL-3.0"]
```

The `attestations` variable is a JSON array where each entry has:
1. an `imageReference` to match images;
2. a type which specifies the name of the attestation; and
3. a list of conditions we want to verify the attestation data

In the example above we are verifying the following:
1. the attestations `sbom/cyclone-dx` and `application/sarif+json` exist for all images
2. the `creationInfo.licenseListVersion` is equal to 3.17 in the SBOM and GPL licenses are not present.
3. the attestation `application/vnd.cyclonedx` is available for all versions of the `844333597536.dkr.ecr.us-west-2.amazonaws.com/kyverno-demo` image and does not contain GPL licenses.

**NOTE:** The conditions key in the attestations must be escaped with `\` so Kyverno does not substitute them before executing the extension service.

## Caching

To prevent repeated lookups for verified images, the Nirmata extension has a built-in cache.

Caching is enabled by default and can be managed using the `--cacheEnabled` flag. The cache is a TTL-based cache, i.e, entries expire automatically after some time and the value of TTL can be customized using `--cacheTTLDurationSeconds` (default is 3600) and the max number of entries in the cache can be configured using `--cacheMaxSize` (default is 1000).

The cache stores the verification outcomes of images for the trust policy and verification outcomes of attestations with the trust policy and conditions. The cache is an in-memory cache that gets cleared when the pod is recreated. The cache will also be cleared when there is any change in trust policies and trust stores.

## Multi-Tenancy

In a shared cluster, each team may have different signatures and trust policies. To support such use cases, the extension allows configuring multiple [trust policies](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-policy) and [trust stores](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-store) as Kubernetes custom resources.

The extension service allows specifying what trust policy they want to use for verification thus enabling multi-tenancy. Multiple teams can share one cluster and have different trust policies separate from each other.
To specify the trust policy to use, we can pass the `trustPolicy` variable in the request.
```yaml
- key: trustPolicy
value: "tp-{{request.namespace}}"
```
or we can set the `DEFAULT_TRUST_POLICY` env variable. In the above example, we are dynamically using the trust policy for the namespace of the request.

## High Availability

Kyverno-notation-aws can be installed in a highly-available manner where additional replicas can be deployed for the plugin. The plugin does not use leader election for inbound API requests which means verification requests can be distributed and processed by all available replicas. Leader election is required for certificate management so therefore only one replica will handle these tasks at a given time.

Multiple replicas configured for the plugin can be used for both availability and scale. Vertical scaling of the individual replicas’ resources may also be performed to increase combined throughput.

# Setup
1. Setup your environment variables:
```sh
Expand Down Expand Up @@ -181,15 +65,15 @@ notation sign $IMAGE --key kyvernodemo --signature-manifest image
kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/config/install-latest-testing.yaml
```

**Note: Kyverno version should be higher than v1.11.0**
**Note: Kyverno v1.11.0 or higher is required**

2. Install the kyverno-notation-aws extension service

```sh
kubectl apply -f configs/install.yaml
```

3. Create CRs for Notation TrustPolicy and TrustStore
3. Create resources for the Notation TrustPolicy and TrustStore

```sh
kubectl apply -f configs/crds/
Expand All @@ -199,7 +83,9 @@ kubectl apply -f configs/crds/
kubectl apply -f configs/samples/truststore.yaml
```

Update the `${REGION}`, `${ACCOUNT}` and `${AWS_SIGNER_PROFILE_NAME}` in the [trustpolicy.yaml](configs/samples/trustpolicy.yaml) and then install in your cluster:
**NOTE 1**: Update the `${REGION}`, `${ACCOUNT}` and `${AWS_SIGNER_PROFILE_NAME}` in the [trustpolicy.yaml](configs/samples/trustpolicy.yaml) and then install in your cluster:

**NOTE 2**: The sample is configured to use commercial regions. For AWS GovCloud (US) see [Using AWS GovCloud](#using-aws-govcloud-and-commercial-regions).

```yaml
trustedIdentities:
Expand Down Expand Up @@ -340,3 +226,154 @@ The output should look like this:
"verified": true
}
````


# Features

## Image Signature Verification

The Nirmata extension service is invoked from a Kyverno policy which passes it a list of images to be verified. The service then verifies [notation](https://notaryproject.dev/) format signatures for container images using the [AWS Signer](https://docs.aws.amazon.com/signer/index.html) notation plugin and returns responses back to Kyverno.

The service manages Notation [trust policies](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-policy) and [trust stores](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-store) as Kubernetes resources.

## Image Digest Mutation

To ensure image integrity and prevent tampering, the service replaces image tags, which are mutable and can be spoofed, with digests.

The Kyverno policy passes the `images` variable to the services' `/checkimages` endpoint. The result returns a list of images with their JSON path and digests so Kyverno can mutate each image in the admission payload.
Here is an example:
**Response object structure**
```json
{
"verified": true,
"message": "...",
"results": [
{
"op": "replace",
"path": "/spec/containers/0/image",
"value": "<ACCOUNT>.dkr.ecr.<REGION>.amazonaws.com/<REPO>@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108"
}
]
}
```
**Kyverno policy fragment**
```yaml
mutate:
foreach:
- list: "response.results"
patchesJson6902: |-
- path: '{{ element.path }}'
op: '{{ element.op }}'
value: '{{ element.value }}'
```
## Attestation Verification
In addition to verifying signatures, the extension service can verify signed metadata i.e. [attestations](https://nirmata.com/2022/03/15/a-map-for-kubernetes-supply-chain-security/).
To verify attestations, the Kyverno policy can optionally pass a variable called `attestations` in the request:
```yaml
- key: attestations
value:
- imageReference: "*"
type:
- name: sbom/cyclone-dx
conditions:
all:
- key: \{{creationInfo.licenseListVersion}}
operator: Equals
value: "3.17"
message: invalid license version
- name: application/sarif+json
conditions:
all:
- key: \{{ element.components[].licenses[].expression }}
operator: AllNotIn
value: ["GPL-2.0", "GPL-3.0"]
- imageReference: "844333597536.dkr.ecr.us-west-2.amazonaws.com/kyverno-demo*" # this is just an example
type:
- name: application/vnd.cyclonedx
conditions:
all:
- key: \{{ element.components[].licenses[].expression }}
operator: AllNotIn
value: ["GPL-2.0", "GPL-3.0"]
```
The `attestations` variable is a JSON array where each entry has:
1. an `imageReference` to match images;
2. a type which specifies the name of the attestation; and
3. a list of conditions we want to verify the attestation data
In the example above we are verifying the following:
1. the attestations `sbom/cyclone-dx` and `application/sarif+json` exist for all images
2. the `creationInfo.licenseListVersion` is equal to 3.17 in the SBOM and GPL licenses are not present.
3. the attestation `application/vnd.cyclonedx` is available for all versions of the `844333597536.dkr.ecr.us-west-2.amazonaws.com/kyverno-demo` image and does not contain GPL licenses.
**NOTE:** The conditions key in the attestations must be escaped with `\` so Kyverno does not substitute them before executing the extension service.
## Caching
To prevent repeated lookups for verified images, the Nirmata extension has a built-in cache.
Caching is enabled by default and can be managed using the `--cacheEnabled` flag. The cache is a TTL-based cache, i.e, entries expire automatically after some time and the value of TTL can be customized using `--cacheTTLDurationSeconds` (default is 3600) and the max number of entries in the cache can be configured using `--cacheMaxSize` (default is 1000).
The cache stores the verification outcomes of images for the trust policy and verification outcomes of attestations with the trust policy and conditions. The cache is an in-memory cache that gets cleared when the pod is recreated. The cache will also be cleared when there is any change in trust policies and trust stores.
## Multi-Tenancy
In a shared cluster, each team may have different signatures and trust policies. To support such use cases, the extension allows configuring multiple [trust policies](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-policy) and [trust stores](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-store) as Kubernetes custom resources.
The extension service allows specifying what trust policy they want to use for verification thus enabling multi-tenancy. Multiple teams can share one cluster and have different trust policies separate from each other.
To specify the trust policy to use, we can pass the `trustPolicy` variable in the request.
```yaml
- key: trustPolicy
value: "tp-{{request.namespace}}"
```
or we can set the `DEFAULT_TRUST_POLICY` env variable. In the above example, we are dynamically using the trust policy for the namespace of the request.
## High Availability
Kyverno-notation-aws can be installed in a highly-available manner where additional replicas can be deployed for the plugin. The plugin does not use leader election for inbound API requests which means verification requests can be distributed and processed by all available replicas. Leader election is required for certificate management so therefore only one replica will handle these tasks at a given time.
Multiple replicas configured for the plugin can be used for both availability and scale. Vertical scaling of the individual replicas’ resources may also be performed to increase combined throughput.
## Using Other Regions
A TrustPolicy can reference one or more TrustStore resources. For example, here is how a policy can be configured for both AWS GovCloud and commercial regions:
```yaml
apiVersion: notation.nirmata.io/v1alpha1
kind: TrustPolicy
metadata:
name: aws-signer-tp
spec:
version: '1.0'
trustPolicyName: aws-signer-tp
trustPolicies:
- name: aws-signer-tp
registryScopes:
- "*"
signatureVerification:
level: strict
override: {}
trustStores:
- signingAuthority:aws-signer-ts
- signingAuthority:aws-us-gov-signer-ts
trustedIdentities:
- arn:aws:signer:Region:111122223333:/signing-profiles/ecr_signing_profile
- arn:aws:signer:Region:111122223333:/signing-profiles/ecr_signing_profile2
```
Each TrustStore will then have to be configured with the appropriate root certificates, for the region.
The [sample TrustStore](./configs/samples/truststore.yaml) contains examples you can customize with your account and region information.
For more information, please refer to: https://docs.aws.amazon.com/signer/latest/developerguide/image-verification.html.
31 changes: 30 additions & 1 deletion configs/samples/truststore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ metadata:
spec:
trustStoreName: aws-signer-ts
type: signingAuthority
# The AWS root cert for commercial regions can be downloaded from:
# https://d2hvyiie56hcat.cloudfront.net/aws-signer-notation-root.cert
caBundle: |-
-----BEGIN CERTIFICATE-----
MIICWTCCAd6gAwIBAgIRAMq5Lmt4rqnUdi8qM4eIGbYwCgYIKoZIzj0EAwMwbDEL
Expand Down Expand Up @@ -49,4 +51,31 @@ spec:
ByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ
5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0
uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
-----END CERTIFICATE-----
-----END CERTIFICATE-----
---
apiVersion: notation.nirmata.io/v1alpha1
kind: TrustStore
metadata:
name: aws-us-gov-signer-ts
spec:
trustStoreName: aws-us-gov-signer-ts
type: signingAuthority
# The AWS root cert for the US GovCloud partition can be downloaded from:
# https://d2hvyiie56hcat.cloudfront.net/aws-us-gov-signer-notation-root.cert
caBundle: |-
-----BEGIN CERTIFICATE-----
MIICdDCCAfqgAwIBAgIRANXkpKrZj0L324qGaqRhW/cwCgYIKoZIzj0EAwMwejEL
MAkGA1UEBhMCVVMxDDAKBgNVBAoMA0FXUzEVMBMGA1UECwwMQ3J5cHRvZ3JhcGh5
MQswCQYDVQQIDAJXQTE5MDcGA1UEAwwwQVdTIFNpZ25lciBDb2RlIFNpZ25pbmcg
R292Q2xvdWQgKFVTKSBSb290IENBIEcxMCAXDTI0MDMwNjIzMzgyOFoYDzIxMjQw
MzA3MDAzODI4WjB6MQswCQYDVQQGEwJVUzEMMAoGA1UECgwDQVdTMRUwEwYDVQQL
DAxDcnlwdG9ncmFwaHkxCzAJBgNVBAgMAldBMTkwNwYDVQQDDDBBV1MgU2lnbmVy
IENvZGUgU2lnbmluZyBHb3ZDbG91ZCAoVVMpIFJvb3QgQ0EgRzEwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAARog54ObzWaGU6fAOcL4Af+P93l2t8Dl9hVD2n0eSSfmPq1
3jtXgjcpXZIjMfoiWQPJTvyAB3opRyvO3grvUaWxRnjtwB/Pusj4tzhnaN+b80eJ
iRn6AzrI9vBssd1ZyRKjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJF4
zoYzTyn/5s8EleoNvek9QeE6MA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAwNo
ADBlAjEA8tcKeLPxBB0mRmfkJn5+hgYxZaRGQatO5mxmjkB/DNIfJ1WeEE3tbCHr
pNJL32FUAjBQY82UNV5yJrKFHOxuiQ+athQZUHLvWvAIXKExt9wvLdtKzfpag8BI
o2A2A4nk0jk=
-----END CERTIFICATE-----⏎

0 comments on commit 5eb72ef

Please sign in to comment.