Use kritis-validation-hook with Container Registry, Key Management Service (KMS), and Security Center to enforce image signature verification at deploy time. Only images signed by trusted authorities are admitted to the cluster, reducing the risk of running tampered or unauthorized container images.
How it works
Four services work together to deliver end-to-end image signing and verification:
| Service | Role |
|---|---|
| KMS | Generates and stores the RSA key pair used to sign images |
| Security Center | Manages witnesses (signing authorities) and security policies that bind a witness to a cluster namespace |
| Container Registry | Automatically signs images pushed to enabled namespaces using the KMS key via the configured witness |
| kritis-validation-hook | Runs as an admission webhook in your ACK cluster and blocks unsigned or unattested images from being deployed |
When signature verification is active, any kubectl deployment request for an unsigned image is denied before the pod is scheduled.
Prerequisites
Before you begin, ensure that you have:
An ACK cluster with cluster authorization configured. For details, see Authorize a cluster to access resources
An Alibaba Cloud Container Registry (ACR) Enterprise Edition instance with Instance Type set to Advanced. To create one, click Create ACR EE in the Container Registry console and select Advanced
Images referenced by digest (format:
image@sha256:<hash>). Images referenced by tag are blocked even if signed
Step 1: Install kritis-validation-hook
Log on to the ACK console. In the left-side navigation pane, click Clusters.
On the Clusters page, find the cluster you want to manage and click its name. In the left-side navigation pane, choose Operations > Add-ons.
On the Add-ons page, click the Security tab, find kritis-validation-hook, and click Install.
Step 2: Create a signing key in KMS
Create a Customer Master Key (CMK) in KMS to use for image signing. For instructions, see Manage a key.
Set Key Spec to RSA_2048 and Purpose to Sign/Verify. Other key specs or purposes are not supported for image signing.
Step 3: Create a witness in Security Center
A witness represents a trusted signing authority. Security policies reference witnesses to determine which images are trusted in a given namespace.
Log on to the Security Center consoleSecurity Center console. In the top navigation bar, select the region of the asset you want to manage. Supported regions: China and Outside China.
In the left-side navigation pane, choose Protection Configuration > Container Protection > Container Signature.
On the Witness tab, click Create a witness, configure the parameters, and click OK.
| Parameter | Description |
|---|---|
| Witness | A name that identifies this signing authority. Security policies reference this name to enable signature verification for a cluster namespace. |
| Select a certificate | Select the KMS CMK you created in Step 2. |
| Description | An optional description of the witness. |
Step 4: Enable image signing in Container Registry
Log on to the Container Registry console. In the top navigation bar, select a region.
In the left-side navigation pane, click Instances.
On the Instances page, find your ACR Enterprise Edition instance and click its name or click Manage.
In the left-side navigation pane, choose Repository > Namespaces. Create a namespace and enable image signing for it. For details, see Manage namespaces.
Enable image signing for the namespace:
In the left-side navigation pane, choose Security and Trust > Image Signature.
On the Image Signature tab, click Create a signature rule. When configuring the rule, select the witness you created in Step 3. For details, see Configure a signature rule for automatic image signing.
Step 5: Enable signature verification in Security Center
Create a security policy to bind the witness to a cluster namespace. Once the policy is enabled, kritis-validation-hook enforces signature verification for all deployments in that namespace.
Log on to the Security Center consoleSecurity Center console.
In the left-side navigation pane, choose Protection Configuration > Container Protection > Container Signature.
On the Security Policy tab, click Add Policy, configure the parameters, and click OK.
| Parameter | Description |
|---|---|
| Policy Name | A name for the security policy. |
| Witness | Select the witness you created in Step 3. |
| Application Cluster | Select the cluster group, then select the Cluster Namespace to protect. |
| Policy Enabled | Turn on the switch. The policy is disabled by default and takes effect only after you enable it. |
| Note | An optional description of the policy. |
Verify signature enforcement
kritis-validation-hook only supports images specified by digest. Images specified by tag are always rejected.
Run the following commands to confirm that signature verification is working.
Test 1: Deploy an unsigned image by tag — expected to be rejected
kubectl -n default create deployment not-sign --image=alpine:3.11 -- sleep 10Expected output:
Error from server: admission webhook "kritis-validation-hook-deployments.grafeas.io" denied the request: image alpine:3.11 is not attestedTest 2: Deploy an unsigned image by digest — expected to be rejected
kubectl -n default create deployment not-sign --image=alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 -- sleep 10Expected output:
Error from server: admission webhook "kritis-validation-hook-deployments.grafeas.io" denied the request: image alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 is not attestedTest 3: Push an image to the signing-enabled namespace, then deploy by digest — expected to succeed
Push the image to trigger automatic signing:
docker push kritis-demo***.cn-hongkong.cr.aliyuncs.com/kritis-demo***/alpine:3.11Expected output (the digest is recorded after signing):
The push refers to repository [kritis-demo***.cn-hongkong.cr.aliyuncs.com/kritis-demo***/alpine]
5216338b40a7: Pushed
3.11: digest: sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 size: 528Deploy using the digest from the push output:
kubectl -n default create deployment is-signed --image=kritis-demo***.cn-hongkong.cr.aliyuncs.com/kritis-demo***/alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 -- sleep 10Expected output:
deployment.apps/is-signed createdSignature verification is working correctly. Unsigned images are blocked, and signed images referenced by digest are admitted.