The module lifecycle stagePreview
The module has requirements for installation

The module supports the following authentication and authorization methods:

The permission to get the list of available repositories (catalog) is available to all authenticated users regardless of the authentication method.

Each root directory in the registry corresponds to a Kubernetes namespace name. If that namespace is deleted, all images in that directory and subdirectories will be deleted regardless of the authentication method.

Authentication with Kubernetes tokens

In this authentication mode, the following parameters are used:

Access to repository paths is determined by Kubernetes RBAC rules for the PayloadRepositoryAccess resource.

RBAC and PayloadRepositoryAccess

When authenticating with a Kubernetes token, access to repository paths is controlled using Kubernetes RBAC applied to the virtual resource PayloadRepositoryAccess:

  • API group: payload-registry.deckhouse.io
  • Resource name: payloadrepositoryaccesses (PayloadRepositoryAccess)
  • Purpose: A virtual resource used only for configuring access to the registry via Kubernetes RBAC.

PayloadRepositoryAccess objects are not created in Kubernetes; they are used to grant permissions through Role or ClusterRole on this resource, for the registry and Kubernetes API extension to check access to repository paths and tags.

The resourceNames field defines repository path patterns.

Possible pattern substitutions:

Pattern Description
* Any sequence of characters except / (single path segment)
/**/ Zero or more directories (recursive traversal)
? Exactly one character (except /) in a path segment
[class] One character from a set or range, e.g. [a-z0-9]
{alt1,alt2,...} One of the comma-separated alternatives

The double asterisk ** must be a separate path segment.

A pattern like /path** is invalid and is treated the same as /path*; use /path*/** for the intended effect.

The pattern /path/** matches all directories and files under path, while /path/**/ matches only directories.

Path matching is case-insensitive: the pattern and the requested path are lowercased before comparison.

If the requested path matches the allowed resourceNames (or when resourceNames is absent) and the access level (verb) matches, access is granted.

Access levels (verbs)

Verb Registry operation
get Pull image and get tag info via Kubernetes API extension
list Get list of tags in namespace repositories via Kubernetes API extension
create Push image
delete Delete image, including via Kubernetes API extension

Example RBAC configuration

The following is an example of granting a ServiceAccount full access (including getting and deleting tags via the Kubernetes API extension) to repositories in namespace project-1:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: payload-registry-full
  namespace: project-1
