thomseddon / traefik-forward-auth

Minimal forward authentication service that provides Google/OpenID oauth based login and authentication for the traefik reverse proxy
MIT License
2.14k stars 408 forks source link

Keycloak connection refused #314

Open shoaloak opened 2 years ago

shoaloak commented 2 years ago

Hi there, I'm new to traefik so excuse me if I'm asking something obvious. Also if you spot something weird and/or redundant in my config please let me know :smiley:

I'm trying to set up forward-auth together with Keycloak to provide authentication for (now just one of) my services. I have the feeling I'm close to getting it working, but I'm getting the following log error: forward-auth | level=fatal msg="Get https://sso.mydomain.net/realms/myrealm/.well-known/openid-configuration: dial tcp <public_ip>:443: connect: connection refused"

I can access the sso URL from my personal machine over the internet, so I'm not entirely sure what is wrong. When accessing auth.mydomain.net, i get a 500 server error and nothing loads.

Traefik also picks up this error: proxy_traefik | level=debug msg="Error calling http://forward-auth:4181. Cause: Get \"http://forward-auth:4181\": dial tcp: lookup forward-auth on 127.0.0.11:53: no such host" middlewareName=forward-auth@file middlewareType=ForwardedAuthType

So it fails to find the forward-auth container locally and keycloak publically.... Any help would be much appreciated!


Here is a mock diagram of the basic setup

graph TD
    I((Interwebz)) --> T{proxy_traefik}
    T ==>|sso| K(Keycloak)
    T ==>|app| A(app)
    T ==>|auth| F(traefik-forward-auth)

My traefik compose file:

version: "3.9"
services:
  traefik:
    container_name: proxy_traefik
    image: traefik:v2.6.6
    restart: always
    ports:
      # The HTTP port
      - "80:80"
      # The HTTPS port
      - "443:443"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    networks:
      # Create before (docker network create routing-network)
      - routing-network
    volumes:
      # So that Traefik can listen to the Docker events
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # Store certificates
      - "./letsencrypt:/letsencrypt"
      # Config with middlewares
      - "./config:/etc/traefik/conf:ro"
    command:
      # Enable Docker in Traefik so it reads labels from Docker services
      - "--providers.docker=true"
      # Don't want all services exposed
      - "--providers.docker.exposedByDefault=false"
      # One network to rule them all
      - "--providers.docker.network=routing-network"
      # Don't share info
      - "--global.sendAnonymousUsage=false"

      # Config for shared middlewarez, directory is recommended
      - "--providers.file.directory=/etc/traefik/conf"

      # HTTP
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
      # Redirect to HTTPS
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"

      # TLS
      - "--certificatesresolvers.acme-resolver.acme.email=<REDACTED>"
      - "--certificatesresolvers.acme-resolver.acme.tlschallenge=true"
      - "--certificatesresolvers.acme-resolver.acme.storage=/letsencrypt/acme.json"

      # Use when debugging
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      #- "--certificatesresolvers.acme-resolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"

networks:
  routing-network:
    external: true

My config file:

http:
  middlewares:
    forward-auth:
      forwardauth:
        address: "http://forward-auth:4181"
        trustForwardHeader: true
        authResponseHeaders: "X-Forwarded-User"

my Keycloak compose file:

version: "3.9"
services:
  keycloak:
    container_name: sso_keycloak
    #image: quay.io/keycloak/keycloak:18.0.0
    build:
      context: ./keycloak
    environment:
      - KC_HOSTNAME=sso.mydomain.net
      # Enables communication through HTTP between the proxy and Keycloak.
      - KC_PROXY=edge
      - KC_DB=postgres
      - KC_DB_USERNAME=${DB_USER}
      - KC_DB_PASSWORD=${DB_PASSWORD}
      - KC_DB_URL_HOST=database_postgresql
      - KEYCLOAK_ADMIN=${KC_USER}
      - KEYCLOAK_ADMIN_PASSWORD=${KC_PASSWORD}
    networks:
      - database-network
      - routing-network
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=routing-network"

      # Routing
      - "traefik.http.routers.keycloak.entrypoints=websecure"
      - "traefik.http.routers.keycloak.rule=Host(`sso.mydomain.net`)"

      # Uncomment this for /admin access
      #- "traefik.http.routers.keycloak.rule=PathPrefix(`/js/`, `/realms/`, `/resources/`) || Path(`/robots.txt`)"

      # TLS
      - "traefik.http.routers.keycloak.tls=true"
      - "traefik.http.routers.keycloak.tls.certresolver=acme-resolver"

networks:
  database-network:
    external: true
  routing-network:
    external: true

My traefik-forward-auth compose:

version: "3.9"
services:
  forward-auth:
    container_name: forward-auth
    image: thomseddon/traefik-forward-auth:2
    networks:
      - routing-network
    environment:
      - AUTH_HOST=${AUTH_HOST}
      - COOKIE_DOMAIN=${COOKIE_DOMAIN}
      - SECRET=${SECRET}
      #- URL_PATH=/_oauth
      - PORT=4181
      - DEFAULT_PROVIDER=oidc
      - PROVIDERS_OIDC_ISSUER_URL=${OIDC_ISSUER}
      - PROVIDERS_OIDC_CLIENT_ID=${CLIENT_ID}
      - PROVIDERS_OIDC_CLIENT_SECRET=${CLIENT_SECRET}
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=routing-network"

      # Routing
      - "traefik.http.services.auth.loadbalancer.server.port=4181"
      - "traefik.http.routers.auth.entrypoints=websecure"
      - "traefik.http.routers.auth.rule=Host(`auth.mydomain.net`)"

      # TLS
      - "traefik.http.routers.auth.tls=true"
      - "traefik.http.routers.auth.tls.certresolver=acme-resolver"

      # Auth
      - "traefik.http.routers.auth.middlewares=forward-auth@file"

