ImageConfig is an API for centralized control over the configuration of Crossplane package images. It allows you to configure package manager behavior for images globally, without needing to be referenced by other objects.

Matching image references

spec.matchImages is a list of image references that the ImageConfig applies to. Each item in the list specifies the type and configuration of the image reference to match. The only supported type is Prefix, which matches the prefix of the image reference. No wildcards are supported. The type defaults to Prefix and can be omitted.

When there are multiple ImageConfigs matching an image reference, the one with the longest matching prefix is selected. If there are multiple ImageConfigs with the same longest matching prefix, one of them is selected arbitrarily. Please note that this situation occurs only if there are overlapping prefixes in the matchImages lists of different ImageConfig resources, which should be avoided.

The default registry isn’t taken into account for ImageConfig matching. That is, an ImageConfig matching the prefix xpkg.crossplane.io/crossplane-contrib doesn’t match the following provider, even if the default registry is xpkg.crossplane.io:

1apiVersion: pkg.crossplane.io/v1
2kind: Provider
3metadata:
4  name: provider-nop
5spec:
6  package: crossplane-contrib/provider-nop:v0.4.0

Configuring a pull secret

You can use ImageConfig to inject a pull secret into the Crossplane package manager registry client whenever it interacts with the registry, such as for dependency resolution or image pulls.

In the following example, the ImageConfig resource named acme-packages is configured to inject the pull secret named acme-registry-credentials whenever it needs to interact with the registry for images with the prefix registry1.com/acme-co/.

 1apiVersion: pkg.crossplane.io/v1beta1
 2kind: ImageConfig
 3metadata:
 4  name: acme-packages
 5spec:
 6  matchImages:
 7    - type: Prefix
 8      prefix: registry1.com/acme-co/
 9  registry:
10    authentication:
11      pullSecretRef:
12        name: acme-registry-credentials

spec.registry.authentication.pullSecretRef is a reference to the pull secret that should be injected into the registry client. The secret must be of type kubernetes.io/dockerconfigjson and must be in the Crossplane installation namespace, typically crossplane-system. One can create the secret using the following command:

1kubectl -n crossplane-system create secret docker-registry acme-registry-credentials --docker-server=registry1.com --docker-username=<user> --docker-password=<password>

Configuring signature verification

Important
Signature verification is an alpha feature and needs to be enabled with the --enable-signature-verification feature flag.

You can use ImageConfig to configure signature verification for images. When signature verification is enabled, the package manager verifies the signature of each image before pulling it. If the signature isn’t valid, the package manager rejects the package deployment.

In the following example, the ImageConfig resource named verify-acme-packages is configured to verify the signature of images with the prefixes registry1.com/acme-co/configuration-foo and registry1.com/acme-co/configuration-bar.

In the example below, the ImageConfig resource named verify-acme-packages is set up to verify the signatures of images with the prefixes registry1.com/acme-co/configuration-foo and registry1.com/acme-co/configuration-bar.

 1apiVersion: pkg.crossplane.io/v1beta1
 2kind: ImageConfig
 3metadata:
 4  name: verify-acme-packages
 5spec:
 6  matchImages:
 7    - type: Prefix
 8      prefix: registry1.com/acme-co/configuration-foo
 9    - type: Prefix
10      prefix: registry1.com/acme-co/configuration-bar
11  verification:
12    provider: Cosign
13    cosign:
14      authorities:
15        - name: verify acme packages
16          keyless:
17            identities:
18              - issuer: https://token.actions.githubusercontent.com
19                subject: https://github.com/acme-co/crossplane-packages/.github/workflows/supplychain.yml@refs/heads/main
20          attestations:
21            - name: verify attestations
22              predicateType: spdxjson

spec.verification.provider specifies the signature verification provider. The only supported provider is Cosign. spec.verification.cosign contains the configuration for the Cosign provider. The authorities field contains the configuration for the authorities that sign the images. The attestations field contains the configuration for verifying the attestations of the images.

The ImageConfig API follows the same API shape as Policy Controller from Sigstore. Crossplane initially supports a subset of the Policy Controller configuration options which can be found in the API reference for the ImageConfig resource together with their descriptions.

When multiple authorities are provided, the package manager verifies the signature against each authority until it finds a valid one. If any of the authorities’ signatures are valid, the package manager accepts the image. Similarly, when multiple identities or attestations are provided, the package manager verifies until it finds a valid match and fails if none of them matches.

Matching the image reference to the ImageConfig works similarly to the pull secret configuration, as described in the previous section.

Checking the signature verification status

When signature verification is enabled, the respective controller reports the verification status as a condition of type Verified on the package revision resources. This condition indicates whether the signature verification was successful, failed, skipped, or incomplete due to an error.

Example conditions

Verification skipped: The package manager skipped signature verification for the package revision because there were no matching ImageConfig with signature verification configuration.

1  - lastTransitionTime: "2024-10-23T16:38:51Z"
2    reason: SignatureVerificationSkipped
3    status: "True"
4    type: Verified

Verification successful: The package manager successfully verified the signature of the image in the package revision.

1  - lastTransitionTime: "2024-10-23T16:43:05Z"
2    message: Signature verification succeeded with ImageConfig named "verify-acme-packages"
3    reason: VerificationSucceeded
4    status: "True"
5    type: Verified

Verification failed: The package manager failed to verify the signature of the image in the package revision.

1  - lastTransitionTime: "2024-10-23T16:42:44Z"
2    message: 'Signature verification failed with ImageConfig named "verify-acme-packages":
3      [signature keyless validation failed for authority verify acme packages
4      for registry1.com/acme-co/configuration-foo:v0.2.0: no signatures found: ]'
5    reason: SignatureVerificationFailed
6    status: "False"
7    type: Verified

Verification incomplete: The package manager encountered an error while verifying the signature of the image in the package revision.

1  - lastTransitionTime: "2024-10-23T16:44:22Z"
2    message: 'Error occurred during signature verification cannot get image verification
3      config: cannot get cosign verification config: no data found for key "cosign.pub"
4      in secret "cosign-public-key"'
5    reason: SignatureVerificationIncomplete
6    status: "False"
7    type: Verified

If you can’t see this condition on the package revision resource, namely ProviderRevision, ConfigurationRevision, or FunctionRevision, ensure that the feature is enabled.

Rewriting image paths

You can use an ImageConfig to pull package images from an alternative location such as a private registry. spec.rewriteImages specifies how to rewrite the paths of matched images.

Only prefix replacement is supported. The prefix specified in spec.rewriteImage.prefix replaces the matched prefix from matchImages. For example, the following ImageConfig replaces xpkg.crossplane.io with registry1.com for any image with the prefix xpkg.crossplane.io.

1apiVersion: pkg.crossplane.io/v1beta1
2kind: ImageConfig
3metadata:
4  name: private-registry-rewrite
5spec:
6  matchImages:
7    - prefix: xpkg.crossplane.io
8  rewriteImage:
9    prefix: registry1.com

In this example, installing the provider package xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.4.0 will result in the package manager pulling the provider from registry1.com/crossplane-contrib/provider-nop:v0.4.0.

Rewriting image paths via ImageConfig is useful when mirroring packages to a private registry, because it allows a package and all its dependencies to be pulled from the same registry. For example, the provider xpkg.crossplane.io/crossplane-contrib/provider-aws-s3 has a dependency on xpkg.crossplane.io/crossplane-contrib/provider-family-aws. If you mirror the packages to your own registry at registry1.com and install them without an ImageConfig, the package manager still attempts to pull the dependency from xpkg.crossplane.io. With the preceding ImageConfig, the dependency is pulled from registry1.com.

Rewriting an image path with ImageConfig doesn’t change the spec.package field of the package resource. The rewritten path is recorded in the status.resolvedPackage field. The preceding example results in the following:

1kubectl describe provider crossplane-contrib-provider-family-aws
2...
3Spec:
4  ...
5  Package:                        xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v1.22.0
6Status:
7  ...
8  Resolved Package:        registry1.com/crossplane-contrib/provider-family-aws:v1.22.0

Interaction with other operations

Tip
Image rewriting is always done before other ImageConfig operations. If you wish to configure pull secrets or signature verification as well as rewriting, additional ImageConfig resources must match the rewritten image path.

For example, if you are mirroring packages from xpkg.crossplane.io to registry1.com and need to configure pull secrets for registry1.com, two ImageConfig resources are necessary:

 1# Rewrite xpkg.crossplane.io -> registry1.com
 2---
 3apiVersion: pkg.crossplane.io/v1beta1
 4kind: ImageConfig
 5metadata:
 6  name: private-registry-rewrite
 7spec:
 8  matchImages:
 9    - prefix: xpkg.crossplane.io
10  rewriteImage:
11    prefix: registry1.com
12
13# Configure pull secrets for registry1.com
14---
15apiVersion: pkg.crossplane.io/v1beta1
16kind: ImageConfig
17metadata:
18  name: private-registry-auth
19spec:
20  matchImages:
21    - type: Prefix
22      prefix: registry1.com
23  registry:
24    authentication:
25      pullSecretRef:
26        name: private-registry-credentials

Debugging

When the package manager selects an ImageConfig for a package, it throws an event with the reason ImageConfigSelection and the name of the selected ImageConfig and injected pull secret. You can find these events both on the package and package revision resources. The package manager also updates the appliedImageConfigRefs field in the package status to show the purpose for which each ImageConfig was selected.

For example, the following event and status show that the ImageConfig named acme-packages was used to provide a pull secret for the configuration named acme-configuration-foo:

 1kubectl describe configuration acme-configuration-foo
 2...
 3Status:
 4  Applied Image Config Refs:
 5    Name:    acme-packages
 6    Reason:  SetImagePullSecret
 7...
 8Events:
 9  Type     Reason                Age                From                                              Message
10  ----     ------                ----               ----                                              -------
11  Normal   ImageConfigSelection  45s                packages/configuration.pkg.crossplane.io          Selected pullSecret "acme-registry-credentials" from ImageConfig "acme-packages" for registry authentication

If you can’t find the expected event and appliedImageConfigRefs entry, ensure the prefix of the image reference matches the matchImages list of any ImageConfig resources in the cluster.