Accessing private image repositories

When the image repository visibility is set to private (the default), you need to authenticate before you can pull images. Konflux provides an RBAC image proxy that controls access based on your permissions.

Who can pull images and access scope

Access to pull images is controlled at the tenant level through Kubernetes RBAC:

  • Users or service accounts who have permission to get, list, or watch ImageRepository resources in a tenant can pull images from all components in that tenant

  • Image path format: proxy_host/redhat-user-workloads(-stage)/tenant/component:tag

  • Without the required RBAC permissions, image pulls will fail

To grant this access, a tenant maintainer creates a Role that permits reading ImageRepository resources, then binds that role to a subject with a RoleBinding:

Tenant administrators cannot create new custom Group objects, because groups are managed by the identity provider. You can still bind the Role to an existing group, such as system:authenticated, but for most cases bind it to a ServiceAccount (for automation) or a User (for local development).

Token types and scope

  • User tokens:

    • Any Konflux user can obtain a user token through the proxy authentication flow

    • Issued by the proxy’s Dex (not SSO), so they can ONLY be used for pulling images through the proxy

    • Cannot be used for OpenShift API authentication

    • Expire after 24 hours

    • Best for local development and manual testing

  • Service account tokens:

    • Any Konflux user who has permission to create secrets in a namespace can create a service account token in that namespace

    • Can authenticate against both the proxy AND the OpenShift API (works like a regular OpenShift service account)

    • Do not expire (valid until the secret is deleted)

    • Best for automated systems and CI/CD pipelines

Finding your proxy URL

The examples on this page use image-rbac-proxy.apps.example.com as a placeholder. Replace it with the RBAC image proxy hostname for the cluster that hosts your tenant. The hostname follows this pattern:

image-rbac-proxy.apps.<cluster-domain>

For example, on the stone-prod-p02 cluster the proxy hostname is:

image-rbac-proxy.apps.stone-prod-p02.hjvn.p1.openshiftapps.com

The proxy hostname matches the domain of the Konflux instance you use, so the login command shown in the UI is always the authoritative source for your cluster. To find the exact hostname:

  1. Open the Component details page for any of your components in the Konflux UI.

  2. In the Registry login information section, read the podman login command. The host in that command is the proxy hostname for your cluster.

  3. Copy the private image path shown for the component. It begins with the same proxy hostname.

Granting pull access with a service account

For automated access from external systems such as Testing Farm or CI/CD pipelines, grant a service account permission to pull images. Create the following objects in this order, because each object depends on the ones before it: the Secret and the RoleBinding both reference the ServiceAccount, so the service account must exist first.

  1. Create a Role that permits reading ImageRepository resources:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: repo-viewer
      namespace: <your-namespace>
    rules:
      - apiGroups:
          - appstudio.redhat.com
        resources:
          - imagerepositories
        verbs:
          - get
          - watch
          - list
  2. Create a ServiceAccount:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: external-puller
      namespace: <your-namespace>
  3. Create a Secret that holds a non-expiring token for the service account. The kubernetes.io/service-account.name annotation must reference the service account created in the previous step:

    apiVersion: v1
    kind: Secret
    metadata:
      name: external-puller-token
      namespace: <your-namespace>
      annotations:
        kubernetes.io/service-account.name: external-puller
    type: kubernetes.io/service-account-token
  4. Create a RoleBinding that binds the Role to the ServiceAccount:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: repo-viewer
      namespace: <your-namespace>
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: repo-viewer
    subjects:
      - kind: ServiceAccount
        name: external-puller
        namespace: <your-namespace>
  5. Get the service account token from the secret:

    kubectl get secret external-puller-token -n <your-namespace> -o jsonpath='{.data.token}' | base64 -d
  6. Use the token to authenticate to the registry in your external system:

    podman login -u external-puller image-rbac-proxy.apps.example.com
    # When prompted for password, paste the service account token

    Then pull images:

    podman pull image-rbac-proxy.apps.example.com/redhat-user-workloads/my-tenant/my-app:b153d64
Replace image-rbac-proxy.apps.example.com with your cluster’s proxy hostname. See Finding your proxy URL.
If a token is compromised, delete the secret to revoke the token, then create a new one. The username must match the service account name.

Getting registry login credentials via the UI

To access private images locally with your own user token:

  1. Ask a tenant maintainer to bind the pull Role to your user. This uses the same Role shown in Granting pull access with a service account, with a User subject instead of a ServiceAccount:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: repo-viewer-user
      namespace: <your-namespace>
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: repo-viewer
    subjects:
      - apiGroup: rbac.authorization.k8s.io
        kind: User
        name: <your-username>
  2. Navigate to the Component details page for your component

  3. In the Registry login information section, copy and run the podman login command in your terminal:

    podman login -u unused image-rbac-proxy.apps.example.com
  4. Click the OAuth URL link to get your authentication token

  5. Paste the token when prompted for password

  6. Copy the private image path from the UI and pull the image:

    podman pull image-rbac-proxy.apps.example.com/redhat-user-workloads/my-tenant/my-app:b153d64
    The image path includes the proxy host (e.g., image-rbac-proxy.apps.example.com) which enforces access control. You must use this proxy URL, not a direct registry URL. Replace it with your cluster’s proxy hostname; see Finding your proxy URL.