Open
Description
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:
- Scenario 1: mTLS without any accessControl options
- unauthenticated request are blocked but authenticated requests have full access
- 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
- Scenario 3: mTLS with accessControl options and htpasswd file
- mTLS is completly ignored
To reproduce
Scenario 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"
}
}
}
- 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
- Seen error
This works as expected but doesn't meet the requirement that only some users should be allowed to push.
Scenario 2
- 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"
]
}
}
}
}
}
- Client tool used
zot verify <config-file>
- Seen error
invalid server config: access control config requires one of httpasswd, ldap or openid authentication or using only 'anonymousPolicy' policies
Scenario 3
- 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"
}
}
}
}
- 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>
- 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:
- 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
- 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)
- 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.