mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 18:06:34 +02:00
remove forward auth (#3628)
This commit is contained in:
parent
ba07afc245
commit
fa26587f19
68 changed files with 302 additions and 5072 deletions
|
@ -1,33 +0,0 @@
|
|||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/go/.devcontainer/base.Dockerfile
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/go:0-1@sha256:ec4067ba197ea0c44268641bd252c0bdfa61228202cee5f447925f9ac76d59b3
|
||||
|
||||
# [Optional] Install a version of Node.js using nvm for front end dev
|
||||
ARG INSTALL_NODE="true"
|
||||
ARG NODE_VERSION="lts/*"
|
||||
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
||||
|
||||
# install envoy
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg-agent \
|
||||
software-properties-common
|
||||
|
||||
RUN curl -sL 'https://getenvoy.io/gpg' | sudo apt-key add -
|
||||
|
||||
RUN add-apt-repository \
|
||||
"deb [arch=amd64] https://dl.bintray.com/tetrate/getenvoy-deb \
|
||||
$(lsb_release -cs) \
|
||||
stable"
|
||||
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends getenvoy-envoy
|
||||
|
||||
|
||||
# [Optional] Uncomment the next line to use go get to install anything else you need
|
||||
# RUN go get -x <your-dependency-or-tool>
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
|
@ -1,21 +0,0 @@
|
|||
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/go
|
||||
{
|
||||
"name": "pomerium-remote-containers",
|
||||
"runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"go.useGoProxyToCheckForToolUpdates": false,
|
||||
"go.gopath": "/go",
|
||||
"go.useLanguageServer": true
|
||||
},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": ["golang.Go"],
|
||||
"postCreateCommand": "go version",
|
||||
"dockerComposeFile": ["envs/nginx.yaml"],
|
||||
// "dockerComposeFile": ["envs/traefik.yaml"],
|
||||
"service": "pomerium",
|
||||
"shutdownAction": "none",
|
||||
"workspaceFolder": "/workspace"
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: openresty/openresty
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ../../examples/nginx/verify.conf:/etc/nginx/conf.d/verify.conf
|
||||
- ../../examples/nginx/pomerium.conf:/etc/nginx/conf.d/pomerium.conf
|
||||
- ../../examples/nginx/proxy.conf:/etc/nginx/proxy.conf
|
||||
- ../../examples/nginx/_wildcard.localhost.pomerium.io.pem:/etc/nginx/nginx.pem
|
||||
- ../../examples/nginx/_wildcard.localhost.pomerium.io-key.pem:/etc/nginx/nginx-key.pem
|
||||
|
||||
verify:
|
||||
image: pomerium/verify
|
||||
expose:
|
||||
- 80
|
||||
|
||||
pomerium:
|
||||
build: ../.
|
||||
volumes:
|
||||
- ../../:/workspace:cached
|
||||
command: /bin/sh -c "while sleep 1000; do :; done"
|
||||
environment:
|
||||
- INSECURE_SERVER=TRUE
|
||||
- ADDRESS=:80
|
||||
- FORWARD_AUTH_URL=https://fwdauth.localhost.pomerium.io
|
||||
- JWT_CLAIMS_HEADERS="email,groups,user"
|
||||
expose:
|
||||
- 80
|
|
@ -1,50 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.3
|
||||
command:
|
||||
- "--accesslog=true"
|
||||
- "--api.insecure=true"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entryPoints.websecure.forwardedHeaders.insecure"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker=true"
|
||||
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
verify:
|
||||
image: pomerium/verify:latest
|
||||
labels:
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.authResponseHeaders=X-Pomerium-Claim-Email,X-Pomerium-Claim-User,X-Pomerium-Claim-Groups,X-Pomerium-Jwt-Assertion"
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.address=http://pomerium/"
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.trustForwardHeader=true"
|
||||
- "traefik.http.routers.verify.middlewares=pomerium@docker"
|
||||
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.verify.rule=Host(`verify.localhost.pomerium.io`)"
|
||||
- "traefik.http.routers.verify.entrypoints=websecure"
|
||||
- "traefik.http.routers.verify.tls=true"
|
||||
|
||||
pomerium:
|
||||
build: ../.
|
||||
volumes:
|
||||
- ../../:/workspace:cached
|
||||
command: /bin/sh -c "while sleep 1000; do :; done"
|
||||
environment:
|
||||
- INSECURE_SERVER=TRUE
|
||||
- ADDRESS=:80
|
||||
- FORWARD_AUTH_URL=http://pomerium
|
||||
- JWT_CLAIMS_HEADERS="email,groups,user"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.pomerium.rule=Host(`authenticate.localhost.pomerium.io`)"
|
||||
- "traefik.http.routers.pomerium.entrypoints=websecure"
|
||||
- "traefik.http.routers.pomerium.tls=true"
|
||||
expose:
|
||||
- 80
|
|
@ -1,21 +0,0 @@
|
|||
# Remote dev containers
|
||||
|
||||
## What
|
||||
|
||||
These are configurations for Visual Studio Code telling it how to create or access a development container with a well-defined tool and runtime stack.
|
||||
|
||||
Basically, this allows us to run VS Code from within a container, remotely.
|
||||
|
||||
## Why
|
||||
|
||||
Integrating, testing, and debugging Pomerium behind other fronting proxies (nginx/traefik) in forward-auth configuration is a real pain. In particular, it is difficult to do step debugging inside a containerized environment where part of that environment lives outside the network stack of the other components.
|
||||
|
||||
It turns out that bringing the debug environment to the containerized environment is easier than bringing the request flow.
|
||||
|
||||
## How
|
||||
|
||||
- Install [Remote-container](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
||||
- Change `devcontainer.json` to use the docker compose file you want to test with
|
||||
- run `Remote-Containers: Rebuild Container` from the Command Palette
|
||||
- ???
|
||||
- Debug, code, etc as your normally would.
|
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
|
@ -116,7 +116,7 @@ jobs:
|
|||
go-version: [1.19.x]
|
||||
node-version: [16.x]
|
||||
platform: [ubuntu-latest]
|
||||
deployment: [kubernetes, multi, nginx, single, traefik]
|
||||
deployment: [kubernetes, multi, single]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f
|
||||
|
|
|
@ -201,11 +201,6 @@ func (a *Authenticate) SignIn(w http.ResponseWriter, r *http.Request) error {
|
|||
jwtAudience = append(jwtAudience, callbackURL.Host)
|
||||
}
|
||||
|
||||
// add an additional claim for the forward-auth host, if set
|
||||
if fwdAuth := r.FormValue(urlutil.QueryForwardAuth); fwdAuth != "" {
|
||||
jwtAudience = append(jwtAudience, fwdAuth)
|
||||
}
|
||||
|
||||
s, err := a.getSessionFromCtx(ctx)
|
||||
if err != nil {
|
||||
state.sessionStore.ClearSession(w, r)
|
||||
|
|
|
@ -133,7 +133,6 @@ func TestAuthenticate_SignIn(t *testing.T) {
|
|||
{"good with callback uri set", "https", "corp.example.example", map[string]string{urlutil.QueryCallbackURI: "https://some.example/", urlutil.QueryRedirectURI: "https://dst.some.example/"}, &mstore.Store{Session: &sessions.State{}}, identity.MockProvider{}, &mock.Encoder{}, http.StatusFound},
|
||||
{"bad callback uri set", "https", "corp.example.example", map[string]string{urlutil.QueryCallbackURI: "^", urlutil.QueryRedirectURI: "https://dst.some.example/"}, &mstore.Store{Session: &sessions.State{}}, identity.MockProvider{}, &mock.Encoder{}, http.StatusBadRequest},
|
||||
{"good programmatic request", "https", "corp.example.example", map[string]string{urlutil.QueryIsProgrammatic: "true", urlutil.QueryRedirectURI: "https://dst.some.example/"}, &mstore.Store{Session: &sessions.State{}}, identity.MockProvider{}, &mock.Encoder{}, http.StatusFound},
|
||||
{"good additional audience", "https", "corp.example.example", map[string]string{urlutil.QueryForwardAuth: "x.y.z", urlutil.QueryRedirectURI: "https://dst.some.example/"}, &mstore.Store{Session: &sessions.State{}}, identity.MockProvider{}, &mock.Encoder{}, http.StatusFound},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
|
|
@ -32,25 +32,24 @@ func (a *Authorize) handleResult(
|
|||
in *envoy_service_auth_v3.CheckRequest,
|
||||
request *evaluator.Request,
|
||||
result *evaluator.Result,
|
||||
isForwardAuthVerify bool,
|
||||
) (*envoy_service_auth_v3.CheckResponse, error) {
|
||||
// when the user is unauthenticated it means they haven't
|
||||
// logged in yet, so redirect to authenticate
|
||||
if result.Allow.Reasons.Has(criteria.ReasonUserUnauthenticated) ||
|
||||
result.Deny.Reasons.Has(criteria.ReasonUserUnauthenticated) {
|
||||
return a.requireLoginResponse(ctx, in, request, isForwardAuthVerify)
|
||||
return a.requireLoginResponse(ctx, in, request)
|
||||
}
|
||||
|
||||
// when the user's device is unauthenticated it means they haven't
|
||||
// registered a webauthn device yet, so redirect to the webauthn flow
|
||||
if result.Allow.Reasons.Has(criteria.ReasonDeviceUnauthenticated) ||
|
||||
result.Deny.Reasons.Has(criteria.ReasonDeviceUnauthenticated) {
|
||||
return a.requireWebAuthnResponse(ctx, in, request, result, isForwardAuthVerify)
|
||||
return a.requireWebAuthnResponse(ctx, in, request, result)
|
||||
}
|
||||
|
||||
// if there's a deny, the result is denied using the deny reasons.
|
||||
if result.Deny.Value {
|
||||
return a.handleResultDenied(ctx, in, request, result, isForwardAuthVerify, result.Deny.Reasons)
|
||||
return a.handleResultDenied(ctx, in, request, result, result.Deny.Reasons)
|
||||
}
|
||||
|
||||
// if there's an allow, the result is allowed.
|
||||
|
@ -59,7 +58,7 @@ func (a *Authorize) handleResult(
|
|||
}
|
||||
|
||||
// otherwise, the result is denied using the allow reasons.
|
||||
return a.handleResultDenied(ctx, in, request, result, isForwardAuthVerify, result.Allow.Reasons)
|
||||
return a.handleResultDenied(ctx, in, request, result, result.Allow.Reasons)
|
||||
}
|
||||
|
||||
func (a *Authorize) handleResultAllowed(
|
||||
|
@ -75,7 +74,6 @@ func (a *Authorize) handleResultDenied(
|
|||
in *envoy_service_auth_v3.CheckRequest,
|
||||
request *evaluator.Request,
|
||||
result *evaluator.Result,
|
||||
isForwardAuthVerify bool,
|
||||
reasons criteria.Reasons,
|
||||
) (*envoy_service_auth_v3.CheckResponse, error) {
|
||||
denyStatusCode := int32(http.StatusForbidden)
|
||||
|
@ -83,7 +81,7 @@ func (a *Authorize) handleResultDenied(
|
|||
|
||||
switch {
|
||||
case reasons.Has(criteria.ReasonDeviceUnauthenticated):
|
||||
return a.requireWebAuthnResponse(ctx, in, request, result, isForwardAuthVerify)
|
||||
return a.requireWebAuthnResponse(ctx, in, request, result)
|
||||
case reasons.Has(criteria.ReasonDeviceUnauthorized):
|
||||
denyStatusCode = httputil.StatusDeviceUnauthorized
|
||||
denyStatusText = httputil.DetailsText(httputil.StatusDeviceUnauthorized)
|
||||
|
@ -122,42 +120,36 @@ func (a *Authorize) deniedResponse(
|
|||
in *envoy_service_auth_v3.CheckRequest,
|
||||
code int32, reason string, headers map[string]string,
|
||||
) (*envoy_service_auth_v3.CheckResponse, error) {
|
||||
respBody := []byte(reason)
|
||||
respHeader := []*envoy_config_core_v3.HeaderValueOption{}
|
||||
|
||||
forwardAuthURL, _ := a.currentOptions.Load().GetForwardAuthURL()
|
||||
if forwardAuthURL == nil {
|
||||
// create a http response writer recorder
|
||||
w := httptest.NewRecorder()
|
||||
r := getHTTPRequestFromCheckRequest(in)
|
||||
// create a http response writer recorder
|
||||
w := httptest.NewRecorder()
|
||||
r := getHTTPRequestFromCheckRequest(in)
|
||||
|
||||
// build the user info / debug endpoint
|
||||
debugEndpoint, _ := a.userInfoEndpointURL(in) // if there's an error, we just wont display it
|
||||
// build the user info / debug endpoint
|
||||
debugEndpoint, _ := a.userInfoEndpointURL(in) // if there's an error, we just wont display it
|
||||
|
||||
// run the request through our go error handler
|
||||
httpErr := httputil.HTTPError{
|
||||
Status: int(code),
|
||||
Err: errors.New(reason),
|
||||
DebugURL: debugEndpoint,
|
||||
RequestID: requestid.FromContext(ctx),
|
||||
BrandingOptions: a.currentOptions.Load().BrandingOptions,
|
||||
}
|
||||
httpErr.ErrorResponse(ctx, w, r)
|
||||
|
||||
// transpose the go http response writer into a envoy response
|
||||
resp := w.Result()
|
||||
defer resp.Body.Close()
|
||||
var err error
|
||||
respBody, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error(ctx).Err(err).Msg("error executing error template")
|
||||
return nil, err
|
||||
}
|
||||
// convert go headers to envoy headers
|
||||
respHeader = append(respHeader, toEnvoyHeaders(resp.Header)...)
|
||||
} else {
|
||||
respHeader = append(respHeader, mkHeader("Content-Type", "text/plain", false))
|
||||
// run the request through our go error handler
|
||||
httpErr := httputil.HTTPError{
|
||||
Status: int(code),
|
||||
Err: errors.New(reason),
|
||||
DebugURL: debugEndpoint,
|
||||
RequestID: requestid.FromContext(ctx),
|
||||
BrandingOptions: a.currentOptions.Load().BrandingOptions,
|
||||
}
|
||||
httpErr.ErrorResponse(ctx, w, r)
|
||||
|
||||
// transpose the go http response writer into a envoy response
|
||||
resp := w.Result()
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error(ctx).Err(err).Msg("error executing error template")
|
||||
return nil, err
|
||||
}
|
||||
// convert go headers to envoy headers
|
||||
respHeader = append(respHeader, toEnvoyHeaders(resp.Header)...)
|
||||
|
||||
// add any additional headers
|
||||
for k, v := range headers {
|
||||
|
@ -182,7 +174,6 @@ func (a *Authorize) requireLoginResponse(
|
|||
ctx context.Context,
|
||||
in *envoy_service_auth_v3.CheckRequest,
|
||||
request *evaluator.Request,
|
||||
isForwardAuthVerify bool,
|
||||
) (*envoy_service_auth_v3.CheckResponse, error) {
|
||||
opts := a.currentOptions.Load()
|
||||
state := a.state.Load()
|
||||
|
@ -191,7 +182,7 @@ func (a *Authorize) requireLoginResponse(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if !a.shouldRedirect(in) || isForwardAuthVerify {
|
||||
if !a.shouldRedirect(in) {
|
||||
return a.deniedResponse(ctx, in, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), nil)
|
||||
}
|
||||
|
||||
|
@ -223,7 +214,6 @@ func (a *Authorize) requireWebAuthnResponse(
|
|||
in *envoy_service_auth_v3.CheckRequest,
|
||||
request *evaluator.Request,
|
||||
result *evaluator.Result,
|
||||
isForwardAuthVerify bool,
|
||||
) (*envoy_service_auth_v3.CheckResponse, error) {
|
||||
opts := a.currentOptions.Load()
|
||||
state := a.state.Load()
|
||||
|
@ -232,7 +222,7 @@ func (a *Authorize) requireWebAuthnResponse(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if !a.shouldRedirect(in) || isForwardAuthVerify {
|
||||
if !a.shouldRedirect(in) {
|
||||
return a.deniedResponse(ctx, in, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,7 @@ func TestAuthorize_handleResult(t *testing.T) {
|
|||
&evaluator.Request{},
|
||||
&evaluator.Result{
|
||||
Allow: evaluator.NewRuleResult(false, criteria.ReasonUserUnauthenticated),
|
||||
},
|
||||
false)
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 302, int(res.GetDeniedResponse().GetStatus().GetCode()))
|
||||
|
||||
|
@ -47,8 +46,7 @@ func TestAuthorize_handleResult(t *testing.T) {
|
|||
&evaluator.Request{},
|
||||
&evaluator.Result{
|
||||
Deny: evaluator.NewRuleResult(false, criteria.ReasonUserUnauthenticated),
|
||||
},
|
||||
false)
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 302, int(res.GetDeniedResponse().GetStatus().GetCode()))
|
||||
})
|
||||
|
@ -191,8 +189,7 @@ func TestRequireLogin(t *testing.T) {
|
|||
t.Run("accept empty", func(t *testing.T) {
|
||||
res, err := a.requireLoginResponse(context.Background(),
|
||||
&envoy_service_auth_v3.CheckRequest{},
|
||||
&evaluator.Request{},
|
||||
false)
|
||||
&evaluator.Request{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusFound, int(res.GetDeniedResponse().GetStatus().GetCode()))
|
||||
})
|
||||
|
@ -209,8 +206,7 @@ func TestRequireLogin(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
&evaluator.Request{},
|
||||
false)
|
||||
&evaluator.Request{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusFound, int(res.GetDeniedResponse().GetStatus().GetCode()))
|
||||
})
|
||||
|
@ -227,8 +223,7 @@ func TestRequireLogin(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
&evaluator.Request{},
|
||||
false)
|
||||
&evaluator.Request{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusUnauthorized, int(res.GetDeniedResponse().GetStatus().GetCode()))
|
||||
})
|
||||
|
|
|
@ -43,18 +43,6 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v3.CheckRe
|
|||
hreq := getHTTPRequestFromCheckRequest(in)
|
||||
ctx = requestid.WithValue(ctx, requestid.FromHTTPHeader(hreq.Header))
|
||||
|
||||
isForwardAuth := a.isForwardAuth(in)
|
||||
if isForwardAuth {
|
||||
// update the incoming http request's uri to match the forwarded URI
|
||||
fwdAuthURI := urlutil.GetForwardAuthURL(hreq)
|
||||
in.Attributes.Request.Http.Scheme = fwdAuthURI.Scheme
|
||||
in.Attributes.Request.Http.Host = fwdAuthURI.Host
|
||||
in.Attributes.Request.Http.Path = fwdAuthURI.EscapedPath()
|
||||
if fwdAuthURI.RawQuery != "" {
|
||||
in.Attributes.Request.Http.Path += "?" + fwdAuthURI.RawQuery
|
||||
}
|
||||
}
|
||||
|
||||
sessionState, _ := state.sessionStore.LoadSessionState(hreq)
|
||||
|
||||
var s sessionOrServiceAccount
|
||||
|
@ -93,22 +81,7 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v3.CheckRe
|
|||
ctx = contextutil.WithPolicyEvaluationTraces(ctx, res.Traces)
|
||||
}
|
||||
|
||||
isForwardAuthVerify := isForwardAuth && hreq.URL.Path == "/verify"
|
||||
return a.handleResult(ctx, in, req, res, isForwardAuthVerify)
|
||||
}
|
||||
|
||||
// isForwardAuth returns if the current request is a forward auth route.
|
||||
func (a *Authorize) isForwardAuth(req *envoy_service_auth_v3.CheckRequest) bool {
|
||||
opts := a.currentOptions.Load()
|
||||
|
||||
forwardAuthURL, err := opts.GetForwardAuthURL()
|
||||
if err != nil || forwardAuthURL == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
checkURL := getCheckRequestURL(req)
|
||||
|
||||
return urlutil.StripPort(checkURL.Host) == urlutil.StripPort(forwardAuthURL.Host)
|
||||
return a.handleResult(ctx, in, req, res)
|
||||
}
|
||||
|
||||
func (a *Authorize) getEvaluatorRequestFromCheckRequest(
|
||||
|
|
|
@ -6,17 +6,13 @@ import (
|
|||
"testing"
|
||||
|
||||
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/atomicutil"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
)
|
||||
|
@ -102,161 +98,6 @@ func Test_getEvaluatorRequest(t *testing.T) {
|
|||
assert.Equal(t, expect, actual)
|
||||
}
|
||||
|
||||
func Test_handleForwardAuth(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
checkReq *envoy_service_auth_v3.CheckRequest
|
||||
forwardAuthURL string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "enabled",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/verify?uri=" + url.QueryEscape("https://example.com/some/path?qs=1"),
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "disabled",
|
||||
checkReq: nil,
|
||||
forwardAuthURL: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "honor x-forwarded-uri set",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/",
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
Headers: map[string]string{
|
||||
httputil.HeaderForwardedURI: "/foo/bar",
|
||||
httputil.HeaderForwardedProto: "https",
|
||||
httputil.HeaderForwardedHost: "example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "request with invalid forward auth url",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/verify?uri=" + url.QueryEscape("https://example.com?q=foo"),
|
||||
Host: "fake-forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "request with invalid path",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/foo?uri=" + url.QueryEscape("https://example.com?q=foo"),
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "request with empty uri",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/verify?uri=",
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "request with invalid uri",
|
||||
checkReq: &envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/verify?uri= http://example.com/foo",
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
forwardAuthURL: "https://forward-auth.example.com",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
a.currentOptions.Store(&config.Options{ForwardAuthURLString: tc.forwardAuthURL})
|
||||
|
||||
got := a.isForwardAuth(tc.checkReq)
|
||||
|
||||
if diff := cmp.Diff(got, tc.want); diff != "" {
|
||||
t.Errorf("Authorize.Check() = %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getEvaluatorRequestWithPortInHostHeader(t *testing.T) {
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
a.currentOptions.Store(&config.Options{
|
||||
|
@ -322,100 +163,6 @@ func (m mockDataBrokerServiceClient) Put(ctx context.Context, in *databroker.Put
|
|||
return m.put(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func TestAuthorize_Check(t *testing.T) {
|
||||
opt := config.NewDefaultOptions()
|
||||
opt.AuthenticateURLString = "https://authenticate.example.com"
|
||||
opt.DataBrokerURLString = "https://databroker.example.com"
|
||||
opt.SharedKey = "E8wWIMnihUx+AUfRegAQDNs8eRb3UrB5G3zlJW9XJDM="
|
||||
a, err := New(&config.Config{Options: opt})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.currentOptions.Store(&config.Options{ForwardAuthURLString: "https://forward-auth.example.com"})
|
||||
|
||||
cmpOpts := []cmp.Option{
|
||||
cmpopts.IgnoreUnexported(envoy_service_auth_v3.CheckResponse{}),
|
||||
cmpopts.IgnoreUnexported(status.Status{}),
|
||||
cmpopts.IgnoreTypes(envoy_service_auth_v3.DeniedHttpResponse{}),
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
in *envoy_service_auth_v3.CheckRequest
|
||||
want *envoy_service_auth_v3.CheckResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"basic deny",
|
||||
&envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Id: "id-1234",
|
||||
Method: "GET",
|
||||
Headers: map[string]string{
|
||||
"accept": "application/json",
|
||||
"x-forwarded-proto": "https",
|
||||
},
|
||||
Path: "/some/path?qs=1",
|
||||
Host: "example.com",
|
||||
Scheme: "http",
|
||||
Body: "BODY",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&envoy_service_auth_v3.CheckResponse{
|
||||
Status: &status.Status{Code: 7, Message: "Access Denied"},
|
||||
HttpResponse: &envoy_service_auth_v3.CheckResponse_DeniedResponse{
|
||||
DeniedResponse: &envoy_service_auth_v3.DeniedHttpResponse{},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"basic forward-auth deny",
|
||||
&envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Source: &envoy_service_auth_v3.AttributeContext_Peer{
|
||||
Certificate: url.QueryEscape(certPEM),
|
||||
},
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Method: "GET",
|
||||
Path: "/verify?uri=" + url.QueryEscape("https://example.com/some/path?qs=1"),
|
||||
Host: "forward-auth.example.com",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&envoy_service_auth_v3.CheckResponse{
|
||||
Status: &status.Status{Code: 7, Message: "Access Denied"},
|
||||
HttpResponse: &envoy_service_auth_v3.CheckResponse_DeniedResponse{
|
||||
DeniedResponse: &envoy_service_auth_v3.DeniedHttpResponse{},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := a.Check(context.TODO(), tt.in)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Authorize.Check() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, tt.want, cmpOpts...); diff != "" {
|
||||
t.Errorf("NewStore() = %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseURL(rawURL string) url.URL {
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
|
|
|
@ -84,86 +84,9 @@ func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, domain string
|
|||
b.buildControlPlanePathRoute("/", false),
|
||||
)
|
||||
}
|
||||
// if we're the proxy and this is the forward-auth url
|
||||
forwardAuthURL, err := options.GetForwardAuthURL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config.IsProxy(options.Services) && hostMatchesDomain(forwardAuthURL, domain) {
|
||||
// disable ext_authz and pass request to proxy handlers that enable authN flow
|
||||
r, err := b.buildControlPlanePathAndQueryRoute("/verify", []string{urlutil.QueryForwardAuthURI, urlutil.QuerySessionEncrypted, urlutil.QueryRedirectURI})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routes = append(routes, r)
|
||||
r, err = b.buildControlPlanePathAndQueryRoute("/", []string{urlutil.QueryForwardAuthURI, urlutil.QuerySessionEncrypted, urlutil.QueryRedirectURI})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routes = append(routes, r)
|
||||
r, err = b.buildControlPlanePathAndQueryRoute("/", []string{urlutil.QueryForwardAuthURI})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routes = append(routes, r)
|
||||
|
||||
// otherwise, enforce ext_authz; pass all other requests through to an upstream
|
||||
// handler that will simply respond with http status 200 / OK indicating that
|
||||
// the fronting forward-auth proxy can continue.
|
||||
r, err = b.buildControlPlaneProtectedPrefixRoute("/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routes = append(routes, r)
|
||||
}
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
func (b *Builder) buildControlPlaneProtectedPrefixRoute(prefix string) (*envoy_config_route_v3.Route, error) {
|
||||
return &envoy_config_route_v3.Route{
|
||||
Name: "pomerium-protected-prefix-" + prefix,
|
||||
Match: &envoy_config_route_v3.RouteMatch{
|
||||
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{Prefix: prefix},
|
||||
},
|
||||
Action: &envoy_config_route_v3.Route_Route{
|
||||
Route: &envoy_config_route_v3.RouteAction{
|
||||
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
||||
Cluster: httpCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Builder) buildControlPlanePathAndQueryRoute(path string, queryparams []string) (*envoy_config_route_v3.Route, error) {
|
||||
var queryParameterMatchers []*envoy_config_route_v3.QueryParameterMatcher
|
||||
for _, q := range queryparams {
|
||||
queryParameterMatchers = append(queryParameterMatchers,
|
||||
&envoy_config_route_v3.QueryParameterMatcher{
|
||||
Name: q,
|
||||
QueryParameterMatchSpecifier: &envoy_config_route_v3.QueryParameterMatcher_PresentMatch{PresentMatch: true},
|
||||
})
|
||||
}
|
||||
|
||||
return &envoy_config_route_v3.Route{
|
||||
Name: "pomerium-path-and-query" + path,
|
||||
Match: &envoy_config_route_v3.RouteMatch{
|
||||
PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{Path: path},
|
||||
QueryParameters: queryParameterMatchers,
|
||||
},
|
||||
Action: &envoy_config_route_v3.Route_Route{
|
||||
Route: &envoy_config_route_v3.RouteAction{
|
||||
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
||||
Cluster: httpCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
TypedPerFilterConfig: map[string]*any.Any{
|
||||
"envoy.filters.http.ext_authz": disableExtAuthz,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Builder) buildControlPlanePathRoute(path string, protected bool) *envoy_config_route_v3.Route {
|
||||
r := &envoy_config_route_v3.Route{
|
||||
Name: "pomerium-path-" + path,
|
||||
|
|
|
@ -82,7 +82,6 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
|||
Services: "all",
|
||||
AuthenticateURLString: "https://authenticate.example.com",
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
ForwardAuthURLString: "https://forward-auth.example.com",
|
||||
}
|
||||
routes, err := b.buildPomeriumHTTPRoutes(options, "authenticate.example.com")
|
||||
require.NoError(t, err)
|
||||
|
@ -116,7 +115,6 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
|||
Services: "all",
|
||||
AuthenticateURLString: "https://authenticate.example.com",
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
ForwardAuthURLString: "https://forward-auth.example.com",
|
||||
Policies: []config.Policy{{
|
||||
From: "https://from.example.com",
|
||||
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||
|
@ -143,7 +141,6 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
|||
Services: "all",
|
||||
AuthenticateURLString: "https://authenticate.example.com",
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
ForwardAuthURLString: "https://forward-auth.example.com",
|
||||
Policies: []config.Policy{{
|
||||
From: "https://from.example.com",
|
||||
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||
|
|
|
@ -222,14 +222,6 @@ type Options struct {
|
|||
GRPCClientTimeout time.Duration `mapstructure:"grpc_client_timeout" yaml:"grpc_client_timeout,omitempty"`
|
||||
GRPCClientDNSRoundRobin bool `mapstructure:"grpc_client_dns_roundrobin" yaml:"grpc_client_dns_roundrobin,omitempty"`
|
||||
|
||||
// ForwardAuthEndpoint allows for a given route to be used as a forward-auth
|
||||
// endpoint instead of a reverse proxy. Some third-party proxies that do not
|
||||
// have rich access control capabilities (nginx, envoy, ambassador, traefik)
|
||||
// allow you to delegate and authenticate each request to your website
|
||||
// with an external server or service. Pomerium can be configured to accept
|
||||
// these requests with this switch
|
||||
ForwardAuthURLString string `mapstructure:"forward_auth_url" yaml:"forward_auth_url,omitempty"`
|
||||
|
||||
// DataBrokerURLString is the routable destination of the databroker service's gRPC endpoint.
|
||||
DataBrokerURLString string `mapstructure:"databroker_service_url" yaml:"databroker_service_url,omitempty"`
|
||||
DataBrokerURLStrings []string `mapstructure:"databroker_service_urls" yaml:"databroker_service_urls,omitempty"`
|
||||
|
@ -602,13 +594,6 @@ func (o *Options) Validate() error {
|
|||
}
|
||||
}
|
||||
|
||||
if o.ForwardAuthURLString != "" {
|
||||
_, err := urlutil.ParseAndValidateURL(o.ForwardAuthURLString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: bad forward-auth-url %s : %w", o.ForwardAuthURLString, err)
|
||||
}
|
||||
}
|
||||
|
||||
if o.PolicyFile != "" {
|
||||
return errors.New("config: policy file setting is deprecated")
|
||||
}
|
||||
|
@ -823,15 +808,6 @@ func (o *Options) getURLs(strs ...string) ([]*url.URL, error) {
|
|||
return urls, nil
|
||||
}
|
||||
|
||||
// GetForwardAuthURL returns the ForwardAuthURL.
|
||||
func (o *Options) GetForwardAuthURL() (*url.URL, error) {
|
||||
rawurl := o.ForwardAuthURLString
|
||||
if rawurl == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return urlutil.ParseAndValidateURL(rawurl)
|
||||
}
|
||||
|
||||
// GetGRPCAddr gets the gRPC address.
|
||||
func (o *Options) GetGRPCAddr() string {
|
||||
// to avoid port collision when running on localhost
|
||||
|
@ -1114,11 +1090,6 @@ func (o *Options) GetAllRouteableHTTPDomains() ([]string, error) {
|
|||
// GetAllRouteableHTTPDomainsForTLSServerName returns all the possible HTTP domains handled by the Pomerium options
|
||||
// for the given TLS server name.
|
||||
func (o *Options) GetAllRouteableHTTPDomainsForTLSServerName(tlsServerName string) ([]string, error) {
|
||||
forwardAuthURL, err := o.GetForwardAuthURL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domains := sets.NewSorted[string]()
|
||||
if IsAuthenticate(o.Services) {
|
||||
authenticateURL, err := o.GetInternalAuthenticateURL()
|
||||
|
@ -1162,13 +1133,6 @@ func (o *Options) GetAllRouteableHTTPDomainsForTLSServerName(tlsServerName strin
|
|||
}
|
||||
}
|
||||
}
|
||||
if forwardAuthURL != nil {
|
||||
for _, h := range urlutil.GetDomainsForURL(*forwardAuthURL) {
|
||||
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||
domains.Add(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return domains.ToSlice(), nil
|
||||
|
@ -1457,9 +1421,6 @@ func (o *Options) ApplySettings(ctx context.Context, settings *config.Settings)
|
|||
if settings.GrpcInsecure != nil {
|
||||
o.GRPCInsecure = settings.GetGrpcInsecure()
|
||||
}
|
||||
if settings.ForwardAuthUrl != nil {
|
||||
o.ForwardAuthURLString = settings.GetForwardAuthUrl()
|
||||
}
|
||||
if len(settings.DatabrokerServiceUrls) > 0 {
|
||||
o.DataBrokerURLStrings = settings.GetDatabrokerServiceUrls()
|
||||
}
|
||||
|
|
|
@ -361,8 +361,6 @@ func Test_NewOptionsFromConfigEnvVar(t *testing.T) {
|
|||
{"no certs no insecure mode set", map[string]string{"SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, false},
|
||||
{"good disable headers ", map[string]string{"HEADERS": "disable:true", "INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, false},
|
||||
{"bad whitespace in secret", map[string]string{"INSECURE_SERVER": "true", "SERVICES": "authenticate", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM=\n"}, true},
|
||||
{"good forward auth url", map[string]string{"FORWARD_AUTH_URL": "https://databroker.example", "INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, false},
|
||||
{"bad forward auth url", map[string]string{"FORWARD_AUTH_URL": "databroker.example", "INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, true},
|
||||
{"same addr and grpc addr", map[string]string{"SERVICES": "databroker", "ADDRESS": "0", "GRPC_ADDRESS": "0", "INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, false},
|
||||
{"bad cert files", map[string]string{"INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM=", "CERTIFICATES": "./test-data/example-cert.pem"}, true},
|
||||
{"good cert file", map[string]string{"CERTIFICATE_FILE": "./testdata/example-cert.pem", "CERTIFICATE_KEY_FILE": "./testdata/example-key.pem", "INSECURE_SERVER": "true", "SHARED_SECRET": "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="}, false},
|
||||
|
@ -631,7 +629,6 @@ func TestOptions_DefaultURL(t *testing.T) {
|
|||
AuthenticateURLString: "https://authenticate.example.com",
|
||||
AuthorizeURLString: "https://authorize.example.com",
|
||||
DataBrokerURLString: "https://databroker.example.com",
|
||||
ForwardAuthURLString: "https://forwardauth.example.com",
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -641,11 +638,9 @@ func TestOptions_DefaultURL(t *testing.T) {
|
|||
{"default authenticate url", defaultOptions.GetAuthenticateURL, "https://127.0.0.1"},
|
||||
{"default authorize url", defaultOptions.GetAuthenticateURL, "https://127.0.0.1"},
|
||||
{"default databroker url", defaultOptions.GetAuthenticateURL, "https://127.0.0.1"},
|
||||
{"default forward auth url", defaultOptions.GetAuthenticateURL, "https://127.0.0.1"},
|
||||
{"good authenticate url", opts.GetAuthenticateURL, "https://authenticate.example.com"},
|
||||
{"good authorize url", firstURL(opts.GetAuthorizeURLs), "https://authorize.example.com"},
|
||||
{"good databroker url", firstURL(opts.GetDataBrokerURLs), "https://databroker.example.com"},
|
||||
{"good forward auth url", opts.GetForwardAuthURL, "https://forwardauth.example.com"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: pomerium/nginx-proxy:latest
|
||||
ports:
|
||||
- "443:443"
|
||||
volumes:
|
||||
# NOTE!!! : nginx must be supplied with your wildcard certificates.
|
||||
# see : https://github.com/jwilder/nginx-proxy#wildcard-certificates
|
||||
- ~/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer:/etc/nginx/certs/corp.beyondperimeter.com.crt:ro
|
||||
- ~/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key:/etc/nginx/certs/corp.beyondperimeter.com.key:ro
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
|
||||
pomerium-authenticate:
|
||||
image: pomerium/pomerium:latest # or `build: .` to build from source
|
||||
restart: always
|
||||
environment:
|
||||
- SERVICES=authenticate
|
||||
- INSECURE_SERVER=TRUE
|
||||
# NOTE!: Replace with your identity provider settings https://www.pomerium.com/docs/identity-providers.html
|
||||
# - IDP_PROVIDER=okta
|
||||
# - IDP_PROVIDER_URL=https://beyondperimeter.okta.com
|
||||
# - IDP_CLIENT_ID=REPLACE_ME
|
||||
# - IDP_CLIENT_SECRET=REPLACE_ME
|
||||
# NOTE! Generate new secret keys! e.g. `head -c32 /dev/urandom | base64`
|
||||
# Generated secret keys must match between services
|
||||
- SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M=
|
||||
- COOKIE_SECRET=V2JBZk0zWGtsL29UcFUvWjVDWWQ2UHExNXJ0b2VhcDI=
|
||||
# Tell nginx how to proxy pomerium's routes
|
||||
- VIRTUAL_PROTO=http
|
||||
- VIRTUAL_HOST=authenticate.corp.beyondperimeter.com
|
||||
- VIRTUAL_PORT=443
|
||||
- DATABROKER_SERVICE_URL=http://pomerium-databroker:443
|
||||
volumes:
|
||||
- ../config/config.example.yaml:/pomerium/config.yaml:ro
|
||||
|
||||
expose:
|
||||
- 443
|
||||
|
||||
pomerium-proxy:
|
||||
image: pomerium/pomerium:latest # or `build: .` to build from source
|
||||
restart: always
|
||||
environment:
|
||||
- SERVICES=proxy
|
||||
- INSECURE_SERVER=TRUE
|
||||
# IMPORTANT! If you are running pomerium behind another ingress (loadbalancer/firewall/etc)
|
||||
# you must tell pomerium proxy how to communicate using an internal hostname for RPC
|
||||
- AUTHORIZE_SERVICE_URL=http://pomerium-authorize:443
|
||||
# When communicating internally, rPC is going to get a name conflict expecting an external
|
||||
# facing certificate name (i.e. authenticate-service.local vs *.corp.example.com).
|
||||
- SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M=
|
||||
- COOKIE_SECRET=V2JBZk0zWGtsL29UcFUvWjVDWWQ2UHExNXJ0b2VhcDI=
|
||||
# Tell nginx how to proxy pomerium's routes
|
||||
- VIRTUAL_PROTO=http
|
||||
- VIRTUAL_HOST=*.corp.beyondperimeter.com
|
||||
- VIRTUAL_PORT=443
|
||||
volumes:
|
||||
- ../config/config.example.yaml:/pomerium/config.yaml:ro
|
||||
expose:
|
||||
- 443
|
||||
|
||||
pomerium-authorize:
|
||||
image: pomerium/pomerium:latest # or `build: .` to build from source
|
||||
restart: always
|
||||
environment:
|
||||
- SERVICES=authorize
|
||||
- SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M=
|
||||
- GRPC_INSECURE=TRUE
|
||||
- GRPC_ADDRESS=:443
|
||||
|
||||
volumes:
|
||||
# Retrieve non-secret config keys from the config file : https://www.pomerium.com/docs/reference/
|
||||
|
||||
# See `config.example.yaml` and modify to fit your needs.
|
||||
- ../config/config.example.yaml:/pomerium/config.yaml:ro
|
||||
expose:
|
||||
- 443
|
||||
|
||||
pomerium-databroker:
|
||||
image: pomerium/pomerium:latest # or `build: .` to build from source
|
||||
restart: always
|
||||
environment:
|
||||
- SERVICES=databroker
|
||||
- SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M=
|
||||
- GRPC_INSECURE=TRUE
|
||||
- GRPC_ADDRESS=:443
|
||||
volumes:
|
||||
# Retrieve non-secret config keys from the config file : https://www.pomerium.com/docs/reference/
|
||||
|
||||
# See `config.example.yaml` and modify to fit your needs.
|
||||
- ../config/config.example.yaml:/pomerium/config.yaml:ro
|
||||
expose:
|
||||
- 443
|
||||
|
||||
# https://verify.corp.beyondperimeter.com
|
||||
verify:
|
||||
image: pomerium/verify:latest
|
||||
expose:
|
||||
- 80
|
||||
# https://hello.corp.beyondperimeter.com
|
||||
hello:
|
||||
image: gcr.io/google-samples/hello-app:1.0
|
||||
expose:
|
||||
- 8080
|
|
@ -28,8 +28,8 @@ echo "=> install pomerium with helm"
|
|||
helm install \
|
||||
pomerium \
|
||||
pomerium/pomerium \
|
||||
--set ingress.secret.cert="$(base64 -i $HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer)" \
|
||||
--set ingress.secret.key="$(base64 -i $HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key)" \
|
||||
--set ingress.secret.cert="$(base64 -i "$HOME"/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer)" \
|
||||
--set ingress.secret.key="$(base64 -i "$HOME"/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key)" \
|
||||
--values docs/configuration/examples/kubernetes/values.yaml
|
||||
|
||||
# When done, clean up by deleting the cluster!
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Pomerium as external auth provider for Nginx
|
||||
|
||||
Run this demo locally on your docker-compose capable workstation, or replace `localhost.pomerium.io` with your own domain if running on a server.
|
||||
|
||||
## Includes
|
||||
|
||||
- Authentication and Authorization managed by pomerium
|
||||
- Routing / reverse proxying handled by nginx
|
||||
|
||||
## How
|
||||
|
||||
- Update `config.yaml` for your e-mail address, if not using gmail/google.
|
||||
- Replace secrets in `config.yaml`.
|
||||
- Run `docker-compose up` from this directory.
|
||||
- Navigate to `https://verify.localhost.pomerium.io`
|
||||
- ???
|
||||
- Profit
|
|
@ -1,28 +0,0 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXfeTmeNmQFK3r
|
||||
CrLcdh9pVrsSjbNOAP2BIQ3AfGdf/S0UqjU1UhXOb2gLm5Dsj/vFvs/fSkiahBdj
|
||||
7zR1dh7jdOnf3QgcAjIMTo7sJggsABHBF0vHVMXJtNoWmZ+AYOirsn22N3EoUNmX
|
||||
jlr19LnW07DtkHJFPYsYFy01uOEKGbzKQh8E6DFv3tPNp/raUHkGSAUpT11tZcdf
|
||||
vbSHuSN4xzGOs6T9QCnu0wCGb2MJNa8l5dhtVuy59jcZWM2i4EBLnXsYbHhkg/uZ
|
||||
xnVfm3YxgNM8bA2T1DqSUxjpLt7Dty9MHBaEyHVrH/nXYluF1wI7jNC2A7dE6VKq
|
||||
AkSmFKG7AgMBAAECggEARCYmW9TgSTahAfIyOpKIwJGTO/zgNc0OXuYLKVKuhqbU
|
||||
uPJTPXemOdD1wKYEISwv3YvIxb8CUwtvMkWV+4fNoPV6eTe3ttPi7A10Ga61auTi
|
||||
uIQbjQB8RJwTVI5k6P681n/uTdAe0zcueUWl8p7gntX34EmMOeWKtaWuwIylbsG8
|
||||
Ftvls8dI/soHUBgZT9HHo3ZitaRQtDYN+YjqAWfQCtPFrBJ5TPS9W6z3cmB/2l19
|
||||
nkwZljomj+mJZseEStQUOH/YXf7jpZCWNuxj9l9C+/F5pmiQX6w87thohVXFPmXx
|
||||
zEExPHePvThx4CxrUGyBeWfzUaYMfzx1T/gyMixDYQKBgQD642G2ElXQSnlZZoLf
|
||||
gMYTazAjtv7PIRVcVjOJfUORx5LP4sV7CkWokIMdbzfiVkerWt6kb2HDhBskvdFW
|
||||
ag6Fl8t/Miyi+ZTrE/PmZJqs7fGtmSqjY8wWKfcN6gyTPkh789DXU7ddJIiJLQ10
|
||||
sf5Mg2sQkMLQo5XnnauV/SmKiQKBgQDb4eL/MmSR7yKnjxjvek7xXJGqaEXBmazn
|
||||
pUhp6B+7aHsAg/u71DjzirMn2Ra3+WQ+sDQwbkMQuokqBPUij0Bcv61QSaocjrnb
|
||||
PmwtXlHeyk9RnGj60oW55gIuJw0EseI17IaqHJPyDNVCQ9WJteI4y8Da+m0E5ohZ
|
||||
udXzk9DpIwKBgCK3xnS4ktFxDNvXOLMPEdnsEkxO7XHiRR9y+kzDXc9Vi7ZizisZ
|
||||
n8wUu2AeXOBgSiinOXoNw7yXkl4COm633GyWNd3TJqQi332sVCsErvbRMolwUZss
|
||||
mzhR9FMjmTvi+YrVkYfKmOw1uwMojd0hKGyUHwO61IqkqIDVq8Hkt5PpAoGBAMlH
|
||||
RdwF7ToJhdeMjm7pr0oSSuWK/g/y9Ow3yMnpyuJrCe2248FUy61k0gswFjPi/3jD
|
||||
I4MR7CJsHxNv5lX0fB5q9+P/CtGJdWjVA4GkTZ175I/4dcDk5bT+cBB/ftNFYqWq
|
||||
Frux3Vw9kxpNrjOZY7RKEAhkJVfPEBHSo5+NODexAoGAXohoO9jOeLtYFOYRdKxj
|
||||
bbL7fwiR+ecBakiuakoIFc+ibH57fDvxA6YkbLFOVNrpsTVNIbgO9Jois3GhrEGH
|
||||
8TbGfohpmwC7nZ62aFJSNxD48gYvYzMamo0WymM1uH3jwlJY/kVO6KHopcN8+kQS
|
||||
/zG8+V/OgnBBvyfWWX8ygio=
|
||||
-----END PRIVATE KEY-----
|
|
@ -1,24 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEAjCCAmqgAwIBAgIRAJGdiQDsLfchZYUtx06mQpswDQYJKoZIhvcNAQELBQAw
|
||||
RTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMQ0wCwYDVQQLEwR0ZXN0
|
||||
MRQwEgYDVQQDEwtta2NlcnQgdGVzdDAeFw0xOTA2MDEwMDAwMDBaFw0zMDA4MjQx
|
||||
OTQyNTBaMDgxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0
|
||||
ZTENMAsGA1UECxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
ANd95OZ42ZAUresKstx2H2lWuxKNs04A/YEhDcB8Z1/9LRSqNTVSFc5vaAubkOyP
|
||||
+8W+z99KSJqEF2PvNHV2HuN06d/dCBwCMgxOjuwmCCwAEcEXS8dUxcm02haZn4Bg
|
||||
6KuyfbY3cShQ2ZeOWvX0udbTsO2QckU9ixgXLTW44QoZvMpCHwToMW/e082n+tpQ
|
||||
eQZIBSlPXW1lx1+9tIe5I3jHMY6zpP1AKe7TAIZvYwk1ryXl2G1W7Ln2NxlYzaLg
|
||||
QEudexhseGSD+5nGdV+bdjGA0zxsDZPUOpJTGOku3sO3L0wcFoTIdWsf+ddiW4XX
|
||||
AjuM0LYDt0TpUqoCRKYUobsCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud
|
||||
JQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU0t8UaNj7
|
||||
xry1h0qnTAm8Sxv69aMwIgYDVR0RBBswGYIXKi5sb2NhbGhvc3QucG9tZXJpdW0u
|
||||
aW8wDQYJKoZIhvcNAQELBQADggGBAJhOdplKGoR7/83qDjELdjhaoecZASqs5M+P
|
||||
Sxm7z5s+KSbElebw6/rHJciKAlT9tqHQO6CqliQ9hl4AHWxi+cjpwfxyqWn/VGIa
|
||||
4WoGyInd/I2PDne+5bIj0MXkikilk5NsJtypvGGjZJTF2T07QfXLlLi3nYTMHYzt
|
||||
TLZpu7vK+B2ZGCGG4o9pws5ZFjtuOXEDGsE1APPp3xjvC/uJt2xgqo4XcRGIVHgm
|
||||
mY2yi5KmUCAv0HHdDjxZoqEDazv8t/VuPc3hJcuUcIBZvyMFyPNMqN5ePI7D5TkD
|
||||
zOqW28I8jpB5zdDpCr4qXsU+Cf+4fB0jDncBq95n1v8EJsm7zeTIFZNgLv3ISthF
|
||||
lGEFS1zv+ybCOYPl3H0yd13S6N4QUHbESXHvZ2l2V1qDiKrfFcVhQ5ZEDD7/HDqT
|
||||
N+v7zzMOzmPNCSiky1lMMj/vP87AjaliJnvBcT4F5iU867ws/Refh+yege2l6roO
|
||||
LEM1YmdMYuNFbCsS2BbQsK9mbDkcmQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -1,26 +0,0 @@
|
|||
# Main configuration flags : https://www.pomerium.com/docs/reference/
|
||||
|
||||
pomerium_debug: true
|
||||
address: :80
|
||||
cookie_secret: YVFTMIfW8yBJw+a6sYwdW8rHbU+IAAV/SUkCTg9Jtpo=
|
||||
shared_secret: 80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ=
|
||||
|
||||
idp_provider: "google"
|
||||
idp_client_id: REPLACEME
|
||||
idp_client_secret: REPLACEME
|
||||
|
||||
insecure_server: true
|
||||
forward_auth_url: http://fwdauth.localhost.pomerium.io
|
||||
authenticate_service_url: https://authenticate.localhost.pomerium.io
|
||||
|
||||
routes:
|
||||
- from: https://verify.localhost.pomerium.io
|
||||
to: http://verify:8000
|
||||
policy:
|
||||
- allow:
|
||||
or:
|
||||
- domain:
|
||||
is: pomerium.com
|
||||
- domain:
|
||||
is: gmail.com
|
||||
pass_identity_headers: true
|
|
@ -1,29 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
# to emulate nginx-ingress behavior, use openresty which comes with 'escaped_request_uri'
|
||||
# pre-compiled. Also uncomment lines marked `uncomment to emulate nginx-ingress behavior`
|
||||
# in the nginx `.conf` configuration files.
|
||||
# image: openresty/openresty
|
||||
image: nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./verify.conf:/etc/nginx/conf.d/verify.conf
|
||||
- ./pomerium.conf:/etc/nginx/conf.d/pomerium.conf
|
||||
- ./_wildcard.localhost.pomerium.io.pem:/etc/nginx/nginx.pem
|
||||
- ./_wildcard.localhost.pomerium.io-key.pem:/etc/nginx/nginx-key.pem
|
||||
- ./proxy.conf:/etc/nginx/proxy.conf
|
||||
|
||||
verify:
|
||||
image: pomerium/verify
|
||||
expose:
|
||||
- 8000
|
||||
pomerium:
|
||||
image: pomerium/pomerium:latest
|
||||
volumes:
|
||||
- ./config.yaml:/pomerium/config.yaml:ro
|
||||
expose:
|
||||
- 80
|
|
@ -1,18 +0,0 @@
|
|||
# Pomerium endpoint
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name authenticate.localhost.pomerium.io fwdauth.localhost.pomerium.io;
|
||||
ssl_certificate /etc/nginx/nginx.pem;
|
||||
ssl_certificate_key /etc/nginx/nginx-key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://pomerium;
|
||||
include /etc/nginx/proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
# Define an upstream so that we don't need resolvers when we use variables in proxy_pass directives
|
||||
# https://stackoverflow.com/questions/17685674/nginx-proxy-pass-with-remote-addr
|
||||
upstream pomerium {
|
||||
server pomerium;
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
set $pass_access_scheme $scheme;
|
||||
|
||||
set $pass_server_port $server_port;
|
||||
|
||||
set $best_http_host $http_host;
|
||||
set $pass_port $pass_server_port;
|
||||
|
||||
set $proxy_alternative_upstream_name "";
|
||||
|
||||
client_max_body_size 1m;
|
||||
|
||||
|
||||
proxy_set_header Host $best_http_host;
|
||||
|
||||
# Pass the extracted client certificate to the backend
|
||||
|
||||
# Allow websocket connections
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
|
||||
proxy_set_header Connection "";
|
||||
|
||||
# uncomment to emulate nginx-ingress
|
||||
# set_escape_uri $escaped_request_uri $request_uri;
|
||||
|
||||
# proxy_set_header X-Request-ID $req_id;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Host $best_http_host;
|
||||
proxy_set_header X-Forwarded-Port $pass_port;
|
||||
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
|
||||
|
||||
proxy_set_header X-Scheme $pass_access_scheme;
|
||||
|
||||
# Pass the original X-Forwarded-For
|
||||
proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
|
||||
|
||||
# mitigate HTTPoxy Vulnerability
|
||||
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
|
||||
proxy_set_header Proxy "";
|
||||
|
||||
# Custom headers to proxied server
|
||||
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 4 4k;
|
||||
|
||||
proxy_max_temp_file_size 1024m;
|
||||
|
||||
proxy_request_buffering on;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_cookie_domain off;
|
||||
proxy_cookie_path off;
|
||||
|
||||
# In case of errors try the next upstream server before returning an error
|
||||
proxy_next_upstream error timeout;
|
||||
proxy_next_upstream_timeout 0;
|
||||
proxy_next_upstream_tries 3;
|
||||
|
||||
proxy_redirect off;
|
|
@ -1,40 +0,0 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCub8x6MRI1aWZV
|
||||
k7qfpQn7CK6fCHNceBhSQFMHBJXQLEAe34uNgF1h+NQGM2zaKDZ8hIsRNZq0dV/g
|
||||
Xyd7AMA5C8DyyHfqzoiHJeTXKoqGEmi/MyXfnHr6N4rQpoG97SbACKYfNOh/MD05
|
||||
gIg51LrbTK1GzFyg0AVntsvmm3r3NNHv/BJKVKV+2HZx1D83xcBstdLDAPdtmU3z
|
||||
STzixQYDTlzs1gUrJPfJAi1sAMM/RbDKTmgsYJopxADRYldOIvZEZqPrupInUi4v
|
||||
iFEosb0dpSSeHkKBgVl81X2ro+WH4vgfoeGkpu6mh67FfN1WljMf63E6yOEBcqxE
|
||||
+Vc9O+ysruODnma1d+DfXoHoZInUhzUM7nTdbsftmb0C5bFA3ts16WGZ1g21Hi7m
|
||||
NH2MdW2hLyRngAU9AHTWObdBxb4MBmBSF5ZIElcsfLABilHG508L2ZYM+uqOb0iW
|
||||
AMcVyrli7EaDEOF/oUv7WsDAekwGKKfy9exfWhw7+yn+UYG4oPUCAwEAAQKCAYAx
|
||||
e5d2xjrTGf4koo6bQPcO1kyq4nvPLGZB1ut2ny9caWEbIPD2iAZ1h1+mDqp/TE8A
|
||||
jZzhmeIz9OPowzVw6CqfRB1NAd86pbIHHJHJE9FN7ST3sCu7PimIl37yZ3mAhiiq
|
||||
6wks6xZVFjsX98UtGpKTKTIyVkCkgb42yJ0Y4txECiDPwiLyIQb9b6xR6BKy4I8Q
|
||||
h5etJ7YIyidZr1ntPlTRVUZ5DNFUht0fkVWPQLwiU8Ot8AYPKKwy0t4kh5Aao0Hf
|
||||
CDQP6Y5/XXKLl5bNi/SO5eg6jk3DnILwPkjXM3tVxcag+KmMc4GfVmVVDP+QkmVl
|
||||
LtGOHuBeyicdC5/jt6xMwbsEdY/YFjlO4WDH/5e8F7KG1X3OjTmqwdNjSNg4rXni
|
||||
u0ZEG+/o80ha21lCys+QpQ9PQmYPaGlzVPY9z0F6JsAlXNbNRIIOsJNEKlAICWXF
|
||||
9YyAaD8pV60UhK67q5wZ3uxyAjplM5+930asL5MPgb4BEvRY4bWlOe55lySXsbUC
|
||||
gcEA0HnqdCQBfmiylZv4Uh8JVojSZcZFtFU8V02TY/XrWjwzWv8z1ZXnzx18kAz7
|
||||
islThqlvr38HXwFfUNDhI/IIp+8zcvT9T56e1T8jYxhcaTZBEZ7XlG/jWbWbRx/k
|
||||
JEctixh7J5EhbsxhC7TfuH9lQ2r50WvmmrGpLoqHDe5fyKFTpbUkrGB19idiw9oI
|
||||
awjxOgN+uRrTFjuOPhxgfSwJGwPnE0my8lS/5fPvNUuQdWecqEe3CTFjVXY44IzB
|
||||
7W9HAoHBANYzbsNClt8HgLyp0XZg4W19BuCic6qJZhOSVoUlGFTTa2dTQnSfq5NL
|
||||
O1GCfZ/fy0QZvvBebf+Mf3WycEv/BbxRT0lDP0QjdamHkn9mGK+ODmYxvPu7Lqk9
|
||||
5acrXM8uXuK4bkT2eXKE2H7x9jrnxpSI/zE3cwic+GlQWH85ywAKwT07g3BiM5GJ
|
||||
pHpoJGwxraBUDb6HPTgTsVzPtvCbKqYw9uUalPDGI1Pc0iEitT5s41HT57P10hnD
|
||||
gOkIyOXj4wKBwEBQfC3cNcHDluRku5TKEl1p1E6lfjeF3Bmqyv+ZjEPIMqet91W6
|
||||
60qP9C+Ucb19IpF2kAf6DlIW4ErURcCLGHSGbL7YKZV4f9OVqNsXVtr2a9h9wk/+
|
||||
vIqeZgrpIb63Xqt8n/Gy6jd+QaoU4LfQRXMo+2zJ9theWq0K+2Mm2NHSQzXpziiH
|
||||
kZygxe1ZxCMRHSoijeOZDOnc8aLjqjizbxOwfocKw3PTBWhxeqhcaXJuxnt7tFHX
|
||||
tKdW03Eiu2j+XQKBwQCdyCcX1+4wfWNcFa9Aht6m+wjc4W1YOnuhgRMQYqHIoi+k
|
||||
XdU++Pq2th0MzpVg9cXR9TEL+FMIgeLFvNoxcLo13KMNsWZh98jNRxsnkvouHvMG
|
||||
Xi76MwiNDBYljLCBwIOOeBJp5DDTpX2gDPW2sFI7yapJA7JNrurhEJkPpm+dKU7s
|
||||
nvEUEJIx63Tn4dyqgfGGf0Pci9wReZgVaMA1/eZtovXLD0iVDy6osKlsVRey0xyj
|
||||
gvdTPYk1Byjm/1yU0scCgcEAgCzLcqc7O1t9kXNo48Lh+O3wtxYVZ0FTHAz0TtcR
|
||||
oVaRaok3aSEkCuZlBf4a9CJCKxzkDPg7dNNcUt5ng16XxJoEcIgf8FeS+BZS9L0O
|
||||
bLOQoAggW41OlRnX9yQIti9w/MR+qRzKSftTZcP8ySls4SCphlqsx/a7JXncgwI8
|
||||
QmML5MzfffKdB1RNs5yVWyzSsxHgmVGLcA9UziomcUPCrpXp10C/yzGnMPAyAwlo
|
||||
9k5AET80ZLKc7XYQ0NxI2yCf
|
||||
-----END PRIVATE KEY-----
|
|
@ -1,26 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWTCCAsGgAwIBAgIQBA3zYaPnHKhRmKC37lWvEjANBgkqhkiG9w0BAQsFADBF
|
||||
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExDTALBgNVBAsTBHRlc3Qx
|
||||
FDASBgNVBAMTC21rY2VydCB0ZXN0MB4XDTIwMDgyNDE5NDIwOVoXDTMwMDgyNDE5
|
||||
NDIwOVowRTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMQ0wCwYDVQQL
|
||||
EwR0ZXN0MRQwEgYDVQQDEwtta2NlcnQgdGVzdDCCAaIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggGPADCCAYoCggGBAK5vzHoxEjVpZlWTup+lCfsIrp8Ic1x4GFJAUwcEldAsQB7f
|
||||
i42AXWH41AYzbNooNnyEixE1mrR1X+BfJ3sAwDkLwPLId+rOiIcl5NcqioYSaL8z
|
||||
Jd+cevo3itCmgb3tJsAIph806H8wPTmAiDnUuttMrUbMXKDQBWe2y+abevc00e/8
|
||||
EkpUpX7YdnHUPzfFwGy10sMA922ZTfNJPOLFBgNOXOzWBSsk98kCLWwAwz9FsMpO
|
||||
aCxgminEANFiV04i9kRmo+u6kidSLi+IUSixvR2lJJ4eQoGBWXzVfauj5Yfi+B+h
|
||||
4aSm7qaHrsV83VaWMx/rcTrI4QFyrET5Vz077Kyu44OeZrV34N9egehkidSHNQzu
|
||||
dN1ux+2ZvQLlsUDe2zXpYZnWDbUeLuY0fYx1baEvJGeABT0AdNY5t0HFvgwGYFIX
|
||||
lkgSVyx8sAGKUcbnTwvZlgz66o5vSJYAxxXKuWLsRoMQ4X+hS/tawMB6TAYop/L1
|
||||
7F9aHDv7Kf5Rgbig9QIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/
|
||||
BAgwBgEB/wIBADAdBgNVHQ4EFgQU0t8UaNj7xry1h0qnTAm8Sxv69aMwDQYJKoZI
|
||||
hvcNAQELBQADggGBAFZT6Zdg+tt+8t6Bo9Boe8uOKnqrCSuOCyMIajDLgijPRlHf
|
||||
iJRggRjGT2Ig7c0nzL5SfeuExoMPMUmkfNAKki3VhK7cxLijDtn4fOmyyW5OO7AT
|
||||
zwSmOyakHXq4ip3klysNGVPzxjwHBuK5rCdPa2X1WXN4PeM6NQvGZB34hQ1962om
|
||||
1gad4YardZ81fVLJfOlCtIPD87TSreVGxiawUIAAGWgDuVMouN4PvqTUyEmorgxi
|
||||
hSaiVDCSlS/nuW5fuOGzZ1Ko9UhbCsmO3bbLzXKcjuwKeyzgyjozHMyx5gUhhOFk
|
||||
kqDIuIven3j+uLke0WAK++Z11vM8fVn0wB80RqubuTbqJzvH3w0R/PWVd0yAMFNu
|
||||
Y2Z+AZ0OwMm9BtqfwoW5PZSIMF06q6IbLmuLEH/5dE9xDN0s5Ia8gn7ySYqso+62
|
||||
yJjURRgGJeXLkrjfeSav39D0bg+JCB7J63Z7BCz6/Jv1TL45yWbeMmtqFPH6nS5t
|
||||
25uIk/1regWTCajVMg==
|
||||
-----END CERTIFICATE-----
|
|
@ -1,70 +0,0 @@
|
|||
# Protected application
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl http2;
|
||||
|
||||
server_name verify.localhost.pomerium.io;
|
||||
ssl_certificate /etc/nginx/nginx.pem;
|
||||
ssl_certificate_key /etc/nginx/nginx-key.pem;
|
||||
|
||||
|
||||
location = /ext_authz {
|
||||
internal;
|
||||
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header X-Forwarded-Proto "";
|
||||
|
||||
proxy_set_header Host fwdauth.localhost.pomerium.io;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
|
||||
proxy_set_header X-Auth-Request-Redirect $request_uri;
|
||||
|
||||
proxy_buffering off;
|
||||
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 4 4k;
|
||||
proxy_request_buffering on;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_ssl_server_name on;
|
||||
proxy_pass_request_headers on;
|
||||
|
||||
client_max_body_size 1m;
|
||||
|
||||
# Pass the extracted client certificate to the auth provider
|
||||
|
||||
set $target http://pomerium/verify?uri=$scheme://$http_host$request_uri;
|
||||
|
||||
# uncomment to emulate nginx-ingress behavior
|
||||
# set $target http://pomerium/verify?uri=$scheme://$http_host$request_uri&rd=$pass_access_scheme://$http_host$escaped_request_uri;
|
||||
proxy_pass $target;
|
||||
}
|
||||
|
||||
location @authredirect {
|
||||
internal;
|
||||
add_header Set-Cookie $auth_cookie;
|
||||
|
||||
# uncomment to emulate nginx-ingress behavior
|
||||
# return 302 https://fwdauth.localhost.pomerium.io/?uri=$scheme://$host$request_uri&rd=$pass_access_scheme://$http_host$escaped_request_uri;
|
||||
|
||||
return 302
|
||||
https://fwdauth.localhost.pomerium.io/?uri=$scheme://$host$request_uri;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://verify:8000;
|
||||
|
||||
include /etc/nginx/proxy.conf;
|
||||
# If we get a 401, respond with a named location
|
||||
error_page 401 = @authredirect;
|
||||
# this location requires authentication
|
||||
auth_request /ext_authz;
|
||||
auth_request_set $auth_cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $auth_cookie;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
# Pomerium as forward-auth provider for Traefik on Kubernetes
|
||||
|
||||
Run this demo locally on your kubernetes capable workstation or:
|
||||
- use `kubectl port-forward service/traefik 80:80 443:443`
|
||||
- replace `localhost.pomerium.io` with your own domain
|
||||
|
||||
## Includes
|
||||
|
||||
- Authentication and Authorization managed by pomerium
|
||||
- Routing / reverse proxying handled by traefik
|
||||
- Installation using upstream `helm` charts
|
||||
|
||||
## How
|
||||
|
||||
- Update `values/pomerium.yaml` for your e-mail address, if not using gmail/google.
|
||||
- Replace IdP secrets in `values/pomerium.yaml`.
|
||||
- Run `./add_repos.sh` from this directory.
|
||||
- Run `./install.sh` from this directory.
|
||||
- Navigate to `https://hello.localhost.pomerium.io`
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash -x
|
||||
|
||||
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
helm repo add pomerium https://helm.pomerium.io
|
||||
helm repo add traefik https://containous.github.io/traefik-helm-chart
|
|
@ -1,10 +0,0 @@
|
|||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: auth
|
||||
spec:
|
||||
forwardAuth:
|
||||
address: https://pomerium-proxy.pomerium
|
||||
tls:
|
||||
insecureSkipVerify: true
|
||||
trustForwardHeader: true
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash -x
|
||||
|
||||
kubectl create namespace pomerium
|
||||
|
||||
# Create shared TLS secret
|
||||
kubectl create secret tls wildcard-tls \
|
||||
--namespace pomerium \
|
||||
--cert=_wildcard.localhost.pomerium.io.pem \
|
||||
--key=_wildcard.localhost.pomerium.io-key.pem
|
||||
|
||||
# Install Traefik helm chart
|
||||
helm upgrade --install --wait \
|
||||
--namespace pomerium \
|
||||
traefik traefik/traefik \
|
||||
--values values/traefik.yaml
|
||||
|
||||
# Install Pomerium helm chart
|
||||
helm upgrade --install --wait \
|
||||
--namespace pomerium \
|
||||
pomerium pomerium/pomerium \
|
||||
--values values/pomerium.yaml
|
||||
|
||||
# Create middleware
|
||||
kubectl --namespace pomerium apply -f crds/middleware.yaml
|
||||
|
||||
# Install hello app
|
||||
helm upgrade --install --wait \
|
||||
--namespace pomerium \
|
||||
--version 6.2.1 \
|
||||
hello bitnami/nginx \
|
||||
--values values/hello.yaml
|
|
@ -1,15 +0,0 @@
|
|||
ingress:
|
||||
enabled: true
|
||||
hosts:
|
||||
- name: hello.localhost.pomerium.io
|
||||
path: /
|
||||
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.middlewares: pomerium-auth@kubernetescrd
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
tls:
|
||||
- hosts:
|
||||
- hello.localhost.pomerium.io
|
||||
secretName: wildcard-tls
|
||||
service:
|
||||
type: ClusterIP
|
|
@ -1,27 +0,0 @@
|
|||
authenticate:
|
||||
idp:
|
||||
provider: REPLACEME
|
||||
url: REPLACEME
|
||||
clientID: REPLACEME
|
||||
clientSecret: REPLACEME
|
||||
|
||||
config:
|
||||
rootDomain: localhost.pomerium.io
|
||||
sharedSecret: R0+XRoGVpcoi4PfB8tMlvnrS5XUasO+D1frAEdYcYjs=
|
||||
cookieSecret: FLPCOQKigK5EQnyXlBhchl5fgzNKqi3ubtvOGt477Dg=
|
||||
generateTLS: true
|
||||
routes:
|
||||
- from: https://hello.localhost.pomerium.io
|
||||
to: http://hello-nginx
|
||||
policy:
|
||||
- allow:
|
||||
or:
|
||||
- domain:
|
||||
is: gmail.com
|
||||
ingress:
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
secretName: wildcard-tls
|
||||
forwardAuth:
|
||||
enabled: true
|
||||
internal: true
|
|
@ -1,3 +0,0 @@
|
|||
additionalArguments:
|
||||
- "--serverstransport.insecureskipverify=true"
|
||||
- "--entryPoints.websecure.forwardedHeaders.insecure"
|
|
@ -1,17 +0,0 @@
|
|||
# Pomerium as forward-auth provider for Traefik
|
||||
|
||||
Run this demo locally on your docker-compose capable workstation, or replace `localhost.pomerium.io` with your own domain if running on a server.
|
||||
|
||||
## Includes
|
||||
|
||||
- Authentication and Authorization managed by pomerium
|
||||
- Routing / reverse proxying handled by traefik
|
||||
|
||||
## How
|
||||
|
||||
- Update `config.yaml` for your e-mail address, if not using gmail/google.
|
||||
- Replace secrets in `config.yaml`.
|
||||
- Run `docker-compose up` from this directory.
|
||||
- Navigate to `https://verify.localhost.pomerium.io`
|
||||
- ???
|
||||
- Profit
|
|
@ -1,27 +0,0 @@
|
|||
# Main configuration flags : https://www.pomerium.com/docs/reference/
|
||||
|
||||
pomerium_debug: true
|
||||
address: :80
|
||||
cookie_secret: YVFTMIfW8yBJw+a6sYwdW8rHbU+IAAV/SUkCTg9Jtpo=
|
||||
shared_secret: 80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ=
|
||||
|
||||
idp_provider: "google"
|
||||
idp_client_id: REPLACEME
|
||||
idp_client_secret: REPLACEME
|
||||
|
||||
insecure_server: true
|
||||
forward_auth_url: http://pomerium
|
||||
authenticate_service_url: https://authenticate.localhost.pomerium.io
|
||||
jwt_claims_headers: email,groups,user
|
||||
|
||||
routes:
|
||||
- from: https://verify.localhost.pomerium.io
|
||||
to: https://httpbin
|
||||
policy:
|
||||
- allow:
|
||||
or:
|
||||
- domain:
|
||||
is: pomerium.io
|
||||
- domain:
|
||||
is: gmail.com
|
||||
pass_identity_headers: true
|
|
@ -1,44 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.1
|
||||
command:
|
||||
- "--accesslog=true"
|
||||
- "--api.insecure=true"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entryPoints.websecure.forwardedHeaders.insecure"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker=true"
|
||||
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
verify:
|
||||
image: pomerium/verify:latest
|
||||
labels:
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.authResponseHeaders=X-Pomerium-Claim-Email,X-Pomerium-Claim-User,X-Pomerium-Claim-Groups,X-Pomerium-Jwt-Assertion"
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.address=http://pomerium/"
|
||||
- "traefik.http.middlewares.pomerium.forwardauth.trustForwardHeader=true"
|
||||
|
||||
- "traefik.http.routers.verify.middlewares=pomerium@docker"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.verify.rule=Host(`verify.localhost.pomerium.io`)"
|
||||
- "traefik.http.routers.verify.entrypoints=websecure"
|
||||
- "traefik.http.routers.verify.tls=true"
|
||||
|
||||
pomerium:
|
||||
image: pomerium/pomerium:latest
|
||||
volumes:
|
||||
- ./config.yaml:/pomerium/config.yaml:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.pomerium.rule=Host(`authenticate.localhost.pomerium.io`)"
|
||||
- "traefik.http.routers.pomerium.entrypoints=websecure"
|
||||
- "traefik.http.routers.pomerium.tls=true"
|
||||
expose:
|
||||
- 80
|
|
@ -1,25 +0,0 @@
|
|||
# dashboard-forwardauth.ingress.yaml
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: dashboard-forwardauth
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
cert-manager.io/issuer: "letsencrypt-prod" # see `letsencrypt.issuer.yaml`
|
||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
||||
nginx.ingress.kubernetes.io/auth-url: "https://forwardauth.domain.example/verify?uri=$scheme://$host$request_uri"
|
||||
nginx.ingress.kubernetes.io/auth-signin: "https://forwardauth.domain.example?uri=$scheme://$host$request_uri"
|
||||
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- dashboard-forwardauth.domain.example
|
||||
secretName: dashboard-forwardauth-tls
|
||||
rules:
|
||||
- host: dashboard-forwardauth.domain.example
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: helm-dashboard-kubernetes-dashboard
|
||||
servicePort: https
|
|
@ -18,20 +18,12 @@ func TestAuthorization(t *testing.T) {
|
|||
accessType := []string{"direct", "api"}
|
||||
for _, at := range accessType {
|
||||
t.Run(at, func(t *testing.T) {
|
||||
var withAPI, withForwardAuth flows.AuthenticateOption
|
||||
var withAPI flows.AuthenticateOption
|
||||
|
||||
if at == "api" {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
withAPI = flows.WithAPI()
|
||||
}
|
||||
|
||||
if ClusterType == "nginx" {
|
||||
withForwardAuth = flows.WithForwardAuth(true)
|
||||
}
|
||||
|
||||
t.Run("public", func(t *testing.T) {
|
||||
client := getClient()
|
||||
|
||||
|
@ -53,7 +45,7 @@ func TestAuthorization(t *testing.T) {
|
|||
t.Run("allowed", func(t *testing.T) {
|
||||
client := getClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||
withAPI, withForwardAuth, flows.WithEmail("user1@dogs.test"))
|
||||
withAPI, flows.WithEmail("user1@dogs.test"))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for dogs.test")
|
||||
}
|
||||
|
@ -61,7 +53,7 @@ func TestAuthorization(t *testing.T) {
|
|||
t.Run("not allowed", func(t *testing.T) {
|
||||
client := getClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||
withAPI, withForwardAuth, flows.WithEmail("user1@cats.test"))
|
||||
withAPI, flows.WithEmail("user1@cats.test"))
|
||||
if assert.NoError(t, err) {
|
||||
assertDeniedAccess(t, res, "expected Forbidden for cats.test, but got: %d", res.StatusCode)
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -48,11 +48,6 @@ func TestDashboard(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHealth(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer clearTimeout()
|
||||
|
||||
|
|
|
@ -13,16 +13,14 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/integration/forms"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
const (
|
||||
authenticateHostname = "authenticate.localhost.pomerium.io"
|
||||
forwardAuthenticateHostname = "forward-authenticate.localhost.pomerium.io"
|
||||
idpHostname = "mock-idp.localhost.pomerium.io"
|
||||
pomeriumCallbackPath = "/.pomerium/callback/"
|
||||
pomeriumAPIPath = "/.pomerium/api/v1/login"
|
||||
authenticateHostname = "authenticate.localhost.pomerium.io"
|
||||
idpHostname = "mock-idp.localhost.pomerium.io"
|
||||
pomeriumCallbackPath = "/.pomerium/callback/"
|
||||
pomeriumAPIPath = "/.pomerium/api/v1/login"
|
||||
)
|
||||
|
||||
type authenticateConfig struct {
|
||||
|
@ -30,7 +28,6 @@ type authenticateConfig struct {
|
|||
groups []string
|
||||
tokenExpiration time.Duration
|
||||
apiPath string
|
||||
forwardAuth bool
|
||||
}
|
||||
|
||||
// An AuthenticateOption is an option for authentication.
|
||||
|
@ -48,13 +45,6 @@ func getAuthenticateConfig(options ...AuthenticateOption) *authenticateConfig {
|
|||
return cfg
|
||||
}
|
||||
|
||||
// WithForwardAuth enables/disables forward auth.
|
||||
func WithForwardAuth(fa bool) AuthenticateOption {
|
||||
return func(cfg *authenticateConfig) {
|
||||
cfg.forwardAuth = fa
|
||||
}
|
||||
}
|
||||
|
||||
// WithEmail sets the email to use.
|
||||
func WithEmail(email string) AuthenticateOption {
|
||||
return func(cfg *authenticateConfig) {
|
||||
|
@ -145,7 +135,7 @@ func Authenticate(ctx context.Context, client *http.Client, url *url.URL, option
|
|||
}
|
||||
|
||||
// (2) redirect to idp
|
||||
for req.URL.Hostname() == authenticateHostname || req.URL.Hostname() == forwardAuthenticateHostname {
|
||||
for req.URL.Hostname() == authenticateHostname {
|
||||
res, err = client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -201,34 +191,10 @@ func Authenticate(ctx context.Context, client *http.Client, url *url.URL, option
|
|||
}
|
||||
|
||||
// (5) finally to callback
|
||||
if !cfg.forwardAuth && req.URL.Path != pomeriumCallbackPath {
|
||||
if req.URL.Path != pomeriumCallbackPath {
|
||||
return nil, fmt.Errorf("expected to redirect 5 back to %s, but got %s", pomeriumCallbackPath, req.URL.String())
|
||||
}
|
||||
|
||||
if cfg.forwardAuth {
|
||||
for i := 0; ; i++ {
|
||||
res, err = client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != 302 {
|
||||
break
|
||||
}
|
||||
originalURL := req.URL.String()
|
||||
req, err = requestFromRedirectResponse(ctx, res, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected redirect to %s: %w", originalHostname, err)
|
||||
}
|
||||
log.Info(ctx).
|
||||
Int("count", i).
|
||||
Str("from", originalURL).
|
||||
Str("to", req.URL.String()).
|
||||
Msg("forward-auth redirect")
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
res, err = client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -53,11 +53,6 @@ func TestQueryStringParams(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCORS(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
|
||||
defer clearTimeout()
|
||||
|
@ -97,11 +92,6 @@ func TestCORS(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPreserveHostHeader(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
|
||||
defer clearTimeout()
|
||||
|
@ -159,11 +149,6 @@ func TestPreserveHostHeader(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetRequestHeaders(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
|
||||
defer clearTimeout()
|
||||
|
@ -221,11 +206,6 @@ func TestRemoveRequestHeaders(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWebsocket(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
|
||||
defer clearTimeout()
|
||||
|
@ -290,11 +270,6 @@ func TestGoogleCloudRun(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLoadBalancer(t *testing.T) {
|
||||
if ClusterType == "traefik" || ClusterType == "nginx" {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Minute*10)
|
||||
defer clearTimeout()
|
||||
|
||||
|
|
|
@ -1,184 +0,0 @@
|
|||
local utils = import '../utils.libsonnet';
|
||||
local Routes = (import './routes.libsonnet').Routes;
|
||||
|
||||
local ProxyConfig() =
|
||||
|||
|
||||
set $pass_access_scheme $scheme;
|
||||
set $pass_server_port $server_port;
|
||||
set $best_http_host $http_host;
|
||||
set $pass_port $pass_server_port;
|
||||
set $proxy_alternative_upstream_name "";
|
||||
client_max_body_size 1m;
|
||||
proxy_set_header Host $best_http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Host $best_http_host;
|
||||
proxy_set_header X-Forwarded-Port $pass_port;
|
||||
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
|
||||
proxy_set_header X-Scheme $pass_access_scheme;
|
||||
proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
|
||||
proxy_set_header Proxy "";
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_buffering off;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 4 4k;
|
||||
proxy_max_temp_file_size 1024m;
|
||||
proxy_request_buffering on;
|
||||
proxy_http_version 1.1;
|
||||
proxy_cookie_domain off;
|
||||
proxy_cookie_path off;
|
||||
proxy_next_upstream error timeout;
|
||||
proxy_next_upstream_timeout 0;
|
||||
proxy_next_upstream_tries 3;
|
||||
proxy_redirect off;
|
||||
|||;
|
||||
|
||||
local AuthenticateConfig() =
|
||||
|||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name authenticate.localhost.pomerium.io forward-authenticate.localhost.pomerium.io;
|
||||
ssl_certificate /etc/_wildcard.localhost.pomerium.io.pem;
|
||||
ssl_certificate_key /etc/_wildcard.localhost.pomerium.io-key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://pomerium;
|
||||
include /etc/nginx/proxy.conf;
|
||||
}
|
||||
}
|
||||
upstream pomerium {
|
||||
server pomerium;
|
||||
}
|
||||
|||;
|
||||
|
||||
local AuthzConfig() =
|
||||
|||
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header X-Forwarded-Proto "";
|
||||
proxy_set_header Host forward-authenticate.localhost.pomerium.io;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Auth-Request-Redirect $request_uri;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_buffer_size 256k;
|
||||
proxy_buffers 4 256k;
|
||||
proxy_busy_buffers_size 256k;
|
||||
proxy_request_buffering on;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_ssl_server_name on;
|
||||
proxy_pass_request_headers on;
|
||||
|
||||
client_max_body_size 1m;
|
||||
|
||||
set $target http://pomerium/verify?uri=$scheme://$http_host$request_uri;
|
||||
proxy_pass $target;
|
||||
|||;
|
||||
|
||||
local RouteLocationConfig(route) =
|
||||
local rule =
|
||||
if std.objectHas(route, 'prefix') then '^~ ' + route.prefix
|
||||
else if std.objectHas(route, 'path') then '= ' + route.path
|
||||
else '/';
|
||||
local to =
|
||||
if std.isArray(route.to) then route.to[0]
|
||||
else route.to;
|
||||
|||
|
||||
location %s {
|
||||
proxy_pass %s;
|
||||
|
||||
include /etc/nginx/proxy.conf;
|
||||
# If we get a 401, respond with a named location
|
||||
error_page 401 = @authredirect;
|
||||
# this location requires authentication
|
||||
auth_request /ext_authz;
|
||||
auth_request_set $auth_cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $auth_cookie;
|
||||
}
|
||||
||| % [rule, to];
|
||||
|
||||
local DomainServerConfig(domain, routes) =
|
||||
local locations = std.join('\n', std.map(function(route) RouteLocationConfig(route), routes));
|
||||
|||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name %s;
|
||||
ssl_certificate /etc/_wildcard.localhost.pomerium.io.pem;
|
||||
ssl_certificate_key /etc/_wildcard.localhost.pomerium.io-key.pem;
|
||||
|
||||
location = /ext_authz {
|
||||
internal;
|
||||
include /etc/nginx/authz.conf;
|
||||
}
|
||||
|
||||
location @authredirect {
|
||||
internal;
|
||||
add_header Set-Cookie $auth_cookie;
|
||||
return 302 https://forward-authenticate.localhost.pomerium.io/?uri=$scheme://$host$request_uri;
|
||||
}
|
||||
|
||||
%s
|
||||
}
|
||||
||| % [domain, locations];
|
||||
|
||||
local RoutesConfig(mode, idp, dns_suffix) =
|
||||
local routes = Routes(mode, idp, dns_suffix);
|
||||
local domains = std.set(std.map(function(route) utils.ParseURL(route.from).host, routes));
|
||||
std.join('\n', [
|
||||
local routesForDomain = std.filter(function(route)
|
||||
local url = utils.ParseURL(route.from);
|
||||
url.host == domain && (url.scheme == 'http' || url.scheme == 'https'),
|
||||
routes);
|
||||
DomainServerConfig(domain, routesForDomain)
|
||||
for domain in domains
|
||||
]);
|
||||
|
||||
local WriteFile(path, contents) =
|
||||
|||
|
||||
cat <<-'END_OF_NGINX' | tee %s
|
||||
%s
|
||||
END_OF_NGINX
|
||||
||| % [path, std.strReplace(contents, '$', '$$')];
|
||||
|
||||
local Command(mode, idp, dns_suffix) =
|
||||
[
|
||||
'sh',
|
||||
'-c',
|
||||
std.join('\n\n', [
|
||||
WriteFile('/etc/nginx/conf.d/authenticate.conf', AuthenticateConfig()),
|
||||
WriteFile('/etc/nginx/conf.d/routes.conf', RoutesConfig(mode, idp, dns_suffix)),
|
||||
WriteFile('/etc/nginx/authz.conf', AuthzConfig()),
|
||||
WriteFile('/etc/nginx/proxy.conf', ProxyConfig()),
|
||||
WriteFile('/etc/_wildcard.localhost.pomerium.io.pem', importstr '../files/trusted.pem'),
|
||||
WriteFile('/etc/_wildcard.localhost.pomerium.io-key.pem', importstr '../files/trusted-key.pem'),
|
||||
"nginx -g 'daemon off;'",
|
||||
]),
|
||||
];
|
||||
|
||||
function(mode, idp, dns_suffix='') {
|
||||
local image = 'nginx:1.21.1',
|
||||
|
||||
compose: {
|
||||
services: utils.ComposeService('nginx', {
|
||||
image: image,
|
||||
depends_on: {
|
||||
'pomerium-ready': {
|
||||
condition: 'service_completed_successfully',
|
||||
},
|
||||
},
|
||||
entrypoint: Command(mode, idp, dns_suffix),
|
||||
ports: [
|
||||
'80:80/tcp',
|
||||
'443:443/tcp',
|
||||
],
|
||||
}, ['mock-idp.localhost.pomerium.io']),
|
||||
},
|
||||
}
|
|
@ -103,12 +103,6 @@ local Environment(mode, idp, dns_suffix) =
|
|||
DATABROKER_SERVICE_URL: 'https://pomerium-databroker:5443',
|
||||
GRPC_ADDRESS: ':5443',
|
||||
GRPC_INSECURE: 'false',
|
||||
} else if mode == 'traefik' then {
|
||||
FORWARD_AUTH_URL: 'https://forward-authenticate.localhost.pomerium.io',
|
||||
} else if mode == 'nginx' then {
|
||||
ADDRESS: ':80',
|
||||
INSECURE_SERVER: 'true',
|
||||
FORWARD_AUTH_URL: 'https://forward-authenticate.localhost.pomerium.io',
|
||||
} else {};
|
||||
|
||||
local ComposeService(name, definition, additionalAliases=[]) =
|
||||
|
@ -186,24 +180,6 @@ function(mode, idp, dns_suffix='') {
|
|||
'9901:9901/tcp',
|
||||
],
|
||||
}, ['mock-idp.localhost.pomerium.io'])
|
||||
else if mode == 'traefik' || mode == 'nginx' then
|
||||
ComposeService(name, {
|
||||
image: image,
|
||||
environment: environment,
|
||||
}, ['authenticate.localhost.pomerium.io', 'forward-authenticate.localhost.pomerium.io']) +
|
||||
ComposeService(name + '-ready', {
|
||||
image: 'powerman/dockerize:0.16.3',
|
||||
command: [
|
||||
'-skip-tls-verify',
|
||||
'-wait',
|
||||
if mode == 'nginx' then
|
||||
'http://' + name + ':80/healthz'
|
||||
else
|
||||
'https://' + name + ':443/healthz',
|
||||
'-timeout',
|
||||
'10m',
|
||||
],
|
||||
})
|
||||
else
|
||||
ComposeService(name, {
|
||||
image: image,
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
local utils = import '../utils.libsonnet';
|
||||
local Routes = (import './routes.libsonnet').Routes;
|
||||
|
||||
local StaticConfig() =
|
||||
{
|
||||
global: {
|
||||
checkNewVersion: false,
|
||||
sendAnonymousUsage: false,
|
||||
},
|
||||
log: {
|
||||
level: 'DEBUG',
|
||||
},
|
||||
accessLog: {},
|
||||
entryPoints: {
|
||||
web: {
|
||||
address: ':80',
|
||||
forwardedheaders: {
|
||||
insecure: true,
|
||||
},
|
||||
},
|
||||
websecure: {
|
||||
address: ':443',
|
||||
forwardedheaders: {
|
||||
insecure: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
api: {
|
||||
insecure: true,
|
||||
},
|
||||
providers: {
|
||||
file: {
|
||||
filename: 'traefik-dynamic.yaml',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
local Rule(route) =
|
||||
local url = utils.ParseURL(route.from);
|
||||
std.join(
|
||||
' && ',
|
||||
['Host(`' + url.host + '`)'] +
|
||||
(if std.objectHas(route, 'prefix') then
|
||||
['PathPrefix(`' + route.prefix + '`)'] else []) +
|
||||
(if std.objectHas(route, 'path') then
|
||||
['Path(`' + route.path + '`)'] else [])
|
||||
);
|
||||
|
||||
local DynamicConfig(mode, idp, dns_suffix='') =
|
||||
{
|
||||
local routes = Routes(mode, idp, dns_suffix) + [
|
||||
{
|
||||
from: 'https://authenticate.localhost.pomerium.io',
|
||||
to: 'https://pomerium' + dns_suffix + ':443',
|
||||
allow_public_unauthenticated_access: true,
|
||||
tls_skip_verify: true,
|
||||
preserve_host_header: true,
|
||||
},
|
||||
],
|
||||
|
||||
tls: {
|
||||
certificates: [{
|
||||
certFile: '_wildcard.localhost.pomerium.io.pem',
|
||||
keyFile: '_wildcard.localhost.pomerium.io-key.pem',
|
||||
}],
|
||||
},
|
||||
http: {
|
||||
serversTransports: {
|
||||
insecure: {
|
||||
insecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
routers: {
|
||||
['route%d' % i]: {
|
||||
service: 'route%d' % i,
|
||||
rule: Rule(routes[i]),
|
||||
tls: {},
|
||||
middlewares:
|
||||
(if routes[i].from == 'https://authenticate.localhost.pomerium.io' then
|
||||
[]
|
||||
else
|
||||
['authz']) +
|
||||
(if std.objectHas(routes[i], 'set_request_headers') then
|
||||
['set-request-headers-%d' % i]
|
||||
else
|
||||
[]),
|
||||
}
|
||||
for i in std.range(0, std.length(routes) - 1)
|
||||
},
|
||||
services: {
|
||||
['route%d' % i]: {
|
||||
loadBalancer:
|
||||
{
|
||||
servers: [{
|
||||
url: routes[i].to,
|
||||
}],
|
||||
} +
|
||||
(if std.startsWith(routes[i].to, 'https://') then
|
||||
{ serversTransport: 'insecure' }
|
||||
else
|
||||
{}) +
|
||||
(if std.objectHas(routes[i], 'preserve_host_header') && routes[i].preserve_host_header then
|
||||
{ passHostHeader: true }
|
||||
else
|
||||
{ passHostHeader: false }),
|
||||
}
|
||||
for i in std.range(0, std.length(routes) - 1)
|
||||
},
|
||||
middlewares: {
|
||||
authz: {
|
||||
forwardAuth: {
|
||||
address: 'https://forward-authenticate.localhost.pomerium.io',
|
||||
trustForwardHeader: true,
|
||||
authResponseHeaders: ['x-pomerium-jwt-assertion', 'x-pomerium-claim-email', 'authorization'],
|
||||
tls: {
|
||||
insecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
} + {
|
||||
['set-request-headers-%d' % i]: {
|
||||
headers: {
|
||||
customRequestHeaders: {
|
||||
[k]: routes[i].set_request_headers[k]
|
||||
for k in std.objectFields(routes[i].set_request_headers)
|
||||
},
|
||||
},
|
||||
}
|
||||
for i in std.range(0, std.length(routes) - 1)
|
||||
if std.objectHas(routes[i], 'set_request_headers')
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
local Command(mode, idp, dns_suffix='') =
|
||||
[
|
||||
'sh',
|
||||
'-c',
|
||||
|||
|
||||
cat <<-'END_OF_TRAEFIK' | tee traefik.yaml
|
||||
%s
|
||||
END_OF_TRAEFIK
|
||||
cat <<-'END_OF_TRAEFIK' | tee traefik-dynamic.yaml
|
||||
%s
|
||||
END_OF_TRAEFIK
|
||||
cat <<-'END_OF_TRAEFIK' | tee _wildcard.localhost.pomerium.io.pem
|
||||
%s
|
||||
END_OF_TRAEFIK
|
||||
cat <<-'END_OF_TRAEFIK' | tee _wildcard.localhost.pomerium.io-key.pem
|
||||
%s
|
||||
END_OF_TRAEFIK
|
||||
|
||||
traefik -configFile=traefik.yaml
|
||||
||| % [
|
||||
std.manifestJsonEx(StaticConfig(), ' '),
|
||||
std.manifestJsonEx(DynamicConfig(mode, idp, dns_suffix), ' '),
|
||||
importstr '../files/trusted.pem',
|
||||
importstr '../files/trusted-key.pem',
|
||||
],
|
||||
];
|
||||
|
||||
function(mode, idp, dns_suffix='') {
|
||||
local image = 'traefik:latest',
|
||||
compose: {
|
||||
services:
|
||||
utils.ComposeService('traefik', {
|
||||
image: image,
|
||||
depends_on: {
|
||||
pomerium: {
|
||||
condition: 'service_started',
|
||||
},
|
||||
},
|
||||
command: Command(mode, idp, dns_suffix),
|
||||
ports: [
|
||||
'80:80/tcp',
|
||||
'443:443/tcp',
|
||||
],
|
||||
}, ['authenticate.localhost.pomerium.io', 'mock-idp.localhost.pomerium.io']),
|
||||
},
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
(import '../../deployments/nginx.libsonnet')('oidc')
|
|
@ -1 +0,0 @@
|
|||
(import '../../deployments/traefik.libsonnet')('oidc')
|
|
@ -1,17 +0,0 @@
|
|||
local utils = import '../utils.libsonnet';
|
||||
|
||||
function(idp) utils.Merge([
|
||||
(import '../backends/fortio.libsonnet')().compose,
|
||||
(import '../backends/httpdetails.libsonnet')().compose,
|
||||
(import '../backends/mock-idp.libsonnet')(idp).compose,
|
||||
(import '../backends/pomerium.libsonnet')('nginx', idp).compose,
|
||||
(import '../backends/postgres.libsonnet')().compose,
|
||||
(import '../backends/verify.libsonnet')('nginx').compose,
|
||||
(import '../backends/websocket-echo.libsonnet')().compose,
|
||||
(import '../backends/nginx.libsonnet')('single', idp).compose,
|
||||
{
|
||||
networks: {
|
||||
main: {},
|
||||
},
|
||||
},
|
||||
])
|
|
@ -1,17 +0,0 @@
|
|||
local utils = import '../utils.libsonnet';
|
||||
|
||||
function(idp) utils.Merge([
|
||||
(import '../backends/fortio.libsonnet')().compose,
|
||||
(import '../backends/httpdetails.libsonnet')().compose,
|
||||
(import '../backends/mock-idp.libsonnet')(idp).compose,
|
||||
(import '../backends/pomerium.libsonnet')('traefik', idp).compose,
|
||||
(import '../backends/postgres.libsonnet')().compose,
|
||||
(import '../backends/traefik.libsonnet')('single', idp).compose,
|
||||
(import '../backends/verify.libsonnet')('traefik').compose,
|
||||
(import '../backends/websocket-echo.libsonnet')().compose,
|
||||
{
|
||||
networks: {
|
||||
main: {},
|
||||
},
|
||||
},
|
||||
])
|
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/handlers"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/telemetry"
|
||||
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
||||
|
@ -39,7 +38,6 @@ func (srv *Server) addHTTPMiddleware(root *mux.Router, cfg *config.Config) {
|
|||
Msg("http-request")
|
||||
}))
|
||||
root.Use(gorillahandlers.RecoveryHandler())
|
||||
root.Use(log.HeadersHandler(httputil.HeadersXForwarded))
|
||||
root.Use(log.RemoteAddrHandler("ip"))
|
||||
root.Use(log.UserAgentHandler("user_agent"))
|
||||
root.Use(log.RefererHandler("referer"))
|
||||
|
|
|
@ -42,46 +42,6 @@ var HeadersContentSecurityPolicy = map[string]string{
|
|||
"Referrer-Policy": "Same-origin",
|
||||
}
|
||||
|
||||
// Forward headers contains information from the client-facing side of proxy
|
||||
// servers that is altered or lost when a proxy is involved in the path of the
|
||||
// request.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7239
|
||||
// https://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
const (
|
||||
HeaderForwardedFor = "X-Forwarded-For"
|
||||
HeaderForwardedHost = "X-Forwarded-Host"
|
||||
HeaderForwardedMethod = "X-Forwarded-Method" // traefik
|
||||
HeaderForwardedPort = "X-Forwarded-Port"
|
||||
HeaderForwardedProto = "X-Forwarded-Proto"
|
||||
HeaderForwardedServer = "X-Forwarded-Server"
|
||||
HeaderForwardedURI = "X-Forwarded-Uri" // traefik
|
||||
HeaderOriginalMethod = "X-Original-Method" // nginx
|
||||
HeaderOriginalURL = "X-Original-Url" // nginx
|
||||
HeaderRealIP = "X-Real-Ip"
|
||||
HeaderSentFrom = "X-Sent-From"
|
||||
)
|
||||
|
||||
// HeadersXForwarded is the slice of the header keys used to contain information
|
||||
// from the client-facing side of proxy servers that is altered or lost when a
|
||||
// proxy is involved in the path of the request.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7239
|
||||
// https://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
var HeadersXForwarded = []string{
|
||||
HeaderForwardedFor,
|
||||
HeaderForwardedHost,
|
||||
HeaderForwardedMethod,
|
||||
HeaderForwardedPort,
|
||||
HeaderForwardedProto,
|
||||
HeaderForwardedServer,
|
||||
HeaderForwardedURI,
|
||||
HeaderOriginalMethod,
|
||||
HeaderOriginalURL,
|
||||
HeaderRealIP,
|
||||
HeaderSentFrom,
|
||||
}
|
||||
|
||||
// PomeriumJWTHeaderName returns the header name set by pomerium for given JWT claim field.
|
||||
func PomeriumJWTHeaderName(claim string) string {
|
||||
return "x-pomerium-claim-" + claim
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package urlutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Forward headers contains information from the client-facing side of proxy
|
||||
// servers that is altered or lost when a proxy is involved in the path of the
|
||||
// request.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7239
|
||||
// https://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
const (
|
||||
HeaderForwardedHost = "X-Forwarded-Host"
|
||||
HeaderForwardedProto = "X-Forwarded-Proto"
|
||||
HeaderForwardedURI = "X-Forwarded-Uri" // traefik
|
||||
HeaderOriginalURL = "X-Original-Url" // nginx
|
||||
)
|
||||
|
||||
// GetForwardAuthURL gets the forward-auth URL for the given request.
|
||||
func GetForwardAuthURL(r *http.Request) *url.URL {
|
||||
urqQuery := r.URL.Query().Get("uri")
|
||||
u, _ := ParseAndValidateURL(urqQuery)
|
||||
if u == nil {
|
||||
u = &url.URL{
|
||||
Scheme: r.Header.Get(HeaderForwardedProto),
|
||||
Host: r.Header.Get(HeaderForwardedHost),
|
||||
}
|
||||
rawPath := r.Header.Get(HeaderForwardedURI)
|
||||
if idx := strings.Index(rawPath, "?"); idx >= 0 {
|
||||
u.Path = rawPath[:idx]
|
||||
u.RawQuery = rawPath[idx+1:]
|
||||
} else {
|
||||
u.Path = rawPath
|
||||
}
|
||||
}
|
||||
originalURL := r.Header.Get(HeaderOriginalURL)
|
||||
if originalURL != "" {
|
||||
k, _ := ParseAndValidateURL(originalURL)
|
||||
if k != nil {
|
||||
u = k
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package urlutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetForwardAuthURL(t *testing.T) {
|
||||
t.Run("double-escaping", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://example.com", nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("X-Forwarded-Proto", "https")
|
||||
req.Header.Set("X-Forwarded-Host", "protected-host.tld")
|
||||
req.Header.Set("X-Forwarded-Uri", "/example?a=b&c=d")
|
||||
|
||||
u := GetForwardAuthURL(req)
|
||||
assert.Equal(t, "https://protected-host.tld/example?a=b&c=d", u.String())
|
||||
})
|
||||
}
|
|
@ -10,12 +10,10 @@ const (
|
|||
QueryEnrollmentToken = "pomerium_enrollment_token" //nolint
|
||||
QueryIdentityProviderID = "pomerium_idp_id"
|
||||
QueryIsProgrammatic = "pomerium_programmatic"
|
||||
QueryForwardAuth = "pomerium_forward_auth"
|
||||
QueryPomeriumJWT = "pomerium_jwt"
|
||||
QuerySession = "pomerium_session"
|
||||
QuerySessionEncrypted = "pomerium_session_encrypted"
|
||||
QueryRedirectURI = "pomerium_redirect_uri"
|
||||
QueryForwardAuthURI = "uri"
|
||||
)
|
||||
|
||||
// URL signature based query params used for verifying the authenticity of a URL.
|
||||
|
|
|
@ -199,6 +199,7 @@ type Selector struct {
|
|||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Filter:
|
||||
//
|
||||
// *Selector_All
|
||||
// *Selector_Tag
|
||||
// *Selector_IdFilter_
|
||||
|
@ -828,6 +829,7 @@ type Connection struct {
|
|||
// the URL of the pomerium server to connect to
|
||||
PomeriumUrl *string `protobuf:"bytes,4,opt,name=pomerium_url,json=pomeriumUrl,proto3,oneof" json:"pomerium_url,omitempty"`
|
||||
// Types that are assignable to TlsOptions:
|
||||
//
|
||||
// *Connection_DisableTlsVerification
|
||||
// *Connection_CaCert
|
||||
TlsOptions isConnection_TlsOptions `protobuf_oneof:"tls_options"`
|
||||
|
|
|
@ -144,6 +144,7 @@ type RouteRewriteHeader struct {
|
|||
|
||||
Header string `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
|
||||
// Types that are assignable to Matcher:
|
||||
//
|
||||
// *RouteRewriteHeader_Prefix
|
||||
Matcher isRouteRewriteHeader_Matcher `protobuf_oneof:"matcher"`
|
||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
|
@ -939,21 +940,21 @@ type Settings struct {
|
|||
SigningKey *string `protobuf:"bytes,36,opt,name=signing_key,json=signingKey,proto3,oneof" json:"signing_key,omitempty"`
|
||||
SetResponseHeaders map[string]string `protobuf:"bytes,69,rep,name=set_response_headers,json=setResponseHeaders,proto3" json:"set_response_headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
// repeated string jwt_claims_headers = 37;
|
||||
JwtClaimsHeaders map[string]string `protobuf:"bytes,63,rep,name=jwt_claims_headers,json=jwtClaimsHeaders,proto3" json:"jwt_claims_headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
DefaultUpstreamTimeout *durationpb.Duration `protobuf:"bytes,39,opt,name=default_upstream_timeout,json=defaultUpstreamTimeout,proto3,oneof" json:"default_upstream_timeout,omitempty"`
|
||||
MetricsAddress *string `protobuf:"bytes,40,opt,name=metrics_address,json=metricsAddress,proto3,oneof" json:"metrics_address,omitempty"`
|
||||
MetricsBasicAuth *string `protobuf:"bytes,64,opt,name=metrics_basic_auth,json=metricsBasicAuth,proto3,oneof" json:"metrics_basic_auth,omitempty"`
|
||||
MetricsCertificate *Settings_Certificate `protobuf:"bytes,65,opt,name=metrics_certificate,json=metricsCertificate,proto3,oneof" json:"metrics_certificate,omitempty"`
|
||||
MetricsClientCa *string `protobuf:"bytes,66,opt,name=metrics_client_ca,json=metricsClientCa,proto3,oneof" json:"metrics_client_ca,omitempty"`
|
||||
MetricsClientCaFile *string `protobuf:"bytes,67,opt,name=metrics_client_ca_file,json=metricsClientCaFile,proto3,oneof" json:"metrics_client_ca_file,omitempty"`
|
||||
TracingProvider *string `protobuf:"bytes,41,opt,name=tracing_provider,json=tracingProvider,proto3,oneof" json:"tracing_provider,omitempty"`
|
||||
TracingSampleRate *float64 `protobuf:"fixed64,42,opt,name=tracing_sample_rate,json=tracingSampleRate,proto3,oneof" json:"tracing_sample_rate,omitempty"`
|
||||
TracingJaegerCollectorEndpoint *string `protobuf:"bytes,43,opt,name=tracing_jaeger_collector_endpoint,json=tracingJaegerCollectorEndpoint,proto3,oneof" json:"tracing_jaeger_collector_endpoint,omitempty"`
|
||||
TracingJaegerAgentEndpoint *string `protobuf:"bytes,44,opt,name=tracing_jaeger_agent_endpoint,json=tracingJaegerAgentEndpoint,proto3,oneof" json:"tracing_jaeger_agent_endpoint,omitempty"`
|
||||
TracingZipkinEndpoint *string `protobuf:"bytes,45,opt,name=tracing_zipkin_endpoint,json=tracingZipkinEndpoint,proto3,oneof" json:"tracing_zipkin_endpoint,omitempty"`
|
||||
GrpcAddress *string `protobuf:"bytes,46,opt,name=grpc_address,json=grpcAddress,proto3,oneof" json:"grpc_address,omitempty"`
|
||||
GrpcInsecure *bool `protobuf:"varint,47,opt,name=grpc_insecure,json=grpcInsecure,proto3,oneof" json:"grpc_insecure,omitempty"`
|
||||
ForwardAuthUrl *string `protobuf:"bytes,50,opt,name=forward_auth_url,json=forwardAuthUrl,proto3,oneof" json:"forward_auth_url,omitempty"`
|
||||
JwtClaimsHeaders map[string]string `protobuf:"bytes,63,rep,name=jwt_claims_headers,json=jwtClaimsHeaders,proto3" json:"jwt_claims_headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
DefaultUpstreamTimeout *durationpb.Duration `protobuf:"bytes,39,opt,name=default_upstream_timeout,json=defaultUpstreamTimeout,proto3,oneof" json:"default_upstream_timeout,omitempty"`
|
||||
MetricsAddress *string `protobuf:"bytes,40,opt,name=metrics_address,json=metricsAddress,proto3,oneof" json:"metrics_address,omitempty"`
|
||||
MetricsBasicAuth *string `protobuf:"bytes,64,opt,name=metrics_basic_auth,json=metricsBasicAuth,proto3,oneof" json:"metrics_basic_auth,omitempty"`
|
||||
MetricsCertificate *Settings_Certificate `protobuf:"bytes,65,opt,name=metrics_certificate,json=metricsCertificate,proto3,oneof" json:"metrics_certificate,omitempty"`
|
||||
MetricsClientCa *string `protobuf:"bytes,66,opt,name=metrics_client_ca,json=metricsClientCa,proto3,oneof" json:"metrics_client_ca,omitempty"`
|
||||
MetricsClientCaFile *string `protobuf:"bytes,67,opt,name=metrics_client_ca_file,json=metricsClientCaFile,proto3,oneof" json:"metrics_client_ca_file,omitempty"`
|
||||
TracingProvider *string `protobuf:"bytes,41,opt,name=tracing_provider,json=tracingProvider,proto3,oneof" json:"tracing_provider,omitempty"`
|
||||
TracingSampleRate *float64 `protobuf:"fixed64,42,opt,name=tracing_sample_rate,json=tracingSampleRate,proto3,oneof" json:"tracing_sample_rate,omitempty"`
|
||||
TracingJaegerCollectorEndpoint *string `protobuf:"bytes,43,opt,name=tracing_jaeger_collector_endpoint,json=tracingJaegerCollectorEndpoint,proto3,oneof" json:"tracing_jaeger_collector_endpoint,omitempty"`
|
||||
TracingJaegerAgentEndpoint *string `protobuf:"bytes,44,opt,name=tracing_jaeger_agent_endpoint,json=tracingJaegerAgentEndpoint,proto3,oneof" json:"tracing_jaeger_agent_endpoint,omitempty"`
|
||||
TracingZipkinEndpoint *string `protobuf:"bytes,45,opt,name=tracing_zipkin_endpoint,json=tracingZipkinEndpoint,proto3,oneof" json:"tracing_zipkin_endpoint,omitempty"`
|
||||
GrpcAddress *string `protobuf:"bytes,46,opt,name=grpc_address,json=grpcAddress,proto3,oneof" json:"grpc_address,omitempty"`
|
||||
GrpcInsecure *bool `protobuf:"varint,47,opt,name=grpc_insecure,json=grpcInsecure,proto3,oneof" json:"grpc_insecure,omitempty"`
|
||||
// optional string forward_auth_url = 50;
|
||||
DatabrokerServiceUrls []string `protobuf:"bytes,52,rep,name=databroker_service_urls,json=databrokerServiceUrls,proto3" json:"databroker_service_urls,omitempty"`
|
||||
DatabrokerInternalServiceUrl *string `protobuf:"bytes,84,opt,name=databroker_internal_service_url,json=databrokerInternalServiceUrl,proto3,oneof" json:"databroker_internal_service_url,omitempty"`
|
||||
ClientCa *string `protobuf:"bytes,53,opt,name=client_ca,json=clientCa,proto3,oneof" json:"client_ca,omitempty"`
|
||||
|
@ -1367,13 +1368,6 @@ func (x *Settings) GetGrpcInsecure() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (x *Settings) GetForwardAuthUrl() string {
|
||||
if x != nil && x.ForwardAuthUrl != nil {
|
||||
return *x.ForwardAuthUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Settings) GetDatabrokerServiceUrls() []string {
|
||||
if x != nil {
|
||||
return x.DatabrokerServiceUrls
|
||||
|
@ -1941,7 +1935,7 @@ var file_config_proto_rawDesc = []byte{
|
|||
0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9d, 0x32, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd9, 0x31, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x73, 0x12, 0x2c, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x47, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01,
|
||||
|
@ -2116,237 +2110,233 @@ var file_config_proto_rawDesc = []byte{
|
|||
0x2a, 0x52, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01,
|
||||
0x01, 0x12, 0x28, 0x0a, 0x0d, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75,
|
||||
0x72, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x08, 0x48, 0x2b, 0x52, 0x0c, 0x67, 0x72, 0x70, 0x63,
|
||||
0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x66,
|
||||
0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x18,
|
||||
0x32, 0x20, 0x01, 0x28, 0x09, 0x48, 0x2c, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
|
||||
0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x61,
|
||||
0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x5f, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x34, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x64, 0x61, 0x74,
|
||||
0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x72,
|
||||
0x6c, 0x73, 0x12, 0x4a, 0x0a, 0x1f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
|
||||
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x54, 0x20, 0x01, 0x28, 0x09, 0x48, 0x2d, 0x52, 0x1c, 0x64,
|
||||
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20,
|
||||
0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x18, 0x35, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x2e, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x88, 0x01, 0x01,
|
||||
0x12, 0x29, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x09, 0x48, 0x2f, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x43, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x6c, 0x18, 0x4a, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x30, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12,
|
||||
0x2b, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x6c, 0x5f, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x18, 0x4b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x31, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x43, 0x72, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x76, 0x0a, 0x36,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x37, 0x20, 0x01, 0x28, 0x09, 0x48, 0x32, 0x52, 0x31,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74,
|
||||
0x18, 0x38, 0x20, 0x01, 0x28, 0x08, 0x48, 0x33, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x5f, 0x63, 0x61, 0x18, 0x4c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x34, 0x52, 0x0a, 0x61, 0x75,
|
||||
0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x43, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x4d, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x35, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x45,
|
||||
0x6d, 0x61, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x4e,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x36, 0x52, 0x10, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74,
|
||||
0x45, 0x61, 0x62, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6d, 0x61, 0x63, 0x5f,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x4f, 0x20, 0x01, 0x28, 0x09, 0x48, 0x37, 0x52, 0x11, 0x61, 0x75, 0x74,
|
||||
0x6f, 0x63, 0x65, 0x72, 0x74, 0x45, 0x61, 0x62, 0x4d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x88, 0x01,
|
||||
0x01, 0x12, 0x33, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x72,
|
||||
0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x48, 0x38,
|
||||
0x52, 0x11, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65,
|
||||
0x64, 0x43, 0x61, 0x88, 0x01, 0x01, 0x12, 0x3c, 0x0a, 0x18, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x18, 0x51, 0x20, 0x01, 0x28, 0x09, 0x48, 0x39, 0x52, 0x15, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x61, 0x46, 0x69, 0x6c,
|
||||
0x65, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74,
|
||||
0x5f, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x18, 0x39, 0x20, 0x01,
|
||||
0x28, 0x08, 0x48, 0x3a, 0x52, 0x12, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x55, 0x73,
|
||||
0x65, 0x53, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x14, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61,
|
||||
0x70, 0x6c, 0x65, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x3b, 0x52, 0x12, 0x61, 0x75, 0x74,
|
||||
0x6f, 0x63, 0x65, 0x72, 0x74, 0x4d, 0x75, 0x73, 0x74, 0x53, 0x74, 0x61, 0x70, 0x6c, 0x65, 0x88,
|
||||
0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x64,
|
||||
0x69, 0x72, 0x18, 0x3b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x3c, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x44, 0x69, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x73, 0x6b,
|
||||
0x69, 0x70, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x3d, 0x20,
|
||||
0x01, 0x28, 0x08, 0x48, 0x3d, 0x52, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x58, 0x66, 0x66, 0x41, 0x70,
|
||||
0x70, 0x65, 0x6e, 0x64, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14, 0x78, 0x66, 0x66, 0x5f, 0x6e,
|
||||
0x75, 0x6d, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18,
|
||||
0x46, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x3e, 0x52, 0x11, 0x78, 0x66, 0x66, 0x4e, 0x75, 0x6d, 0x54,
|
||||
0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x70, 0x73, 0x88, 0x01, 0x01, 0x12, 0x53, 0x0a,
|
||||
0x26, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72, 0x65,
|
||||
0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x77, 0x68,
|
||||
0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x44, 0x20, 0x03, 0x28, 0x09, 0x52, 0x23, 0x70,
|
||||
0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x52, 0x65, 0x64, 0x69, 0x72,
|
||||
0x65, 0x63, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69,
|
||||
0x73, 0x74, 0x12, 0x48, 0x0a, 0x09, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x48, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d,
|
||||
0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
|
||||
0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x48, 0x3f, 0x52,
|
||||
0x08, 0x61, 0x75, 0x64, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x80, 0x01, 0x0a,
|
||||
0x0a, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x49, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x5c, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x6e, 0x65, 0x74,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e,
|
||||
0x48, 0x74, 0x74, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x48,
|
||||
0x40, 0x52, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12,
|
||||
0x28, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x18, 0x55, 0x20, 0x01, 0x28, 0x09, 0x48, 0x41, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72,
|
||||
0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x65, 0x63,
|
||||
0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x56, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x42, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43,
|
||||
0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x16, 0x64, 0x61, 0x72, 0x6b, 0x6d,
|
||||
0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x18, 0x57, 0x20, 0x01, 0x28, 0x09, 0x48, 0x43, 0x52, 0x14, 0x64, 0x61, 0x72, 0x6b, 0x6d,
|
||||
0x6f, 0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88,
|
||||
0x01, 0x01, 0x12, 0x3d, 0x0a, 0x18, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x73,
|
||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x58,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x44, 0x52, 0x16, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65,
|
||||
0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01,
|
||||
0x01, 0x12, 0x1e, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x59, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x45, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x88, 0x01,
|
||||
0x01, 0x12, 0x24, 0x0a, 0x0b, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c,
|
||||
0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x46, 0x52, 0x0a, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f,
|
||||
0x6e, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x46, 0x0a, 0x1d, 0x65, 0x72, 0x72, 0x6f, 0x72,
|
||||
0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70,
|
||||
0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x5b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x47,
|
||||
0x52, 0x1a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x69,
|
||||
0x72, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x88, 0x01, 0x01, 0x1a,
|
||||
0x81, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12,
|
||||
0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08,
|
||||
0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||
0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x65, 0x72,
|
||||
0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x79,
|
||||
0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x42, 0x79,
|
||||
0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61,
|
||||
0x72, 0x61, 0x6d, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, 0x15,
|
||||
0x4a, 0x77, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x42,
|
||||
0x0c, 0x0a, 0x0a, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x12, 0x0a,
|
||||
0x10, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x12, 0x0a, 0x10,
|
||||
0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x42, 0x14, 0x0a, 0x12, 0x5f, 0x64, 0x6e, 0x73, 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x5f,
|
||||
0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f,
|
||||
0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x0f, 0x0a,
|
||||
0x0d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x42, 0x10,
|
||||
0x0a, 0x0e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65,
|
||||
0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x69, 0x64, 0x6c,
|
||||
0x65, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x24,
|
||||
0x0a, 0x22, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x5f, 0x75, 0x72, 0x6c, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x70,
|
||||
0x61, 0x74, 0x68, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x73,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65,
|
||||
0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b,
|
||||
0x69, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x63, 0x6f,
|
||||
0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x42, 0x10,
|
||||
0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
|
||||
0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x69, 0x64, 0x70,
|
||||
0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69, 0x64,
|
||||
0x70, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x21,
|
||||
0x0a, 0x1f, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x72,
|
||||
0x6c, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42,
|
||||
0x18, 0x0a, 0x16, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f,
|
||||
0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x74, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x64, 0x65, 0x66,
|
||||
0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
|
||||
0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x6d, 0x65,
|
||||
0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68,
|
||||
0x42, 0x16, 0x0a, 0x14, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x6d, 0x65, 0x74,
|
||||
0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x42, 0x19,
|
||||
0x0a, 0x17, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74, 0x72,
|
||||
0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x42, 0x16,
|
||||
0x0a, 0x14, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x42, 0x24, 0x0a, 0x22, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x20, 0x0a, 0x1e,
|
||||
0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x5f,
|
||||
0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x1a,
|
||||
0x0a, 0x18, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x7a, 0x69, 0x70, 0x6b, 0x69,
|
||||
0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x67,
|
||||
0x72, 0x70, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x10, 0x0a, 0x0e, 0x5f,
|
||||
0x67, 0x72, 0x70, 0x63, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x13, 0x0a,
|
||||
0x11, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75,
|
||||
0x72, 0x6c, 0x42, 0x22, 0x0a, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65,
|
||||
0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x17, 0x64,
|
||||
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x5f, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x34, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x64, 0x61,
|
||||
0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55,
|
||||
0x72, 0x6c, 0x73, 0x12, 0x4a, 0x0a, 0x1f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65,
|
||||
0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x63, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x63, 0x72, 0x6c, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x63, 0x72, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x39, 0x0a, 0x37, 0x5f, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||
0x63, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||
0x65, 0x6d, 0x61, 0x69, 0x6c, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x42, 0x17, 0x0a,
|
||||
0x15, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6d,
|
||||
0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x42, 0x1b,
|
||||
0x0a, 0x19, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x17, 0x0a, 0x15, 0x5f,
|
||||
0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61,
|
||||
0x67, 0x69, 0x6e, 0x67, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x5f, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x70, 0x6c, 0x65, 0x42, 0x0f, 0x0a,
|
||||
0x0d, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x42, 0x12,
|
||||
0x0a, 0x10, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x61, 0x70, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x74,
|
||||
0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
|
||||
0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f,
|
||||
0x64, 0x65, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x72, 0x69,
|
||||
0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73,
|
||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x19,
|
||||
0x0a, 0x17, 0x5f, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d,
|
||||
0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x64, 0x61,
|
||||
0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79,
|
||||
0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x5f,
|
||||
0x75, 0x72, 0x6c, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f,
|
||||
0x75, 0x72, 0x6c, 0x42, 0x20, 0x0a, 0x1e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
||||
0x67, 0x72, 0x61, 0x70, 0x68, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x63, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x54, 0x20, 0x01, 0x28, 0x09, 0x48, 0x2c, 0x52, 0x1c,
|
||||
0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12,
|
||||
0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x18, 0x35, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x2d, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x88, 0x01,
|
||||
0x01, 0x12, 0x29, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x09, 0x48, 0x2e, 0x52, 0x0c, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x43, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x6c, 0x18, 0x4a, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x2f, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x6c, 0x88, 0x01, 0x01,
|
||||
0x12, 0x2b, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x6c, 0x5f, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x18, 0x4b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x30, 0x52, 0x0d, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x43, 0x72, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x76, 0x0a,
|
||||
0x36, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x37, 0x20, 0x01, 0x28, 0x09, 0x48, 0x31, 0x52,
|
||||
0x31, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x18, 0x38, 0x20, 0x01, 0x28, 0x08, 0x48, 0x32, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x5f, 0x63, 0x61, 0x18, 0x4c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x33, 0x52, 0x0a, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x43, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e,
|
||||
0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x4d,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x34, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74,
|
||||
0x45, 0x6d, 0x61, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x4e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x35, 0x52, 0x10, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x45, 0x61, 0x62, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14,
|
||||
0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6d, 0x61, 0x63,
|
||||
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x4f, 0x20, 0x01, 0x28, 0x09, 0x48, 0x36, 0x52, 0x11, 0x61, 0x75,
|
||||
0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x45, 0x61, 0x62, 0x4d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x88,
|
||||
0x01, 0x01, 0x12, 0x33, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x74,
|
||||
0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x37, 0x52, 0x11, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||
0x65, 0x64, 0x43, 0x61, 0x88, 0x01, 0x01, 0x12, 0x3c, 0x0a, 0x18, 0x61, 0x75, 0x74, 0x6f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x5f, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x18, 0x51, 0x20, 0x01, 0x28, 0x09, 0x48, 0x38, 0x52, 0x15, 0x61, 0x75, 0x74,
|
||||
0x6f, 0x63, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x61, 0x46, 0x69,
|
||||
0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x18, 0x39, 0x20,
|
||||
0x01, 0x28, 0x08, 0x48, 0x39, 0x52, 0x12, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x55,
|
||||
0x73, 0x65, 0x53, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x14,
|
||||
0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x73, 0x74,
|
||||
0x61, 0x70, 0x6c, 0x65, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x3a, 0x52, 0x12, 0x61, 0x75,
|
||||
0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x4d, 0x75, 0x73, 0x74, 0x53, 0x74, 0x61, 0x70, 0x6c, 0x65,
|
||||
0x88, 0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||
0x64, 0x69, 0x72, 0x18, 0x3b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x3b, 0x52, 0x0b, 0x61, 0x75, 0x74,
|
||||
0x6f, 0x63, 0x65, 0x72, 0x74, 0x44, 0x69, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x73,
|
||||
0x6b, 0x69, 0x70, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x3d,
|
||||
0x20, 0x01, 0x28, 0x08, 0x48, 0x3c, 0x52, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x58, 0x66, 0x66, 0x41,
|
||||
0x70, 0x70, 0x65, 0x6e, 0x64, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14, 0x78, 0x66, 0x66, 0x5f,
|
||||
0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x70, 0x73,
|
||||
0x18, 0x46, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x3d, 0x52, 0x11, 0x78, 0x66, 0x66, 0x4e, 0x75, 0x6d,
|
||||
0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x70, 0x73, 0x88, 0x01, 0x01, 0x12, 0x53,
|
||||
0x0a, 0x26, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72,
|
||||
0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x77,
|
||||
0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x44, 0x20, 0x03, 0x28, 0x09, 0x52, 0x23,
|
||||
0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x52, 0x65, 0x64, 0x69,
|
||||
0x72, 0x65, 0x63, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c,
|
||||
0x69, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x09, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x48, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75,
|
||||
0x6d, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
|
||||
0x79, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x48, 0x3e,
|
||||
0x52, 0x08, 0x61, 0x75, 0x64, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x80, 0x01,
|
||||
0x0a, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x49, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x5c, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x6e, 0x65,
|
||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x76, 0x33,
|
||||
0x2e, 0x48, 0x74, 0x74, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65,
|
||||
0x48, 0x3f, 0x52, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01,
|
||||
0x12, 0x28, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x18, 0x55, 0x20, 0x01, 0x28, 0x09, 0x48, 0x40, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61,
|
||||
0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x65,
|
||||
0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x56, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x41, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79,
|
||||
0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x16, 0x64, 0x61, 0x72, 0x6b,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c,
|
||||
0x6f, 0x72, 0x18, 0x57, 0x20, 0x01, 0x28, 0x09, 0x48, 0x42, 0x52, 0x14, 0x64, 0x61, 0x72, 0x6b,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x18, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f,
|
||||
0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18,
|
||||
0x58, 0x20, 0x01, 0x28, 0x09, 0x48, 0x43, 0x52, 0x16, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88,
|
||||
0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x59,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x44, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x88,
|
||||
0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72,
|
||||
0x6c, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x45, 0x52, 0x0a, 0x66, 0x61, 0x76, 0x69, 0x63,
|
||||
0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x46, 0x0a, 0x1d, 0x65, 0x72, 0x72, 0x6f,
|
||||
0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f,
|
||||
0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x5b, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x46, 0x52, 0x1a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46,
|
||||
0x69, 0x72, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x88, 0x01, 0x01,
|
||||
0x1a, 0x81, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a,
|
||||
0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x65, 0x72, 0x74,
|
||||
0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x65,
|
||||
0x72, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x62,
|
||||
0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x42,
|
||||
0x79, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50,
|
||||
0x61, 0x72, 0x61, 0x6d, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a,
|
||||
0x15, 0x4a, 0x77, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
|
||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||
0x38, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67,
|
||||
0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x12,
|
||||
0x0a, 0x10, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x73, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x12, 0x0a,
|
||||
0x10, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x64, 0x6e, 0x73, 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70,
|
||||
0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x68, 0x74, 0x74, 0x70,
|
||||
0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x0f,
|
||||
0x0a, 0x0d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x42,
|
||||
0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x77, 0x72, 0x69, 0x74,
|
||||
0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x69, 0x64,
|
||||
0x6c, 0x65, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x42,
|
||||
0x24, 0x0a, 0x22, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f,
|
||||
0x70, 0x61, 0x74, 0x68, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f,
|
||||
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69,
|
||||
0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f,
|
||||
0x6b, 0x69, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x63,
|
||||
0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x42,
|
||||
0x10, 0x0a, 0x0e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72,
|
||||
0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x69, 0x64,
|
||||
0x70, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69,
|
||||
0x64, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x42,
|
||||
0x21, 0x0a, 0x1f, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75,
|
||||
0x72, 0x6c, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x42, 0x18, 0x0a, 0x16, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x63,
|
||||
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f,
|
||||
0x72, 0x69, 0x74, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x64, 0x65,
|
||||
0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
|
||||
0x63, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x6d,
|
||||
0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74,
|
||||
0x68, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x65,
|
||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x6d, 0x65,
|
||||
0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x42,
|
||||
0x19, 0x0a, 0x17, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74,
|
||||
0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x42,
|
||||
0x16, 0x0a, 0x14, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x61, 0x6d, 0x70,
|
||||
0x6c, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x42, 0x24, 0x0a, 0x22, 0x5f, 0x74, 0x72, 0x61, 0x63,
|
||||
0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x20, 0x0a,
|
||||
0x1e, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72,
|
||||
0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42,
|
||||
0x1a, 0x0a, 0x18, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x7a, 0x69, 0x70, 0x6b,
|
||||
0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x0f, 0x0a, 0x0d, 0x5f,
|
||||
0x67, 0x72, 0x70, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x10, 0x0a, 0x0e,
|
||||
0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x22,
|
||||
0x0a, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75,
|
||||
0x72, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61,
|
||||
0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63,
|
||||
0x72, 0x6c, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72,
|
||||
0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x39, 0x0a, 0x37, 0x5f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x6c, 0x65,
|
||||
0x73, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x42, 0x0e,
|
||||
0x0a, 0x0c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x63, 0x61, 0x42, 0x11,
|
||||
0x0a, 0x0f, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x6d, 0x61, 0x69,
|
||||
0x6c, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65,
|
||||
0x61, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75,
|
||||
0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x61, 0x62, 0x5f, 0x6d, 0x61, 0x63, 0x5f, 0x6b,
|
||||
0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||
0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f,
|
||||
0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67,
|
||||
0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x75,
|
||||
0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x70, 0x6c, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x61, 0x75,
|
||||
0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73,
|
||||
0x6b, 0x69, 0x70, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x42, 0x17,
|
||||
0x0a, 0x15, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74,
|
||||
0x65, 0x64, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x61, 0x75, 0x64, 0x69,
|
||||
0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x5f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
|
||||
0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e,
|
||||
0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x19, 0x0a, 0x17, 0x5f, 0x64,
|
||||
0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f,
|
||||
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f,
|
||||
0x64, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c,
|
||||
0x6f, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x42,
|
||||
0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x42,
|
||||
0x20, 0x0a, 0x1e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70,
|
||||
0x68, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75,
|
||||
0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -192,7 +192,7 @@ message Settings {
|
|||
optional string tracing_zipkin_endpoint = 45;
|
||||
optional string grpc_address = 46;
|
||||
optional bool grpc_insecure = 47;
|
||||
optional string forward_auth_url = 50;
|
||||
// optional string forward_auth_url = 50;
|
||||
repeated string databroker_service_urls = 52;
|
||||
optional string databroker_internal_service_url = 84;
|
||||
optional string client_ca = 53;
|
||||
|
|
|
@ -841,6 +841,7 @@ type SyncLatestResponse struct {
|
|||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Response:
|
||||
//
|
||||
// *SyncLatestResponse_Record
|
||||
// *SyncLatestResponse_Versions
|
||||
Response isSyncLatestResponse_Response `protobuf_oneof:"response"`
|
||||
|
|
|
@ -332,6 +332,7 @@ type Type struct {
|
|||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Types that are assignable to Specifier:
|
||||
//
|
||||
// *Type_Webauthn
|
||||
Specifier isType_Specifier `protobuf_oneof:"specifier"`
|
||||
}
|
||||
|
@ -521,6 +522,7 @@ type Credential struct {
|
|||
EnrollmentId string `protobuf:"bytes,3,opt,name=enrollment_id,json=enrollmentId,proto3" json:"enrollment_id,omitempty"`
|
||||
UserId string `protobuf:"bytes,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
// Types that are assignable to Specifier:
|
||||
//
|
||||
// *Credential_Webauthn
|
||||
Specifier isCredential_Specifier `protobuf_oneof:"specifier"`
|
||||
}
|
||||
|
|
|
@ -315,6 +315,7 @@ type Session_DeviceCredential struct {
|
|||
|
||||
TypeId string `protobuf:"bytes,1,opt,name=type_id,json=typeId,proto3" json:"type_id,omitempty"`
|
||||
// Types that are assignable to Credential:
|
||||
//
|
||||
// *Session_DeviceCredential_Unavailable
|
||||
// *Session_DeviceCredential_Id
|
||||
Credential isSession_DeviceCredential_Credential `protobuf_oneof:"credential"`
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
// registerFwdAuthHandlers returns a set of handlers that support using pomerium
|
||||
// as a "forward-auth" provider with other reverse proxies like nginx, traefik.
|
||||
//
|
||||
// see : https://www.pomerium.com/docs/reference/forward-auth
|
||||
func (p *Proxy) registerFwdAuthHandlers() http.Handler {
|
||||
r := httputil.NewRouter()
|
||||
// NGNIX's forward-auth capabilities are split across two settings:
|
||||
// `auth-url` and `auth-signin` which correspond to `verify` and `auth-url`
|
||||
//
|
||||
// NOTE: Route order matters here which makes the request flow confusing
|
||||
// to reason about so each step has a postfix order step.
|
||||
|
||||
// nginx 3: save the returned session post authenticate flow
|
||||
r.Handle("/verify", httputil.HandlerFunc(p.nginxCallback)).
|
||||
Queries(urlutil.QueryForwardAuthURI, "{uri}",
|
||||
urlutil.QuerySessionEncrypted, "",
|
||||
urlutil.QueryRedirectURI, "")
|
||||
|
||||
// nginx 1: verify, fronted by ext_authz
|
||||
r.Handle("/verify", httputil.HandlerFunc(p.allowUpstream)).
|
||||
Queries(urlutil.QueryForwardAuthURI, "{uri}")
|
||||
|
||||
// nginx 4: redirect the user back to their originally requested location.
|
||||
r.Handle("/", httputil.HandlerFunc(p.nginxPostCallbackRedirect)).
|
||||
Queries(urlutil.QueryForwardAuthURI, "{uri}",
|
||||
urlutil.QuerySessionEncrypted, "",
|
||||
urlutil.QueryRedirectURI, "")
|
||||
|
||||
// traefik 2: save the returned session post authenticate flow
|
||||
r.Handle("/", httputil.HandlerFunc(p.forwardedURIHeaderCallback)).
|
||||
HeadersRegexp(httputil.HeaderForwardedURI, urlutil.QuerySessionEncrypted)
|
||||
|
||||
r.Handle("/", httputil.HandlerFunc(p.startAuthN)).
|
||||
Queries(urlutil.QueryForwardAuthURI, "{uri}")
|
||||
|
||||
// otherwise, send a 200 OK for any other route.
|
||||
// these routes do _not_ enforce authZ, they are helper routes.
|
||||
r.NotFoundHandler = httputil.HandlerFunc(p.allowUpstream)
|
||||
return r
|
||||
}
|
||||
|
||||
// nginxPostCallbackRedirect redirects the user to their original destination
|
||||
// in order to drop the authenticate related query params
|
||||
func (p *Proxy) nginxPostCallbackRedirect(w http.ResponseWriter, r *http.Request) error {
|
||||
u, err := url.Parse(r.FormValue(urlutil.QueryRedirectURI))
|
||||
if err != nil {
|
||||
return httputil.NewError(http.StatusBadRequest, err)
|
||||
}
|
||||
httputil.Redirect(w, r, u.String(), http.StatusFound)
|
||||
return nil
|
||||
}
|
||||
|
||||
// nginxCallback saves the returned session post callback and then returns an
|
||||
// unauthorized status in order to restart the request flow process. Strangely
|
||||
// we need to throw a 401 after saving the session to redirect the user
|
||||
// to their originally desired location.
|
||||
func (p *Proxy) nginxCallback(w http.ResponseWriter, r *http.Request) error {
|
||||
encryptedSession := r.FormValue(urlutil.QuerySessionEncrypted)
|
||||
if _, err := p.saveCallbackSession(w, r, encryptedSession); err != nil {
|
||||
return httputil.NewError(http.StatusBadRequest, err)
|
||||
}
|
||||
return httputil.NewError(http.StatusUnauthorized, errors.New("mock error to restart redirect flow"))
|
||||
}
|
||||
|
||||
// forwardedURIHeaderCallback handles the post-authentication callback from
|
||||
// forwarding proxies that support the `X-Forwarded-Uri`.
|
||||
func (p *Proxy) forwardedURIHeaderCallback(w http.ResponseWriter, r *http.Request) error {
|
||||
forwardedURL, err := url.Parse(r.Header.Get(httputil.HeaderForwardedURI))
|
||||
if err != nil {
|
||||
return httputil.NewError(http.StatusBadRequest, err)
|
||||
}
|
||||
q := forwardedURL.Query()
|
||||
redirectURLString := q.Get(urlutil.QueryRedirectURI)
|
||||
encryptedSession := q.Get(urlutil.QuerySessionEncrypted)
|
||||
|
||||
if _, err := p.saveCallbackSession(w, r, encryptedSession); err != nil {
|
||||
return httputil.NewError(http.StatusBadRequest, err)
|
||||
}
|
||||
httputil.Redirect(w, r, redirectURLString, http.StatusFound)
|
||||
return nil
|
||||
}
|
||||
|
||||
// allowUpstream will return status 200 (OK) unless auth_status is set to forbidden.
|
||||
// This handler is expected to be behind a routed protected by envoy's control plane (ext_authz).
|
||||
func (p *Proxy) allowUpstream(w http.ResponseWriter, r *http.Request) error {
|
||||
if status := r.FormValue("auth_status"); status == fmt.Sprint(http.StatusForbidden) {
|
||||
return httputil.NewError(http.StatusForbidden, errors.New(http.StatusText(http.StatusForbidden)))
|
||||
}
|
||||
// in forward-auth configuration we want to treat our request headers as response headers
|
||||
// so that they can be forwarded by the fronting proxy, if desired
|
||||
for k, vs := range r.Header {
|
||||
for _, v := range vs {
|
||||
w.Header().Set(k, v)
|
||||
}
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, http.StatusText(http.StatusOK))
|
||||
return nil
|
||||
}
|
||||
|
||||
// startAuthN redirects an unauthenticated user to start forward-auth
|
||||
// authentication flow
|
||||
func (p *Proxy) startAuthN(w http.ResponseWriter, r *http.Request) error {
|
||||
state := p.state.Load()
|
||||
uriString := r.FormValue(urlutil.QueryForwardAuthURI)
|
||||
if uriString == "" {
|
||||
uriString = "https://" + // always use HTTPS for external urls
|
||||
r.Header.Get(httputil.HeaderForwardedHost) +
|
||||
r.Header.Get(httputil.HeaderForwardedURI)
|
||||
}
|
||||
uri, err := urlutil.ParseAndValidateURL(uriString)
|
||||
if err != nil {
|
||||
return httputil.NewError(http.StatusBadRequest, err)
|
||||
}
|
||||
// add any non-empty existing path from the forwarded URI
|
||||
if xfu := r.Header.Get(httputil.HeaderForwardedURI); xfu != "" && xfu != "/" {
|
||||
uri.Path = xfu
|
||||
}
|
||||
|
||||
authN := *state.authenticateSigninURL
|
||||
q := authN.Query()
|
||||
q.Set(urlutil.QueryCallbackURI, uri.String())
|
||||
q.Set(urlutil.QueryRedirectURI, uri.String()) // final destination
|
||||
q.Set(urlutil.QueryForwardAuth, urlutil.StripPort(r.Host)) // add fwd auth to trusted audience
|
||||
authN.RawQuery = q.Encode()
|
||||
httputil.Redirect(w, r, urlutil.NewSignedURL(state.sharedKey, &authN).String(), http.StatusFound)
|
||||
return nil
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
envoy_service_auth_v2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/encoding"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/encoding/mock"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
mstore "github.com/pomerium/pomerium/internal/sessions/mock"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
type mockCheckClient struct {
|
||||
response *envoy_service_auth_v2.CheckResponse
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *mockCheckClient) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRequest, opts ...grpc.CallOption) (*envoy_service_auth_v2.CheckResponse, error) {
|
||||
return m.response, m.err
|
||||
}
|
||||
|
||||
func TestProxy_ForwardAuth(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
t.Parallel()
|
||||
|
||||
allowClient := &mockCheckClient{
|
||||
response: &envoy_service_auth_v2.CheckResponse{
|
||||
Status: &status.Status{Code: int32(codes.OK), Message: "OK"},
|
||||
HttpResponse: &envoy_service_auth_v2.CheckResponse_OkResponse{},
|
||||
},
|
||||
}
|
||||
|
||||
opts := testOptions(t)
|
||||
tests := []struct {
|
||||
name string
|
||||
options *config.Options
|
||||
ctxError error
|
||||
method string
|
||||
|
||||
headers map[string]string
|
||||
qp map[string]string
|
||||
|
||||
requestURI string
|
||||
verifyURI string
|
||||
|
||||
cipher encoding.MarshalUnmarshaler
|
||||
sessionStore sessions.SessionStore
|
||||
authorizer envoy_service_auth_v2.AuthorizationClient
|
||||
wantStatus int
|
||||
wantBody string
|
||||
}{
|
||||
{"good verify only, no redirect", opts, nil, http.MethodGet, nil, nil, "https://some.domain.example/verify", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusOK, ""},
|
||||
{"bad empty domain uri", opts, nil, http.MethodGet, nil, map[string]string{"uri": ""}, "https://some.domain.example/", "", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, "{\"Status\":400}\n"},
|
||||
{"bad naked domain uri", opts, nil, http.MethodGet, nil, nil, "https://some.domain.example/", "a.naked.domain", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, "{\"Status\":400}\n"},
|
||||
{"bad empty verification uri", opts, nil, http.MethodGet, nil, nil, "https://some.domain.example/", " ", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, "{\"Status\":400}\n"},
|
||||
// traefik
|
||||
{"good traefik callback", opts, nil, http.MethodGet, map[string]string{httputil.HeaderForwardedURI: "https://some.domain.example?" + urlutil.QuerySessionEncrypted + "=" + goodEncryptionString}, nil, "https://some.domain.example/", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusFound, ""},
|
||||
{"bad traefik callback bad session", opts, nil, http.MethodGet, map[string]string{httputil.HeaderForwardedURI: "https://some.domain.example?" + urlutil.QuerySessionEncrypted + "=" + goodEncryptionString + "garbage"}, nil, "https://some.domain.example/", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, ""},
|
||||
{"bad traefik callback bad url", opts, nil, http.MethodGet, map[string]string{httputil.HeaderForwardedURI: urlutil.QuerySessionEncrypted + ""}, nil, "https://some.domain.example/", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, ""},
|
||||
{"good traefik verify uri from headers", opts, nil, http.MethodGet, map[string]string{httputil.HeaderForwardedProto: "https", httputil.HeaderForwardedHost: "some.domain.example:8080"}, nil, "https://some.domain.example/", "", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusOK, ""},
|
||||
{"good traefik verify uri from insecure headers", opts, nil, http.MethodGet, map[string]string{httputil.HeaderForwardedProto: "http", httputil.HeaderForwardedHost: "some.domain.example:8080"}, nil, "https://some.domain.example/", "", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusOK, ""},
|
||||
|
||||
// // nginx
|
||||
{"good nginx callback redirect", opts, nil, http.MethodGet, nil, map[string]string{urlutil.QueryRedirectURI: "https://some.domain.example/", urlutil.QuerySessionEncrypted: goodEncryptionString}, "https://some.domain.example/", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusFound, ""},
|
||||
{"good nginx callback set session okay but return unauthorized", opts, nil, http.MethodGet, nil, map[string]string{urlutil.QueryRedirectURI: "https://some.domain.example/", urlutil.QuerySessionEncrypted: goodEncryptionString}, "https://some.domain.example/verify", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusUnauthorized, ""},
|
||||
{"bad nginx callback failed to set session", opts, nil, http.MethodGet, nil, map[string]string{urlutil.QueryRedirectURI: "https://some.domain.example/", urlutil.QuerySessionEncrypted: goodEncryptionString + "nope"}, "https://some.domain.example/verify", "https://some.domain.example", &mock.Encoder{}, &mstore.Store{Session: &sessions.State{}}, allowClient, http.StatusBadRequest, ""},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p, err := New(&config.Config{Options: tt.options})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.OnConfigChange(ctx, &config.Config{Options: tt.options})
|
||||
state := p.state.Load()
|
||||
state.sessionStore = tt.sessionStore
|
||||
signer, err := jws.NewHS256Signer(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
state.encoder = signer
|
||||
uri, err := url.Parse(tt.requestURI)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
queryString := uri.Query()
|
||||
for k, v := range tt.qp {
|
||||
queryString.Set(k, v)
|
||||
}
|
||||
if tt.verifyURI != "" {
|
||||
queryString.Set("uri", tt.verifyURI)
|
||||
}
|
||||
|
||||
uri.RawQuery = queryString.Encode()
|
||||
|
||||
r := httptest.NewRequest(tt.method, uri.String(), nil)
|
||||
ss, _ := tt.sessionStore.LoadSession(r)
|
||||
|
||||
ctx := r.Context()
|
||||
ctx = sessions.NewContext(ctx, ss, tt.ctxError)
|
||||
r = r.WithContext(ctx)
|
||||
r.Header.Set("Accept", "application/json")
|
||||
if len(tt.headers) != 0 {
|
||||
for k, v := range tt.headers {
|
||||
r.Header.Set(k, v)
|
||||
}
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
router := p.registerFwdAuthHandlers()
|
||||
router.ServeHTTP(w, r)
|
||||
if status := w.Code; status != tt.wantStatus {
|
||||
t.Errorf("status code: got %v want %v in %s", status, tt.wantStatus, tt.name)
|
||||
t.Errorf("\n%+v", w.Body.String())
|
||||
}
|
||||
|
||||
if tt.wantBody != "" {
|
||||
body := w.Body.String()
|
||||
if diff := cmp.Diff(body, tt.wantBody); diff != "" {
|
||||
t.Errorf("wrong body\n%s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
@ -35,7 +34,7 @@ func TestProxy_RobotsTxt(t *testing.T) {
|
|||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
expected := fmt.Sprintf("User-agent: *\nDisallow: /")
|
||||
expected := "User-agent: *\nDisallow: /"
|
||||
if rr.Body.String() != expected {
|
||||
t.Errorf("handler returned wrong body: got %v want %v", rr.Body.String(), expected)
|
||||
}
|
||||
|
|
|
@ -116,16 +116,6 @@ func (p *Proxy) setHandlers(opts *config.Options) error {
|
|||
// dashboard handlers are registered to all routes
|
||||
r = p.registerDashboardHandlers(r)
|
||||
|
||||
forwardAuthURL, err := opts.GetForwardAuthURL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if forwardAuthURL != nil {
|
||||
// if a forward auth endpoint is set, register its handlers
|
||||
h := r.Host(forwardAuthURL.Hostname()).Subrouter()
|
||||
h.PathPrefix("/").Handler(p.registerFwdAuthHandlers())
|
||||
}
|
||||
|
||||
p.currentRouter.Store(r)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -158,8 +158,7 @@ func Test_UpdateOptions(t *testing.T) {
|
|||
corsPreflight.Policies = []config.Policy{{To: toFoo, From: "http://bar.example", CORSAllowPreflight: true}}
|
||||
disableAuth := testOptions(t)
|
||||
disableAuth.Policies = []config.Policy{{To: toFoo, From: "http://bar.example", AllowPublicUnauthenticatedAccess: true}}
|
||||
fwdAuth := testOptions(t)
|
||||
fwdAuth.ForwardAuthURLString = "https://corp.example.example"
|
||||
|
||||
reqHeaders := testOptions(t)
|
||||
reqHeaders.Policies = []config.Policy{{To: toFoo, From: "http://bar.example", SetRequestHeaders: map[string]string{"x": "y"}}}
|
||||
preserveHostHeader := testOptions(t)
|
||||
|
@ -185,7 +184,6 @@ func Test_UpdateOptions(t *testing.T) {
|
|||
{"no websockets, custom timeout", good, customTimeout, "https://corp.example.example", false, true},
|
||||
{"enable cors preflight", good, corsPreflight, "https://corp.example.example", false, true},
|
||||
{"disable auth", good, disableAuth, "https://corp.example.example", false, true},
|
||||
{"enable forward auth", good, fwdAuth, "https://corp.example.example", false, true},
|
||||
{"set request headers", good, reqHeaders, "https://corp.example.example", false, true},
|
||||
{"preserve host headers", preserveHostHeader, preserveHostHeader, "https://corp.example.example", false, true},
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue