Skip to content

Instantly share code, notes, and snippets.

@haani-niyaz
Last active March 22, 2023 12:37
Show Gist options
  • Save haani-niyaz/86d5f654ed2d0a7ed4abadd5ba22075f to your computer and use it in GitHub Desktop.
Save haani-niyaz/86d5f654ed2d0a7ed4abadd5ba22075f to your computer and use it in GitHub Desktop.
HAProxy config for nexus docker repo with no connector

HAPROXY Docker Nexus (No HTTP Connector)

Background

  1. The docker-login repo is setup with minimal (read-only) access which allows all users to login. This creates the necessary credentials store required for all subsequent docker operations. The team docker repositories will be setup with RBAC to only allow access to members of that respective team to perform docker push/pull operations.

  2. The proxy will inspect the context path for the docker pull/push operations and proceed only if authorization is successful.

  3. The repositories are created with the prefix docker i.e: docker-team-a or docker-team-b

  4. The context path such as team-a and team-b is critical part of the onboarding and authorization process. RBAC will manage the authorization by disallowing for instance, a member of Team A to push to team-b repo.

  5. The repository structure will have a mandatory namespace such as team-a:

v2
|_ team-a
   |_ haproxy
   |_ centos
  1. The push/pull operations must have the namespace i.e:
$ docker push repo.example.com/team-a/alpine:3.4
$ docker pull repo.example.com/team-a/alpine:3.4
  1. All images must be tagged with the namespace i.e: repo.example.com/team-a/alpine:3.4

HAProxy Config

Frontend config to handle access to any docker repo without a http connector.

frontend http-in
    bind *:80
    mode http
   option forwardfor
    option http-server-close
    option httpchk
    http-request set-header X-Forwarded-Proto https
    
    # Determine docker cli connections as those containing `docker` within the User-Agent header
    acl docker-cli hdr_sub(user-agent) docker
    
    acl nexus_repo hdr_reg(host) -i repo\.[A-z0-9\.]+example\.com
    acl docker-api-v1 path_reg -i ^/v1/
    
    # This is how we identify docker login requests
    # This is sent to the bare login repo (docker-login) which has the permissions restricted to login only.
    acl docker-api-v2 path_reg -i ^/v2/$
    
    # We don't support docker V1 API so block any clients from attempting to connect with a more meaningful error
    http_request deny deny_status 403 if docker-api-v1
    
    # The incoming request path is in the form of:
    # docker push repo.example.com/team-a/alpine:3.4
    # '[METHOD] /v2/team-a/alpine/blobs/XXXX'
    # We want to instead send this as '/repository/docker-team-a/v2/team-a/alpine/blobs/XXXX'
    
    # Set a variable from the request path but strips '/V2/' i.e: team-a/alpine/blobs/XXXX
    http_request set-var(req.registry) path,regsub(^/v2/,) if { path_beg /v2/ }
    
    # Splits the variable set previously with delimeter '/' and picks the first value i.e: team-a
    # Forms the request path '/repository/docker-team-a/v2/team-a/alpine/blobs/XXXX'
    http_request set-path /repository/docker-%[var(req.registry),field(1,'/')]/%[path] if !docker-api-v2 docker-cli nexus_repo
    
    # All login attempts are sent to the docker-login repo
    http_request set-path /repository/docker-login/%[path] if docker-cli docker-api-v2 nexus_repo
    default_backend k8s-http_backend
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment