outpost: separate ak-api and proxy further for future outposts
This commit is contained in:
		@ -1,4 +1,4 @@
 | 
				
			|||||||
package cmd
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
@ -8,18 +8,21 @@ import (
 | 
				
			|||||||
	"os/signal"
 | 
						"os/signal"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/server"
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/ak"
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/proxy"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const helpMessage = `authentik proxy
 | 
					const helpMessage = `authentik proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Required environment variables:
 | 
					Required environment variables:
 | 
				
			||||||
 - AUTHENTIK_HOST: URL to connect to (format "http://authentik.company")
 | 
					- AUTHENTIK_HOST: URL to connect to (format "http://authentik.company")
 | 
				
			||||||
 - AUTHENTIK_TOKEN: Token to authenticate with
 | 
					- AUTHENTIK_TOKEN: Token to authenticate with
 | 
				
			||||||
 - AUTHENTIK_INSECURE: Skip SSL Certificate verification`
 | 
					- AUTHENTIK_INSECURE: Skip SSL Certificate verification`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RunServer main entrypoint, runs the full server
 | 
					func main() {
 | 
				
			||||||
func RunServer() {
 | 
						log.SetLevel(log.DebugLevel)
 | 
				
			||||||
	pbURL, found := os.LookupEnv("AUTHENTIK_HOST")
 | 
						pbURL, found := os.LookupEnv("AUTHENTIK_HOST")
 | 
				
			||||||
	if !found {
 | 
						if !found {
 | 
				
			||||||
		fmt.Println("env AUTHENTIK_HOST not set!")
 | 
							fmt.Println("env AUTHENTIK_HOST not set!")
 | 
				
			||||||
@ -42,11 +45,13 @@ func RunServer() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	rand.Seed(time.Now().UnixNano())
 | 
						rand.Seed(time.Now().UnixNano())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ac := server.NewAPIController(*pbURLActual, pbToken)
 | 
						ac := ak.NewAPIController(*pbURLActual, pbToken)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interrupt := make(chan os.Signal, 1)
 | 
						interrupt := make(chan os.Signal, 1)
 | 
				
			||||||
	signal.Notify(interrupt, os.Interrupt)
 | 
						signal.Notify(interrupt, os.Interrupt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ac.Server = proxy.NewServer(ac)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ac.Start()
 | 
						ac.Start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
@ -4,6 +4,7 @@ go 1.14
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	cloud.google.com/go v0.64.0 // indirect
 | 
						cloud.google.com/go v0.64.0 // indirect
 | 
				
			||||||
 | 
						github.com/BeryJu/authentik/proxy v0.0.0-20210116180903-8acb9dde5f2f
 | 
				
			||||||
	github.com/coreos/go-oidc v2.2.1+incompatible
 | 
						github.com/coreos/go-oidc v2.2.1+incompatible
 | 
				
			||||||
	github.com/getsentry/sentry-go v0.9.0
 | 
						github.com/getsentry/sentry-go v0.9.0
 | 
				
			||||||
	github.com/go-openapi/errors v0.19.9
 | 
						github.com/go-openapi/errors v0.19.9
 | 
				
			||||||
@ -19,8 +20,10 @@ require (
 | 
				
			|||||||
	github.com/justinas/alice v1.2.0
 | 
						github.com/justinas/alice v1.2.0
 | 
				
			||||||
	github.com/kr/pretty v0.2.1 // indirect
 | 
						github.com/kr/pretty v0.2.1 // indirect
 | 
				
			||||||
	github.com/magiconair/properties v1.8.4 // indirect
 | 
						github.com/magiconair/properties v1.8.4 // indirect
 | 
				
			||||||
 | 
						github.com/mitchellh/mapstructure v1.4.1 // indirect
 | 
				
			||||||
	github.com/oauth2-proxy/oauth2-proxy v0.0.0-20200831161845-e4e5580852dc
 | 
						github.com/oauth2-proxy/oauth2-proxy v0.0.0-20200831161845-e4e5580852dc
 | 
				
			||||||
	github.com/pelletier/go-toml v1.8.1 // indirect
 | 
						github.com/pelletier/go-toml v1.8.1 // indirect
 | 
				
			||||||
 | 
						github.com/pkg/errors v0.9.1
 | 
				
			||||||
	github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f // indirect
 | 
						github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f // indirect
 | 
				
			||||||
	github.com/recws-org/recws v1.2.2
 | 
						github.com/recws-org/recws v1.2.2
 | 
				
			||||||
	github.com/sirupsen/logrus v1.7.0
 | 
						github.com/sirupsen/logrus v1.7.0
 | 
				
			||||||
@ -30,11 +33,11 @@ require (
 | 
				
			|||||||
	github.com/spf13/pflag v1.0.5 // indirect
 | 
						github.com/spf13/pflag v1.0.5 // indirect
 | 
				
			||||||
	github.com/spf13/viper v1.7.1 // indirect
 | 
						github.com/spf13/viper v1.7.1 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
 | 
						golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
 | 
				
			||||||
	golang.org/x/mod v0.4.0 // indirect
 | 
						golang.org/x/mod v0.4.1 // indirect
 | 
				
			||||||
	golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
 | 
						golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
 | 
				
			||||||
	golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 // indirect
 | 
						golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 // indirect
 | 
				
			||||||
	golang.org/x/text v0.3.5 // indirect
 | 
						golang.org/x/text v0.3.5 // indirect
 | 
				
			||||||
	golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e // indirect
 | 
						golang.org/x/tools v0.0.0-20210115202250-e0d201561e39 // indirect
 | 
				
			||||||
	gopkg.in/ini.v1 v1.62.0 // indirect
 | 
						gopkg.in/ini.v1 v1.62.0 // indirect
 | 
				
			||||||
	gopkg.in/square/go-jose.v2 v2.5.1 // indirect
 | 
						gopkg.in/square/go-jose.v2 v2.5.1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
@ -36,8 +36,11 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
 | 
				
			|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 | 
					dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 | 
				
			||||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
 | 
					github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
 | 
				
			||||||
github.com/BeryJu/authentik v0.0.0-20210108085217-fd6d99f4f999 h1:ymxzvnxKNUomJIRG1VP3I6ls5mWn8r1xWD82bHASEk0=
 | 
					github.com/BeryJu/authentik v0.0.0-20210108085217-fd6d99f4f999 h1:ymxzvnxKNUomJIRG1VP3I6ls5mWn8r1xWD82bHASEk0=
 | 
				
			||||||
 | 
					github.com/BeryJu/authentik v0.0.0-20210116180903-8acb9dde5f2f h1:pLOJgn8bIzavtn0h874lys3gs7uk1RnMqMWIttOWY8Y=
 | 
				
			||||||
github.com/BeryJu/authentik/outpost v0.0.0-20210108085217-fd6d99f4f999 h1:XYHeaZx7fm4JNx77MHMO6ek/Gdp+sZa2jIJyjC294Gw=
 | 
					github.com/BeryJu/authentik/outpost v0.0.0-20210108085217-fd6d99f4f999 h1:XYHeaZx7fm4JNx77MHMO6ek/Gdp+sZa2jIJyjC294Gw=
 | 
				
			||||||
github.com/BeryJu/authentik/proxy v0.0.0-20210108085217-fd6d99f4f999 h1:XYHeaZx7fm4JNx77MHMO6ek/Gdp+sZa2jIJyjC294Gw=
 | 
					github.com/BeryJu/authentik/proxy v0.0.0-20210108085217-fd6d99f4f999 h1:XYHeaZx7fm4JNx77MHMO6ek/Gdp+sZa2jIJyjC294Gw=
 | 
				
			||||||
 | 
					github.com/BeryJu/authentik/proxy v0.0.0-20210116180903-8acb9dde5f2f h1:bp617AbteaVcZBXMtr4/A+FSSVGKqRWlTo5chcirq8k=
 | 
				
			||||||
 | 
					github.com/BeryJu/authentik/proxy v0.0.0-20210116180903-8acb9dde5f2f/go.mod h1:6/VeRMuLHUE3Ywr1uIpjxnmOJJsAfld7OOOi+uocxQw=
 | 
				
			||||||
github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb h1:ZVN4Iat3runWOFLaBCDVU5a9X/XikSRBosye++6gojw=
 | 
					github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb h1:ZVN4Iat3runWOFLaBCDVU5a9X/XikSRBosye++6gojw=
 | 
				
			||||||
github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb/go.mod h1:WsAABbY4HQBgd3mGuG4KMNTbHJCPvx9IVBHzysbknss=
 | 
					github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb/go.mod h1:WsAABbY4HQBgd3mGuG4KMNTbHJCPvx9IVBHzysbknss=
 | 
				
			||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
					github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
				
			||||||
@ -508,6 +511,8 @@ github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8
 | 
				
			|||||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
					github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
 | 
					github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
 | 
				
			||||||
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
					github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
 | 
					github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
 | 
				
			||||||
 | 
					github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
					github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
				
			||||||
@ -752,6 +757,8 @@ golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
 | 
				
			|||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
 | 
					golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
 | 
				
			||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
 | 
					golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
 | 
				
			||||||
 | 
					golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
@ -880,6 +887,8 @@ golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq
 | 
				
			|||||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 h1:wHn06sgWHMO1VsQ8F+KzDJx/JzqfsNLnc+oEi07qD7s=
 | 
					golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 h1:wHn06sgWHMO1VsQ8F+KzDJx/JzqfsNLnc+oEi07qD7s=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210108172913-0df2131ae363/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
@ -955,6 +964,8 @@ golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a h1:pdfjQ7VswBeGam3EpuEJ4e8
 | 
				
			|||||||
golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e h1:Z2uDrs8MyXUWJbwGc4V+nGjV4Ygo+oubBbWSVQw21/I=
 | 
					golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e h1:Z2uDrs8MyXUWJbwGc4V+nGjV4Ygo+oubBbWSVQw21/I=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.0.0-20210115202250-e0d201561e39 h1:BTs2GMGSMWpgtCpv1CE7vkJTv7XcHdcLLnAMu7UbgTY=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.0.0-20210115202250-e0d201561e39/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,5 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/cmd"
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	log.SetLevel(log.DebugLevel)
 | 
					
 | 
				
			||||||
	cmd.RunServer()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										100
									
								
								outpost/pkg/ak/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								outpost/pkg/ak/api.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg"
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/client"
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/client/outposts"
 | 
				
			||||||
 | 
						"github.com/go-openapi/runtime"
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"github.com/recws-org/recws"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						httptransport "github.com/go-openapi/runtime/client"
 | 
				
			||||||
 | 
						"github.com/go-openapi/strfmt"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfigLogLevel = "log_level"
 | 
				
			||||||
 | 
					const ConfigErrorReportingEnabled = "error_reporting_enabled"
 | 
				
			||||||
 | 
					const ConfigErrorReportingEnvironment = "error_reporting_environment"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// APIController main controller which connects to the authentik api via http and ws
 | 
				
			||||||
 | 
					type APIController struct {
 | 
				
			||||||
 | 
						Client *client.Authentik
 | 
				
			||||||
 | 
						Auth   runtime.ClientAuthInfoWriter
 | 
				
			||||||
 | 
						token  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Server Outpost
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lastBundleHash string
 | 
				
			||||||
 | 
						logger         *log.Entry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reloadOffset time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wsConn *recws.RecConn
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewAPIController initialise new API Controller instance from URL and API token
 | 
				
			||||||
 | 
					func NewAPIController(pbURL url.URL, token string) *APIController {
 | 
				
			||||||
 | 
						transport := httptransport.New(pbURL.Host, client.DefaultBasePath, []string{pbURL.Scheme})
 | 
				
			||||||
 | 
						transport.Transport = SetUserAgent(getTLSTransport(), fmt.Sprintf("authentik-proxy@%s", pkg.VERSION))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create the transport
 | 
				
			||||||
 | 
						auth := httptransport.BasicAuth("", token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create the API client, with the transport
 | 
				
			||||||
 | 
						apiClient := client.New(transport, strfmt.Default)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Because we don't know the outpost UUID, we simply do a list and pick the first
 | 
				
			||||||
 | 
						// The service account this token belongs to should only have access to a single outpost
 | 
				
			||||||
 | 
						outposts, err := apiClient.Outposts.OutpostsOutpostsList(outposts.NewOutpostsOutpostsListParams(), auth)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						outpost := outposts.Payload.Results[0]
 | 
				
			||||||
 | 
						doGlobalSetup(outpost.Config.(map[string]interface{}))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ac := &APIController{
 | 
				
			||||||
 | 
							Client: apiClient,
 | 
				
			||||||
 | 
							Auth:   auth,
 | 
				
			||||||
 | 
							token:  token,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							logger: log.WithField("component", "ak-api-controller"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							reloadOffset: time.Duration(rand.Intn(10)) * time.Second,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lastBundleHash: "",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ac.logger.Debugf("HA Reload offset: %s", ac.reloadOffset)
 | 
				
			||||||
 | 
						ac.initWS(pbURL, outpost.Pk)
 | 
				
			||||||
 | 
						return ac
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *APIController) GetLastBundleHash() string {
 | 
				
			||||||
 | 
						return a.lastBundleHash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Start Starts all handlers, non-blocking
 | 
				
			||||||
 | 
					func (a *APIController) Start() error {
 | 
				
			||||||
 | 
						err := a.Server.Refresh()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errors.Wrap(err, "failed to run initial refresh")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							a.logger.Debug("Starting WS Handler...")
 | 
				
			||||||
 | 
							a.startWSHandler()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							a.logger.Debug("Starting WS Health notifier...")
 | 
				
			||||||
 | 
							a.startWSHealth()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							a.Server.Start()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "net/http"
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								outpost/pkg/ak/api_update.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								outpost/pkg/ak/api_update.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/sha512"
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/client/outposts"
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/models"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *APIController) Update() ([]*models.ProxyOutpostConfig, error) {
 | 
				
			||||||
 | 
						providers, err := a.Client.Outposts.OutpostsProxyList(outposts.NewOutpostsProxyListParams(), a.Auth)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							a.logger.WithError(err).Error("Failed to fetch providers")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Check provider hash to see if anything is changed
 | 
				
			||||||
 | 
						hasher := sha512.New()
 | 
				
			||||||
 | 
						bin, _ := providers.Payload.MarshalBinary()
 | 
				
			||||||
 | 
						hash := hex.EncodeToString(hasher.Sum(bin))
 | 
				
			||||||
 | 
						if hash == a.lastBundleHash {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						a.lastBundleHash = hash
 | 
				
			||||||
 | 
						return providers.Payload.Results, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
@ -40,7 +40,7 @@ func (ac *APIController) initWS(pbURL url.URL, outpostUUID strfmt.UUID) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	ws.Dial(fmt.Sprintf(pathTemplate, scheme, pbURL.Host, outpostUUID.String()), header)
 | 
						ws.Dial(fmt.Sprintf(pathTemplate, scheme, pbURL.Host, outpostUUID.String()), header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ac.logger.WithField("component", "ws").WithField("outpost", outpostUUID.String()).Debug("connecting to authentik")
 | 
						ac.logger.WithField("component", "ak-ws").WithField("outpost", outpostUUID.String()).Debug("connecting to authentik")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ac.wsConn = ws
 | 
						ac.wsConn = ws
 | 
				
			||||||
	// Send hello message with our version
 | 
						// Send hello message with our version
 | 
				
			||||||
@ -52,7 +52,7 @@ func (ac *APIController) initWS(pbURL url.URL, outpostUUID strfmt.UUID) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	err := ws.WriteJSON(msg)
 | 
						err := ws.WriteJSON(msg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ac.logger.WithField("component", "ws").WithError(err).Warning("Failed to hello to authentik")
 | 
							ac.logger.WithField("component", "ak-ws").WithError(err).Warning("Failed to hello to authentik")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,7 +87,7 @@ func (ac *APIController) startWSHandler() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		if wsMsg.Instruction == WebsocketInstructionTriggerUpdate {
 | 
							if wsMsg.Instruction == WebsocketInstructionTriggerUpdate {
 | 
				
			||||||
			time.Sleep(ac.reloadOffset)
 | 
								time.Sleep(ac.reloadOffset)
 | 
				
			||||||
			err := ac.UpdateIfRequired()
 | 
								err := ac.Server.Refresh()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ac.logger.WithField("loop", "ws-handler").WithError(err).Debug("Failed to update")
 | 
									ac.logger.WithField("loop", "ws-handler").WithError(err).Debug("Failed to update")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type websocketInstruction int
 | 
					type websocketInstruction int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
@ -13,8 +13,8 @@ import (
 | 
				
			|||||||
	log "github.com/sirupsen/logrus"
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func generateSelfSignedCert() (tls.Certificate, error) {
 | 
					// GenerateSelfSignedCert Generate a self-signed TLS Certificate, to be used as fallback
 | 
				
			||||||
 | 
					func GenerateSelfSignedCert() (tls.Certificate, error) {
 | 
				
			||||||
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
 | 
						priv, err := rsa.GenerateKey(rand.Reader, 2048)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatalf("Failed to generate private key: %v", err)
 | 
							log.Fatalf("Failed to generate private key: %v", err)
 | 
				
			||||||
							
								
								
									
										60
									
								
								outpost/pkg/ak/global.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								outpost/pkg/ak/global.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg"
 | 
				
			||||||
 | 
						"github.com/getsentry/sentry-go"
 | 
				
			||||||
 | 
						httptransport "github.com/go-openapi/runtime/client"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func doGlobalSetup(config map[string]interface{}) {
 | 
				
			||||||
 | 
						log.SetFormatter(&log.JSONFormatter{})
 | 
				
			||||||
 | 
						switch config[ConfigLogLevel].(string) {
 | 
				
			||||||
 | 
						case "debug":
 | 
				
			||||||
 | 
							log.SetLevel(log.DebugLevel)
 | 
				
			||||||
 | 
						case "info":
 | 
				
			||||||
 | 
							log.SetLevel(log.InfoLevel)
 | 
				
			||||||
 | 
						case "warning":
 | 
				
			||||||
 | 
							log.SetLevel(log.WarnLevel)
 | 
				
			||||||
 | 
						case "error":
 | 
				
			||||||
 | 
							log.SetLevel(log.ErrorLevel)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							log.SetLevel(log.DebugLevel)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.WithField("version", pkg.VERSION).Info("Starting authentik proxy")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dsn string
 | 
				
			||||||
 | 
						if config[ConfigErrorReportingEnabled].(bool) {
 | 
				
			||||||
 | 
							dsn = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"
 | 
				
			||||||
 | 
							log.Debug("Error reporting enabled")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := sentry.Init(sentry.ClientOptions{
 | 
				
			||||||
 | 
							Dsn:         dsn,
 | 
				
			||||||
 | 
							Environment: config[ConfigErrorReportingEnvironment].(string),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("sentry.Init: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer sentry.Flush(2 * time.Second)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getTLSTransport() http.RoundTripper {
 | 
				
			||||||
 | 
						value, set := os.LookupEnv("AUTHENTIK_INSECURE")
 | 
				
			||||||
 | 
						if !set {
 | 
				
			||||||
 | 
							value = "false"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tlsTransport, err := httptransport.TLSTransport(httptransport.TLSClientOptions{
 | 
				
			||||||
 | 
							InsecureSkipVerify: strings.ToLower(value) == "true",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return tlsTransport
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								outpost/pkg/ak/outpost.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								outpost/pkg/ak/outpost.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package ak
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Outpost interface {
 | 
				
			||||||
 | 
						Start() error
 | 
				
			||||||
 | 
						Refresh() error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								outpost/pkg/proxy/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								outpost/pkg/proxy/api.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/models"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) Refresh() error {
 | 
				
			||||||
 | 
						providers, err := s.ak.Update()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if providers == nil {
 | 
				
			||||||
 | 
							s.logger.Debug("Providers have not changed, not updating")
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bundles := s.bundleProviders(providers)
 | 
				
			||||||
 | 
						s.updateHTTPServer(bundles)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) bundleProviders(providers []*models.ProxyOutpostConfig) []*providerBundle {
 | 
				
			||||||
 | 
						bundles := make([]*providerBundle, len(providers))
 | 
				
			||||||
 | 
						for idx, provider := range providers {
 | 
				
			||||||
 | 
							externalHost, err := url.Parse(*provider.ExternalHost)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.WithError(err).Warning("Failed to parse URL, skipping provider")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							bundles[idx] = &providerBundle{
 | 
				
			||||||
 | 
								s:    s,
 | 
				
			||||||
 | 
								Host: externalHost.Host,
 | 
				
			||||||
 | 
								log:  log.WithField("component", "proxy-bundle").WithField("provider", provider.Name),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							bundles[idx].Build(provider)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return bundles
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) updateHTTPServer(bundles []*providerBundle) {
 | 
				
			||||||
 | 
						newMap := make(map[string]*providerBundle)
 | 
				
			||||||
 | 
						for _, bundle := range bundles {
 | 
				
			||||||
 | 
							newMap[bundle.Host] = bundle
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.logger.Debug("Swapped maps")
 | 
				
			||||||
 | 
						s.Handlers = newMap
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@ -11,7 +11,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/client/crypto"
 | 
						"github.com/BeryJu/authentik/outpost/pkg/client/crypto"
 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/models"
 | 
						"github.com/BeryJu/authentik/outpost/pkg/models"
 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/proxy"
 | 
					 | 
				
			||||||
	"github.com/jinzhu/copier"
 | 
						"github.com/jinzhu/copier"
 | 
				
			||||||
	"github.com/justinas/alice"
 | 
						"github.com/justinas/alice"
 | 
				
			||||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | 
						"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | 
				
			||||||
@ -23,11 +22,13 @@ import (
 | 
				
			|||||||
type providerBundle struct {
 | 
					type providerBundle struct {
 | 
				
			||||||
	http.Handler
 | 
						http.Handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a     *APIController
 | 
						s     *Server
 | 
				
			||||||
	proxy *proxy.OAuthProxy
 | 
						proxy *OAuthProxy
 | 
				
			||||||
	Host  string
 | 
						Host  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cert *tls.Certificate
 | 
						cert *tls.Certificate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log *log.Entry
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *options.Options {
 | 
					func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *options.Options {
 | 
				
			||||||
@ -37,7 +38,7 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	providerOpts := &options.Options{}
 | 
						providerOpts := &options.Options{}
 | 
				
			||||||
	copier.Copy(&providerOpts, &pb.a.commonOpts)
 | 
						copier.Copy(&providerOpts, getCommonOptions())
 | 
				
			||||||
	providerOpts.ClientID = provider.ClientID
 | 
						providerOpts.ClientID = provider.ClientID
 | 
				
			||||||
	providerOpts.ClientSecret = provider.ClientSecret
 | 
						providerOpts.ClientSecret = provider.ClientSecret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,22 +67,22 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if provider.Certificate != nil {
 | 
						if provider.Certificate != nil {
 | 
				
			||||||
		pb.a.logger.WithField("provider", provider.ClientID).Debug("Enabling TLS")
 | 
							pb.log.WithField("provider", provider.ClientID).Debug("Enabling TLS")
 | 
				
			||||||
		cert, err := pb.a.client.Crypto.CryptoCertificatekeypairsRead(&crypto.CryptoCertificatekeypairsReadParams{
 | 
							cert, err := pb.s.ak.Client.Crypto.CryptoCertificatekeypairsRead(&crypto.CryptoCertificatekeypairsReadParams{
 | 
				
			||||||
			Context: context.Background(),
 | 
								Context: context.Background(),
 | 
				
			||||||
			KpUUID:  *provider.Certificate,
 | 
								KpUUID:  *provider.Certificate,
 | 
				
			||||||
		}, pb.a.auth)
 | 
							}, pb.s.ak.Auth)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			pb.a.logger.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to fetch certificate")
 | 
								pb.log.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to fetch certificate")
 | 
				
			||||||
			return providerOpts
 | 
								return providerOpts
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		x509cert, err := tls.X509KeyPair([]byte(*cert.Payload.CertificateData), []byte(cert.Payload.KeyData))
 | 
							x509cert, err := tls.X509KeyPair([]byte(*cert.Payload.CertificateData), []byte(cert.Payload.KeyData))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			pb.a.logger.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to parse certificate")
 | 
								pb.log.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to parse certificate")
 | 
				
			||||||
			return providerOpts
 | 
								return providerOpts
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pb.cert = &x509cert
 | 
							pb.cert = &x509cert
 | 
				
			||||||
		pb.a.logger.WithField("provider", provider.ClientID).WithField("certificate-key-pair", *cert.Payload.Name).Debug("Loaded certificates")
 | 
							pb.log.WithField("provider", provider.ClientID).WithField("certificate-key-pair", *cert.Payload.Name).Debug("Loaded certificates")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return providerOpts
 | 
						return providerOpts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -119,7 +120,7 @@ func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
 | 
				
			|||||||
		log.Printf("%s", err)
 | 
							log.Printf("%s", err)
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	oauthproxy, err := proxy.NewOAuthProxy(opts)
 | 
						oauthproxy, err := NewOAuthProxy(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
 | 
							log.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
							
								
								
									
										20
									
								
								outpost/pkg/proxy/common.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								outpost/pkg/proxy/common.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCommonOptions() *options.Options {
 | 
				
			||||||
 | 
						commonOpts := options.NewOptions()
 | 
				
			||||||
 | 
						commonOpts.Cookie.Name = "authentik_proxy"
 | 
				
			||||||
 | 
						commonOpts.Cookie.Expire = 24 * time.Hour
 | 
				
			||||||
 | 
						commonOpts.EmailDomains = []string{"*"}
 | 
				
			||||||
 | 
						commonOpts.ProviderType = "oidc"
 | 
				
			||||||
 | 
						commonOpts.ProxyPrefix = "/akprox"
 | 
				
			||||||
 | 
						commonOpts.Logging.SilencePing = true
 | 
				
			||||||
 | 
						commonOpts.SetAuthorization = false
 | 
				
			||||||
 | 
						commonOpts.Scope = "openid email profile ak_proxy"
 | 
				
			||||||
 | 
						return commonOpts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
@ -95,7 +95,7 @@ type loggingHandler struct {
 | 
				
			|||||||
func LoggingHandler(h http.Handler) http.Handler {
 | 
					func LoggingHandler(h http.Handler) http.Handler {
 | 
				
			||||||
	return loggingHandler{
 | 
						return loggingHandler{
 | 
				
			||||||
		handler: h,
 | 
							handler: h,
 | 
				
			||||||
		logger:  log.WithField("component", "http-server"),
 | 
							logger:  log.WithField("component", "proxy-http-server"),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package server
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/BeryJu/authentik/outpost/pkg/ak"
 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,70 +16,26 @@ import (
 | 
				
			|||||||
type Server struct {
 | 
					type Server struct {
 | 
				
			||||||
	Handlers map[string]*providerBundle
 | 
						Handlers map[string]*providerBundle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stop   chan struct{} // channel for waiting shutdown
 | 
						stop        chan struct{} // channel for waiting shutdown
 | 
				
			||||||
	logger *log.Entry
 | 
						logger      *log.Entry
 | 
				
			||||||
 | 
						ak          *ak.APIController
 | 
				
			||||||
	defaultCert tls.Certificate
 | 
						defaultCert tls.Certificate
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewServer initialise a new HTTP Server
 | 
					// NewServer initialise a new HTTP Server
 | 
				
			||||||
func NewServer() *Server {
 | 
					func NewServer(ac *ak.APIController) *Server {
 | 
				
			||||||
	defaultCert, err := generateSelfSignedCert()
 | 
						defaultCert, err := ak.GenerateSelfSignedCert()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Warning(err)
 | 
							log.Warning(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &Server{
 | 
						return &Server{
 | 
				
			||||||
		Handlers:    make(map[string]*providerBundle),
 | 
							Handlers:    make(map[string]*providerBundle),
 | 
				
			||||||
		logger:      log.WithField("component", "http-server"),
 | 
							logger:      log.WithField("component", "proxy-http-server"),
 | 
				
			||||||
		defaultCert: defaultCert,
 | 
							defaultCert: defaultCert,
 | 
				
			||||||
 | 
							ak:          ac,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ServeHTTP constructs a net.Listener and starts handling HTTP requests
 | 
					 | 
				
			||||||
func (s *Server) ServeHTTP() {
 | 
					 | 
				
			||||||
	listenAddress := "0.0.0.0:4180"
 | 
					 | 
				
			||||||
	listener, err := net.Listen("tcp", listenAddress)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		s.logger.Fatalf("FATAL: listen (%s) failed - %s", listenAddress, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.logger.Printf("listening on %s", listener.Addr())
 | 
					 | 
				
			||||||
	s.serve(listener)
 | 
					 | 
				
			||||||
	s.logger.Printf("closing %s", listener.Addr())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *Server) getCertificates(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
 | 
					 | 
				
			||||||
	handler, ok := s.Handlers[info.ServerName]
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		s.logger.WithField("server-name", info.ServerName).Debug("Handler does not exist")
 | 
					 | 
				
			||||||
		return &s.defaultCert, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if handler.cert == nil {
 | 
					 | 
				
			||||||
		s.logger.WithField("server-name", info.ServerName).Debug("Handler does not have a certificate")
 | 
					 | 
				
			||||||
		return &s.defaultCert, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return handler.cert, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
 | 
					 | 
				
			||||||
func (s *Server) ServeHTTPS() {
 | 
					 | 
				
			||||||
	listenAddress := "0.0.0.0:4443"
 | 
					 | 
				
			||||||
	config := &tls.Config{
 | 
					 | 
				
			||||||
		MinVersion:     tls.VersionTLS12,
 | 
					 | 
				
			||||||
		MaxVersion:     tls.VersionTLS12,
 | 
					 | 
				
			||||||
		GetCertificate: s.getCertificates,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ln, err := net.Listen("tcp", listenAddress)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		s.logger.Fatalf("FATAL: listen (%s) failed - %s", listenAddress, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.logger.Printf("listening on %s", ln.Addr())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
 | 
					 | 
				
			||||||
	s.serve(tlsListener)
 | 
					 | 
				
			||||||
	s.logger.Printf("closing %s", tlsListener.Addr())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
 | 
					func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	if r.URL.Path == "/akprox/ping" {
 | 
						if r.URL.Path == "/akprox/ping" {
 | 
				
			||||||
		w.WriteHeader(204)
 | 
							w.WriteHeader(204)
 | 
				
			||||||
							
								
								
									
										68
									
								
								outpost/pkg/proxy/server_https.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								outpost/pkg/proxy/server_https.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					package proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ServeHTTP constructs a net.Listener and starts handling HTTP requests
 | 
				
			||||||
 | 
					func (s *Server) ServeHTTP() {
 | 
				
			||||||
 | 
						listenAddress := "0.0.0.0:4180"
 | 
				
			||||||
 | 
						listener, err := net.Listen("tcp", listenAddress)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							s.logger.Fatalf("FATAL: listen (%s) failed - %s", listenAddress, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.logger.Printf("listening on %s", listener.Addr())
 | 
				
			||||||
 | 
						s.serve(listener)
 | 
				
			||||||
 | 
						s.logger.Printf("closing %s", listener.Addr())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) getCertificates(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
 | 
				
			||||||
 | 
						handler, ok := s.Handlers[info.ServerName]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							s.logger.WithField("server-name", info.ServerName).Debug("Handler does not exist")
 | 
				
			||||||
 | 
							return &s.defaultCert, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if handler.cert == nil {
 | 
				
			||||||
 | 
							s.logger.WithField("server-name", info.ServerName).Debug("Handler does not have a certificate")
 | 
				
			||||||
 | 
							return &s.defaultCert, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return handler.cert, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
 | 
				
			||||||
 | 
					func (s *Server) ServeHTTPS() {
 | 
				
			||||||
 | 
						listenAddress := "0.0.0.0:4443"
 | 
				
			||||||
 | 
						config := &tls.Config{
 | 
				
			||||||
 | 
							MinVersion:     tls.VersionTLS12,
 | 
				
			||||||
 | 
							MaxVersion:     tls.VersionTLS12,
 | 
				
			||||||
 | 
							GetCertificate: s.getCertificates,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ln, err := net.Listen("tcp", listenAddress)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							s.logger.Fatalf("FATAL: listen (%s) failed - %s", listenAddress, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.logger.Printf("listening on %s", ln.Addr())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
 | 
				
			||||||
 | 
						s.serve(tlsListener)
 | 
				
			||||||
 | 
						s.logger.Printf("closing %s", tlsListener.Addr())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) Start() error {
 | 
				
			||||||
 | 
						wg := sync.WaitGroup{}
 | 
				
			||||||
 | 
						wg.Add(2)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							defer wg.Done()
 | 
				
			||||||
 | 
							s.logger.Debug("Starting HTTP Server...")
 | 
				
			||||||
 | 
							s.ServeHTTP()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							defer wg.Done()
 | 
				
			||||||
 | 
							s.logger.Debug("Starting HTTPs Server...")
 | 
				
			||||||
 | 
							s.ServeHTTPS()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,225 +0,0 @@
 | 
				
			|||||||
package server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto/sha512"
 | 
					 | 
				
			||||||
	"encoding/hex"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"math/rand"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"net/url"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg"
 | 
					 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/client"
 | 
					 | 
				
			||||||
	"github.com/BeryJu/authentik/outpost/pkg/client/outposts"
 | 
					 | 
				
			||||||
	"github.com/getsentry/sentry-go"
 | 
					 | 
				
			||||||
	"github.com/go-openapi/runtime"
 | 
					 | 
				
			||||||
	"github.com/recws-org/recws"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	httptransport "github.com/go-openapi/runtime/client"
 | 
					 | 
				
			||||||
	"github.com/go-openapi/strfmt"
 | 
					 | 
				
			||||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ConfigLogLevel = "log_level"
 | 
					 | 
				
			||||||
const ConfigErrorReportingEnabled = "error_reporting_enabled"
 | 
					 | 
				
			||||||
const ConfigErrorReportingEnvironment = "error_reporting_environment"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// APIController main controller which connects to the authentik api via http and ws
 | 
					 | 
				
			||||||
type APIController struct {
 | 
					 | 
				
			||||||
	client *client.Authentik
 | 
					 | 
				
			||||||
	auth   runtime.ClientAuthInfoWriter
 | 
					 | 
				
			||||||
	token  string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server *Server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	commonOpts *options.Options
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lastBundleHash string
 | 
					 | 
				
			||||||
	logger         *log.Entry
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	reloadOffset time.Duration
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wsConn *recws.RecConn
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getCommonOptions() *options.Options {
 | 
					 | 
				
			||||||
	commonOpts := options.NewOptions()
 | 
					 | 
				
			||||||
	commonOpts.Cookie.Name = "authentik_proxy"
 | 
					 | 
				
			||||||
	commonOpts.Cookie.Expire = 24 * time.Hour
 | 
					 | 
				
			||||||
	commonOpts.EmailDomains = []string{"*"}
 | 
					 | 
				
			||||||
	commonOpts.ProviderType = "oidc"
 | 
					 | 
				
			||||||
	commonOpts.ProxyPrefix = "/akprox"
 | 
					 | 
				
			||||||
	commonOpts.Logging.SilencePing = true
 | 
					 | 
				
			||||||
	commonOpts.SetAuthorization = false
 | 
					 | 
				
			||||||
	commonOpts.Scope = "openid email profile ak_proxy"
 | 
					 | 
				
			||||||
	return commonOpts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func doGlobalSetup(config map[string]interface{}) {
 | 
					 | 
				
			||||||
	log.SetFormatter(&log.JSONFormatter{})
 | 
					 | 
				
			||||||
	switch config[ConfigLogLevel].(string) {
 | 
					 | 
				
			||||||
	case "debug":
 | 
					 | 
				
			||||||
		log.SetLevel(log.DebugLevel)
 | 
					 | 
				
			||||||
	case "info":
 | 
					 | 
				
			||||||
		log.SetLevel(log.InfoLevel)
 | 
					 | 
				
			||||||
	case "warning":
 | 
					 | 
				
			||||||
		log.SetLevel(log.WarnLevel)
 | 
					 | 
				
			||||||
	case "error":
 | 
					 | 
				
			||||||
		log.SetLevel(log.ErrorLevel)
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		log.SetLevel(log.DebugLevel)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	log.WithField("version", pkg.VERSION).Info("Starting authentik proxy")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var dsn string
 | 
					 | 
				
			||||||
	if config[ConfigErrorReportingEnabled].(bool) {
 | 
					 | 
				
			||||||
		dsn = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"
 | 
					 | 
				
			||||||
		log.Debug("Error reporting enabled")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err := sentry.Init(sentry.ClientOptions{
 | 
					 | 
				
			||||||
		Dsn:         dsn,
 | 
					 | 
				
			||||||
		Environment: config[ConfigErrorReportingEnvironment].(string),
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatalf("sentry.Init: %s", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defer sentry.Flush(2 * time.Second)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getTLSTransport() http.RoundTripper {
 | 
					 | 
				
			||||||
	value, set := os.LookupEnv("AUTHENTIK_INSECURE")
 | 
					 | 
				
			||||||
	if !set {
 | 
					 | 
				
			||||||
		value = "false"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tlsTransport, err := httptransport.TLSTransport(httptransport.TLSClientOptions{
 | 
					 | 
				
			||||||
		InsecureSkipVerify: strings.ToLower(value) == "true",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return tlsTransport
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewAPIController initialise new API Controller instance from URL and API token
 | 
					 | 
				
			||||||
func NewAPIController(pbURL url.URL, token string) *APIController {
 | 
					 | 
				
			||||||
	transport := httptransport.New(pbURL.Host, client.DefaultBasePath, []string{pbURL.Scheme})
 | 
					 | 
				
			||||||
	transport.Transport = SetUserAgent(getTLSTransport(), fmt.Sprintf("authentik-proxy@%s", pkg.VERSION))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create the transport
 | 
					 | 
				
			||||||
	auth := httptransport.BasicAuth("", token)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create the API client, with the transport
 | 
					 | 
				
			||||||
	apiClient := client.New(transport, strfmt.Default)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Because we don't know the outpost UUID, we simply do a list and pick the first
 | 
					 | 
				
			||||||
	// The service account this token belongs to should only have access to a single outpost
 | 
					 | 
				
			||||||
	outposts, err := apiClient.Outposts.OutpostsOutpostsList(outposts.NewOutpostsOutpostsListParams(), auth)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	outpost := outposts.Payload.Results[0]
 | 
					 | 
				
			||||||
	doGlobalSetup(outpost.Config.(map[string]interface{}))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ac := &APIController{
 | 
					 | 
				
			||||||
		client: apiClient,
 | 
					 | 
				
			||||||
		auth:   auth,
 | 
					 | 
				
			||||||
		token:  token,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		logger:     log.WithField("component", "api-controller"),
 | 
					 | 
				
			||||||
		commonOpts: getCommonOptions(),
 | 
					 | 
				
			||||||
		server:     NewServer(),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		reloadOffset: time.Duration(rand.Intn(10)) * time.Second,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		lastBundleHash: "",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ac.logger.Debugf("HA Reload offset: %s", ac.reloadOffset)
 | 
					 | 
				
			||||||
	ac.initWS(pbURL, outpost.Pk)
 | 
					 | 
				
			||||||
	return ac
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a *APIController) bundleProviders() ([]*providerBundle, error) {
 | 
					 | 
				
			||||||
	providers, err := a.client.Outposts.OutpostsProxyList(outposts.NewOutpostsProxyListParams(), a.auth)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		a.logger.WithError(err).Error("Failed to fetch providers")
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check provider hash to see if anything is changed
 | 
					 | 
				
			||||||
	hasher := sha512.New()
 | 
					 | 
				
			||||||
	bin, _ := providers.Payload.MarshalBinary()
 | 
					 | 
				
			||||||
	hash := hex.EncodeToString(hasher.Sum(bin))
 | 
					 | 
				
			||||||
	if hash == a.lastBundleHash {
 | 
					 | 
				
			||||||
		return nil, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	a.lastBundleHash = hash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bundles := make([]*providerBundle, len(providers.Payload.Results))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for idx, provider := range providers.Payload.Results {
 | 
					 | 
				
			||||||
		externalHost, err := url.Parse(*provider.ExternalHost)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			log.WithError(err).Warning("Failed to parse URL, skipping provider")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		bundles[idx] = &providerBundle{
 | 
					 | 
				
			||||||
			a:    a,
 | 
					 | 
				
			||||||
			Host: externalHost.Host,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		bundles[idx].Build(provider)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return bundles, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a *APIController) updateHTTPServer(bundles []*providerBundle) {
 | 
					 | 
				
			||||||
	newMap := make(map[string]*providerBundle)
 | 
					 | 
				
			||||||
	for _, bundle := range bundles {
 | 
					 | 
				
			||||||
		newMap[bundle.Host] = bundle
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	a.logger.Debug("Swapped maps")
 | 
					 | 
				
			||||||
	a.server.Handlers = newMap
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// UpdateIfRequired Updates the HTTP Server config if required, automatically swaps the handlers
 | 
					 | 
				
			||||||
func (a *APIController) UpdateIfRequired() error {
 | 
					 | 
				
			||||||
	bundles, err := a.bundleProviders()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if bundles == nil {
 | 
					 | 
				
			||||||
		a.logger.Debug("Providers have not changed, not updating")
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	a.updateHTTPServer(bundles)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Start Starts all handlers, non-blocking
 | 
					 | 
				
			||||||
func (a *APIController) Start() error {
 | 
					 | 
				
			||||||
	err := a.UpdateIfRequired()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		a.logger.Debug("Starting HTTP Server...")
 | 
					 | 
				
			||||||
		a.server.ServeHTTP()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		a.logger.Debug("Starting HTTPs Server...")
 | 
					 | 
				
			||||||
		a.server.ServeHTTPS()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		a.logger.Debug("Starting WS Handler...")
 | 
					 | 
				
			||||||
		a.startWSHandler()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		a.logger.Debug("Starting WS Health notifier...")
 | 
					 | 
				
			||||||
		a.startWSHealth()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user