×

Overview

You can control which images can be imported, tagged, and run in a cluster. There are two facilities for this purpose.

Allowed Registries for import is an image policy configuration that allows you to restrict image origins to particular set of external registries. This set of rules is applied to any image being imported or tagged into any image stream. Therefore any image referencing registry not matched by the rule set will be rejected.

ImagePolicy admission plug-in lets you specify which images are allowed to be run on your cluster. This is currently considered beta. It allows you to control:

  • Image sources: which registries can be used to pull images

  • Image resolution: force pods to run with immutable digests to ensure the image does not change due to a re-tag

  • Container image label restrictions: limits or requires labels on an image

  • Image annotation restrictions: limits or requires the annotations on an image in the integrated container image registry

Configuring Registries Allowed for Import

You can configure registries allowed for import in master-config.yaml under imagePolicyConfig:allowedRegistriesForImport section as demonstrated in the following example. If the setting is not present, all images are allowed, which is the default.

Example 1. Example Configuration of Registries Allowed for Import
imagePolicyConfig:
  allowedRegistriesForImport:
  -
    domainName: registry.redhat.io (1)
  -
    domainName: *.mydomain.com
    insecure: true (2)
  -
    domainName: local.registry.corp:5000 (3)
1 Allow any image from the specified secure registry.
2 Allow any image from any insecure registry hosted on any sub-domain of mydomain.com. The mydomain.com is not whitelisted.
3 Allow any image from the given registry with port specified.

Each rule is composed of the following attributes:

  • domainName: is a hostname optionally terminated by :<port> suffix where special wildcard characters (?, *) are recognized. The former matches a sequence of characters of any length while the later matches exactly one character. The wildcard characters can be present both before and after : separator. The wildcards apply only to the part before or after the separator regardless of separator’s presence.

  • insecure: is a boolean used to decide which ports are matched if the :<port> part is missing from domainName. If true, the domainName will match registries with :80 suffix or unspecified port as long as the insecure flag is used during import. If false, registries with :443 suffix or unspecified port will be matched.

