Descripción
Se describe al detalle cómo Nginx Proxy Manager (NPM) delega la autenticación del servicio Grafana MIMIR a Keycloak. Concretamente la aplicación cliente usa OAuth2 Client Credentials para poder validar su acceso al servicio. El vídeo describe con todo lujo de detalles el proceso y hace demostraciones además de proporcionar los ficheros de configuración necesarios.
Secuencia del proceso OAuth2 Client Credentials con reverse proxy
Esquea origina hecho con mermaid:
sequenceDiagram
autonumber
participant ClientApp as Client App
participant Proxy as Reverse Proxy (NPM)
participant Server as Service
participant IdP as IdP (Keycloak)
ClientApp->>IdP: Authenticate<br />Client ID + Client Secret
IdP->>ClientApp: ID + Secret are valid<br />Return Access Token
ClientApp->>Proxy: GET /api/resource<br />using Access Token in headers
Proxy->>IdP: Access Token valid?
IdP->>Proxy: Yes, is valid
Proxy->>Server: GET /api/resource<br />w/user metadata:::redLine
Server->>Proxy: response GET /api/resource :::redLine
Proxy->>ClientApp: response GET /api/resource
%%{init:{'theme':'forest'}}%%
Fichero .png con código vectorial de .drawio incluido
📎 OAuth2.drawio.png 760.0KB
Configuración NGINX Proxy Manager (NPM)
Capturas de pantalla de la configuración de
metrics.i40sys.com con las customizaciones para cargar las particularidades de la configuración OAuth2.ficheros de configuración custom
/data/nginx/custom/i40sys_mimir_custom_root.conf
# no hay configuraciones necesarias para OAuth2 Client Credentials
# este fichero se llenará con OAuth2 Authorization Code/data/nginx/custom/i40sys_mimir_custom.conf
client_body_buffer_size 256M;
proxy_read_timeout 600;
proxy_connect_timeout 600;
proxy_send_timeout 600;
client_header_timeout 600s;
client_body_timeout 600s;
proxy_request_buffering off;
location /access-token/validation {
internal;
proxy_method GET;
proxy_pass https://iam_i40sys-keycloak-1:8443/realms/observability/protocol/openid-connect/userinfo;
proxy_set_header Host iam.i40sys.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location ~ ^/(api|prometheus)/ {
proxy_pass http://observability_i40sys-mimir-1$request_uri;
auth_request /access-token/validation;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}notas sobre el docker-compose.yaml
El fichero de configuración es estándard, es decir, cualquier fichero que uses está bien. Lo más relevante a tener en cuenta es que el volumen que contiene los ficheros custom debe montarse en
/data para que los anteriores ficheros esten mapeados.Concretamente la configuración es:
services:
nginx-reverse-proxy:
image: 'lepresidente/nginxproxymanager:latest'
...
volumes:
- "/data/rproxy/data:/data"
...concretamente en nuestro escenario el fichero
docker-compose.yaml es algo complejo porqué NPM usa Crowdsec para hacer filtrado. Dejamos una copia a continuación por si puede ayudar a alguien.docker-compose.yaml
services:
nginx-reverse-proxy:
container_name: nginx-reverse-proxy
image: 'lepresidente/nginxproxymanager:latest'
hostname: "nginx-reverse-proxy"
security_opt:
- no-new-privileges=true
entrypoint:
- "/init"
environment:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
CURL_CA_BUNDLE: /etc/ssl/certs/ca-certificates.crt
SUPPRESS_NO_CONFIG_WARNING: 1
S6_BEHAVIOUR_IF_STAGE2_FAILS: 1
S6_CMD_WAIT_FOR_SERVICES_MAXTIME: 0
S6_FIX_ATTRS_HIDDEN: 1
S6_KILL_FINISH_MAXTIME: 10000
S6_VERBOSITY: 1
NODE_ENV: production
CROWDSEC_BOUNCER_APIKEY: ${CROWDSEC_BOUNCER_APIKEY}
CROWDSEC_OPENRESTY_BOUNCER: |
ENABLED=true
API_URL=http://crowdsec:8080
API_KEY=${CROWDSEC_BOUNCER_APIKEY}
EXCLUDE_DOMAINS="metrics.i40sys.com,iam.i40sys.com,logs.i40sys.com,proxy.i40sys.com"
# Uncomment this if IPv6 is not enabled on your host
# DISABLE_IPV6: 'true'
ipc: "private"
restart: "unless-stopped"
volumes:
- "/data/rproxy/data:/data"
- "/data/rproxy/letsencrypt:/etc/letsencrypt"
working_dir: "/app"
networks:
- "services"
- "crowdsec"
ports:
- "10.2.0.134:81:81/tcp"
- 80:80
- 443:443
crowdsec:
image: docker.io/crowdsecurity/crowdsec:latest
container_name: crowdsec
environment:
- COLLECTIONS=crowdsecurity/nginx-proxy-manager
volumes:
- /docker-data/crowdsec/db:/var/lib/crowdsec/data/
- /docker-data/crowdsec/config:/etc/crowdsec/
#- ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml
- /data/rproxy/data/logs/:/var/log/npm:ro
networks:
crowdsec:
restart: unless-stopped
security_opt:
- no-new-privileges=true
depends_on:
- nginx-reverse-proxy
networks:
crowdsec:
external: true
name: "crowdsec"
services:
external: true
name: "services"References
- Nuestros vídoes y posts de Logs and Metrics
Securing Grafana with Keycloak SSO Integration- keycloak-production-docker-compose
Welcome | OAuth2 Proxy
hub.docker.com





