kritis-validation-hook is a key component that is used to verify the signatures of container images. You can use signature verification to ensure that only images signed by trusted authorities are deployed. This reduces the risk of malicious code execution. This topic provides examples on how kritis-validation-hook is used to verify signatures.

Prerequisites

A managed or dedicated Kubernetes cluster is created. For more information, see Create an ACK managed cluster or Create an ACK dedicated cluster.

Background information

kritis-validation-hook is developed based on the open source project kritis and is integrated with Container Registry. You can use kritis-validation-hook to verify the signatures of images that are signed by Key Management Service (KMS). You can also use kritis-validation-hook together with Security Center, KMS, and Container Registry to automate image signing and signature verification. This helps you build a secure environment for clusters. For more information about how to enable automatic signature verification for container images, see Use kritis-validation-hook to automatically verify the signatures of container images.

Authorize a cluster to access resources

To ensure that kritis-validation-hook works as normal, you must grant the following permissions to the Resource Access Management (RAM) role of the cluster:

Notice
  • If you use a managed Kubernetes cluster, you must grant the following permissions to the worker RAM role of the cluster.
  • If you use a dedicated Kubernetes cluster, you must grant the following permissions to the master RAM role and the worker RAM role of the cluster.
cr:ListInstance
cr:ListMetadataOccurrences

If you want to grant the preceding permissions to the RAM role of your cluster, perform the following steps:

  1. Log on to the ACK console.
  2. In the left-side navigation pane of the ACK console, click Clusters.
  3. On the Clusters page, find the cluster that you want to manage and click the name of the cluster or click Details in the Actions column. The details page of the cluster appears.
  4. On the Cluster Information page, click the Cluster Resources tab and find the RAM role of the cluster.
    • If the cluster is a managed Kubernetes cluster, click the name of the RAM role to the right of the Worker RAM Role field.
    • If the cluster is a dedicated Kubernetes cluster, you must click the name of the RAM role to the right of Master RAM Role and also the name of the RAM role to the right of Worker RAM Role.
  5. On the RAM role details page, click the Permissions tab, and then click k8s******RolePolicy-**** in the Policy column.
  6. On the policy details page, click the Policy Document tab, and then click Modify Policy Document.
  7. In the Modify Policy Document panel, add the following policy content to the Action section and click OK:
    {
        "Action": [
            "cr:ListInstance",
            "cr:ListMetadataOccurrences"
        ],
        "Resource": [
            "*"
        ],
        "Effect": "Allow"
    }

Example on how to enable signature verification

The following example demonstrates how kritis-validation-hook is used to enable signature verification for the default namespace.
Note This example does not include further details about image signing because you cannot use kritis-validation-hook to sign images. For more information, see Sign container images. The following information specifies the address of the image that is signed in this example. Replace it with the address of the image that you want to use.
  • The signed image: kritis-demo-registry.cn-hangzhou.cr.aliyuncs.com/kritis-demo/alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45.

    If no immutable tag is added to the image, you must specify the image by using the digest of the image. For more information, see Configure a repository to be immutable.

  • The witness name (image signature key) that is used to sign the image: demo-aa.
  • Run the cat publickey.txt | base64 | tr -d '\n' command to generate a public key that is encoded by using Base64: LS0tLS1CRUdJTiBQ***.

    The public key that corresponds to the KMS key is stored in the publickey.txt file.

  • The ID of the KMS key: 4a2ef103-5aa3-4220-****.
  1. Create an AttestationAuthority object to declare a trusted authority.
    1. Use the following template to create an AttestationAuthority.yaml file:
      apiVersion: kritis.grafeas.io/v1beta1
      kind: AttestationAuthority
      metadata:
        name: demo-aa
      spec:
        noteReference: namespaces/demo-aa
        publicKeyData: LS0tLS1CRUdJTiBQ***
        publicKeyId: 4a2ef103-5aa3-4220-****
    2. Run the following command to apply the trusted authority:
      kubectl apply -f AttestationAuthority.yaml
  2. Create a GenericAttestationPolicy object to declare a signature verification policy and use the trusted authority to verify image signatures.
    1. Use the following template to create a GenericAttestationPolicy.yaml file:
      apiVersion: kritis.grafeas.io/v1beta1
      kind: GenericAttestationPolicy
      metadata:
        name: demo-gap
      spec:
        attestationAuthorityNames:
        - demo-aa
    2. Run the following command to apply the signature verification policy:
      kubectl apply -f GenericAttestationPolicy.yaml
  3. Use an image that is not signed by the specified trusted authority to test the signature verification feature.
    • Run the following command to test signature verification:
      kubectl create deployment test-denied --image=alpine:3.11

      Expected output:

      Error from server: admission webhook "kritis-validation-hook-deployments.grafeas.io" denied the request: image alpine:3.11 is not attested
    • Run the following command to test signature verification:
      kubectl create deployment test-denied --image=kritis-demo-registry.cn-hangzhou.cr.aliyuncs.com/kritis-demo/alpine:3.11

      Expected output:

      Error from server: admission webhook "kritis-validation-hook-deployments.grafeas.io" denied the request: image kritis-demo-registry.cn-hangzhou.cr.aliyuncs.com/kritis-demo/alpine:3.11 is not attested

    The output indicates that the image fails to pass the verification and the request to deploy a pod from the image is denied.

  4. Use an image that is signed by the specified trusted authority to test the signature verification feature.

    Run the following command to test signature verification:

    kubectl create deployment test-allow --image=kritis-demo-registry.cn-hangzhou.cr.aliyuncs.com/kritis-demo/alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45

    Expected output:

    deployment.apps/test-allow created

    The output indicates that the image passes the verification and a pod is deployed from the image.

