Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Shells Virtual Desktop
BMail.ag - Secure Email Service
Server.net
CPLicense.net
VPS Server
Buy VPN
Vultr
VMs for AI
HostDare
HostDare
ReliableSite White-Label Dedicated Hosting for Resellers
InterServer VPS
BMail.ag - Secure Email Service
Best VPN
High-Performance Bare Metal Server Solutions
Karvl.com
Server Mania Cloud Hosting
DataWagon Hosting
AlphaVPS Hosting
Evoxt.com
Clouvider
VPS Hosting with NVMe
Residential IPs in the US & 4G Mobile Proxies in EU & US with Unlimited Bandwidth
ReliableSite White-Label Dedicated Hosting for Resellers
Rabisu - Hosting Solutions
Shells Virtual Desktop
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Need help with Docker Registry Authorization, nginx and tokens

Disclaimer:
I do not know GO (at all) javascript (only basics) and i do not wanna use htpasswd/apache utility but my own API i already have up and running (because it's 100x easier to add/change IP whitelist + more usernames/passwords + more features/expandability

I tried googling all my issues + asking on discords + made a thread on official docker forum + asked on github (5 year old unclosed issue)

Here is my issue:

i used this tutorial to create a private docker repository (with slight changes)

this is what i tried:

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
    volumes:
      - ./data:/data
    network_mode: host

basically im creating a normal registry but exposing it on localhost:5000

now to convert from localhost to SSL im using nginx

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

    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;
    }

        location = /auth {
                proxy_pass_request_headers      on;
                proxy_pass http://localhost:8080/api/authorize_docker;
                proxy_pass_header token;
                proxy_set_header Authorization $http_authorization;
                proxy_pass_header  Authorization;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header  X-Forwarded-Proto $scheme;
}

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
}

the auth_request /auth; and /auth do work and call my API on http://localhost:8080/api/authorize_docker

the authorize_docker part is running this script

@app.route("/api/authorize_docker")
async def authorize_docker():
    data = await request.data
    data2 = await request.get_data()
    js = await request.json
    js2 = await request.get_json()
    form = await request.form
    files = await request.files
    values = await request.values
    # stream = await request.stream
    print(request.authorization)
    print(await request.get_data())
    print(request.headers)
    if matti_check(request.headers["X-Real-Ip"]):
        return "Welcome_Matti"
    else:
        print(request.headers)
        return "ERROR", 500

im basically printing a bunch of stuff (for testing) and returning 200 if the request comes from my IP (it does work !)

however when i inspect the data on my API or wireshark there is no user/password being passed anywhere (??)

i basically run this to log in

Powershell Windows 10
docker login https://dockerhub.thechemicalworkshop.com/
Username: user
Password:
Login Succeeded

the python logs give me this:

4|TCW-API  | None
4|TCW-API  | b''
4|TCW-API  | Remote-Addr: 127.0.0.1
4|TCW-API  | X-Real-Ip: REDACTED
4|TCW-API  | X-Forwarded-Proto: https
4|TCW-API  | Host: localhost:8080
4|TCW-API  | Connection: close
4|TCW-API  | User-Agent: docker/20.10.14 go/go1.16.15 git-commit/87a90dc kernel/5.10.104-linuxkit os/linux arch/amd64 UpstreamClient(Docker-Client/20.10.14 \(windows\))
4|TCW-API  | Accept-Encoding: gzip
4|TCW-API  |
4|TCW-API  | [2022-04-29 22:28:14,748] 127.0.0.1:39722 GET /api/authorize_docker 1.0 200 13 32601
4|TCW-API  | None
4|TCW-API  | b''
4|TCW-API  | Remote-Addr: 127.0.0.1
4|TCW-API  | X-Real-Ip: REDACTED
4|TCW-API  | X-Forwarded-Proto: https
4|TCW-API  | Host: localhost:8080
4|TCW-API  | Connection: close
4|TCW-API  | User-Agent: docker/20.10.14 go/go1.16.15 git-commit/87a90dc kernel/5.10.104-linuxkit os/linux arch/amd64 UpstreamClient(Docker-Client/20.10.14 \(windows\))
4|TCW-API  | Accept-Encoding: gzip
4|TCW-API  |
4|TCW-API  | [2022-04-29 22:28:15,865] 127.0.0.1:39730 GET /api/authorize_docker 1.0 200 13 21546

(why are there 2 calls and not 1?)

anyways, there is NO user, password, authentication bearer token or anything (it should be login, password and hashed bearer token)

so i looked for other ways to authorize


i found this project Authorization for Private Docker Registry | by Thilina Manamgoda | Medium

and adjusted my configs:

docker

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/fullchain.pem
    volumes:
      - ./data:/data
      - ./ssl:/ssl
    network_mode: host

and it does work ! python receives user and password + bearer hashed
the problem is docker now wants a authorization token, so to generate/return it i'm using this:

python API

