outpost: migrate to openapitools/openapi-generator-cli
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		
							
								
								
									
										3
									
								
								outpost/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								outpost/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1 @@
 | 
			
		||||
pkg/client/
 | 
			
		||||
pkg/models/
 | 
			
		||||
api/
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,4 @@
 | 
			
		||||
all: clean generate
 | 
			
		||||
 | 
			
		||||
generate:
 | 
			
		||||
	go get -u github.com/go-swagger/go-swagger/cmd/swagger
 | 
			
		||||
	swagger generate client -f ../schema.yml -A authentik -t pkg/
 | 
			
		||||
all: clean
 | 
			
		||||
 | 
			
		||||
run:
 | 
			
		||||
	go run -v .
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,16 @@
 | 
			
		||||
# authentik outpost
 | 
			
		||||
 | 
			
		||||
[](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=8)
 | 
			
		||||
[](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=8)
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
Reverse Proxy based on [oauth2_proxy](https://github.com/oauth2-proxy/oauth2-proxy), completely managed and monitored by authentik.
 | 
			
		||||
 | 
			
		||||
LDAP Server using [ldap](https://github.com/nmcclain/ldap), completely managed and monitored by authentik.
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
authentik Proxy is built to be configured by authentik itself, hence the only options you can directly give it are connection params.
 | 
			
		||||
authentik Outpost is built to be configured by authentik itself, hence the only options you can directly give it are connection params.
 | 
			
		||||
 | 
			
		||||
The following environment variable are implemented:
 | 
			
		||||
 | 
			
		||||
@ -19,6 +22,6 @@ The following environment variable are implemented:
 | 
			
		||||
 | 
			
		||||
## Development
 | 
			
		||||
 | 
			
		||||
authentik Proxy uses an auto-generated API Client to communicate with authentik. This client is not kept in git. To generate the client locally, run `make generate`.
 | 
			
		||||
authentik outpost uses an auto-generated API Client to communicate with authentik. This client is not kept in git. To generate the client locally, run `make gen-outpost` in the root directory of the repo.
 | 
			
		||||
 | 
			
		||||
Afterwards you can build the proxy like any other Go project, using `go build`.
 | 
			
		||||
Afterwards you can build the outpost like any other Go project, using `go build ./cmd/proxy/server.go` or `go build ./cmd/ldap/server.go`.
 | 
			
		||||
 | 
			
		||||
@ -25,14 +25,21 @@ stages:
 | 
			
		||||
          - task: CmdLine@2
 | 
			
		||||
            inputs:
 | 
			
		||||
              script: |
 | 
			
		||||
                sudo wget -O /usr/local/bin/swagger https://github.com/go-swagger/go-swagger/releases/latest/download/swagger_linux_amd64
 | 
			
		||||
                sudo chmod +x /usr/local/bin/swagger
 | 
			
		||||
                mkdir -p $(go env GOPATH)
 | 
			
		||||
                swagger generate client -f ../schema.yml -A authentik -t pkg/
 | 
			
		||||
                cp ../schema.yml .
 | 
			
		||||
                docker run \
 | 
			
		||||
                  --rm -v $(pwd):/local \
 | 
			
		||||
                  openapitools/openapi-generator-cli generate \
 | 
			
		||||
                  --git-host goauthentik.io \
 | 
			
		||||
                  --git-repo-id outpost \
 | 
			
		||||
                  --git-user-id api \
 | 
			
		||||
                  -i /local/schema.yml \
 | 
			
		||||
                  -g go \
 | 
			
		||||
                  -o /local/api \
 | 
			
		||||
                  --additional-properties=packageName=api,enumClassPrefix=true
 | 
			
		||||
              workingDirectory: 'outpost/'
 | 
			
		||||
          - task: PublishPipelineArtifact@1
 | 
			
		||||
            inputs:
 | 
			
		||||
              targetPath: 'outpost/pkg/'
 | 
			
		||||
              targetPath: 'outpost/api/'
 | 
			
		||||
              artifact: 'go_swagger_client'
 | 
			
		||||
              publishLocation: 'pipeline'
 | 
			
		||||
  - stage: lint
 | 
			
		||||
@ -48,11 +55,16 @@ stages:
 | 
			
		||||
            inputs:
 | 
			
		||||
              buildType: 'current'
 | 
			
		||||
              artifactName: 'go_swagger_client'
 | 
			
		||||
              path: "outpost/pkg/"
 | 
			
		||||
              path: "outpost/api/"
 | 
			
		||||
          - task: CmdLine@2
 | 
			
		||||
            inputs:
 | 
			
		||||
              script: |
 | 
			
		||||
                docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.39.0 golangci-lint run -v --timeout 200s
 | 
			
		||||
                docker run \
 | 
			
		||||
                  --rm \
 | 
			
		||||
                  -v $(pwd):/app \
 | 
			
		||||
                  -w /app \
 | 
			
		||||
                  golangci/golangci-lint:v1.39.0 \
 | 
			
		||||
                  golangci-lint run -v --timeout 200s
 | 
			
		||||
              workingDirectory: 'outpost/'
 | 
			
		||||
  - stage: build_go
 | 
			
		||||
    jobs:
 | 
			
		||||
@ -67,7 +79,7 @@ stages:
 | 
			
		||||
            inputs:
 | 
			
		||||
              buildType: 'current'
 | 
			
		||||
              artifactName: 'go_swagger_client'
 | 
			
		||||
              path: "outpost/pkg/"
 | 
			
		||||
              path: "outpost/api/"
 | 
			
		||||
          - task: Go@0
 | 
			
		||||
            inputs:
 | 
			
		||||
              command: 'build'
 | 
			
		||||
@ -84,7 +96,7 @@ stages:
 | 
			
		||||
            inputs:
 | 
			
		||||
              buildType: 'current'
 | 
			
		||||
              artifactName: 'go_swagger_client'
 | 
			
		||||
              path: "outpost/pkg/"
 | 
			
		||||
              path: "outpost/api/"
 | 
			
		||||
          - task: Go@0
 | 
			
		||||
            inputs:
 | 
			
		||||
              command: 'build'
 | 
			
		||||
@ -103,7 +115,7 @@ stages:
 | 
			
		||||
            inputs:
 | 
			
		||||
              buildType: 'current'
 | 
			
		||||
              artifactName: 'go_swagger_client'
 | 
			
		||||
              path: "outpost/pkg/"
 | 
			
		||||
              path: "outpost/api/"
 | 
			
		||||
          - task: Bash@3
 | 
			
		||||
            inputs:
 | 
			
		||||
              targetType: 'inline'
 | 
			
		||||
@ -139,7 +151,7 @@ stages:
 | 
			
		||||
            inputs:
 | 
			
		||||
              buildType: 'current'
 | 
			
		||||
              artifactName: 'go_swagger_client'
 | 
			
		||||
              path: "outpost/pkg/"
 | 
			
		||||
              path: "outpost/api/"
 | 
			
		||||
          - task: Bash@3
 | 
			
		||||
            inputs:
 | 
			
		||||
              targetType: 'inline'
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,19 @@
 | 
			
		||||
module goauthentik.io/outpost
 | 
			
		||||
 | 
			
		||||
go 1.14
 | 
			
		||||
go 1.16
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
 | 
			
		||||
	github.com/coreos/go-oidc v2.2.1+incompatible
 | 
			
		||||
	github.com/felixge/httpsnoop v1.0.2 // indirect
 | 
			
		||||
	github.com/getsentry/sentry-go v0.10.0
 | 
			
		||||
	github.com/go-ldap/ldap/v3 v3.3.0
 | 
			
		||||
	github.com/go-openapi/analysis v0.20.1 // indirect
 | 
			
		||||
	github.com/go-openapi/errors v0.20.0
 | 
			
		||||
	github.com/go-openapi/errors v0.20.0 // indirect
 | 
			
		||||
	github.com/go-openapi/runtime v0.19.28
 | 
			
		||||
	github.com/go-openapi/strfmt v0.20.1
 | 
			
		||||
	github.com/go-openapi/swag v0.19.15
 | 
			
		||||
	github.com/go-openapi/validate v0.20.2
 | 
			
		||||
	github.com/go-openapi/swag v0.19.15 // indirect
 | 
			
		||||
	github.com/go-openapi/validate v0.20.2 // indirect
 | 
			
		||||
	github.com/go-redis/redis/v7 v7.4.0 // indirect
 | 
			
		||||
	github.com/go-swagger/go-swagger v0.27.0 // indirect
 | 
			
		||||
	github.com/golang/protobuf v1.5.2 // indirect
 | 
			
		||||
	github.com/google/uuid v1.2.0
 | 
			
		||||
	github.com/gorilla/websocket v1.4.2
 | 
			
		||||
@ -40,9 +38,8 @@ require (
 | 
			
		||||
	go.mongodb.org/mongo-driver v1.5.2 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
 | 
			
		||||
	golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558
 | 
			
		||||
	golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect
 | 
			
		||||
	golang.org/x/tools v0.1.1 // indirect
 | 
			
		||||
	google.golang.org/appengine v1.6.7 // indirect
 | 
			
		||||
	gopkg.in/ini.v1 v1.62.0 // indirect
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.5.1 // indirect
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 | 
			
		||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 | 
			
		||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
 | 
			
		||||
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
 | 
			
		||||
github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc=
 | 
			
		||||
github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
 | 
			
		||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 | 
			
		||||
@ -104,7 +103,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
 | 
			
		||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
			
		||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
			
		||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 | 
			
		||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
			
		||||
@ -126,9 +124,6 @@ github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHj
 | 
			
		||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
 | 
			
		||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 | 
			
		||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 | 
			
		||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 | 
			
		||||
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
 | 
			
		||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 | 
			
		||||
github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
 | 
			
		||||
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
			
		||||
@ -177,8 +172,6 @@ github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpX
 | 
			
		||||
github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 | 
			
		||||
github.com/go-openapi/errors v0.20.0 h1:Sxpo9PjEHDzhs3FbnGNonvDgWcMW2U7wGTcDDSFSceM=
 | 
			
		||||
github.com/go-openapi/errors v0.20.0/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 | 
			
		||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
 | 
			
		||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 | 
			
		||||
@ -208,7 +201,6 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g
 | 
			
		||||
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.27/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.28 h1:9lYu6axek8LJrVkMVViVirRcpoaCxXX7+sSvmizGVnA=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.28/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
 | 
			
		||||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
 | 
			
		||||
@ -259,9 +251,6 @@ github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRf
 | 
			
		||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 | 
			
		||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 | 
			
		||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 | 
			
		||||
github.com/go-swagger/go-swagger v0.27.0 h1:K7+nkBuf4oS1jTBrdvWqYFpqD69V5CN8HamZzCDDhAI=
 | 
			
		||||
github.com/go-swagger/go-swagger v0.27.0/go.mod h1:WodZVysInJilkW7e6IRw+dZGp5yW6rlMFZ4cb+THl9A=
 | 
			
		||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
 | 
			
		||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
 | 
			
		||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
 | 
			
		||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
 | 
			
		||||
@ -323,7 +312,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
 | 
			
		||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
 | 
			
		||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
 | 
			
		||||
github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
 | 
			
		||||
github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
 | 
			
		||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
@ -358,8 +346,6 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+
 | 
			
		||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
 | 
			
		||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 | 
			
		||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 | 
			
		||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
			
		||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 | 
			
		||||
@ -398,8 +384,6 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
 | 
			
		||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
 | 
			
		||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
 | 
			
		||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
 | 
			
		||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
 | 
			
		||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
 | 
			
		||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=
 | 
			
		||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
 | 
			
		||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 | 
			
		||||
@ -463,7 +447,6 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
 | 
			
		||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 | 
			
		||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 | 
			
		||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 | 
			
		||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
 | 
			
		||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
 | 
			
		||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 | 
			
		||||
@ -531,9 +514,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
 | 
			
		||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 | 
			
		||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 | 
			
		||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 | 
			
		||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
 | 
			
		||||
github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0=
 | 
			
		||||
github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 | 
			
		||||
github.com/pelletier/go-toml v1.9.1 h1:a6qW1EVNZWH9WGI6CsYdD8WAylkoXBS5yv0XHlh17Tc=
 | 
			
		||||
github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 | 
			
		||||
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
 | 
			
		||||
@ -568,7 +548,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
 | 
			
		||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 | 
			
		||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 | 
			
		||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 | 
			
		||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 | 
			
		||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
 | 
			
		||||
@ -595,7 +574,6 @@ github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 | 
			
		||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 | 
			
		||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 | 
			
		||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 | 
			
		||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 | 
			
		||||
@ -604,7 +582,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
			
		||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
			
		||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 | 
			
		||||
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
 | 
			
		||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
 | 
			
		||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
 | 
			
		||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
@ -622,8 +599,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
 | 
			
		||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 | 
			
		||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 | 
			
		||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 | 
			
		||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
 | 
			
		||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
 | 
			
		||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 | 
			
		||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 | 
			
		||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 | 
			
		||||
@ -658,8 +633,6 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ
 | 
			
		||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
 | 
			
		||||
github.com/yuin/gopher-lua v0.0.0-20191213034115-f46add6fdb5c/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
 | 
			
		||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0=
 | 
			
		||||
@ -672,7 +645,6 @@ go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS
 | 
			
		||||
go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.5.2 h1:AsxOLoJTgP6YNM0fXWw4OjdluYmWzQYp+lFJL7xu9fU=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.5.2/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
 | 
			
		||||
@ -735,8 +707,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
 | 
			
		||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 | 
			
		||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
 | 
			
		||||
golang.org/x/mod v0.4.2/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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
@ -777,16 +747,11 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/
 | 
			
		||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
			
		||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
			
		||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
			
		||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
			
		||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
			
		||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
			
		||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6 h1:0PC75Fz/kyMGhL0e1QnypqK2kQMqKt9csD1GnMJR+Zk=
 | 
			
		||||
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
			
		||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
 | 
			
		||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
@ -805,8 +770,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 | 
			
		||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
@ -857,13 +820,7 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 h1:kHSDPqCtsHZOg0nVylfTo20DDhE9gG4Y0jn7hKQ0QAM=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
@ -932,9 +889,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
 | 
			
		||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 | 
			
		||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 | 
			
		||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 | 
			
		||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
			
		||||
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
 | 
			
		||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,21 @@
 | 
			
		||||
package ak
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/go-openapi/runtime"
 | 
			
		||||
	"github.com/go-openapi/strfmt"
 | 
			
		||||
	"github.com/google/uuid"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/recws-org/recws"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
	"goauthentik.io/outpost/pkg"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/outposts"
 | 
			
		||||
 | 
			
		||||
	httptransport "github.com/go-openapi/runtime/client"
 | 
			
		||||
	"github.com/go-openapi/strfmt"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,7 @@ 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
 | 
			
		||||
	Client *api.APIClient
 | 
			
		||||
	token  string
 | 
			
		||||
 | 
			
		||||
	Server Outpost
 | 
			
		||||
@ -41,31 +40,32 @@ type APIController struct {
 | 
			
		||||
 | 
			
		||||
// NewAPIController initialise new API Controller instance from URL and API token
 | 
			
		||||
func NewAPIController(akURL url.URL, token string) *APIController {
 | 
			
		||||
	transport := httptransport.New(akURL.Host, client.DefaultBasePath, []string{akURL.Scheme})
 | 
			
		||||
	transport.Transport = SetUserAgent(getTLSTransport(), pkg.UserAgent())
 | 
			
		||||
 | 
			
		||||
	// create the transport
 | 
			
		||||
	auth := httptransport.BearerToken(token)
 | 
			
		||||
	config := api.NewConfiguration()
 | 
			
		||||
	config.Host = akURL.Host
 | 
			
		||||
	config.Scheme = akURL.Scheme
 | 
			
		||||
	config.HTTPClient = &http.Client{
 | 
			
		||||
		Transport: SetUserAgent(GetTLSTransport(), pkg.UserAgent()),
 | 
			
		||||
	}
 | 
			
		||||
	config.AddDefaultHeader("Authorization", fmt.Sprintf("Bearer %s", token))
 | 
			
		||||
 | 
			
		||||
	// create the API client, with the transport
 | 
			
		||||
	apiClient := client.New(transport, strfmt.Default)
 | 
			
		||||
	apiClient := api.NewAPIClient(config)
 | 
			
		||||
 | 
			
		||||
	log := log.WithField("logger", "authentik.outpost.ak-api-controller")
 | 
			
		||||
 | 
			
		||||
	// 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.OutpostsInstancesList(outposts.NewOutpostsInstancesListParams(), auth)
 | 
			
		||||
	outposts, _, err := apiClient.OutpostsApi.OutpostsInstancesListExecute(apiClient.OutpostsApi.OutpostsInstancesList(context.Background()))
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.WithError(err).Error("Failed to fetch configuration")
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	outpost := outposts.Payload.Results[0]
 | 
			
		||||
	doGlobalSetup(outpost.Config.(map[string]interface{}))
 | 
			
		||||
	outpost := outposts.Results[0]
 | 
			
		||||
	doGlobalSetup(outpost.Config)
 | 
			
		||||
 | 
			
		||||
	ac := &APIController{
 | 
			
		||||
		Client: apiClient,
 | 
			
		||||
		Auth:   auth,
 | 
			
		||||
		token:  token,
 | 
			
		||||
 | 
			
		||||
		logger: log,
 | 
			
		||||
@ -74,7 +74,7 @@ func NewAPIController(akURL url.URL, token string) *APIController {
 | 
			
		||||
		instanceUUID: uuid.New(),
 | 
			
		||||
	}
 | 
			
		||||
	ac.logger.Debugf("HA Reload offset: %s", ac.reloadOffset)
 | 
			
		||||
	ac.initWS(akURL, outpost.Pk)
 | 
			
		||||
	ac.initWS(akURL, strfmt.UUID(outpost.Pk))
 | 
			
		||||
	return ac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,16 @@
 | 
			
		||||
package ak
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/outposts"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (a *APIController) Update() ([]*models.ProxyOutpostConfig, error) {
 | 
			
		||||
	providers, err := a.Client.Outposts.OutpostsProxyList(outposts.NewOutpostsProxyListParams(), a.Auth)
 | 
			
		||||
func (a *APIController) Update() ([]api.ProxyOutpostConfig, error) {
 | 
			
		||||
	providers, _, err := a.Client.OutpostsApi.OutpostsProxyListExecute(a.Client.OutpostsApi.OutpostsProxyList(context.Background()))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		a.logger.WithError(err).Error("Failed to fetch providers")
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return providers.Payload.Results, nil
 | 
			
		||||
	return providers.Results, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@ func doGlobalSetup(config map[string]interface{}) {
 | 
			
		||||
	defer sentry.Flush(2 * time.Second)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getTLSTransport() http.RoundTripper {
 | 
			
		||||
func GetTLSTransport() http.RoundTripper {
 | 
			
		||||
	value, set := os.LookupEnv("AUTHENTIK_INSECURE")
 | 
			
		||||
	if !set {
 | 
			
		||||
		value = "false"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
@ -9,28 +10,27 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/go-openapi/strfmt"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/outposts"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (ls *LDAPServer) Refresh() error {
 | 
			
		||||
	outposts, err := ls.ac.Client.Outposts.OutpostsLdapList(outposts.NewOutpostsLdapListParams(), ls.ac.Auth)
 | 
			
		||||
	outposts, _, err := ls.ac.Client.OutpostsApi.OutpostsLdapListExecute(ls.ac.Client.OutpostsApi.OutpostsLdapList(context.Background()))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if len(outposts.Payload.Results) < 1 {
 | 
			
		||||
	if len(outposts.Results) < 1 {
 | 
			
		||||
		return errors.New("no ldap provider defined")
 | 
			
		||||
	}
 | 
			
		||||
	providers := make([]*ProviderInstance, len(outposts.Payload.Results))
 | 
			
		||||
	for idx, provider := range outposts.Payload.Results {
 | 
			
		||||
		userDN := strings.ToLower(fmt.Sprintf("ou=users,%s", provider.BaseDn))
 | 
			
		||||
		groupDN := strings.ToLower(fmt.Sprintf("ou=groups,%s", provider.BaseDn))
 | 
			
		||||
	providers := make([]*ProviderInstance, len(outposts.Results))
 | 
			
		||||
	for idx, provider := range outposts.Results {
 | 
			
		||||
		userDN := strings.ToLower(fmt.Sprintf("ou=users,%s", *provider.BaseDn))
 | 
			
		||||
		groupDN := strings.ToLower(fmt.Sprintf("ou=groups,%s", *provider.BaseDn))
 | 
			
		||||
		providers[idx] = &ProviderInstance{
 | 
			
		||||
			BaseDN:              provider.BaseDn,
 | 
			
		||||
			BaseDN:              *provider.BaseDn,
 | 
			
		||||
			GroupDN:             groupDN,
 | 
			
		||||
			UserDN:              userDN,
 | 
			
		||||
			appSlug:             *provider.ApplicationSlug,
 | 
			
		||||
			flowSlug:            *provider.BindFlowSlug,
 | 
			
		||||
			searchAllowedGroups: []*strfmt.UUID{provider.SearchGroup},
 | 
			
		||||
			appSlug:             provider.ApplicationSlug,
 | 
			
		||||
			flowSlug:            provider.BindFlowSlug,
 | 
			
		||||
			searchAllowedGroups: []*strfmt.UUID{(*strfmt.UUID)(provider.SearchGroup.Get())},
 | 
			
		||||
			boundUsersMutex:     sync.RWMutex{},
 | 
			
		||||
			boundUsers:          make(map[string]UserFlags),
 | 
			
		||||
			s:                   ls,
 | 
			
		||||
@ -55,14 +55,18 @@ func (ls *LDAPServer) Start() error {
 | 
			
		||||
 | 
			
		||||
type transport struct {
 | 
			
		||||
	headers map[string]string
 | 
			
		||||
	inner   http.RoundTripper
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
 | 
			
		||||
	for key, value := range t.headers {
 | 
			
		||||
		req.Header.Add(key, value)
 | 
			
		||||
	}
 | 
			
		||||
	return http.DefaultTransport.RoundTrip(req)
 | 
			
		||||
	return t.inner.RoundTrip(req)
 | 
			
		||||
}
 | 
			
		||||
func newTransport(headers map[string]string) *transport {
 | 
			
		||||
	return &transport{headers}
 | 
			
		||||
func newTransport(inner http.RoundTripper, headers map[string]string) *transport {
 | 
			
		||||
	return &transport{
 | 
			
		||||
		inner:   inner,
 | 
			
		||||
		headers: headers,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,23 +12,14 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	goldap "github.com/go-ldap/ldap/v3"
 | 
			
		||||
	httptransport "github.com/go-openapi/runtime/client"
 | 
			
		||||
	"github.com/nmcclain/ldap"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/core"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/flows"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
	"goauthentik.io/outpost/pkg"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/ak"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const ContextUserKey = "ak_user"
 | 
			
		||||
 | 
			
		||||
type UIDResponse struct {
 | 
			
		||||
	UIDFIeld string `json:"uid_field"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PasswordResponse struct {
 | 
			
		||||
	Password string `json:"password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pi *ProviderInstance) getUsername(dn string) (string, error) {
 | 
			
		||||
	if !strings.HasSuffix(strings.ToLower(dn), strings.ToLower(pi.BaseDN)) {
 | 
			
		||||
		return "", errors.New("invalid base DN")
 | 
			
		||||
@ -58,16 +49,25 @@ func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn ne
 | 
			
		||||
		pi.log.WithError(err).Warning("Failed to get remote IP")
 | 
			
		||||
		return ldap.LDAPResultOperationsError, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create new http client that also sets the correct ip
 | 
			
		||||
	client := &http.Client{
 | 
			
		||||
	config := api.NewConfiguration()
 | 
			
		||||
	// Carry over the bearer authentication, so that failed login attempts are attributed to the outpost
 | 
			
		||||
	config.DefaultHeader = pi.s.ac.Client.GetConfig().DefaultHeader
 | 
			
		||||
	config.Host = pi.s.ac.Client.GetConfig().Host
 | 
			
		||||
	config.Scheme = pi.s.ac.Client.GetConfig().Scheme
 | 
			
		||||
	config.HTTPClient = &http.Client{
 | 
			
		||||
		Jar: jar,
 | 
			
		||||
		Transport: newTransport(map[string]string{
 | 
			
		||||
		Transport: newTransport(ak.SetUserAgent(ak.GetTLSTransport(), pkg.UserAgent()), map[string]string{
 | 
			
		||||
			"X-authentik-remote-ip": host,
 | 
			
		||||
		}),
 | 
			
		||||
	}
 | 
			
		||||
	// create the API client, with the transport
 | 
			
		||||
	apiClient := api.NewAPIClient(config)
 | 
			
		||||
 | 
			
		||||
	params := url.Values{}
 | 
			
		||||
	params.Add("goauthentik.io/outpost/ldap", "true")
 | 
			
		||||
	passed, err := pi.solveFlowChallenge(username, bindPW, client, params.Encode(), 1)
 | 
			
		||||
	passed, err := pi.solveFlowChallenge(username, bindPW, apiClient, params.Encode(), 1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to solve challenge")
 | 
			
		||||
		return ldap.LDAPResultOperationsError, nil
 | 
			
		||||
@ -75,33 +75,26 @@ func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn ne
 | 
			
		||||
	if !passed {
 | 
			
		||||
		return ldap.LDAPResultInvalidCredentials, nil
 | 
			
		||||
	}
 | 
			
		||||
	_, err = pi.s.ac.Client.Core.CoreApplicationsCheckAccess(&core.CoreApplicationsCheckAccessParams{
 | 
			
		||||
		Slug:       pi.appSlug,
 | 
			
		||||
		Context:    context.Background(),
 | 
			
		||||
		HTTPClient: client,
 | 
			
		||||
	}, httptransport.PassThroughAuth)
 | 
			
		||||
	r, err := pi.s.ac.Client.CoreApi.CoreApplicationsCheckAccessRetrieve(context.Background(), pi.appSlug).Execute()
 | 
			
		||||
	if r.StatusCode == 403 {
 | 
			
		||||
		pi.log.WithField("bindDN", bindDN).Info("Access denied for user")
 | 
			
		||||
		return ldap.LDAPResultInsufficientAccessRights, nil
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if _, denied := err.(*core.CoreApplicationsCheckAccessForbidden); denied {
 | 
			
		||||
			pi.log.WithField("bindDN", bindDN).Info("Access denied for user")
 | 
			
		||||
			return ldap.LDAPResultInsufficientAccessRights, nil
 | 
			
		||||
		}
 | 
			
		||||
		pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to check access")
 | 
			
		||||
		return ldap.LDAPResultOperationsError, nil
 | 
			
		||||
	}
 | 
			
		||||
	pi.log.WithField("bindDN", bindDN).Info("User has access")
 | 
			
		||||
	// Get user info to store in context
 | 
			
		||||
	userInfo, err := pi.s.ac.Client.Core.CoreUsersMe(&core.CoreUsersMeParams{
 | 
			
		||||
		Context:    context.Background(),
 | 
			
		||||
		HTTPClient: client,
 | 
			
		||||
	}, httptransport.PassThroughAuth)
 | 
			
		||||
	userInfo, _, err := pi.s.ac.Client.CoreApi.CoreUsersMeRetrieve(context.Background()).Execute()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to get user info")
 | 
			
		||||
		return ldap.LDAPResultOperationsError, nil
 | 
			
		||||
	}
 | 
			
		||||
	pi.boundUsersMutex.Lock()
 | 
			
		||||
	pi.boundUsers[bindDN] = UserFlags{
 | 
			
		||||
		UserInfo:  *userInfo.Payload.User,
 | 
			
		||||
		CanSearch: pi.SearchAccessCheck(userInfo.Payload.User),
 | 
			
		||||
		UserInfo:  userInfo.User,
 | 
			
		||||
		CanSearch: pi.SearchAccessCheck(userInfo.User),
 | 
			
		||||
	}
 | 
			
		||||
	defer pi.boundUsersMutex.Unlock()
 | 
			
		||||
	pi.delayDeleteUserInfo(username)
 | 
			
		||||
@ -109,11 +102,11 @@ func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn ne
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SearchAccessCheck Check if the current user is allowed to search
 | 
			
		||||
func (pi *ProviderInstance) SearchAccessCheck(user *models.User) bool {
 | 
			
		||||
func (pi *ProviderInstance) SearchAccessCheck(user api.User) bool {
 | 
			
		||||
	for _, group := range user.Groups {
 | 
			
		||||
		for _, allowedGroup := range pi.searchAllowedGroups {
 | 
			
		||||
			pi.log.WithField("userGroup", group.Pk).WithField("allowedGroup", allowedGroup).Trace("Checking search access")
 | 
			
		||||
			if group.Pk.String() == allowedGroup.String() {
 | 
			
		||||
			if group.Pk == allowedGroup.String() {
 | 
			
		||||
				pi.log.WithField("group", group.Name).Info("Allowed access to search")
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
@ -140,51 +133,48 @@ func (pi *ProviderInstance) delayDeleteUserInfo(dn string) {
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *http.Client, urlParams string, depth int) (bool, error) {
 | 
			
		||||
	challenge, err := pi.s.ac.Client.Flows.FlowsExecutorGet(&flows.FlowsExecutorGetParams{
 | 
			
		||||
		FlowSlug:   pi.flowSlug,
 | 
			
		||||
		Query:      urlParams,
 | 
			
		||||
		Context:    context.Background(),
 | 
			
		||||
		HTTPClient: client,
 | 
			
		||||
	}, pi.s.ac.Auth)
 | 
			
		||||
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *api.APIClient, urlParams string, depth int) (bool, error) {
 | 
			
		||||
	req := client.FlowsApi.FlowsExecutorGet(context.Background(), pi.flowSlug)
 | 
			
		||||
	req.Query(urlParams)
 | 
			
		||||
	challenge, _, err := req.Execute()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		pi.log.WithError(err).Warning("Failed to get challenge")
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	pi.log.WithField("component", challenge.Payload.Component).WithField("type", *challenge.Payload.Type).Debug("Got challenge")
 | 
			
		||||
	responseParams := &flows.FlowsExecutorSolveParams{
 | 
			
		||||
		FlowSlug:   pi.flowSlug,
 | 
			
		||||
		Query:      urlParams,
 | 
			
		||||
		Context:    context.Background(),
 | 
			
		||||
		HTTPClient: client,
 | 
			
		||||
	}
 | 
			
		||||
	switch challenge.Payload.Component {
 | 
			
		||||
	pi.log.WithField("component", challenge.Component).WithField("type", challenge.Type).Debug("Got challenge")
 | 
			
		||||
	responseReq := client.FlowsApi.FlowsExecutorSolve(context.Background(), pi.flowSlug)
 | 
			
		||||
	responseReq.Query(urlParams)
 | 
			
		||||
	switch *challenge.Component {
 | 
			
		||||
	case "ak-stage-identification":
 | 
			
		||||
		responseParams.Data = &UIDResponse{UIDFIeld: bindDN}
 | 
			
		||||
		responseReq.RequestBody(map[string]interface{}{
 | 
			
		||||
			"uid_field": bindDN,
 | 
			
		||||
		})
 | 
			
		||||
	case "ak-stage-password":
 | 
			
		||||
		responseParams.Data = &PasswordResponse{Password: password}
 | 
			
		||||
		responseReq.RequestBody(map[string]interface{}{
 | 
			
		||||
			"password": password,
 | 
			
		||||
		})
 | 
			
		||||
	case "ak-stage-access-denied":
 | 
			
		||||
		return false, errors.New("got ak-stage-access-denied")
 | 
			
		||||
	default:
 | 
			
		||||
		return false, fmt.Errorf("unsupported challenge type: %s", challenge.Payload.Component)
 | 
			
		||||
		return false, fmt.Errorf("unsupported challenge type: %s", *challenge.Component)
 | 
			
		||||
	}
 | 
			
		||||
	response, err := pi.s.ac.Client.Flows.FlowsExecutorSolve(responseParams, pi.s.ac.Auth)
 | 
			
		||||
	pi.log.WithField("component", response.Payload.Component).WithField("type", *response.Payload.Type).Debug("Got response")
 | 
			
		||||
	switch response.Payload.Component {
 | 
			
		||||
	response, _, err := responseReq.Execute()
 | 
			
		||||
	pi.log.WithField("component", response.Component).WithField("type", response.Type).Debug("Got response")
 | 
			
		||||
	switch *response.Component {
 | 
			
		||||
	case "ak-stage-access-denied":
 | 
			
		||||
		return false, errors.New("got ak-stage-access-denied")
 | 
			
		||||
	}
 | 
			
		||||
	if *response.Payload.Type == "redirect" {
 | 
			
		||||
	if response.Type == "redirect" {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		pi.log.WithError(err).Warning("Failed to submit challenge")
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(response.Payload.ResponseErrors) > 0 {
 | 
			
		||||
		for key, errs := range response.Payload.ResponseErrors {
 | 
			
		||||
	if len(*response.ResponseErrors) > 0 {
 | 
			
		||||
		for key, errs := range *response.ResponseErrors {
 | 
			
		||||
			for _, err := range errs {
 | 
			
		||||
				pi.log.WithField("key", key).WithField("code", *err.Code).Debug(*err.String)
 | 
			
		||||
				pi.log.WithField("key", key).WithField("code", err.Code).Debug(err.String)
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,13 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/nmcclain/ldap"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/core"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
 | 
			
		||||
@ -43,16 +43,16 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
 | 
			
		||||
	default:
 | 
			
		||||
		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: unhandled filter type: %s [%s]", filterEntity, searchReq.Filter)
 | 
			
		||||
	case GroupObjectClass:
 | 
			
		||||
		groups, err := pi.s.ac.Client.Core.CoreGroupsList(core.NewCoreGroupsListParams(), pi.s.ac.Auth)
 | 
			
		||||
		groups, _, err := pi.s.ac.Client.CoreApi.CoreGroupsListExecute(pi.s.ac.Client.CoreApi.CoreGroupsList(context.Background()))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		pi.log.WithField("count", len(groups.Payload.Results)).Trace("Got results from API")
 | 
			
		||||
		for _, g := range groups.Payload.Results {
 | 
			
		||||
		pi.log.WithField("count", len(groups.Results)).Trace("Got results from API")
 | 
			
		||||
		for _, g := range groups.Results {
 | 
			
		||||
			attrs := []*ldap.EntryAttribute{
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "cn",
 | 
			
		||||
					Values: []string{*g.Name},
 | 
			
		||||
					Values: []string{g.Name},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "uid",
 | 
			
		||||
@ -69,31 +69,31 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
 | 
			
		||||
			entries = append(entries, &ldap.Entry{DN: dn, Attributes: attrs})
 | 
			
		||||
		}
 | 
			
		||||
	case UserObjectClass, "":
 | 
			
		||||
		users, err := pi.s.ac.Client.Core.CoreUsersList(core.NewCoreUsersListParams(), pi.s.ac.Auth)
 | 
			
		||||
		users, _, err := pi.s.ac.Client.CoreApi.CoreUsersListExecute(pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		for _, u := range users.Payload.Results {
 | 
			
		||||
		for _, u := range users.Results {
 | 
			
		||||
			attrs := []*ldap.EntryAttribute{
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "cn",
 | 
			
		||||
					Values: []string{*u.Username},
 | 
			
		||||
					Values: []string{u.Username},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "uid",
 | 
			
		||||
					Values: []string{u.UID},
 | 
			
		||||
					Values: []string{u.Uid},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "name",
 | 
			
		||||
					Values: []string{*u.Name},
 | 
			
		||||
					Values: []string{u.Name},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "displayName",
 | 
			
		||||
					Values: []string{*u.Name},
 | 
			
		||||
					Values: []string{u.Name},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "mail",
 | 
			
		||||
					Values: []string{u.Email.String()},
 | 
			
		||||
					Values: []string{*u.Email},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:   "objectClass",
 | 
			
		||||
@ -101,13 +101,13 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if u.IsActive {
 | 
			
		||||
			if *u.IsActive {
 | 
			
		||||
				attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"inactive"}})
 | 
			
		||||
			} else {
 | 
			
		||||
				attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"active"}})
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if *u.IsSuperuser {
 | 
			
		||||
			if u.IsSuperuser {
 | 
			
		||||
				attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"inactive"}})
 | 
			
		||||
			} else {
 | 
			
		||||
				attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"active"}})
 | 
			
		||||
@ -117,7 +117,7 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
 | 
			
		||||
 | 
			
		||||
			attrs = append(attrs, AKAttrsToLDAP(u.Attributes)...)
 | 
			
		||||
 | 
			
		||||
			dn := fmt.Sprintf("cn=%s,%s", *u.Username, pi.UserDN)
 | 
			
		||||
			dn := fmt.Sprintf("cn=%s,%s", u.Username, pi.UserDN)
 | 
			
		||||
			entries = append(entries, &ldap.Entry{DN: dn, Attributes: attrs})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,8 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/go-openapi/strfmt"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/ak"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
 | 
			
		||||
	"github.com/nmcclain/ldap"
 | 
			
		||||
)
 | 
			
		||||
@ -31,7 +31,7 @@ type ProviderInstance struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UserFlags struct {
 | 
			
		||||
	UserInfo  models.User
 | 
			
		||||
	UserInfo  api.User
 | 
			
		||||
	CanSearch bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/nmcclain/ldap"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
 | 
			
		||||
@ -22,7 +22,7 @@ func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
 | 
			
		||||
	return attrList
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pi *ProviderInstance) GroupsForUser(user *models.User) []string {
 | 
			
		||||
func (pi *ProviderInstance) GroupsForUser(user api.User) []string {
 | 
			
		||||
	groups := make([]string, len(user.Groups))
 | 
			
		||||
	for i, group := range user.Groups {
 | 
			
		||||
		groups[i] = pi.GetGroupDN(group)
 | 
			
		||||
@ -30,6 +30,6 @@ func (pi *ProviderInstance) GroupsForUser(user *models.User) []string {
 | 
			
		||||
	return groups
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pi *ProviderInstance) GetGroupDN(group *models.Group) string {
 | 
			
		||||
	return fmt.Sprintf("cn=%s,%s", *group.Name, pi.GroupDN)
 | 
			
		||||
func (pi *ProviderInstance) GetGroupDN(group api.Group) string {
 | 
			
		||||
	return fmt.Sprintf("cn=%s,%s", group.Name, pi.GroupDN)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (s *Server) Refresh() error {
 | 
			
		||||
@ -21,10 +21,10 @@ func (s *Server) Refresh() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) bundleProviders(providers []*models.ProxyOutpostConfig) []*providerBundle {
 | 
			
		||||
func (s *Server) bundleProviders(providers []api.ProxyOutpostConfig) []*providerBundle {
 | 
			
		||||
	bundles := make([]*providerBundle, len(providers))
 | 
			
		||||
	for idx, provider := range providers {
 | 
			
		||||
		externalHost, err := url.Parse(*provider.ExternalHost)
 | 
			
		||||
		externalHost, err := url.Parse(provider.ExternalHost)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.WithError(err).Warning("Failed to parse URL, skipping provider")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,7 @@ import (
 | 
			
		||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/middleware"
 | 
			
		||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/client/crypto"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type providerBundle struct {
 | 
			
		||||
@ -35,8 +34,8 @@ func intToPointer(i int) *int {
 | 
			
		||||
	return &i
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *options.Options {
 | 
			
		||||
	externalHost, err := url.Parse(*provider.ExternalHost)
 | 
			
		||||
func (pb *providerBundle) prepareOpts(provider api.ProxyOutpostConfig) *options.Options {
 | 
			
		||||
	externalHost, err := url.Parse(provider.ExternalHost)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.WithError(err).Warning("Failed to parse URL, skipping provider")
 | 
			
		||||
		return nil
 | 
			
		||||
@ -47,25 +46,25 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
 | 
			
		||||
		log.WithError(err).Warning("Failed to copy options, skipping provider")
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	providerOpts.ClientID = provider.ClientID
 | 
			
		||||
	providerOpts.ClientSecret = provider.ClientSecret
 | 
			
		||||
	providerOpts.ClientID = *provider.ClientId
 | 
			
		||||
	providerOpts.ClientSecret = *provider.ClientSecret
 | 
			
		||||
 | 
			
		||||
	providerOpts.Cookie.Secret = provider.CookieSecret
 | 
			
		||||
	providerOpts.Cookie.Secret = *provider.CookieSecret
 | 
			
		||||
	providerOpts.Cookie.Secure = externalHost.Scheme == "https"
 | 
			
		||||
 | 
			
		||||
	providerOpts.SkipOIDCDiscovery = true
 | 
			
		||||
	providerOpts.OIDCIssuerURL = *provider.OidcConfiguration.Issuer
 | 
			
		||||
	providerOpts.LoginURL = *provider.OidcConfiguration.AuthorizationEndpoint
 | 
			
		||||
	providerOpts.RedeemURL = *provider.OidcConfiguration.TokenEndpoint
 | 
			
		||||
	providerOpts.OIDCJwksURL = *provider.OidcConfiguration.JwksURI
 | 
			
		||||
	providerOpts.ProfileURL = *provider.OidcConfiguration.UserinfoEndpoint
 | 
			
		||||
	providerOpts.OIDCIssuerURL = provider.OidcConfiguration.Issuer
 | 
			
		||||
	providerOpts.LoginURL = provider.OidcConfiguration.AuthorizationEndpoint
 | 
			
		||||
	providerOpts.RedeemURL = provider.OidcConfiguration.TokenEndpoint
 | 
			
		||||
	providerOpts.OIDCJwksURL = provider.OidcConfiguration.JwksUri
 | 
			
		||||
	providerOpts.ProfileURL = provider.OidcConfiguration.UserinfoEndpoint
 | 
			
		||||
 | 
			
		||||
	if provider.SkipPathRegex != "" {
 | 
			
		||||
		skipRegexes := strings.Split(provider.SkipPathRegex, "\n")
 | 
			
		||||
	if *provider.SkipPathRegex != "" {
 | 
			
		||||
		skipRegexes := strings.Split(*provider.SkipPathRegex, "\n")
 | 
			
		||||
		providerOpts.SkipAuthRegex = skipRegexes
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if provider.ForwardAuthMode {
 | 
			
		||||
	if *provider.ForwardAuthMode {
 | 
			
		||||
		providerOpts.UpstreamServers = []options.Upstream{
 | 
			
		||||
			{
 | 
			
		||||
				ID:         "static",
 | 
			
		||||
@ -78,33 +77,27 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
 | 
			
		||||
		providerOpts.UpstreamServers = []options.Upstream{
 | 
			
		||||
			{
 | 
			
		||||
				ID:                    "default",
 | 
			
		||||
				URI:                   provider.InternalHost,
 | 
			
		||||
				URI:                   *provider.InternalHost,
 | 
			
		||||
				Path:                  "/",
 | 
			
		||||
				InsecureSkipTLSVerify: !provider.InternalHostSslValidation,
 | 
			
		||||
				InsecureSkipTLSVerify: !(*provider.InternalHostSslValidation),
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if provider.Certificate != nil {
 | 
			
		||||
	if provider.Certificate.Get() != nil {
 | 
			
		||||
		pb.log.WithField("provider", provider.Name).Debug("Enabling TLS")
 | 
			
		||||
		cert, err := pb.s.ak.Client.Crypto.CryptoCertificatekeypairsViewCertificate(&crypto.CryptoCertificatekeypairsViewCertificateParams{
 | 
			
		||||
			Context: context.Background(),
 | 
			
		||||
			KpUUID:  *provider.Certificate,
 | 
			
		||||
		}, pb.s.ak.Auth)
 | 
			
		||||
		cert, _, err := pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewCertificateRetrieveExecute(pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewCertificateRetrieve(context.Background(), *provider.Certificate.Get()))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch certificate")
 | 
			
		||||
			return providerOpts
 | 
			
		||||
		}
 | 
			
		||||
		key, err := pb.s.ak.Client.Crypto.CryptoCertificatekeypairsViewPrivateKey(&crypto.CryptoCertificatekeypairsViewPrivateKeyParams{
 | 
			
		||||
			Context: context.Background(),
 | 
			
		||||
			KpUUID:  *provider.Certificate,
 | 
			
		||||
		}, pb.s.ak.Auth)
 | 
			
		||||
		key, _, err := pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewPrivateKeyRetrieveExecute(pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewPrivateKeyRetrieve(context.Background(), *provider.Certificate.Get()))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch private key")
 | 
			
		||||
			return providerOpts
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		x509cert, err := tls.X509KeyPair([]byte(cert.Payload.Data), []byte(key.Payload.Data))
 | 
			
		||||
		x509cert, err := tls.X509KeyPair([]byte(cert.Data), []byte(key.Data))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to parse certificate")
 | 
			
		||||
			return providerOpts
 | 
			
		||||
@ -115,7 +108,7 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
 | 
			
		||||
	return providerOpts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
 | 
			
		||||
func (pb *providerBundle) Build(provider api.ProxyOutpostConfig) {
 | 
			
		||||
	opts := pb.prepareOpts(provider)
 | 
			
		||||
 | 
			
		||||
	chain := alice.New()
 | 
			
		||||
@ -154,10 +147,10 @@ func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if provider.BasicAuthEnabled {
 | 
			
		||||
	if *provider.BasicAuthEnabled {
 | 
			
		||||
		oauthproxy.SetBasicAuth = true
 | 
			
		||||
		oauthproxy.BasicAuthUserAttribute = provider.BasicAuthUserAttribute
 | 
			
		||||
		oauthproxy.BasicAuthPasswordAttribute = provider.BasicAuthPasswordAttribute
 | 
			
		||||
		oauthproxy.BasicAuthUserAttribute = *provider.BasicAuthUserAttribute
 | 
			
		||||
		oauthproxy.BasicAuthPasswordAttribute = *provider.BasicAuthPasswordAttribute
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pb.proxy = oauthproxy
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ import (
 | 
			
		||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/sessions"
 | 
			
		||||
	"github.com/oauth2-proxy/oauth2-proxy/pkg/upstream"
 | 
			
		||||
	"github.com/oauth2-proxy/oauth2-proxy/providers"
 | 
			
		||||
	"goauthentik.io/outpost/pkg/models"
 | 
			
		||||
	"goauthentik.io/outpost/api"
 | 
			
		||||
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
@ -94,7 +94,7 @@ type OAuthProxy struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
 | 
			
		||||
func NewOAuthProxy(opts *options.Options, provider *models.ProxyOutpostConfig) (*OAuthProxy, error) {
 | 
			
		||||
func NewOAuthProxy(opts *options.Options, provider api.ProxyOutpostConfig) (*OAuthProxy, error) {
 | 
			
		||||
	logger := log.WithField("logger", "authentik.outpost.proxy").WithField("provider", provider.Name)
 | 
			
		||||
	sessionStore, err := sessions.NewSessionStore(&opts.Session, &opts.Cookie)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -133,7 +133,7 @@ func NewOAuthProxy(opts *options.Options, provider *models.ProxyOutpostConfig) (
 | 
			
		||||
		CookieRefresh:  opts.Cookie.Refresh,
 | 
			
		||||
		CookieSameSite: opts.Cookie.SameSite,
 | 
			
		||||
 | 
			
		||||
		forwardAuthMode:   provider.ForwardAuthMode,
 | 
			
		||||
		forwardAuthMode:   *provider.ForwardAuthMode,
 | 
			
		||||
		RobotsPath:        "/robots.txt",
 | 
			
		||||
		SignInPath:        fmt.Sprintf("%s/sign_in", opts.ProxyPrefix),
 | 
			
		||||
		SignOutPath:       fmt.Sprintf("%s/sign_out", opts.ProxyPrefix),
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user