If a rule should match both secure and insecure ports of the same domain, the rule must be listed twice (once with insecure=true and once with insecure=false.

Unqualified images references are qualified to docker.io before any rule evaluation. To whitelist them, use domainName: docker.io.

domainName: * rule matches any registry hostname, but port is still restricted to 443. To match arbitrary registry serving on arbitrary port, use domainName: *:*.

Based on the rules established in Example Configuration of Registries Allowed for Import:

  • oc tag --insecure reg.mydomain.com/app:v1 app:v1 is whitelisted by the handling of the mydomain.com rule

  • oc import-image --from reg1.mydomain.com:80/foo foo:latest will be also whitelisted

  • oc tag local.registry.corp/bar bar:latest will be rejected because the port does not match 5000 in the third rule

Rejected image imports will generate error messages similar to the following text:

The ImageStream "bar" is invalid:
* spec.tags[latest].from.name: Forbidden: registry "local.registry.corp" not allowed by whitelist: "local.registry.corp:5000", "*.mydomain.com:80", "registry.redhat.io:443"
* status.tags[latest].items[0].dockerImageReference: Forbidden: registry "local.registry.corp" not allowed by whitelist: "local.registry.corp:5000", "*.mydomain.com:80", "registry.redhat.io:443"

Configuring the ImagePolicy Admission Plug-in

To configure which images can run on your cluster, configure the ImagePolicy Admission plug-in in the master-config.yaml file. You can set one or more rules as required.

  • Reject images with a particular annotation:

    Use this rule to reject all images that have a specific annotation set on them. The following rejects all images using the images.openshift.io/deny-execution annotation:

    - name: execution-denied
      onResources:
      - resource: pods
      - resource: builds
      reject: true
      matchImageAnnotations:
      - key: images.openshift.io/deny-execution (1)
        value: "true"
      skipOnResolutionFailure: true
    1 If a particular image has been deemed harmful, administrators can set this annotation to flag those images.
  • Enable user to run images from Docker Hub:

    Use this rule to allow users to use images from Docker Hub:

    - name: allow-images-from-dockerhub
      onResources:
        - resource: pods
        - resource: builds
        matchRegistries:
        - docker.io

Following is an example configuration for setting multiple ImagePolicy addmission plugin rules in the master-config.yaml file:

Annotated Example File
admissionConfig:
  pluginConfig:
    openshift.io/ImagePolicy:
      configuration:
        kind: ImagePolicyConfig
        apiVersion: v1
        resolveImages: AttemptRewrite (1)
        executionRules: (2)
        - name: execution-denied
          # Reject all images that have the annotation images.openshift.io/deny-execution set to true.
          # This annotation may be set by infrastructure that wishes to flag particular images as dangerous
          onResources: (3)
          - resource: pods
          - resource: builds
          reject: true (4)
          matchImageAnnotations: (5)
          - key: images.openshift.io/deny-execution
            value: "true"
          skipOnResolutionFailure: true (6)
        - name: allow-images-from-internal-registry
          # allows images from the internal registry and tries to resolve them
          onResources:
          - resource: pods
          - resource: builds
          matchIntegratedRegistry: true
        - name: allow-images-from-dockerhub
          onResources:
          - resource: pods
          - resource: builds
          matchRegistries:
          - docker.io
        resolutionRules: (7)
        - targetResource:
            resource: pods
          localNames: true
          policy: AttemptRewrite
        - targetResource: (8)
            group: batch
            resource: jobs
          localNames: true (9)
          policy: AttemptRewrite
1 Try to resolve images to an immutable image digest and update the image pull specification in the pod.
2 Array of rules to evaluate against incoming resources. If you only have reject: true rules, the default is allow all. If you have any accept rule, that is reject: false in any of the rules, the default behaviour of the ImagePolicy switches to deny-all.
3 Indicates which resources to enforce rules upon. If nothing is specified, the default is pods.
4 Indicates that if this rule matches, the pod should be rejected.
5 List of annotations to match on the image object’s metadata.
6 If you are not able to resolve the image, do not fail the pod.
7 Array of rules allowing use of image streams in Kubernetes resources. The default configuration allows pods, replicationcontrollers, replicasets, statefulsets, daemonsets, deployments, and jobs to use same-project image stream tag references in their image fields.
8 Identifies the group and resource to which this rule applies. If resource is *, this rule will apply to all resources in that group.
9 LocalNames will allow single segment names (for example, ruby:2.5) to be interpreted as namespace-local image stream tags, but only if the resource or target image stream has local name resolution enabled.

If you normally rely on infrastructure images being pulled using a default registry prefix (such as docker.io or registry.redhat.io), those images will not match to any matchRegistries value since they will have no registry prefix. To ensure infrastructure images have a registry prefix that can match your image policy, set the imageConfig.format value in your master-config.yaml file.

Using an Admission Controller to Always Pull Images

After an image is pulled to a node, any Pod on that node from any user can use the image without an authorization check against the image. To ensure that Pods do not use images for which they do not have credentials, use the AlwaysPullImages admission controller.

This admission controller modifies every new Pod to force the image pull policy to Always, ensuring that private images can only be used by those who have the credentials to pull them, even if the Pod specification uses an image pull policy of Never.

To enable the AlwaysPullImages admission controller:

  1. Add the following to the master-config.yaml:

    admissionConfig:
      pluginConfig:
        AlwaysPullImages: (1)
          configuration:
            kind: DefaultAdmissionConfig
            apiVersion: v1
            disable: false (2)
    1 Admission plug-in name.
    2 Specify false to indicate that the plug-in should be enabled.
  2. Restart master services running in control plane static Pods using the master-restart command:

    $ master-restart api
    $ master-restart controllers

Testing the ImagePolicy Admission Plug-in

  1. Use the openshift/image-policy-check to test your configuration.

    For example, use the information above, then test like this:

    $ oc import-image openshift/image-policy-check:latest --confirm
  2. Create a pod using this YAML. The pod should be created.

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: test-pod
    spec:
      containers:
      - image: docker.io/openshift/image-policy-check:latest
        name: first
  3. Create another pod pointing to a different registry. The pod should be rejected.

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: test-pod
    spec:
      containers:
      - image: different-registry/openshift/image-policy-check:latest
        name: first
  4. Create a pod pointing to the internal registry using the imported image. The pod should be created and if you look at the image specification, you should see a digest in place of the tag.

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: test-pod
    spec:
      containers:
      - image: <internal registry IP>:5000/<namespace>/image-policy-check:latest
        name: first
  5. Create a pod pointing to the internal registry using the imported image. The pod should be created and if you look at the image specification, you should see the tag unmodified.

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: test-pod
    spec:
      containers:
      - image: <internal registry IP>:5000/<namespace>/image-policy-check:v1
        name: first
  6. Get the digest from oc get istag/image-policy-check:latest and use it for oc annotate images/<digest> images.openshift.io/deny-execution=true. For example:

    $ oc annotate images/sha256:09ce3d8b5b63595ffca6636c7daefb1a615a7c0e3f8ea68e5db044a9340d6ba8 images.openshift.io/deny-execution=true
  7. Create this pod again, and you should see the pod rejected:

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: test-pod
    spec:
      containers:
      - image: <internal registry IP>:5000/<namespace>/image-policy-check:latest
        name: first