networks:
  routing-network:
    external: true

The service in question has the following labels:

labels:
      - "traefik.enable=true"
      - "traefik.docker.network=routing-network"

      # Routing
      - "traefik.http.routers.hedgedoc.entrypoints=websecure"
      - "traefik.http.routers.hedgedoc.rule=Host(`app.mydomain.net`)"

      # TLS
      - "traefik.http.routers.hedgedoc.tls=true"
      - "traefik.http.routers.hedgedoc.tls.certresolver=acme-resolver"

      # Auth
      - "traefik.http.routers.auth.middlewares=forward-auth@file"

My partial, redacted .env

# traefik-forward-auth
CLIENT_ID=traefik-forward-auth # set this in Keycloak
CLIENT_SECRET=<generated by keycloak>
SECRET=<nope>
AUTH_HOST=auth.mydomain.net
COOKIE_DOMAIN=mydomain.net
OIDC_ISSUER=https://sso.mydomain.net/realms/myrealm
lumnikemel commented 1 year ago

@shoaloak Did you ever get this resolved? I have the same problem.

and-ratajski commented 1 year ago

For what I understand you have the middleware configuration in both traefik.toml file and in docker labels for traefik-forward-auth service. I would recommend to do it in one place (docker labels worked for me). At the begging I tried to configure them in traefik.toml but for unknown reason it didn't work.

Here's my configuration that works:

docker-compose.yml

version: '3.5'

services:
  traefik:
    image: traefik:latest
    container_name: cx-example-traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - cx-example-net-dev
    ports:
      - 8080:80
      - 443:443
    volumes:
      # - /etc/localtime:/etc/localtime:ro
      # - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/traefik.toml:/traefik.toml:ro
      - ./traefik/services.toml:/services.toml:ro
      - ./traefik/acme.json:/acme.json
      - ./logs/traefik.log:/traefik.log
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      # - "traefik.http.middlewares.traefik-auth.basicauth.users=dummy:$$apr1$$iHNcpXTy$$cSNZ9EJt3fChWLn3s.v2L1"

      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`localhost`)"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"

      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`localhost`)"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=hypercpq"
      - "traefik.http.routers.traefik-secure.service=api@internal"
      # - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-forward-auth"

  # https://doc.traefik.io/traefik/providers/docker/#docker-api-access
  socket-proxy:
      image: tecnativa/docker-socket-proxy
      container_name: cx-example-socket-proxy
      restart: unless-stopped
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock:ro
      environment:
        CONTAINERS: 1
      networks:
        - cx-example-net-dev

  traefik-forward-auth:
    image: thomseddon/traefik-forward-auth:2
    env_file:
      - ./traefik-forward-auth.env
    networks:
      - cx-example-net-dev
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=cx-example-net-dev"
      - "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4181"
      - "traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User"
      - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181"

  portainer:
      image: portainer/portainer:latest
      container_name: cx-example-portainer
      restart: unless-stopped
      security_opt:
        - no-new-privileges:true
      networks:
        - cx-example-net-dev
      volumes:
        # - /etc/localtime:/etc/localtime:ro
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - cx-example-portainer-dev:/data
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=cx-example-net-dev"
        - "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"

        - "traefik.http.routers.portainer.entrypoints=http"
        - "traefik.http.routers.portainer.middlewares=portainer-https-redirect"

        - "traefik.http.routers.portainer-secure.entrypoints=https"
        - "traefik.http.routers.portainer-secure.rule=Host(`portainer.localhost`)"
        - "traefik.http.routers.portainer-secure.tls=true"
        - "traefik.http.routers.portainer-secure.tls.certresolver=hypercpq"
        - "traefik.http.routers.portainer-secure.middlewares=traefik-forward-auth"
        # - "traefik.http.routers.portainer-secure.service=portainer"

  whoami:
    image: containous/whoami
    container_name: cx-example-whoami
    networks:
      - cx-example-net-dev
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=cx-example-net-dev"
      - "traefik.http.middlewares.whoami-https-redirect.redirectscheme.scheme=https"

      - "traefik.http.routers.whoami.rule=Host(`auth.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=http"
      - "traefik.http.routers.whoami.middlewares=whoami-https-redirect"

      - "traefik.http.routers.whoami-secure.entrypoints=https"
      - "traefik.http.routers.whoami-secure.rule=Host(`auth.localhost`)"
      - "traefik.http.routers.whoami-secure.tls=true"
      - "traefik.http.routers.whoami-secure.tls.certresolver=hypercpq"
      - "traefik.http.routers.whoami-secure.middlewares=traefik-forward-auth"

volumes:
  cx-example-portainer-dev:

networks:
  cx-example-net-dev:
    external: true

./traefik/traefik.toml

[api]
  dashboard = true
  debug = true

[log]
  level = "INFO"
  filePath = "/traefik.log"

[entryPoints]
  [entryPoints.http]
  address = ":80"
  # Redirect to HTTPS (why wouldn't you?)
  [entryPoints.http.http.redirections.entryPoint]
    to = "https"
    scheme = "https"
  [entryPoints.https]
  address = ":443"

[providers.docker]
  endpoint = "tcp://socket-proxy:2375"
  watch = true
  exposedByDefault = false

[providers.file]
  filename = "/etc/traefik/services.toml"
AUTH_HOST=https://localhost
PORT=4181
DEFAULT_PROVIDER=oidc
PROVIDERS_OIDC_ISSUER_URL=<keycloak-url>/realms/<your-realm>
PROVIDERS_OIDC_CLIENT_ID=<client-id>
PROVIDERS_OIDC_CLIENT_SECRET=<client-secret>
SECRET=something-random
#COOKIE_DOMAIN=

Hope that helps.