Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proxy: support external access control request handling (forward auth) #324

Merged
merged 1 commit into from
Oct 4, 2019

Conversation

desimone
Copy link
Contributor

@desimone desimone commented Sep 26, 2019

Flow

diagram

In action

Not that exciting, but I guess that's the point. Subsequent calls to any other routes will be transparent as well.

https://www.youtube.com/watch?v=WXE79juX7zk&feature=youtu.be

Example config

Using Traefik forwardauth

version: "3"

services:
  reverse-proxy:
    # The official v2.0 Traefik docker image
    image: traefik:v2.0
    # Enables the web UI and tells Traefik to listen to docker
    command: --api.insecure=true --providers.docker
    ports:
      # The HTTP port
      - "80:80"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
  whoami:
    # A container that exposes an API to show its IP address
    image: containous/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.corp.beyondperimeter.com`)"
      # Create a middleware named `foo-add-prefix`
      - "traefik.http.middlewares.test-auth.forwardauth.address=https://httpbin.corp.beyondperimeter.com/.pomerium/verify/http://whoami.corp.beyondperimeter.com"
      - "traefik.http.routers.whoami.middlewares=test-auth@docker"
  echo:
    # image: kennethreitz/httpbin
    image: mendhak/http-https-echo
    labels:
      - "traefik.http.routers.httpbin.rule=Host(`whoami.corp.beyondperimeter.com`)"

And using nginx-ingress .

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kuard
  annotations:
    kubernetes.io/ingress.class: "nginx"
    certmanager.k8s.io/issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/auth-url: https://httpbin.corp.beyondperimeter.com:8443/.pomerium/verify/kuard.k8s.corp.beyondperimeter.com?no_redirect=true
    nginx.ingress.kubernetes.io/auth-signin: https://httpbin.corp.beyondperimeter.com:8443/.pomerium/verify/kuard.k8s.corp.beyondperimeter.com

spec:
  tls:
    - hosts:
        - kuard.k8s.corp.beyondperimeter.com
      secretName: quickstart-example-tls
  rules:
    - host: kuard.k8s.corp.beyondperimeter.com
      http:
        paths:
          - path: /
            backend:
              serviceName: kuard
              servicePort: 80

Checklist:

  • updated docs
  • unit tests added
  • related issues referenced
  • updated CHANGELOG.md
  • ready for review

@codecov
Copy link

codecov bot commented Sep 26, 2019

Codecov Report

Merging #324 into master will decrease coverage by 0.2%.
The diff coverage is 77.7%.

@@           Coverage Diff            @@
##           master    #324     +/-   ##
========================================
- Coverage    88.9%   88.7%   -0.3%     
========================================
  Files          49      49             
  Lines        2638    2679     +41     
========================================
+ Hits         2346    2377     +31     
- Misses        221     228      +7     
- Partials       71      74      +3
Impacted Files Coverage Δ
internal/config/policy.go 100% <ø> (ø) ⬆️
proxy/proxy.go 96.4% <0%> (-1.4%) ⬇️
internal/config/options.go 81.6% <0%> (-2.5%) ⬇️
proxy/middleware.go 100% <100%> (ø) ⬆️
internal/templates/templates.go 100% <100%> (ø) ⬆️
authenticate/handlers.go 97.9% <100%> (ø) ⬆️
proxy/handlers.go 97.4% <89.2%> (-2.6%) ⬇️

@lukasmrtvy
Copy link

lukasmrtvy commented Sep 26, 2019

What about this example? Pomerium as auth service is hidden behind Traefik. ( Thats why I wanted to have Pomerium with optional TLS )

version: "3"

services:
  reverse-proxy:
    image: traefik:v1.7-alpine
    command: --docker --entryPoints="Name:http Address::80 Redirect.EntryPoint:https" --entryPoints='Name:https Address::443 TLS' 
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  pomerium:
    image: pomerium/pomerium
    labels:
      - "traefik.frontend.rule=Host:auth.example.com"
      - "traefik.port=443" 
      - "traefik.protocol=http"
    ...
  whoami:
    image: containous/whoami
    labels:
      - "traefik.rule=Host:whoami.example.com"
      - "traefik.port=80" 
      - "traefik.protocol=http"
      - "traefik.frontend.auth.forward=https://auth.example.com"

@desimone
Copy link
Contributor Author

@lukasmrtvy -- Yes, that should work just fine but would require the TLS change ( #64 ) which I'm also taking another look at. In that case, Traefik would be responsible for handling all routing and certificates.

@desimone desimone changed the title proof of concept: support forward-auth flow proxy: support forward-auth flow Sep 30, 2019
@desimone desimone mentioned this pull request Sep 30, 2019
5 tasks
@desimone desimone added this to the v0.4.0 milestone Sep 30, 2019
cmd/pomerium/main.go Outdated Show resolved Hide resolved
proxy/handlers.go Show resolved Hide resolved
proxy/handlers.go Show resolved Hide resolved
@desimone desimone force-pushed the poc/forward-auth-endpoint branch 2 times, most recently from 769b0c6 to caa9377 Compare October 4, 2019 03:22
@desimone desimone changed the title proxy: support forward-auth flow proxy: support external access control request handling (forward auth) Oct 4, 2019
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
@desimone desimone merged commit eaa1e7a into pomerium:master Oct 4, 2019
@desimone desimone deleted the poc/forward-auth-endpoint branch October 4, 2019 04:22
@tlvenn
Copy link

tlvenn commented Oct 4, 2019

This is awesome ! Any chance to have an example with ambassador as well ? Thanks in advance.

@desimone
Copy link
Contributor Author

desimone commented Oct 5, 2019

@tlvenn not at the moment but we'd love the contribution. However, looking at the docs, the approach looks extremely similar to nginx and traefik so it should work out the box.

@lyndon160
Copy link

Hi @desimone, thanks for providing this. Is there a complete docker-compose example of how to use pomerium was a forward auth middleware for ingresses such as Traefik?

The example you gave above appears to be missing the pomerium service and config.

There seems to be some example https://github.com/pomerium/pomerium/tree/master/examples/traefik but it does not appear to work as expected.

Ideally, Traefik would be responsible for managing TLS comms and the pomerium would be just over HTTP. Also, the IAP would only be accessible internally as middleware, not directly via the browser. I've seen merged pull requests for both of these but nothing in the docs to reflect it, making it difficult to use.

Effectively I'm looking to use pomerium in the same way that https://github.com/thomseddon/traefik-forward-auth supports.

pom

@cuonglm
Copy link
Contributor

cuonglm commented Jul 22, 2020

There seems to be some example https://github.com/pomerium/pomerium/tree/master/examples/traefik but it does not appear to work as expected.

Can you elaborate what's exactly "not appear to work as expected"?

@lyndon160
Copy link

lyndon160 commented Jul 22, 2020

Hi @cuonglm, thanks for looking into this. It could be that I have my configuration wrong, please see:

My configuration is almost identical to the one in the example except that I have different IDP creds, have changed the policy domain to my domain, and I've changed the pomerium.forwardauth.address to point to the local pomerium (http://pomerium), which is typically how forward auth and IAPs are used with Traefik.

The example config has this in: - "traefik.http.middlewares.pomerium.forwardauth.address=https://a6acdabcde358bd08f3537f4de7df7eb.m.pipedream.net"

This service appears to just return a 200, presumably allowing all messages through when used as a forward auth, rather than using pomerium? Why is this address used in the example?

Configuring it to point to the local instance causes a 403 through the browser, and through postman with a valid token redirects me to my IDP login page.

I have an extract of the failure logs here when accessing via the browser: https://pastebin.com/r1LTyCt8

On top of this, it is not clear to me why the pomerium instance is exposed via traefik:
- "traefik.http.routers.pomerium.rule=Host(authenticate.localhost.pomerium.io)"

@travisgroth
Copy link
Contributor

The example config has this in: - "traefik.http.middlewares.pomerium.forwardauth.address=https://a6acdabcde358bd08f3537f4de7df7eb.m.pipedream.net"

Hey @lyndon160 this is an error introduced in a recent repo reorganization. #1128 should fix it. For the v0.9.4 version of Pomerium it should be:

- "traefik.http.middlewares.pomerium.forwardauth.address=http://pomerium/?uri=https://httpbin.localhost.pomerium.io"

This will work without the uri parameter in the v0.9.5 release we're doing shortly.

@lyndon160
Copy link

lyndon160 commented Jul 22, 2020

Hey @travisgroth thanks for the help, for the browser flow, this seems to be working as expected now. However, when I use postman with the same client and password grant type, pomerium errors saying:

pomerium_1 | 5:20PM ERR proxy: could not locate session from context error="internal/sessions: session is not found"

INF authorize check allow=false check-request-id=ef54f1b1-057c-4219-acff-05c50905cc3c host=httpbin.localhost.pomerium.io method=GET path= query= request-id=417bdf7e-2964-47fb-8c3c-5f5d2088500d service=authorize status=401

pomerium_1 | 5:20PM INF authenticate: session load error error="Bad Request: internal/sessions: session is not found"

pomerium_1 | 5:20PM ERR proxy: could not locate session from context error="internal/sessions: session is not found"

The result is that postman gets a login page in return, which is not the expected behaviour.

@lyndon160
Copy link

@travisgroth thanks for the help. My issue was answered in #1130.

Unfortunately Pomerium does not appear to suit my use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants