Image Repositories

The GitOps Toolkit Custom Resource Definitions documentation.

The ImageRepository API specifies how to scan OCI image repositories. A repository is a collection of images – e.g., alpine, as opposed to a specific image, e.g., alpine:3.1. ImagePolicy objects can then refer to an ImageRepository in order to select a specific image from those scanned.

Specification

The ImageRepository type holds details for scanning a particular image repository.

// ImageRepositorySpec defines the parameters for scanning an image
// repository, e.g., `fluxcd/flux`.
type ImageRepositorySpec struct {
	// Image is the name of the image repository
	// +required
	Image string `json:"image,omitempty"`
	// Interval is the length of time to wait between
	// scans of the image repository.
	// +required
	Interval metav1.Duration `json:"interval,omitempty"`

	// Timeout for image scanning.
	// Defaults to 'Interval' duration.
	// +optional
	Timeout *metav1.Duration `json:"timeout,omitempty"`

	// SecretRef can be given the name of a secret containing
	// credentials to use for the image registry. The secret should be
	// created with `kubectl create secret docker-registry`, or the
	// equivalent.
	// +optional
	SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`

	// CertSecretRef can be given the name of a secret containing
	// either or both of
	//
	//  - a PEM-encoded client certificate (`certFile`) and private
	//  key (`keyFile`);
	//  - a PEM-encoded CA certificate (`caFile`)
	//
	//  and whichever are supplied, will be used for connecting to the
	//  registry. The client cert and key are useful if you are
	//  authenticating with a certificate; the CA cert is useful if
	//  you are using a self-signed server certificate.
	// +optional
	CertSecretRef *meta.LocalObjectReference `json:"certSecretRef,omitempty"`

	// This flag tells the controller to suspend subsequent image scans.
	// It does not apply to already started scans. Defaults to false.
	// +optional
	Suspend bool `json:"suspend,omitempty"`
}

The Suspend field can be set to true to stop the controller scanning the image repository specified; remove the field value or set to false to resume scanning.

secretRef for credentials

The secretRef names a secret in the same namespace that holds credentials for accessing the image repository. This secret is expected to be in the same format as for imagePullSecrets. The usual way to create such a secret is with

kubectl create secret docker-registry ...

If you are running on a platform (e.g., AWS) that links service permissions (e.g., access to ECR) to service accounts, you may need to create the secret using tooling for that platform instead. There is advice specific to some platforms in the image automation guide.

For a publicly accessible image repository, you don’t need to provide a secretRef.

certSecretRef for TLS certificates

The certSecretRef field names a secret with TLS certificate data. This is for two separate purposes:

  • to provide a client certificate and private key, if you use a certificate to authenticate with the image registry; and,
  • to provide a CA certificate, if the registry uses a self-signed certificate.

These will often go together, if you are hosting an image registry yourself. All the files in the secret are expected to be PEM-encoded. This is an ASCII format for certificates and keys; openssl and such tools will typically give you an option of PEM output.

Assuming you have obtained a certificate file and private key and put them in the files client.crt and client.key respectively, you can create a secret with kubectl like this:

SECRET_NAME=tls-certs
kubectl create secret generic $SECRET_NAME \
  --from-file=certFile=client.crt \
  --from-file=keyFile=client.key

You could also prepare a secret and encrypt it; the important bit is that the data keys in the secret are certFile and keyFile.

If you have a CA certificate for the client to use, the data key for that is caFile. Adapting the previous example, if you have the certificate in the file ca.crt, and the client certificate and key as before, the whole command would be:

SECRET_NAME=tls-certs
kubectl create secret generic $SECRET_NAME \
  --from-file=certFile=client.crt \
  --from-file=keyFile=client.key \
  --from-file=caFile=ca.crt

Status

// ImageRepositoryStatus defines the observed state of ImageRepository
type ImageRepositoryStatus struct {
	// +optional
	Conditions []metav1.Condition `json:"conditions,omitempty"`

	// ObservedGeneration is the last reconciled generation.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// CannonicalName is the name of the image repository with all the
	// implied bits made explicit; e.g., `docker.io/library/alpine`
	// rather than `alpine`.
	// +optional
	CanonicalImageName string `json:"canonicalImageName,omitempty"`

	// LastScanResult contains the number of fetched tags.
	// +optional
	LastScanResult *ScanResult `json:"lastScanResult,omitempty"`

	meta.ReconcileRequestStatus `json:",inline"`
}

The CanonicalName field gives the fully expanded image name, filling in any parts left implicit in the spec. For instance, alpine expands to docker.io/library/alpine.

The LastScanResult field gives a summary of the most recent scan:

type ScanResult struct {
	TagCount int         `json:"tagCount"`
	ScanTime metav1.Time `json:"scanTime,omitempty"`
}

Conditions

There is one condition used: the GitOps toolkit-standard ReadyCondition. This will be marked as true when a scan succeeds, and false when a scan fails.

Examples

Fetch metadata for a public image every ten minutes:

apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 10m
  image: ghcr.io/stefanprodan/podinfo

Fetch metadata for a private image every minute:

apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 1m0s
  image: docker.io/org/image
  secretRef:
    name: regcred

For private images, you can create a Kubernetes secret in the same namespace as the ImageRepository with kubectl create secret docker-registry, and reference it under secretRef.

Last modified 0001-01-01