Configure a signature verification whitelist

In middleware or service mesh scenarios, the images of sidecar containers injected by third-party components may fail to pass signature verification. To resolve this issue, kritis-validation-hook allows you to configure a signature verification whitelist. After you configure a signature verification whitelist, kritis-validation-hook verifies only the signatures of images that are not included in the whitelist. The signatures of images that are included in the whitelist are not verified.

You can configure a signature verification whitelist by defining the admissionallowlists.kritis.grafeas.io resource. The resource is defined in the following custom resource definition (CRD):
apiVersion: kritis.grafeas.io/v1beta1   # This is the default value. Do not change the value. 
kind: AdmissionAllowlist                # This is the default value. Do not change the value. 
metadata:
  name: kritis-allowlist                # The name of the resource. The name must be unique within the cluster. 
spec:
  patterns:                             # The content of the whitelist. You can add one or more images to the whitelist. 
  - namePattern: 'registry*.*.aliyuncs.com/acs/*' # The name of the image whose signature you do not want the system to verify. 
  - namePattern: 'registry-vpc.cn-beijing.aliyuncs.com/arms-docker-repo/*'
    namespace: 'default'    # Optional. The namespace to which the whitelist is applied. If you do not specify a namespace, the whitelist is applied to all namespaces. 

To add a system image of ACK to the whitelist, perform the following steps:

  1. Use the following template to create a kritis-admission-allowlist-acs.yaml file:
    apiVersion: kritis.grafeas.io/v1beta1
    kind: AdmissionAllowlist
    metadata:
      name: allow-acs-images
    spec:
      patterns:
      - namePattern: 'registry*.*.aliyuncs.com/acs/*'
    The namePattern parameter supports exact match and fuzzy match by using asterisks (*).
    • If the value of namePattern does not contain asterisks, exact match is performed. For example, a value of nginx:v0.1.0 matches only nginx:v0.1.0.
    • You must pay attention to the following limits before you use asterisks for fuzzy match:
      • If an asterisk appears at the end of an expression, the asterisk matches all characters except forward slashes (/). For example, a.com/nginx* matches a.com/nginx:v0.1.0 but does not match a.com/nginx/test:v0.1.0.
      • If an asterisk does not appear at the end of an expression, the asterisk matches letters, digits, hyphens (-), and underscores (_). For example, registry-vpc.cn-*.aliyuncs.com/acs/pause:3.2 matches both registry-vpc.cn-hangzhou.aliyuncs.com/acs/pause:3.2 and registry-vpc.cn-beijing.aliyuncs.com/acs/pause:3.2.
    The following list shows the images that you can add to the whitelist in most cases:
    # Images used by Container Service for Kubernetes (ACK).
    - namePattern: 'registry*.*.aliyuncs.com/acs/*'
    
    # Images used by ACK in regions within China.
    - namePattern: 'registry*.cn-*.aliyuncs.com/acs/*'
    
    # Images used by Application Real-Time Monitoring Service (ARMS).
    - namePattern: 'registry*.*.aliyuncs.com/arms-docker-repo/*'
    
    # Images used by ARMS in regions within China.
    - namePattern: 'registry*.cn-*.aliyuncs.com/arms-docker-repo/*'
  2. Run the following command to configure a whitelist:
    kubectl apply -f kritis-admission-allowlist-acs.yaml 

    Expected output:

    admissionallowlist.kritis.grafeas.io/allow-acs-images created
  3. Run the following command to check whether the whitelist takes effect:
    kubectl get admissionallowlists.kritis.grafeas.io

    Expected output:

    NAME               AGE
    allow-acs-images   2m22s