'Docker Registry Authentication/Authorization - signed by untrusted key with ID

Honestly, it this point im begging for help

So im trying to add protection for my docker registry ( i do not wanna use htpassword ) which is run like this:

docker compose file

version: '3'

services:
  registry:
    restart: always
    image: registry:2
    ports:
    - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
      REGISTRY_HTTP_ADDR: 127.0.0.1:5000
      REGISTRY_AUTH: token
      REGISTRY_AUTH_TOKEN_REALM: http://api.thechemicalworkshop.com/api/authorize_docker
      REGISTRY_AUTH_TOKEN_ISSUER: "The Chemical Workshop"
      REGISTRY_AUTH_TOKEN_SERVICE: "dockerhub.thechemicalworkshop.com"
      REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE: /ssl/cert.dockerhub.crt
    volumes:
      - ./data:/data
      - ./ssl:/ssl
    network_mode: host

how it should work is that REGISTRY_AUTH_TOKEN_REALM handles the protection i tired self signed cetfiticates in REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE but same result (more below)

im using nginx as reverse proxy and ssl (should be self explanatory) (and the reason why i host it on localhost)

server {
    client_max_body_size 2000m;
    proxy_pass_request_headers      on;
    server_name dockerhub.thechemicalworkshop.com;

    location / {


    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    proxy_pass                          http://127.0.0.1:5000;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
    proxy_pass_request_headers      on;
    }


listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dockerhub.thechemicalworkshop.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dockerhub.thechemicalworkshop.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

anyways every time i access the registry on server_name it should call REGISTRY_AUTH_TOKEN_REALM to accept/deny

the REGISTRY_AUTH_TOKEN_REALM on stuff is an API in python (quart) with following script:

raw_token = 'eyJ0eXAiOiJKV1Q'

    if matti_check(request.headers["X-Real-Ip"]):
        payload = {"expires_in": 360000,"issued_at": "2022-04-30T15:33:00Z"}

        payload['token'] = raw_token

        response = await make_response(payload)

        return response
    else:
        print(request.headers)
        return "ERROR", 500

token shortened due to space

ignore matti_check() it works fine basically im returning a token alongside some other stuff

to generate the token im using following script:

encoded = jwt.encode(\
    {\
        "iss": "The Chemical Workshop", \
        "aud": "dockerhub.thechemicalworkshop.com",\
        "exp": 1687927320000\
        }, \
        private_key, algorithm="RS256", headers={"kid": "MY4D:MNRW:GY2T:IZBS:HAZT:QZRS:MQ4G:IMBX:GA4D:AYJY:GBST:AMJX"})
print(encoded)

the kid header gets generated by me like this:

  1. first I convert the cerificate using openssl x509 -in cert.dockerhub.crt -noout -outform der -pubkey
  2. I take the key and I sha256 it, for testing I use https://emn178.github.io/online-tools/sha256.html
  3. in the third step I take the first 30 characters and base32 encode it, again using https://emn178.github.io/online-tools/base32_encode.html for testing
  4. then I whack : between every 4 characters

Docker documentation says i should do this to get kid:

  1. Take the DER encoded public key which the JWT token was signed against.

  2. Create a SHA256 hash out of it and truncate to 240bits.

  3. Split the result into 12 base32 encoded groups with : as delimiter.

so I think my approach is correct?

well, it does not work :/

I just get an error docker-registry-registry-1 | time="2022-04-30T17:10:56.438672709Z" level=info msg="token signed by untrusted key with ID: "MY4T:KNRU:GJSW:ENRU:GFRW:CYZW:GNRW:CMLC:GVTG:KM3D:MRSW:CZTD""

Could someone ( i dont know go ) look into portus/docker registry source how they generate a working key?

here is what i tried:

  • asking on docker forum <-- more info
  • asking on lowendtalk
  • asking on like 8 discords
  • trying self signed keys, as well as certbot keys
  • create github issue/ask questions (no anwsers/solutions)
  • ask some random dude from this project on twitter (no anwser)
  • googling, trying to read go code (no luck/anwsers)
  • trying different keys (same result)
  • creating a "bounty" (5$ if you ask, im broke) on fiverr (no capable people or way way overbudget)

Can you guys fix this or give me some lead on how to fix this? my "project" would be opensource as i dont see an implementation in python



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source