rules:
- apiGroups: ["payload-registry.deckhouse.io"]
  resources: ["payloadrepositoryaccesses"]
  resourceNames: 
    - "dist/*"
    - "app/**"
  verbs: ["get", "list", "create", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: payload-registry-read
  namespace: project-1
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: payload-registry-full
subjects:
- kind: ServiceAccount
  name: payload-registry-sa
  namespace: project-1

Authorizing with a token and pushing an image to the registry

To authorize in the container registry using a token, follow these steps:

  1. Create a namespace to which registry images will be bound:

    d8 k create namespace project-1
  2. Authorization in registry using a ServiceAccount token:

    1. Create a Role in that namespace defining access (see example above).

    2. Create a ServiceAccount:

      d8 k -n project-1 create serviceaccount payload-registry-sa
    3. Bind it to the Role with a RoleBinding (see example above).

    4. Log in to payload-registry from your machine:

        docker login payload-registry.${PUBLIC_DOMAIN} -u token --password $(d8 k -n project-1 create token payload-registry-sa)
  3. Authorization in the registry using a token obtained through the kubeconfig generation interface (ID Token):

    1. Bind the user to the Role or ClusterRole with a RoleBinding or ClusterRoleBinding respectively (see example above).

    2. Copy the ID Token from the kubeconfig page.

    3. Log in to the registry from your machine:

      docker login payload-registry.${PUBLIC_DOMAIN} -u token -p <ID Token>
  4. Create an image and assign it a tag:

    docker tag ubuntu:latest payload-registry.${PUBLIC_DOMAIN}/project-1/dist/ubuntu:latest
  5. Push the image to the registry:

    docker push payload-registry.${PUBLIC_DOMAIN}/project-1/dist/ubuntu:latest
  6. Verify the presence of the image in the registry. Example using the crane command:

    crane catalog payload-registry.${PUBLIC_DOMAIN}

Static user configuration (deprecated)

This authentication method is deprecated. Use Kubernetes tokens for authentication.

Static configuration may be removed in future versions.

This method allows configuring static authorization and managing access by project. Each project is a root directory in the registry and corresponds to a Kubernetes namespace name. If that namespace is deleted, all images in that directory and subdirectories will be deleted.

Features:

  • Users are configured via ModuleConfig in section settings.users.
  • Password is not stored in plain text. Only the password hash is specified in the configuration (see Generation of passwordHash for details).

Projects and access levels

A project is a root path in the registry. The project name matches the Kubernetes namespace name.

Each user can have multiple project entries with the following fields:

  • name: Project (namespace) name.
  • subPath: Path or wildcard pattern: *, path-*, path/*, */*. Segment skip ** is not supported.
  • access: Access level.

The following access levels are supported:

Access Allowed operations Condition
READ pull only Always as configured
FULL pull and push Only if a namespace with the same name as the project exists. Otherwise READ is effectively granted

To allow push:

  1. Configure the user with access: FULL for the project and desired subPath.
  2. Create the namespace (e.g. d8 k create namespace <project-name>).

Example static user configuration

Example static user configuration:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: payload-registry
spec:
  version: 1
  enabled: true
  settings:
    users:
      deploy-user:
        passwordHash: "$2y$10$..."   # Bcrypt password hash.
        projects:
          - name: my-app
            subPath: "*"
            access: FULL
      read-only-user:
        passwordHash: "$2y$10$..."
        projects:
          - name: my-app
            subPath: "*"
            access: READ

SubPath patterns: The full path is projectName/subPath. Examples: * (whole project), path-*, path/*, */*. The pattern must not start or end with a slash.

Generation of passwordHash

To generate a bcrypt hash, use the htpasswd command:

echo -n '${PASSWORD}' | htpasswd -BinC 10 "" | cut -d: -f2 | tr -d '\n'; echo

The generated hash should be specified in the users.${USER_NAME}.passwordHash field. Example:

echo -n 'password123' | htpasswd -BinC 10 "" | cut -d: -f2 | tr -d '\n'; echo
$2y$10$CeP/hYvBJ05Ih2azafVyIuuMRpf60am4z6USm4jhHfUPsFDBAmn/u

Example ModuleConfig with password hash specified in users.${USER_NAME}.passwordHash:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: payload-registry
spec:
  version: 1
  enabled: true
  settings:
    users:
      user-1:
        # Bcrypt hash of password `password123`.
        passwordHash: "$2y$10$CeP/hYvBJ05Ih2azafVyIuuMRpf60am4z6USm4jhHfUPsFDBAmn/u"
        projects: []

Adding an image to a project

To add an image to a project, follow these steps:

  1. Configure a user with FULL access to the project. Example:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: payload-registry
    spec:
      version: 1
      enabled: true
      settings:
        users:
          user-1:
            # Bcrypt hash of password `password123`.
            passwordHash: "$2y$10$CeP/hYvBJ05Ih2azafVyIuuMRpf60am4z6USm4jhHfUPsFDBAmn/u"
            projects:
            - name: "project-1"
              subPath: "*"
              access: FULL
  2. Create a namespace with the project name in the cluster:

    d8 k create namespace project-1
  3. Log in to the registry from your machine:

    docker login payload-registry.${PUBLIC_DOMAIN} -u user-1 -p password123
  4. Create an image and assign it a tag:

    docker tag ubuntu:latest payload-registry.${PUBLIC_DOMAIN}/project-1/ubuntu:latest
  5. Push the image to the registry:

    docker push payload-registry.${PUBLIC_DOMAIN}/project-1/ubuntu:latest
  6. Verify the presence of the image in the registry. Example check using the crane command:

    crane catalog payload-registry.${PUBLIC_DOMAIN}