IBM / portieris

A Kubernetes Admission Controller for verifying image trust.
Apache License 2.0
332 stars 78 forks source link

mutateImage: true causes fallback to "latest" which causes trust issues #390

Open CrawX opened 2 years ago

CrawX commented 2 years ago

What commit ID of Portieris did you experience the problem with?

7cc209a

What went wrong?

Deploying an image with mutateImage: true removes the image tag which causes the following behaviour

% kubectl -n mynamespace rollout restart deployment my-deployment
error: failed to patch: admission webhook "trust.hooks.securityenforcement.admission.cloud.ibm.com" denied the request:
trust: policy denied the request: Deny "my-host/my-image@sha256:some-sha-256", failed to get content trust information: No valid trust data for latest

The image in the deployment is specified via a tag (not latest).

What should have happened differently?

kubectl rollout restart should be able to restart my deployment with the same image that was in use before

How can it be reproduced?

Creating a deployment referencing a valid tag (with a signature) and having a latest tag that doesn't have a signature and enabling mutateImage: true in the policy, then try to restart it. Setting mutateImage: false makes it work but comes with the caveats noted in the README.

Any other relevant information

Sample ImagePolicy

apiVersion: portieris.cloud.ibm.com/v1
kind: ImagePolicy
metadata:
  name: default
  namespace: my-namespace
spec:
  repositories:
    - name: "my-host/*"
      policy:
        mutateImage: true
        trust:
          enabled: true
          trustServer: https://my-trustserver

Log output

│ portieris I0615 06:52:07.726466       1 controller.go:64] Processing admission request for UPDATE on my-deployment                                                                                                                                                                                                                                                                                                                 │
│ portieris I0615 06:52:07.726833       1 controller.go:176] Getting policy for container image: my-host/my-image@sha256:some-sha-256   namespace: my-namespace                                                                                                                                                             │
│ portieris I0615 06:52:07.734665       1 controller.go:261] ImagePullSecret my-namespace/registry-credentials found                                                                                                                                                                                                                                                                                                                        │
│ portieris I0615 06:52:07.734683       1 enforcer.go:95] policy.Trust {0xc0013512fc [] https://my-trustserver}                                                                                                                                                                                                                                                                                                            │
│ portieris I0615 06:52:08.232584       1 oauth.go:43] CA not provided at /etc/certs/ca.pem, will use default system pool                                                                                                                                                                                                                                                                                                                  │
│ portieris I0615 06:52:09.106698       1 trust.go:65] GetAllTargetMetadataByName returned err: No valid trust data for latest                                                                                                                                                                                                                                                                                                             │
│ portieris I0615 06:52:09.106731       1 responder.go:93] trust: policy denied the request: Deny "my-host/my-image@sha256:some-sha-256", failed to get content trust information: No valid trust data for latest                                                                                                          │
│ portieris I0615 06:52:09.106742       1 controller.go:125] Deny for images:  [my-host/my-image@sha256:some-sha-256]

To me, it looks like https://github.com/IBM/portieris/blob/main/pkg/verifier/trust/verifier.go#L103 is passing latest as a targetName which passes it to https://github.com/IBM/portieris/blob/main/pkg/verifier/trust/trust.go#L63 which causes GetAllTargetMetadataByName to fail because our latest image doesn't have a signature. The tag is removed by https://github.com/IBM/portieris/blob/main/pkg/controller/multi/controller.go#L225 (also see #90). Having no tag defined causes https://github.com/IBM/portieris/blob/main/helpers/image/image.go#L65 to fallback to latest.

When disabling mutateImage, the image reference is not modified which fixes the problems but comes with the caveats noted in the README.