raw_token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik1ZNFQ6S05SVTpHSlNXOkVOUlU6R0ZSVzpDWVpXOkdOUlc6Q01MQzpHVlRHOktNM0Q6TVJTVzpDWlREIn0.eyJpc3MiOiJUaGUgQ2hlbWljYWwgV29ya3Nob3AiLCJhdWQiOiJkb2NrZXJodWIudGhlY2hlbWljYWx3b3Jrc2hvcC5jb20iLCJleHAiOjE2ODc5MjczMjAwMDB9.wHUtXjyROxSJ4eXlT4VpCaMFczCYnmwqHXpc_G9aAJzTCfhaXTP7ORkWGGWgilDhF4yFOZHSCEhPxWvG7cosCEqeQA1VTX3qVJGEXITvjqkV_QO-oYWlg6VeWib5ex7C8GVCpquOVlnD_bqJ-H_mxFBmoSEtdkBV2_AcXaZYopHVXsGnuWurAPzeNOs0cc2k2Mt9LaveBrQVrrKRSma-5mtoyjfu_HaSqYz6Zv8G1zxN7PZ064nq1XKp1LYt6dF4ShcxQRVMx69H6iefc0-h4ZSRIu_sWSChLr96tYJIestfwHsi_83A-YUcWhYQGQQAfRHuchTJ7BoybmzRzhJhHg'

    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

the longass token gets created using this python script

import jwt

private_key = b'''-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOlBy6Ru+8d5mO
-----END PRIVATE KEY-----'''

public_key = b'''-----BEGIN CERTIFICATE-----
MIIDbTCCAlUCFEAIdgSu+9F+y39e4uqNZLBX02ThMA0GCSqGSIb3DQEBCwUAMHMx
-----END CERTIFICATE-----'''

encoded = jwt.encode(\
    {\
        "iss": "The Chemical Workshop", \
        "aud": "dockerhub.thechemicalworkshop.com",\
        "exp": 1687927320000\
        }, \
        private_key, algorithm="RS256", headers={"kid": "MY4T:KNRU:GJSW:ENRU:GFRW:CYZW:GNRW:CMLC:GVTG:KM3D:MRSW:CZTD"})
print(encoded)

I removed most of the key for space reasons removed most of the key for space reasons

anyways the KID key instructions on docker documentation are:

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 to get 1. i used openssl x509 -in domain.crt -noout -outform der -pubkey (i found it online)

which gives me following key

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzpQcukbvvHeZjpsRmR1T
u27d/Ep1DYvqLwfVsfoxXIU5lUrQ53J3K89Z/hrb8J0hF0ewaaqfzLE5khBY7E/v
10bqiAr9oNTu+3bKM+z9YRaJ4mh1atE3IFsW7uYBAJ8KYykxzUsJ8nJHyqFbJ0nH
pvdlRgoD/+CTn6uIGIrhMx8kgDbXGwX+t/OhsG87jVwfsr5Sa7lVilnMR6HJ/5F8
rAJ/O8sGfBGlbL62qUdbnLxrwxANiyA1p9F3UEoo2GhA9rkD0oileUVeYtVJ9zIu
NARfrProR7X6i8ZSCjF9FyhasyEl/rgNv69CPEFj1HCVYb/CHkCVj1L3Zi1v8K1K
PwIDAQAB
-----END PUBLIC KEY-----

now my question is, do i convert the WHOLE output (including -----BEGIN PUBLIC KEY-----) or just content?

by Create a SHA256 hash out of it and truncate to 240bits i understand SHA256 and keep the first 30 characters ? (is this correct?)

basically i get

hash content
f95642eb641cac63ca1b5fe3cdeafcf9ecb576f7f60c321aa8583e1d86d4cb7f
or
hash everything
75e190d3c15134507fbb352fd4d87301248544a418caf09bd8176c401dc55071

converting first 30 characters into base32 and doing step 3
gives me:

MY4T:KNRU:GJSW:ENRU:GFRW:CYZW:GNRW:CMLC:GVTG:KM3D:MRSW:CZTD
or
G42W:KMJZ:GBSD:GYZR:GUYT:GNBV:GA3W:MYTC:GM2T:EZTE:GRSD:QNZT

the problem is, it does not work

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""

I am super hard stuck and would appreciate any help/tips/lead

there is more info on the docker thread and i will be updating BOTH once i get some lead/updates

Comments

  • I got more lead but no idea what that means
    https://github.com/distribution/distribution/issues/2223#issuecomment-1115381920

    anyone clues?

  • I made a fiverr request and said im giving 5$ bounty whoever can fix this bug
    bunch of morons applied that had no idea what docker is, anyone willing to fix it/help fix it?

  • Honestly you need to narrow down the issue before someone can help you out.

    Also, looking for someone to do what is essentially devops/SRE work for "5$" is a bit of a joke, and I'm not at all surprised at the outcome.

    Thanked by 2devp yoursunny
  • @stevewatson301 said:
    Honestly you need to narrow down the issue before someone can help you out.

    Also, looking for someone to do what is essentially devops/SRE work for "5$" is a bit of a joke, and I'm not at all surprised at the outcome.

    well, im pretty sure there are people that can read thru the source go code and find a working token in minutes

    The 5$ is well, all i can afford at the moment lol but yeah it's not much

    as for narrowing down, am am unsure, whatever i try it comes down to same error message every time (tried different tokens, generating them differently, etc) i can't even find lead how to debug this further

    a step could be installing go and trying other project but that would lead to no-where as i dont understand go code so would be back here asking what does this code mean/do / how is the token generated

Sign In or Register to comment.