Skip to content

[Bug]: unable to use mTLS with accessControl #3085

Open
@frq-asgard-josi

Description

@frq-asgard-josi

zot version

v2.1.2

Describe the bug

What I want:

  • Clients can authenticate via mTLS to get read access and pull images
  • I can push images via a special user that has write access (I don't really care if that user can authenticate via mTLS or a password or a combination of both)
  • anonymous users can't do anything

What actually happens:

  1. Scenario 1: mTLS without any accessControl options
  • unauthenticated request are blocked but authenticated requests have full access
  1. Scenario 2: mTLS with accessControl options
  • Configuration cannot be validated: invalid server config: access control config requires one of httpasswd, ldap or openid authentication or using only 'anonymousPolicy' policies
  1. Scenario 3: mTLS with accessControl options and htpasswd file
  • mTLS is completly ignored

To reproduce

Scenario 1

  1. Configuration
{
  "distSpecVersion": "1.1.0",
  "storage": {
    "rootDirectory": "/data/zot"
  },
  "http": {
    "address": "127.0.0.1",
    "port": "443",
    "tls": {
      "cert": "/etc/certs/host.fullchain.cert.pem",
      "key": "/etc/certs/host.key.pem",
      "cacert": "/etc/certs/ca.crt"
    }
  }
}
  1. Client tool used
    podman login --cert-dir <some-dir> 127.0.0.1:443/hello-world:test -u "$(hostname)" -p=""
    podman pull --cert-dir <some-dir> 127.0.0.1:443/hello-world:test
    podman push --cert-dir <some-dir> 127.0.0.1:443/hello-world:test
  2. Seen error
    This works as expected but doesn't meet the requirement that only some users should be allowed to push.

Scenario 2

  1. Configuration
{
  "distSpecVersion": "1.1.0",
  "storage": {
    "rootDirectory": "/data/zot"
  },
  "http": {
    "address": "127.0.0.1",
    "port": "443",
    "tls": {
      "cert": "/etc/certs/host.fullchain.cert.pem",
      "key": "/etc/certs/host.key.pem",
      "cacert": "/etc/certs/ca.crt"
    },
  "accessControl": {
      "repositories": {
        "**": {
          "policies": [
            {
              "users": [
                "user1"
              ],
              "actions": [
                "read",
                "create",
                "update",
                "delete"
              ]
            }
          ],
          "defaultPolicy": [
            "read"
          ]
        }
      }
    }
  }
}
  1. Client tool used
    zot verify <config-file>
  2. Seen error
    invalid server config: access control config requires one of httpasswd, ldap or openid authentication or using only 'anonymousPolicy' policies

Scenario 3

  1. Configuration
{
  "distSpecVersion": "1.1.0",
  "storage": {
    "rootDirectory": "/data/zot"
  },
  "http": {
    "address": "127.0.0.1",
    "port": "443",
    "tls": {
      "cert": "/etc/certs/host.fullchain.cert.pem",
      "key": "/etc/certs/host.key.pem",
      "cacert": "/etc/certs/ca.crt"
    },
  "accessControl": {
      "repositories": {
        "**": {
          "policies": [
            {
              "users": [
                "user1"
              ],
              "actions": [
                "read",
                "create",
                "update",
                "delete"
              ]
            }
          ],
          "defaultPolicy": [
            "read"
          ]
        }
      }
    },
    "auth": {
      "htpasswd": {
        "path": "/etc/zot/htpasswd"
      }
    }
  }
}
  1. Client tool used
    podman login --cert-dir <some-dir> 127.0.0.1:443/hello-world:test -u "$(hostname)" -p=""
    podman login --cert-dir <some-dir> 127.0.0.1:443/hello-world:test -u "" -p=""
    podman pull --cert-dir <some-dir> 127.0.0.1:443/hello-world:test
    podman push --cert-dir <some-dir> 127.0.0.1:443/hello-world:test
    podman login 127.0.0.1:443/hello-world:test -u <htpasswd-user> -p=<htpasswd-password>
  2. Seen error
    I can only login with the htpasswd credentials. Trying to use mTLS doesn't influence the outcome at all.

Expected behavior

Scenario 2

There should be some way to extract the username from the cert. I could imagine the following approaches:

  • Using the cert subject as a username
  • Using the client provided username if it matches the cert subject or one of the subject alternative names

Scenario 3

I think there are multiple options to approach this:

  1. Only one authentication mechanism should be supported simultaneously
  • In this case scenario 2 must be supported to enable configuring accessControl when mTLS is the authentication mechanism of choice
  1. Multiple (or at least mTLS + htpasswd) authentication mechanisms are supported (w/o the scenario 2 solution)
  • One must initiate a successfull mTLS connection to login via the htpasswd credentials
  • If the user provides valid htpasswd credentials he is authenticated as that user
  • If the user provides no htpasswd credentials it will be treated as an anonymous user (mind that the user still is required to initiate a valid mTLS connection)
  • If the user provides invalid htpasswd credentials login will fail
    (htpasswd in this example could also be LDAP or OIDC)
  1. Multiple (or at least mTLS + htpasswd) authentication mechanisms are supported (w/ the scenario 2 solution)
  • User can authenticate via mTLS or htpasswd/LDAP/oidc, seperate policies for truly anonymous users would still be possible
  • Some way to specifiy which authentication source to use might be needed (This could already exists via some http header)

Screenshots

No response

Additional context

While I am currently not very trained at golang for implementing a fix, I would be willing to extend the documentation on this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrm-externalRoadmap item submitted by non-maintainers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions