authorize: add client mTLS support (#751)

* authorize: add client mtls support

* authorize: better error messages for envoy

* switch from function to input

* add TrustedCa to envoy config so that users are prompted for the correct client certificate

* update documentation

* fix invalid ClientCAFile

* regenerate cache protobuf

* avoid recursion, add test

* move comment line

* use http.StatusOK

* various fixes
This commit is contained in:
Caleb Doxsey 2020-05-21 16:01:07 -06:00 committed by GitHub
parent 3f1faf2e9e
commit e4832cb4ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 995 additions and 279 deletions

View file

@ -2,10 +2,14 @@
// if a given request should be authorized (AuthZ). // if a given request should be authorized (AuthZ).
package authorize package authorize
//go:generate ../scripts/protoc -I ../internal/grpc/authorize/ --go_out=plugins=grpc:../internal/grpc/authorize/ ../internal/grpc/authorize/authorize.proto
import ( import (
"context" "context"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"html/template"
"io/ioutil"
"sync/atomic" "sync/atomic"
"github.com/pomerium/pomerium/authorize/evaluator" "github.com/pomerium/pomerium/authorize/evaluator"
@ -14,6 +18,7 @@ import (
"github.com/pomerium/pomerium/internal/cryptutil" "github.com/pomerium/pomerium/internal/cryptutil"
"github.com/pomerium/pomerium/internal/encoding" "github.com/pomerium/pomerium/internal/encoding"
"github.com/pomerium/pomerium/internal/encoding/jws" "github.com/pomerium/pomerium/internal/encoding/jws"
"github.com/pomerium/pomerium/internal/frontend"
"github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/telemetry/metrics" "github.com/pomerium/pomerium/internal/telemetry/metrics"
"github.com/pomerium/pomerium/internal/telemetry/trace" "github.com/pomerium/pomerium/internal/telemetry/trace"
@ -51,6 +56,7 @@ type Authorize struct {
currentOptions atomicOptions currentOptions atomicOptions
currentEncoder atomicMarshalUnmarshaler currentEncoder atomicMarshalUnmarshaler
templates *template.Template
} }
// New validates and creates a new Authorize service from a set of config options. // New validates and creates a new Authorize service from a set of config options.
@ -58,7 +64,9 @@ func New(opts config.Options) (*Authorize, error) {
if err := validateOptions(opts); err != nil { if err := validateOptions(opts); err != nil {
return nil, fmt.Errorf("authorize: bad options: %w", err) return nil, fmt.Errorf("authorize: bad options: %w", err)
} }
var a Authorize a := Authorize{
templates: template.Must(frontend.NewTemplates()),
}
var host string var host string
if opts.AuthenticateURL != nil { if opts.AuthenticateURL != nil {
@ -117,12 +125,28 @@ func newPolicyEvaluator(opts *config.Options) (evaluator.Evaluator, error) {
jwk.Key = keyBytes jwk.Key = keyBytes
} }
var clientCA string
if opts.ClientCA != "" {
bs, err := base64.StdEncoding.DecodeString(opts.ClientCA)
if err != nil {
return nil, fmt.Errorf("authorize: invalid client ca: %w", err)
}
clientCA = string(bs)
} else if opts.ClientCAFile != "" {
bs, err := ioutil.ReadFile(opts.ClientCAFile)
if err != nil {
return nil, fmt.Errorf("authorize: invalid client ca file: %w", err)
}
clientCA = string(bs)
}
data := map[string]interface{}{ data := map[string]interface{}{
"shared_key": opts.SharedKey, "shared_key": opts.SharedKey,
"route_policies": opts.Policies, "route_policies": opts.Policies,
"admins": opts.Administrators, "admins": opts.Administrators,
"signing_key": jwk, "signing_key": jwk,
"authenticate_url": opts.AuthenticateURLString, "authenticate_url": opts.AuthenticateURLString,
"client_ca": clientCA,
} }
return opa.New(ctx, &opa.Options{Data: data}) return opa.New(ctx, &opa.Options{Data: data})

106
authorize/errors.go Normal file
View file

@ -0,0 +1,106 @@
package authorize
import (
"bytes"
"net/http"
"strings"
envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
envoy_service_auth_v2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2"
envoy_type "github.com/envoyproxy/go-control-plane/envoy/type"
"google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/codes"
"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/log"
)
func (a *Authorize) deniedResponse(in *envoy_service_auth_v2.CheckRequest,
code int32, reason string, headers map[string]string) *envoy_service_auth_v2.CheckResponse {
returnHTMLError := true
inHeaders := in.GetAttributes().GetRequest().GetHttp().GetHeaders()
if inHeaders != nil {
returnHTMLError = strings.Contains(inHeaders["accept"], "text/html")
}
if returnHTMLError {
return a.htmlDeniedResponse(code, reason, headers)
}
return a.plainTextDeniedResponse(code, reason, headers)
}
func (a *Authorize) htmlDeniedResponse(code int32, reason string, headers map[string]string) *envoy_service_auth_v2.CheckResponse {
var details string
switch code {
case httputil.StatusInvalidClientCertificate:
details = "a valid client certificate is required to access this page"
case http.StatusForbidden:
details = "access to this page is forbidden"
default:
details = reason
}
var buf bytes.Buffer
err := a.templates.ExecuteTemplate(&buf, "error.html", map[string]interface{}{
"Status": code,
"StatusText": reason,
"CanDebug": code/100 == 4,
"Error": details,
})
if err != nil {
buf.WriteString(reason)
log.Error().Err(err).Msg("error executing error template")
}
envoyHeaders := []*envoy_api_v2_core.HeaderValueOption{
mkHeader("Content-Type", "text/html"),
}
for k, v := range headers {
envoyHeaders = append(envoyHeaders, mkHeader(k, v))
}
return &envoy_service_auth_v2.CheckResponse{
Status: &status.Status{Code: int32(codes.PermissionDenied), Message: "Access Denied"},
HttpResponse: &envoy_service_auth_v2.CheckResponse_DeniedResponse{
DeniedResponse: &envoy_service_auth_v2.DeniedHttpResponse{
Status: &envoy_type.HttpStatus{
Code: envoy_type.StatusCode(code),
},
Headers: envoyHeaders,
Body: buf.String(),
},
},
}
}
func (a *Authorize) plainTextDeniedResponse(code int32, reason string, headers map[string]string) *envoy_service_auth_v2.CheckResponse {
envoyHeaders := []*envoy_api_v2_core.HeaderValueOption{
mkHeader("Content-Type", "text/plain"),
}
for k, v := range headers {
envoyHeaders = append(envoyHeaders, mkHeader(k, v))
}
return &envoy_service_auth_v2.CheckResponse{
Status: &status.Status{Code: int32(codes.PermissionDenied), Message: "Access Denied"},
HttpResponse: &envoy_service_auth_v2.CheckResponse_DeniedResponse{
DeniedResponse: &envoy_service_auth_v2.DeniedHttpResponse{
Status: &envoy_type.HttpStatus{
Code: envoy_type.StatusCode(code),
},
Headers: envoyHeaders,
Body: reason,
},
},
}
}
func mkHeader(k, v string) *envoy_api_v2_core.HeaderValueOption {
return &envoy_api_v2_core.HeaderValueOption{
Header: &envoy_api_v2_core.HeaderValue{
Key: k,
Value: v,
},
}
}

View file

@ -10,7 +10,7 @@ import (
// Evaluator specifies the interface for a policy engine. // Evaluator specifies the interface for a policy engine.
type Evaluator interface { type Evaluator interface {
IsAuthorized(ctx context.Context, input interface{}) (*pb.IsAuthorizedReply, error) IsAuthorized(ctx context.Context, req *Request) (*pb.IsAuthorizedReply, error)
PutData(ctx context.Context, data map[string]interface{}) error PutData(ctx context.Context, data map[string]interface{}) error
} }
@ -44,6 +44,11 @@ type Request struct {
// It is an error to set this field in an HTTP client request. // It is an error to set this field in an HTTP client request.
RequestURI string `json:"request_uri,omitempty"` RequestURI string `json:"request_uri,omitempty"`
// Connection context
//
// ClientCertificate is the PEM-encoded public certificate used for the user's TLS connection.
ClientCertificate string `json:"client_certificate"`
// Device context // Device context
// //
// todo(bdd): Use the peer TLS certificate to bind device state with a request // todo(bdd): Use the peer TLS certificate to bind device state with a request

View file

@ -0,0 +1,58 @@
package opa
import (
"crypto/x509"
"encoding/pem"
"fmt"
lru "github.com/hashicorp/golang-lru"
)
var isValidClientCertificateCache, _ = lru.New2Q(100)
func isValidClientCertificate(ca, cert string) (bool, error) {
// when ca is the empty string, client certificates are always accepted
if ca == "" {
return true, nil
}
// when cert is the empty string, no client certificate was supplied
if cert == "" {
return false, nil
}
cacheKey := [2]string{ca, cert}
value, ok := isValidClientCertificateCache.Get(cacheKey)
if ok {
return value.(bool), nil
}
roots := x509.NewCertPool()
roots.AppendCertsFromPEM([]byte(ca))
xcert, err := parseCertificate(cert)
if err != nil {
return false, err
}
_, verifyErr := xcert.Verify(x509.VerifyOptions{
Roots: roots,
})
valid := verifyErr == nil
isValidClientCertificateCache.Add(cacheKey, valid)
return valid, nil
}
func parseCertificate(pemStr string) (*x509.Certificate, error) {
block, _ := pem.Decode([]byte(pemStr))
if block == nil {
return nil, fmt.Errorf("invalid certificate")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("unknown PEM type: %s", block.Type)
}
return x509.ParseCertificate(block.Bytes)
}

View file

@ -0,0 +1,122 @@
package opa
import (
"testing"
"github.com/stretchr/testify/assert"
)
const (
testCA = `
-----BEGIN CERTIFICATE-----
MIIEtjCCAx6gAwIBAgIRAJFkXxMjoQzoojykk6CiiGkwDQYJKoZIhvcNAQELBQAw
czEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSQwIgYDVQQLDBtjYWxl
YkBwb3Atb3MgKENhbGViIERveHNleSkxKzApBgNVBAMMIm1rY2VydCBjYWxlYkBw
b3Atb3MgKENhbGViIERveHNleSkwHhcNMjAwNDI0MTY1MzEwWhcNMzAwNDI0MTY1
MzEwWjBzMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExJDAiBgNVBAsM
G2NhbGViQHBvcC1vcyAoQ2FsZWIgRG94c2V5KTErMCkGA1UEAwwibWtjZXJ0IGNh
bGViQHBvcC1vcyAoQ2FsZWIgRG94c2V5KTCCAaIwDQYJKoZIhvcNAQEBBQADggGP
ADCCAYoCggGBAL2QSyQGjaGD97K7HSExJfMcuyEoh+ewAkPZ/HZR4n12zwAn1sLK
RqusKSfMe8qG6KgsojXrJ9AXEkD7x3bmK5j/4M/lwlNGulg+k5MSu3leoLpOZwfX
JQTu+HDzWubu5cjy7taHyeZc35VbOBWEaDJgVxmJvE9TJIOr8POZ7DD/rlkbgQas
s6G/8cg2mRX0Rh3O20/1bvi9Uen/kraBgGMOyG5MfuiiTl3KsrGST848Q+jiSbu3
5F5MAzdO4tlR6kqEZk/Igog6OPkTb82vMli/R+mR37JYncQcj0WNYS4PkfjofVpb
FwrHtfdkVYJ9T2yNvQnJVu6MF9fhj9FqWQbsdbYKlUDow5KwI+BxmCAmGwgzmCOy
ONkglj76fPKFkoF4s+DSFocbAwhdazaViAcCB+x6yohOUjgG7H9NJo0MasPHuqUO
8d56Bf0BTXfNX6nOgYYisrOoEATCbs729vHMaQ/7pG2zf9dnEuw95gZTSr9Rv3dx
2NjmM6+tNOMCzwIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgw
BgEB/wIBADAdBgNVHQ4EFgQUShofXNkcXh2q4wnnWZ2bco24XEQwDQYJKoZIhvcN
AQELBQADggGBAJQzfmr84xtvoUgnq8T4ND0Q166dlnbDnASRFhbmyZcxzvDJsPs4
N45HbIg0xOsXOaBaE+jTSV4GmZ/vtyP8WbQrhabL2zpnjnLF1d9B0qx/RlIzoDEa
e/0zc0R6RAd64/aE/jHNDhfTNXD/NmnI25RqgnsZXXXRVMTl+PzQ1A8XQghZVWHN
vbyFFd3GE5Qs+vxMzwKCqp6f3MI8KyI2aM4hZZ+zULdEuSw0hWzMOkeZY6LC0flW
/rpkT+GLA3uZ357iehSISLqnkIozw92ldov5oZDthoy3i1I6gIDkngk7BGKr42pD
L2sWi1MEEIhymy4K1DnRkGre3mqzus2y/nE4ruuJlctq6QXcCSnko717vukVtoE8
o5SkW4usivU8yZeBLt56sySRyCpe/T1XAFTQZ5Q4S5ssGmNpOLS9Aa5iOUz9/62S
uvjFyvOEE3yqd/d3py8qm6olcjaMooVA8j5G+QF/UiH951azGIez6/Ui1lg1m0T6
+YLkPqNIt0o9dQ==
-----END CERTIFICATE-----
`
testValidCert = `
-----BEGIN CERTIFICATE-----
MIIESDCCArCgAwIBAgIQG/h9GflpINqLLv4Tde9+STANBgkqhkiG9w0BAQsFADBz
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExJDAiBgNVBAsMG2NhbGVi
QHBvcC1vcyAoQ2FsZWIgRG94c2V5KTErMCkGA1UEAwwibWtjZXJ0IGNhbGViQHBv
cC1vcyAoQ2FsZWIgRG94c2V5KTAeFw0xOTA2MDEwMDAwMDBaFw0zMDA1MjAyMDM4
NDRaME8xJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEk
MCIGA1UECwwbY2FsZWJAcG9wLW9zIChDYWxlYiBEb3hzZXkpMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5ouz2dlXHALdxiLcLwAvxg02CN/Jdcrmyyzm
bzKHqIpknotZSlbPgE/mp5wMwIoyMqFIEm3IzXFEf3cjFYYG4b6wp4zlFrx7jCOa
vhEHpH3yM71xt1I/BME6VrmX7sRKO90dwpTxCOadx9aGEn1AlHuPfhMMm/WTLynD
d5hbsHKp7eZMYHvQnferTelq5NnBySBP/HaAtF76qTSQzHev5K/cgioDZAaM0dnP
bicl0Zay+f5INrDr9XtQo/FHwGI/YLMW5TWXYmHjYmdD8s4Tg/KUoRMgJp4mlkkF
9t1pwArbNFU/4wQWPbpWBLh1gcnQxojSZ3a6aI+V+REDzV/PVQIDAQABo3wwejAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwG
A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUShofXNkcXh2q4wnnWZ2bco24XEQwGgYD
VR0RBBMwEYIPZXhhbXBsZS1zdWJqZWN0MA0GCSqGSIb3DQEBCwUAA4IBgQC78S2n
6jcKfWbm24g/U5tkWiBVnBk1jphH7Ct69Lw2JNstGLtNs4AiE9lKmXDQ82MiAFYg
gaeiHRhTebkOTF9Kx3Jwq7bwhhzONqPp5a0SkY4EWjZ7c5k/fZc8DkrRE71hOgMf
rFbRBZCywBVtGbXIA1uMsCijTe4sQF1ZA918NmfjhpIhRHljQJM16RJ753s+0CZ8
WomOW4JrtjJefRuV97PRADvRNQbtZYelnoTfbp1afGhbQpKjyylCDGlpJS4mGrSA
lPaRVhEB+wI8gA3lzpa6adXsc1yueZ19++dxQNYxAawCMQNjjxy3aLWzy8aPWxxq
Qo/Q9rqjre3SpJfARLOV9ezQNbqsXvJW+5DcoG5dx8s6jAhMusNjUHpf6oVgnv65
3Bvl124bZyf9q4lW9g8pvZkrgQ3Fx2IahqhXhyF5zrqf2r9+1l0fXocIUP2GQ+Fr
b9j9bWWhov5aidEjPwpFeTmzcGqCWQBEA4H+yo/4YaIN0sOfE2yaAmc3gcU=
-----END CERTIFICATE-----
`
testUnsignedCert = `
-----BEGIN CERTIFICATE-----
MIIESTCCArGgAwIBAgIRAIE9860UHBIVofXB5cu/aWAwDQYJKoZIhvcNAQELBQAw
czEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSQwIgYDVQQLDBtjYWxl
YkBwb3Atb3MgKENhbGViIERveHNleSkxKzApBgNVBAMMIm1rY2VydCBjYWxlYkBw
b3Atb3MgKENhbGViIERveHNleSkwHhcNMTkwNjAxMDAwMDAwWhcNMzAwNTIwMjIw
NDAxWjBPMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUx
JDAiBgNVBAsMG2NhbGViQHBvcC1vcyAoQ2FsZWIgRG94c2V5KTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAKPgWHAJ58p7ZZ6MHA6QHA9rQQWKSvYbN9zz
fCCURqHFbQHCCJs2D39XPioo9EMZcD6J7ldwEOJsdSNw3+dzBCvIl7wP6fqtbo/3
SNgRaLAB+Mb4S8oek6P6zHkjuOXzodhCZjLO7oxY9pjGREy6hC/SjylJFgw9mKEG
SYmsyCqeP5BfW9DghRgd5uJe0HtwlBZLPS91Mk5whn7YOxnWslS/REwZdd12s3DI
WQdmvGhMakIAiMKmx+LX9qS3Ua2gUArHnSFXcOAg9iK+MM68T1KsQTCYnRZVK4v5
Na4qEjiPhmkzzEExZa787ClL6UXfoXB+jXy2sXu0CDD4tv2D7R8CAwEAAaN8MHow
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAM
BgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFH8wenPOF2tE2EIksItmlkWfgEMkMBoG
A1UdEQQTMBGCD2ludmFsaWQtc3ViamVjdDANBgkqhkiG9w0BAQsFAAOCAYEAJCdl
c6J/x/UY6vEDzplwR8iZ5s7dyKKF7bwNdjEvBREgkTY6GmwDC9HOmWWPs7vENqEX
jUwHEK+v7A7AUIS4WeJrJgogzEDPI7ZlVtzQNviqMavzk/I1Us00WYtMQQFb1Sgz
xIRskug5wH6vPcR4XbCftx6NP9UFG8pJLPTJ67ZUaTP23ccsToMM/Dd17LFrtleE
9xAvdqA54vcBiJ99uts+xWlQznjIgdauNC6sOmL3JAflyj6aBy+Dcos9R35ERIXz
3rRl25yXjtidPDo8YxmtHs+Ijw4R3iJ44NCcc/+LfACYUcua0cBF2Ixk2JrFYx8n
wwRJukrHXI+RFBmSOlUripyyJH92H5vXvj8lO5wM8wVVVe8anr5TOvxFOAjNC5a3
vJByvJQTUEkx8rT7zZi8eSQJHP3Eoqr9g4ajqIU22yrCxiiQXpZLJ4JFQQEgyD9A
Y+E5W+FKfIBv9yvdNBYZsL6IZ0Yh1ctKwB5gnajO8+swx5BeaCIbBrCtOBSB
-----END CERTIFICATE-----
`
)
func Test_isValidClientCertificate(t *testing.T) {
t.Run("no ca", func(t *testing.T) {
valid, err := isValidClientCertificate("", "WHATEVER!")
assert.NoError(t, err, "should not return an error")
assert.True(t, valid, "should return true")
})
t.Run("no cert", func(t *testing.T) {
valid, err := isValidClientCertificate(testCA, "")
assert.NoError(t, err, "should not return an error")
assert.False(t, valid, "should return false")
})
t.Run("valid cert", func(t *testing.T) {
valid, err := isValidClientCertificate(testCA, testValidCert)
assert.NoError(t, err, "should not return an error")
assert.True(t, valid, "should return true")
})
t.Run("unsigned cert", func(t *testing.T) {
valid, err := isValidClientCertificate(testCA, testUnsignedCert)
assert.NoError(t, err, "should not return an error")
assert.False(t, valid, "should return false")
})
t.Run("not a cert", func(t *testing.T) {
valid, err := isValidClientCertificate(testCA, "WHATEVER!")
assert.Error(t, err, "should return an error")
assert.False(t, valid, "should return false")
})
}

View file

@ -1,4 +1,5 @@
//go:generate statik -src=./policy -include=*.rego -ns rego -p policy //go:generate go run github.com/rakyll/statik -src=./policy -include=*.rego -ns rego -p policy
//go:generate go fmt ./policy/statik.go
// Package opa implements the policy evaluator interface to make authorization // Package opa implements the policy evaluator interface to make authorization
// decisions. // decisions.
@ -6,9 +7,11 @@ package opa
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strconv"
"sync" "sync"
"github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/rego"
@ -37,6 +40,7 @@ type PolicyEvaluator struct {
mu sync.RWMutex mu sync.RWMutex
store storage.Store store storage.Store
isAuthorized rego.PreparedEvalQuery isAuthorized rego.PreparedEvalQuery
clientCA string
} }
// Options represent OPA's evaluator configurations. // Options represent OPA's evaluator configurations.
@ -96,10 +100,10 @@ func (pe *PolicyEvaluator) UpdatePolicy(ctx context.Context, authz string) error
} }
// IsAuthorized determines if a given request input is authorized. // IsAuthorized determines if a given request input is authorized.
func (pe *PolicyEvaluator) IsAuthorized(ctx context.Context, input interface{}) (*pb.IsAuthorizedReply, error) { func (pe *PolicyEvaluator) IsAuthorized(ctx context.Context, req *evaluator.Request) (*pb.IsAuthorizedReply, error) {
ctx, span := trace.StartSpan(ctx, "authorize.evaluator.opa.IsAuthorized") ctx, span := trace.StartSpan(ctx, "authorize.evaluator.opa.IsAuthorized")
defer span.End() defer span.End()
return pe.runBoolQuery(ctx, input, pe.isAuthorized) return pe.runBoolQuery(ctx, req, pe.isAuthorized)
} }
// PutData adds (or replaces if the mapping key is the same) contextual data // PutData adds (or replaces if the mapping key is the same) contextual data
@ -110,6 +114,11 @@ func (pe *PolicyEvaluator) PutData(ctx context.Context, data map[string]interfac
pe.mu.Lock() pe.mu.Lock()
defer pe.mu.Unlock() defer pe.mu.Unlock()
if ca, ok := data["client_ca"].(string); ok {
pe.clientCA = ca
}
txn, err := pe.store.NewTransaction(ctx, storage.WriteParams) txn, err := pe.store.NewTransaction(ctx, storage.WriteParams)
if err != nil { if err != nil {
return fmt.Errorf("opa: bad transaction: %w", err) return fmt.Errorf("opa: bad transaction: %w", err)
@ -171,12 +180,48 @@ func decisionFromInterface(i interface{}) (*pb.IsAuthorizedReply, error) {
if v, ok := m["signed_jwt"].(string); ok { if v, ok := m["signed_jwt"].(string); ok {
d.SignedJwt = v d.SignedJwt = v
} }
// http_status = [200, "OK", { "HEADER": "VALUE" }]
if v, ok := m["http_status"].([]interface{}); ok {
d.HttpStatus = new(pb.HTTPStatus)
if len(v) > 0 {
d.HttpStatus.Code = int32(anyToInt(v[0]))
}
if len(v) > 1 {
if msg, ok := v[1].(string); ok {
d.HttpStatus.Message = msg
}
}
if len(v) > 2 {
if headers, ok := v[2].(map[string]interface{}); ok {
d.HttpStatus.Headers = make(map[string]string)
for hk, hv := range headers {
d.HttpStatus.Headers[hk] = fmt.Sprint(hv)
}
}
}
}
return &d, nil return &d, nil
} }
func (pe *PolicyEvaluator) runBoolQuery(ctx context.Context, input interface{}, q rego.PreparedEvalQuery) (*pb.IsAuthorizedReply, error) { func (pe *PolicyEvaluator) runBoolQuery(ctx context.Context, req *evaluator.Request, q rego.PreparedEvalQuery) (*pb.IsAuthorizedReply, error) {
pe.mu.RLock() pe.mu.RLock()
defer pe.mu.RUnlock() defer pe.mu.RUnlock()
// `opa test` doesn't support custom function, so we'll pre-compute is_valid_client_certificate
isValid, err := isValidClientCertificate(pe.clientCA, req.ClientCertificate)
if err != nil {
return nil, fmt.Errorf("certificate error: %w", err)
}
input := struct {
*evaluator.Request
IsValidClientCertificate bool `json:"is_valid_client_certificate"`
}{
Request: req,
IsValidClientCertificate: isValid,
}
rs, err := q.Eval(ctx, rego.EvalInput(input)) rs, err := q.Eval(ctx, rego.EvalInput(input))
if err != nil { if err != nil {
return nil, fmt.Errorf("eval query: %w", err) return nil, fmt.Errorf("eval query: %w", err)
@ -199,3 +244,35 @@ func readPolicy(fn string) ([]byte, error) {
defer r.Close() defer r.Close()
return ioutil.ReadAll(r) return ioutil.ReadAll(r)
} }
func anyToInt(obj interface{}) int {
switch v := obj.(type) {
case int:
return v
case int64:
return int(v)
case int32:
return int(v)
case int16:
return int(v)
case int8:
return int(v)
case uint64:
return int(v)
case uint32:
return int(v)
case uint16:
return int(v)
case uint8:
return int(v)
case json.Number:
i, _ := v.Int64()
return int(i)
case string:
i, _ := strconv.Atoi(v)
return i
default:
i, _ := strconv.Atoi(fmt.Sprint(v))
return i
}
}

View file

@ -5,9 +5,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/pomerium/pomerium/config" "github.com/stretchr/testify/assert"
"gopkg.in/square/go-jose.v2" "gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt" "gopkg.in/square/go-jose.v2/jwt"
"github.com/pomerium/pomerium/authorize/evaluator"
"github.com/pomerium/pomerium/config"
) )
func Test_Eval(t *testing.T) { func Test_Eval(t *testing.T) {
@ -89,11 +92,7 @@ func Test_Eval(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
req := struct { req := &evaluator.Request{
Host string `json:"host,omitempty"`
URL string `json:"url,omitempty"`
User string `json:"user,omitempty"`
}{
Host: tt.route, Host: tt.route,
URL: "https://" + tt.route, URL: "https://" + tt.route,
User: rawJWT, User: rawJWT,
@ -108,3 +107,17 @@ func Test_Eval(t *testing.T) {
}) })
} }
} }
func Test_anyToInt(t *testing.T) {
assert.Equal(t, 5, anyToInt("5"))
assert.Equal(t, 7, anyToInt(7))
assert.Equal(t, 9, anyToInt(int8(9)))
assert.Equal(t, 9, anyToInt(int16(9)))
assert.Equal(t, 9, anyToInt(int32(9)))
assert.Equal(t, 9, anyToInt(int64(9)))
assert.Equal(t, 11, anyToInt(uint8(11)))
assert.Equal(t, 11, anyToInt(uint16(11)))
assert.Equal(t, 11, anyToInt(uint32(11)))
assert.Equal(t, 11, anyToInt(uint64(11)))
assert.Equal(t, 13, anyToInt(13.0))
}

View file

@ -5,6 +5,10 @@ import data.shared_key
default allow = false default allow = false
http_status = [495, "invalid client certificate"]{
not input.is_valid_client_certificate
}
# allow public # allow public
allow { allow {
route := first_allowed_route(input.url) route := first_allowed_route(input.url)

File diff suppressed because one or more lines are too long

View file

@ -20,7 +20,6 @@ import (
envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
envoy_service_auth_v2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2" envoy_service_auth_v2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2"
envoy_type "github.com/envoyproxy/go-control-plane/envoy/type"
"google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
) )
@ -67,6 +66,7 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
RequestURI: requestURL.String(), RequestURI: requestURL.String(),
RemoteAddr: in.GetAttributes().GetSource().GetAddress().String(), RemoteAddr: in.GetAttributes().GetSource().GetAddress().String(),
URL: requestURL.String(), URL: requestURL.String(),
ClientCertificate: getPeerCertificate(in),
} }
reply, err := a.pe.IsAuthorized(ctx, req) reply, err := a.pe.IsAuthorized(ctx, req)
if err != nil { if err != nil {
@ -88,7 +88,12 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
evt = evt.Strs("deny-reasons", reply.GetDenyReasons()) evt = evt.Strs("deny-reasons", reply.GetDenyReasons())
evt = evt.Str("email", reply.GetEmail()) evt = evt.Str("email", reply.GetEmail())
evt = evt.Strs("groups", reply.GetGroups()) evt = evt.Strs("groups", reply.GetGroups())
if sess != nil {
evt = evt.Str("session", string(sess)) evt = evt.Str("session", string(sess))
}
if reply.GetHttpStatus() != nil {
evt = evt.Interface("http_status", reply.GetHttpStatus())
}
evt.Msg("authorize check") evt.Msg("authorize check")
requestHeaders = append(requestHeaders, requestHeaders = append(requestHeaders,
@ -99,6 +104,14 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
}, },
}) })
if reply.GetHttpStatus().GetCode() > 0 && reply.GetHttpStatus().GetCode() != http.StatusOK {
return a.deniedResponse(in,
reply.GetHttpStatus().GetCode(),
reply.GetHttpStatus().GetMessage(),
reply.GetHttpStatus().GetHeaders(),
), nil
}
if reply.Allow { if reply.Allow {
return &envoy_service_auth_v2.CheckResponse{ return &envoy_service_auth_v2.CheckResponse{
Status: &status.Status{Code: int32(codes.OK), Message: "OK"}, Status: &status.Status{Code: int32(codes.OK), Message: "OK"},
@ -123,30 +136,12 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
msg = sesserr.Error() msg = sesserr.Error()
} }
// all other errors // all other errors
return &envoy_service_auth_v2.CheckResponse{ return a.deniedResponse(in, http.StatusForbidden, msg, nil), nil
Status: &status.Status{Code: int32(codes.PermissionDenied), Message: msg},
HttpResponse: &envoy_service_auth_v2.CheckResponse_DeniedResponse{
DeniedResponse: &envoy_service_auth_v2.DeniedHttpResponse{
Status: &envoy_type.HttpStatus{
Code: envoy_type.StatusCode_Forbidden,
},
},
},
}, nil
} }
// no redirect for forward auth, that's handled by a separate config setting // no redirect for forward auth, that's handled by a separate config setting
if isForwardAuth { if isForwardAuth {
return &envoy_service_auth_v2.CheckResponse{ return a.deniedResponse(in, http.StatusUnauthorized, "Unauthenticated", nil), nil
Status: &status.Status{Code: int32(codes.Unauthenticated)},
HttpResponse: &envoy_service_auth_v2.CheckResponse_DeniedResponse{
DeniedResponse: &envoy_service_auth_v2.DeniedHttpResponse{
Status: &envoy_type.HttpStatus{
Code: envoy_type.StatusCode_Unauthorized,
},
},
},
}, nil
} }
signinURL := opts.AuthenticateURL.ResolveReference(&url.URL{Path: "/.pomerium/sign_in"}) signinURL := opts.AuthenticateURL.ResolveReference(&url.URL{Path: "/.pomerium/sign_in"})
@ -155,25 +150,9 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
signinURL.RawQuery = q.Encode() signinURL.RawQuery = q.Encode()
redirectTo := urlutil.NewSignedURL(opts.SharedKey, signinURL).String() redirectTo := urlutil.NewSignedURL(opts.SharedKey, signinURL).String()
return &envoy_service_auth_v2.CheckResponse{ return a.deniedResponse(in, http.StatusFound, "Login", map[string]string{
Status: &status.Status{ "Location": redirectTo,
Code: int32(codes.Unauthenticated), }), nil
Message: "unauthenticated",
},
HttpResponse: &envoy_service_auth_v2.CheckResponse_DeniedResponse{
DeniedResponse: &envoy_service_auth_v2.DeniedHttpResponse{
Status: &envoy_type.HttpStatus{
Code: envoy_type.StatusCode_Found,
},
Headers: []*envoy_api_v2_core.HeaderValueOption{{
Header: &envoy_api_v2_core.HeaderValue{
Key: "Location",
Value: redirectTo,
},
}},
},
},
}, nil
} }
func (a *Authorize) getEnvoyRequestHeaders(rawjwt []byte, isNewSession bool) ([]*envoy_api_v2_core.HeaderValueOption, error) { func (a *Authorize) getEnvoyRequestHeaders(rawjwt []byte, isNewSession bool) ([]*envoy_api_v2_core.HeaderValueOption, error) {
@ -329,3 +308,10 @@ func handleForwardAuth(opts config.Options, req *envoy_service_auth_v2.CheckRequ
return false return false
} }
// getPeerCertificate gets the PEM-encoded peer certificate from the check request
func getPeerCertificate(in *envoy_service_auth_v2.CheckRequest) string {
// ignore the error as we will just return the empty string in that case
cert, _ := url.QueryUnescape(in.GetAttributes().GetSource().GetCertificate())
return cert
}

2
cache/grpc.go vendored
View file

@ -1,4 +1,4 @@
//go:generate protoc -I ../internal/grpc/cache/ --go_out=plugins=grpc:../internal/grpc/cache/ ../internal/grpc/cache/cache.proto //go:generate ../scripts/protoc -I ../internal/grpc/cache/ --go_out=plugins=grpc:../internal/grpc/cache/ ../internal/grpc/cache/cache.proto
package cache package cache

3
cache/grpc_test.go vendored
View file

@ -1,5 +1,3 @@
//go:generate protoc -I ../internal/grpc/cache/ --go_out=plugins=grpc:../internal/grpc/cache/ ../internal/grpc/cache/cache.proto
package cache package cache
import ( import (
@ -12,6 +10,7 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/cryptutil" "github.com/pomerium/pomerium/internal/cryptutil"
"github.com/pomerium/pomerium/internal/grpc/cache" "github.com/pomerium/pomerium/internal/grpc/cache"

View file

@ -238,6 +238,11 @@ type Options struct {
// CacheStorePath is the path to use for a given cache store. e.g. /etc/bolt.db // CacheStorePath is the path to use for a given cache store. e.g. /etc/bolt.db
CacheStorePath string `mapstructure:"cache_store_path" yaml:"cache_store_path,omitempty"` CacheStorePath string `mapstructure:"cache_store_path" yaml:"cache_store_path,omitempty"`
// ClientCA is the base64-encoded certificate authority to validate client mTLS certificates against.
ClientCA string `mapstructure:"client_ca" yaml:"client_ca,omitempty"`
// ClientCAFile points to a file that contains the certificate authority to validate client mTLS certificates against.
ClientCAFile string `mapstructure:"client_ca_file" yaml:"client_ca_file,omitempty"`
viper *viper.Viper viper *viper.Viper
} }
@ -562,6 +567,18 @@ func (o *Options) Validate() error {
o.Certificates = append(o.Certificates, *cert) o.Certificates = append(o.Certificates, *cert)
} }
if o.ClientCA != "" {
if _, err := base64.StdEncoding.DecodeString(o.ClientCA); err != nil {
return fmt.Errorf("config: bad client ca base64: %w", err)
}
}
if o.ClientCAFile != "" {
if _, err := os.Stat(o.ClientCAFile); err != nil {
return fmt.Errorf("config: bad client ca file: %w", err)
}
}
RedirectAndAutocertServer.update(o) RedirectAndAutocertServer.update(o)
err = AutocertManager.update(o) err = AutocertManager.update(o)

View file

@ -209,6 +209,15 @@ certificates:
key: "$HOME/.acme.sh/prometheus.example.com_ecc/prometheus.example.com.key" key: "$HOME/.acme.sh/prometheus.example.com_ecc/prometheus.example.com.key"
``` ```
### Client Certificate Authority
- Environment Variable: `CLIENT_CA` / `CLIENT_CA_FILE`
- Config File Key: `client_ca` / `client_ca_file`
- Type: [base64 encoded] `string` or relative file location
- Optional
The Client Certificate Authority is the x509 _public-key_ used to validate [mTLS](https://en.wikipedia.org/wiki/Mutual_authentication) client certificates. If not set, no client certificate will be required.
### Global Timeouts ### Global Timeouts
- Environmental Variables: `TIMEOUT_READ` `TIMEOUT_WRITE` `TIMEOUT_IDLE` - Environmental Variables: `TIMEOUT_READ` `TIMEOUT_WRITE` `TIMEOUT_IDLE`

1
go.mod
View file

@ -20,6 +20,7 @@ require (
github.com/gorilla/handlers v1.4.2 github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/golang-lru v0.5.4
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/lithammer/shortuuid/v3 v3.0.4 github.com/lithammer/shortuuid/v3 v3.0.4
github.com/mitchellh/hashstructure v1.0.0 github.com/mitchellh/hashstructure v1.0.0

View file

@ -9,6 +9,6 @@ import (
const Luascripts = "luascripts" // static asset namespace const Luascripts = "luascripts" // static asset namespace
func init() { func init() {
data := "PK\x03\x04\x14\x00\x08\x00\x08\x00el\xb3P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x00clean-upstream.luaUT\x05\x00\x01\x8f\xe0\xc3^\x94S\xc1n\x9c0\x10\xbd\xf3\x15O\xf4PV%\x91z\xdd\xc8\xff\xd0{\xd5\"\x17f\x17\xab`\xbb\xf68\x9b\xe4\xd0o\xaf\xbc\x18\x16\x07VU|\xc0cy\xde\x9b\xc7\x9b\xf1)\xe8\x96\x95\xd1p4\x9agj\xac\x19\xc9\xa906\xad1\xbf\x15U\xd3\xd6h9R\x8d\xe9p(\x00\xe0\xe1\x01C\x90\xe8\x0cy\xfd\x99\xe1\x83\xb5\xc61\x8c\x8dlr@+-\x07G8;\x13\xac\x9f!\xde\xe0Bpd\x07\xd9\x12\xf8\xa2\xe2\xd7\xa0\x97\xba\x1b\x08sq\xf1\xf2\xfa\x06\xc9\xe0\x9e@\xba\x839]C\xcfN\xe9\xf3\x95jR\x02\x91\x82\xe3\xd9\x87_k\xadx|D)\xbe\xff|\xfa\xf1\xe5 e\x8d\xb2<|\x14\xb7B9\xe2\xe0t\xc2\x14\xa4\xbb\xa2X|\xeb\xa5o\xac\xa3\x93z\xa9<\xbb\x1aS\x9c\xe1<;\xfc\x15\xd0j\x80\xd4]<\x1ec\xd9\xaf5>\xa5l\x08\x91\x80\xef\xd8I?\x9b\xd7\xc6\xe8\xc6\xd1\x9f@\x9e\xab\xb47\x93cS\x99\xc1\xb4r@O\xb2#\xe7!\x90\xe7\x1c\xd3E\xb5N\x1e\x89e'Yn\xb3\xe7\x9b\xeaP\xac\xf2\xd3t\xac\x9d\x12\x0b\xc9\xf1L\\\x95\xfb\x03\x94\x1cT\xa7=\n\xeeI_\xafo\x85\x96\x06%\xd5\x13w\xc6\x95\xf8Rf26\xa3\x8aK\xd3e\xe1\xba3\xdb[E\xf9\x88\xcfk\x96\x92\xc6v\x91S\xdf\x8a\xdc\x00\xb1\x7f\xf3\xbe5P\x06\xee\x8dSo\xf2\xda\xdd\xffY\x98eo\x9c\xcc\xb9v\xbc|_,\xb3t\x8f\xfb\x0e4\xcd7\x04\xcaoI\x1a\xcau+Vo \x03\xd6\xbb<\x87m\xb3n\x0e\xc7?\xbb/nm\xee\xdd\x87\xe2\xad\xd1>vw\n\x96\xa7\x12\x11\xff\x02\x00\x00\xff\xffPK\x07\x08\x08Z\x88f\xa3\x01\x00\x00\xef\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x10\x9d\xb2P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00 \x00ext-authz-set-cookie.luaUT\x05\x00\x01\xb0\xe4\xc2^\x8c\x91An\x830\x10E\xf7\x9cb\xc4\xcaHI\x0e\x80\x94\x03t\xd1\x13T\x955\xc5C\xb0j\x8fS{\x88\x9aM\xcf^AM\x04\x0dM\x19 \x01\xe2\xff?\xf8\xbf\xb6\xe7Fl` \xbe\x84\xab\x0e\xac#}\xf4\x94D\xe5\xbb\xee\x90\x8d\xa3\xaa\x00\x00p\xa1A\x07\x1d\xa1\xa1\x98\xe0\x08KM\x9d?\xa8\xb9\xd8\\\x19\xbdm\xb4'\xc1{G\x92H\xe8\x9f\xb8\x0d\xaa\xaa\xb3\xf4\x99\x04\x0d\n\xe6\x18\xdbN\x0b\xeb\x13\x89*?\xf7\xe7\xe0)\xda\xde\xef\x13\xc9\xbe \xe1\xddRY\xc1\xd7\x11\xd8:\x90\x8ex\xf4\x0d3_^\xa7\xc1=\x1e\xf3\xd0Z'\x14\xd3\xa1\x139\x1f\\\x8f\xe5\x0e\xca)U'\x12\x9dSw\xb7\xa4\xbb\xd9\xf2OU\xf1[\x1d\xc9\x87\x0b\xfdi\x18\xf5\xc4\xa6\x18\xaeb\x8dM:\x07N\xa4\xa6\x87\x7f\xe8,D\xdb\xf0,-\x1b\xf8\xfc\xe4\xc8\x9b\x83\xe3\xb2\xef\xd3\x83\xbeoh\x07_&\x87l\x86\xd7\x97U\x12\xaf\xab|\xa7Z\xd1\x18U\xce\x8a\xdc=\x08Z\x96\xfc\x1d\x00\x00\xff\xffPK\x07\x08\x93\xe7\xad\x94\x07\x01\x00\x00\x00\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00el\xb3P\x08Z\x88f\xa3\x01\x00\x00\xef\x04\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00clean-upstream.luaUT\x05\x00\x01\x8f\xe0\xc3^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x10\x9d\xb2P\x93\xe7\xad\x94\x07\x01\x00\x00\x00\x03\x00\x00\x18\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xec\x01\x00\x00ext-authz-set-cookie.luaUT\x05\x00\x01\xb0\xe4\xc2^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x98\x00\x00\x00B\x03\x00\x00\x00\x00" data := "PK\x03\x04\x14\x00\x08\x00\x08\x00@\x89\xb3P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x00clean-upstream.luaUT\x05\x00\x01\xe8\x12\xc4^\x94S\xc1n\x9c0\x10\xbd\xf3\x15O\xf4PV%\x91z\xdd\xc8\xff\xd0{\xd5\"\x17f\x17\xab`\xbb\xf68\x9b\xe4\xd0o\xaf\x00\xc3\xe2\x00\xaa\xe2\x03\x1e\xcb\xf3\xde<\xde\x8c/A\xd7\xac\x8c\x86\xa3\xde<SeMON\x85\xbe\xaa\x8d\xf9\xad\xa8\x98\xb6J\xcb\x9eJL\x87S\x06\x00\x0f\x0f\xe8\x82Dc\xc8\xeb\xcf\x0c\x1f\xac5\x8ea\xec\xc0&;\xd4\xd2rp\x84\xab3\xc1\xfa\x19\xe2\x0dn\x04G\xb6\x935\x81oj\xf8\x1a\xb4R7\x1da..^^\xdf \x19\xdc\x12H70\x971\xf4\xec\x94\xbe\x8eT\x93\x12\x88\x18\x9c\xaf>\xfcZk\xc5\xe3#r\xf1\xfd\xe7\xd3\x8f/O\xc8K\xe4\xf9\xe9\xa3\xb8\x15\xca\x11\x07\xa7#&#\xddd\xd9\xe2[+}e\x1d]\xd4K\xe1\xd9\x95\x98\xe2\x04\xe7\xd9\xe1\xaf\x80V\x1d\xa4n\x86\xe3y(\xfb\xb5\xc4\xa7\x98\x0d!\"\xf0\x1d;\xe9g\xf3Z\x19]9\xfa\x13\xc8s\x11\xf7jrl*\xd3\x99ZvhI6\xe4<\x04\xd2\x9cs\xbc(\xd6\xc9=\xb1l$\xcbm\xf6|S\x9c\xb2U~\x9c\x8e\xb5Sb!9_\x89\x8b|\x7f\x80\xa2\x83\xea\xb2G\xc1-\xe9\xf1\xfa^hiPT=q'\\\x91/fFc\x13\xaaai\xba-\\\x07\xb3\xbdU\x94\x8e\xf8\xbcf)ql\x179\xe5\xbd\xc8\x1d0\xf4o\xde\xb7\x06\xca\xc0\xadq\xeaM\x8e\xdd\xfd\x9f\x85I\xf6\xc6\xc9\x94k\xc7\xcb\xf7\xc5\x12K\xf7\xb8\x0f\xa0q\xbe!\x90\x7f\x8b\xd2\x90\xaf[\xb1z\x03 \xb0\xdc\xe59m\x9buwx\xf8\xb3cqks\x0f\x1f\x8a\xb7F\xfb\xa1\xbbS\xb0<\x95\x11\xf1/\x00\x00\xff\xffPK\x07\x08\xfb\x06j<\xa2\x01\x00\x00\xf0\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00bz\xb3P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00 \x00ext-authz-set-cookie.luaUT\x05\x00\x01\xe8\xf8\xc3^\x8c\x91An\x830\x10E\xf7\x9cb\xc4\xcaHI\x0e\x80\x94\x03t\xd1\x13T\x955\xc5C\xb0j\x8fS{\x88\x9aM\xcf^AM\x04\x0dM\x19 \x01\xe2\xff?\xf8\xbf\xb6\xe7Fl` \xbe\x84\xab\x0e\xac#}\xf4\x94D\xe5\xbb\xee\x90\x8d\xa3\xaa\x00\x00p\xa1A\x07\x1d\xa1\xa1\x98\xe0\x08KM\x9d?\xa8\xb9\xd8\\\x19\xbdm\xb4'\xc1{G\x92H\xe8\x9f\xb8\x0d\xaa\xaa\xb3\xf4\x99\x04\x0d\n\xe6\x18\xdbN\x0b\xeb\x13\x89*?\xf7\xe7\xe0)\xda\xde\xef\x13\xc9\xbe \xe1\xddRY\xc1\xd7\x11\xd8:\x90\x8ex\xf4\x0d3_^\xa7\xc1=\x1e\xf3\xd0Z'\x14\xd3\xa1\x139\x1f\\\x8f\xe5\x0e\xca)U'\x12\x9dSw\xb7\xa4\xbb\xd9\xf2OU\xf1[\x1d\xc9\x87\x0b\xfdi\x18\xf5\xc4\xa6\x18\xaeb\x8dM:\x07N\xa4\xa6\x87\x7f\xe8,D\xdb\xf0,-\x1b\xf8\xfc\xe4\xc8\x9b\x83\xe3\xb2\xef\xd3\x83\xbeoh\x07_&\x87l\x86\xd7\x97U\x12\xaf\xab|\xa7Z\xd1\x18U\xce\x8a\xdc=\x08Z\x96\xfc\x1d\x00\x00\xff\xffPK\x07\x08\x93\xe7\xad\x94\x07\x01\x00\x00\x00\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00@\x89\xb3P\xfb\x06j<\xa2\x01\x00\x00\xf0\x04\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00clean-upstream.luaUT\x05\x00\x01\xe8\x12\xc4^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00bz\xb3P\x93\xe7\xad\x94\x07\x01\x00\x00\x00\x03\x00\x00\x18\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xeb\x01\x00\x00ext-authz-set-cookie.luaUT\x05\x00\x01\xe8\xf8\xc3^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x98\x00\x00\x00A\x03\x00\x00\x00\x00"
fs.RegisterWithNamespace("luascripts", data) fs.RegisterWithNamespace("luascripts", data)
} }

View file

@ -1,6 +1,7 @@
package controlplane package controlplane
import ( import (
"encoding/base64"
"sort" "sort"
"time" "time"
@ -164,6 +165,7 @@ func (srv *Server) buildMainHTTPConnectionManagerFilter(options *config.Options,
}, },
}, },
}, },
IncludePeerCertificate: true,
}) })
extAuthzSetCookieLua, _ := ptypes.MarshalAny(&envoy_extensions_filters_http_lua_v3.Lua{ extAuthzSetCookieLua, _ := ptypes.MarshalAny(&envoy_extensions_filters_http_lua_v3.Lua{
@ -326,11 +328,28 @@ func (srv *Server) buildDownstreamTLSContext(options *config.Options, domain str
return nil return nil
} }
var trustedCA *envoy_config_core_v3.DataSource
if options.ClientCA != "" {
bs, err := base64.StdEncoding.DecodeString(options.ClientCA)
if err != nil {
log.Warn().Msg("client_ca does not appear to be a base64 encoded string")
}
trustedCA = inlineBytesAsFilename("client-ca", bs)
} else if options.ClientCAFile != "" {
trustedCA = inlineFilename(options.ClientCAFile)
}
envoyCert := envoyTLSCertificateFromGoTLSCertificate(cert) envoyCert := envoyTLSCertificateFromGoTLSCertificate(cert)
return &envoy_extensions_transport_sockets_tls_v3.DownstreamTlsContext{ return &envoy_extensions_transport_sockets_tls_v3.DownstreamTlsContext{
CommonTlsContext: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext{ CommonTlsContext: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext{
TlsCertificates: []*envoy_extensions_transport_sockets_tls_v3.TlsCertificate{envoyCert}, TlsCertificates: []*envoy_extensions_transport_sockets_tls_v3.TlsCertificate{envoyCert},
AlpnProtocols: []string{"h2", "http/1.1"}, AlpnProtocols: []string{"h2", "http/1.1"},
ValidationContextType: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext_ValidationContext{
ValidationContext: &envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext{
TrustedCa: trustedCA,
TrustChainVerification: envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext_ACCEPT_UNTRUSTED,
},
},
}, },
} }
} }

File diff suppressed because one or more lines are too long

View file

@ -1,30 +1,39 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.23.0
// protoc v3.12.1
// source: authorize.proto // source: authorize.proto
package authorize package authorize
import ( import (
context "context" context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
math "math" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
) )
// Reference imports to suppress errors if they are not otherwise used. const (
var _ = proto.Marshal // Verify that this generated code is sufficiently up-to-date.
var _ = fmt.Errorf _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
var _ = math.Inf // Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion that a sufficiently up-to-date version
// is compatible with the proto package it is being compiled against. // of the legacy proto package is being used.
// A compilation error at this line likely means your copy of the const _ = proto.ProtoPackageIsVersion4
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type IsAuthorizedRequest struct { type IsAuthorizedRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// User Context // User Context
// //
UserToken string `protobuf:"bytes,1,opt,name=user_token,json=userToken,proto3" json:"user_token,omitempty"` UserToken string `protobuf:"bytes,1,opt,name=user_token,json=userToken,proto3" json:"user_token,omitempty"`
@ -43,252 +52,484 @@ type IsAuthorizedRequest struct {
// the network address that sent the request, usually for // the network address that sent the request, usually for
RequestRemoteAddr string `protobuf:"bytes,6,opt,name=request_remote_addr,json=requestRemoteAddr,proto3" json:"request_remote_addr,omitempty"` RequestRemoteAddr string `protobuf:"bytes,6,opt,name=request_remote_addr,json=requestRemoteAddr,proto3" json:"request_remote_addr,omitempty"`
RequestHeaders map[string]*IsAuthorizedRequest_Headers `protobuf:"bytes,7,rep,name=request_headers,json=requestHeaders,proto3" json:"request_headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` RequestHeaders map[string]*IsAuthorizedRequest_Headers `protobuf:"bytes,7,rep,name=request_headers,json=requestHeaders,proto3" json:"request_headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *IsAuthorizedRequest) Reset() { *m = IsAuthorizedRequest{} } func (x *IsAuthorizedRequest) Reset() {
func (m *IsAuthorizedRequest) String() string { return proto.CompactTextString(m) } *x = IsAuthorizedRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_authorize_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *IsAuthorizedRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IsAuthorizedRequest) ProtoMessage() {} func (*IsAuthorizedRequest) ProtoMessage() {}
func (x *IsAuthorizedRequest) ProtoReflect() protoreflect.Message {
mi := &file_authorize_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IsAuthorizedRequest.ProtoReflect.Descriptor instead.
func (*IsAuthorizedRequest) Descriptor() ([]byte, []int) { func (*IsAuthorizedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ffbc3c71370bee9a, []int{0} return file_authorize_proto_rawDescGZIP(), []int{0}
} }
func (m *IsAuthorizedRequest) XXX_Unmarshal(b []byte) error { func (x *IsAuthorizedRequest) GetUserToken() string {
return xxx_messageInfo_IsAuthorizedRequest.Unmarshal(m, b) if x != nil {
} return x.UserToken
func (m *IsAuthorizedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IsAuthorizedRequest.Marshal(b, m, deterministic)
}
func (m *IsAuthorizedRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_IsAuthorizedRequest.Merge(m, src)
}
func (m *IsAuthorizedRequest) XXX_Size() int {
return xxx_messageInfo_IsAuthorizedRequest.Size(m)
}
func (m *IsAuthorizedRequest) XXX_DiscardUnknown() {
xxx_messageInfo_IsAuthorizedRequest.DiscardUnknown(m)
}
var xxx_messageInfo_IsAuthorizedRequest proto.InternalMessageInfo
func (m *IsAuthorizedRequest) GetUserToken() string {
if m != nil {
return m.UserToken
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestMethod() string { func (x *IsAuthorizedRequest) GetRequestMethod() string {
if m != nil { if x != nil {
return m.RequestMethod return x.RequestMethod
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestUrl() string { func (x *IsAuthorizedRequest) GetRequestUrl() string {
if m != nil { if x != nil {
return m.RequestUrl return x.RequestUrl
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestHost() string { func (x *IsAuthorizedRequest) GetRequestHost() string {
if m != nil { if x != nil {
return m.RequestHost return x.RequestHost
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestRequestUri() string { func (x *IsAuthorizedRequest) GetRequestRequestUri() string {
if m != nil { if x != nil {
return m.RequestRequestUri return x.RequestRequestUri
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestRemoteAddr() string { func (x *IsAuthorizedRequest) GetRequestRemoteAddr() string {
if m != nil { if x != nil {
return m.RequestRemoteAddr return x.RequestRemoteAddr
} }
return "" return ""
} }
func (m *IsAuthorizedRequest) GetRequestHeaders() map[string]*IsAuthorizedRequest_Headers { func (x *IsAuthorizedRequest) GetRequestHeaders() map[string]*IsAuthorizedRequest_Headers {
if m != nil { if x != nil {
return m.RequestHeaders return x.RequestHeaders
}
return nil
}
type IsAuthorizedReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Allow bool `protobuf:"varint,1,opt,name=allow,proto3" json:"allow,omitempty"`
SessionExpired bool `protobuf:"varint,2,opt,name=session_expired,json=sessionExpired,proto3" json:"session_expired,omitempty"` // special case
DenyReasons []string `protobuf:"bytes,3,rep,name=deny_reasons,json=denyReasons,proto3" json:"deny_reasons,omitempty"`
SignedJwt string `protobuf:"bytes,4,opt,name=signed_jwt,json=signedJwt,proto3" json:"signed_jwt,omitempty"`
User string `protobuf:"bytes,5,opt,name=user,proto3" json:"user,omitempty"`
Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"`
Groups []string `protobuf:"bytes,7,rep,name=groups,proto3" json:"groups,omitempty"`
HttpStatus *HTTPStatus `protobuf:"bytes,8,opt,name=http_status,json=httpStatus,proto3" json:"http_status,omitempty"`
}
func (x *IsAuthorizedReply) Reset() {
*x = IsAuthorizedReply{}
if protoimpl.UnsafeEnabled {
mi := &file_authorize_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *IsAuthorizedReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IsAuthorizedReply) ProtoMessage() {}
func (x *IsAuthorizedReply) ProtoReflect() protoreflect.Message {
mi := &file_authorize_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IsAuthorizedReply.ProtoReflect.Descriptor instead.
func (*IsAuthorizedReply) Descriptor() ([]byte, []int) {
return file_authorize_proto_rawDescGZIP(), []int{1}
}
func (x *IsAuthorizedReply) GetAllow() bool {
if x != nil {
return x.Allow
}
return false
}
func (x *IsAuthorizedReply) GetSessionExpired() bool {
if x != nil {
return x.SessionExpired
}
return false
}
func (x *IsAuthorizedReply) GetDenyReasons() []string {
if x != nil {
return x.DenyReasons
}
return nil
}
func (x *IsAuthorizedReply) GetSignedJwt() string {
if x != nil {
return x.SignedJwt
}
return ""
}
func (x *IsAuthorizedReply) GetUser() string {
if x != nil {
return x.User
}
return ""
}
func (x *IsAuthorizedReply) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *IsAuthorizedReply) GetGroups() []string {
if x != nil {
return x.Groups
}
return nil
}
func (x *IsAuthorizedReply) GetHttpStatus() *HTTPStatus {
if x != nil {
return x.HttpStatus
}
return nil
}
type HTTPStatus struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *HTTPStatus) Reset() {
*x = HTTPStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_authorize_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *HTTPStatus) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HTTPStatus) ProtoMessage() {}
func (x *HTTPStatus) ProtoReflect() protoreflect.Message {
mi := &file_authorize_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HTTPStatus.ProtoReflect.Descriptor instead.
func (*HTTPStatus) Descriptor() ([]byte, []int) {
return file_authorize_proto_rawDescGZIP(), []int{2}
}
func (x *HTTPStatus) GetCode() int32 {
if x != nil {
return x.Code
}
return 0
}
func (x *HTTPStatus) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *HTTPStatus) GetHeaders() map[string]string {
if x != nil {
return x.Headers
} }
return nil return nil
} }
// headers represents key-value pairs in an HTTP header; map[string][]string // headers represents key-value pairs in an HTTP header; map[string][]string
type IsAuthorizedRequest_Headers struct { type IsAuthorizedRequest_Headers struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Value []string `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` Value []string `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *IsAuthorizedRequest_Headers) Reset() { *m = IsAuthorizedRequest_Headers{} } func (x *IsAuthorizedRequest_Headers) Reset() {
func (m *IsAuthorizedRequest_Headers) String() string { return proto.CompactTextString(m) } *x = IsAuthorizedRequest_Headers{}
if protoimpl.UnsafeEnabled {
mi := &file_authorize_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *IsAuthorizedRequest_Headers) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IsAuthorizedRequest_Headers) ProtoMessage() {} func (*IsAuthorizedRequest_Headers) ProtoMessage() {}
func (x *IsAuthorizedRequest_Headers) ProtoReflect() protoreflect.Message {
mi := &file_authorize_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IsAuthorizedRequest_Headers.ProtoReflect.Descriptor instead.
func (*IsAuthorizedRequest_Headers) Descriptor() ([]byte, []int) { func (*IsAuthorizedRequest_Headers) Descriptor() ([]byte, []int) {
return fileDescriptor_ffbc3c71370bee9a, []int{0, 0} return file_authorize_proto_rawDescGZIP(), []int{0, 0}
} }
func (m *IsAuthorizedRequest_Headers) XXX_Unmarshal(b []byte) error { func (x *IsAuthorizedRequest_Headers) GetValue() []string {
return xxx_messageInfo_IsAuthorizedRequest_Headers.Unmarshal(m, b) if x != nil {
} return x.Value
func (m *IsAuthorizedRequest_Headers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IsAuthorizedRequest_Headers.Marshal(b, m, deterministic)
}
func (m *IsAuthorizedRequest_Headers) XXX_Merge(src proto.Message) {
xxx_messageInfo_IsAuthorizedRequest_Headers.Merge(m, src)
}
func (m *IsAuthorizedRequest_Headers) XXX_Size() int {
return xxx_messageInfo_IsAuthorizedRequest_Headers.Size(m)
}
func (m *IsAuthorizedRequest_Headers) XXX_DiscardUnknown() {
xxx_messageInfo_IsAuthorizedRequest_Headers.DiscardUnknown(m)
}
var xxx_messageInfo_IsAuthorizedRequest_Headers proto.InternalMessageInfo
func (m *IsAuthorizedRequest_Headers) GetValue() []string {
if m != nil {
return m.Value
} }
return nil return nil
} }
type IsAuthorizedReply struct { var File_authorize_proto protoreflect.FileDescriptor
Allow bool `protobuf:"varint,1,opt,name=allow,proto3" json:"allow,omitempty"`
SessionExpired bool `protobuf:"varint,2,opt,name=session_expired,json=sessionExpired,proto3" json:"session_expired,omitempty"` var file_authorize_proto_rawDesc = []byte{
DenyReasons []string `protobuf:"bytes,3,rep,name=deny_reasons,json=denyReasons,proto3" json:"deny_reasons,omitempty"` 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
SignedJwt string `protobuf:"bytes,4,opt,name=signed_jwt,json=signedJwt,proto3" json:"signed_jwt,omitempty"` 0x6f, 0x12, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x22, 0xe8, 0x03, 0x0a,
User string `protobuf:"bytes,5,opt,name=user,proto3" json:"user,omitempty"` 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71,
Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"` 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b,
Groups []string `protobuf:"bytes,7,rep,name=groups,proto3" json:"groups,omitempty"` 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x54, 0x6f,
XXX_NoUnkeyedLiteral struct{} `json:"-"` 0x6b, 0x65, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6d,
XXX_unrecognized []byte `json:"-"` 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x71,
XXX_sizecache int32 `json:"-"` 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x72,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x2e,
0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x55, 0x72, 0x69, 0x12, 0x2e,
0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65,
0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x5b,
0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
0x69, 0x7a, 0x65, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x1f, 0x0a, 0x07, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x69, 0x0a, 0x13,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x02, 0x0a, 0x11, 0x49, 0x73, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a,
0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c,
0x6c, 0x6f, 0x77, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x65,
0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x65,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c,
0x64, 0x65, 0x6e, 0x79, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x79, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x12,
0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6a, 0x77, 0x74, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4a, 0x77, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73,
0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75,
0x70, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73,
0x12, 0x36, 0x0a, 0x0b, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x68, 0x74,
0x74, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb4, 0x01, 0x0a, 0x0a, 0x48, 0x54, 0x54,
0x50, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
0x7a, 0x65, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x48, 0x65,
0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64,
0x65, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 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, 0x32,
0x5c, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x72, 0x12, 0x4e, 0x0a,
0x0c, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x1e, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
func (m *IsAuthorizedReply) Reset() { *m = IsAuthorizedReply{} } var (
func (m *IsAuthorizedReply) String() string { return proto.CompactTextString(m) } file_authorize_proto_rawDescOnce sync.Once
func (*IsAuthorizedReply) ProtoMessage() {} file_authorize_proto_rawDescData = file_authorize_proto_rawDesc
func (*IsAuthorizedReply) Descriptor() ([]byte, []int) { )
return fileDescriptor_ffbc3c71370bee9a, []int{1}
func file_authorize_proto_rawDescGZIP() []byte {
file_authorize_proto_rawDescOnce.Do(func() {
file_authorize_proto_rawDescData = protoimpl.X.CompressGZIP(file_authorize_proto_rawDescData)
})
return file_authorize_proto_rawDescData
} }
func (m *IsAuthorizedReply) XXX_Unmarshal(b []byte) error { var file_authorize_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
return xxx_messageInfo_IsAuthorizedReply.Unmarshal(m, b) var file_authorize_proto_goTypes = []interface{}{
(*IsAuthorizedRequest)(nil), // 0: authorize.IsAuthorizedRequest
(*IsAuthorizedReply)(nil), // 1: authorize.IsAuthorizedReply
(*HTTPStatus)(nil), // 2: authorize.HTTPStatus
(*IsAuthorizedRequest_Headers)(nil), // 3: authorize.IsAuthorizedRequest.Headers
nil, // 4: authorize.IsAuthorizedRequest.RequestHeadersEntry
nil, // 5: authorize.HTTPStatus.HeadersEntry
} }
func (m *IsAuthorizedReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { var file_authorize_proto_depIdxs = []int32{
return xxx_messageInfo_IsAuthorizedReply.Marshal(b, m, deterministic) 4, // 0: authorize.IsAuthorizedRequest.request_headers:type_name -> authorize.IsAuthorizedRequest.RequestHeadersEntry
} 2, // 1: authorize.IsAuthorizedReply.http_status:type_name -> authorize.HTTPStatus
func (m *IsAuthorizedReply) XXX_Merge(src proto.Message) { 5, // 2: authorize.HTTPStatus.headers:type_name -> authorize.HTTPStatus.HeadersEntry
xxx_messageInfo_IsAuthorizedReply.Merge(m, src) 3, // 3: authorize.IsAuthorizedRequest.RequestHeadersEntry.value:type_name -> authorize.IsAuthorizedRequest.Headers
} 0, // 4: authorize.Authorizer.IsAuthorized:input_type -> authorize.IsAuthorizedRequest
func (m *IsAuthorizedReply) XXX_Size() int { 1, // 5: authorize.Authorizer.IsAuthorized:output_type -> authorize.IsAuthorizedReply
return xxx_messageInfo_IsAuthorizedReply.Size(m) 5, // [5:6] is the sub-list for method output_type
} 4, // [4:5] is the sub-list for method input_type
func (m *IsAuthorizedReply) XXX_DiscardUnknown() { 4, // [4:4] is the sub-list for extension type_name
xxx_messageInfo_IsAuthorizedReply.DiscardUnknown(m) 4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
} }
var xxx_messageInfo_IsAuthorizedReply proto.InternalMessageInfo func init() { file_authorize_proto_init() }
func file_authorize_proto_init() {
func (m *IsAuthorizedReply) GetAllow() bool { if File_authorize_proto != nil {
if m != nil { return
return m.Allow
}
return false
}
func (m *IsAuthorizedReply) GetSessionExpired() bool {
if m != nil {
return m.SessionExpired
}
return false
}
func (m *IsAuthorizedReply) GetDenyReasons() []string {
if m != nil {
return m.DenyReasons
} }
if !protoimpl.UnsafeEnabled {
file_authorize_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IsAuthorizedRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil return nil
}
func (m *IsAuthorizedReply) GetSignedJwt() string {
if m != nil {
return m.SignedJwt
} }
return ""
}
func (m *IsAuthorizedReply) GetUser() string {
if m != nil {
return m.User
}
return ""
}
func (m *IsAuthorizedReply) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *IsAuthorizedReply) GetGroups() []string {
if m != nil {
return m.Groups
} }
file_authorize_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IsAuthorizedReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil return nil
} }
}
func init() { file_authorize_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
proto.RegisterType((*IsAuthorizedRequest)(nil), "authorize.IsAuthorizedRequest") switch v := v.(*HTTPStatus); i {
proto.RegisterMapType((map[string]*IsAuthorizedRequest_Headers)(nil), "authorize.IsAuthorizedRequest.RequestHeadersEntry") case 0:
proto.RegisterType((*IsAuthorizedRequest_Headers)(nil), "authorize.IsAuthorizedRequest.Headers") return &v.state
proto.RegisterType((*IsAuthorizedReply)(nil), "authorize.IsAuthorizedReply") case 1:
} return &v.sizeCache
case 2:
func init() { return &v.unknownFields
proto.RegisterFile("authorize.proto", fileDescriptor_ffbc3c71370bee9a) default:
} return nil
}
var fileDescriptor_ffbc3c71370bee9a = []byte{ }
// 431 bytes of a gzipped FileDescriptorProto file_authorize_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0x6e, 0x13, 0x31, switch v := v.(*IsAuthorizedRequest_Headers); i {
0x10, 0xc6, 0xd9, 0x6e, 0x9b, 0x76, 0x27, 0xa5, 0xa1, 0x13, 0x84, 0xac, 0x08, 0x68, 0x88, 0x04, case 0:
0xe4, 0x94, 0x43, 0xb8, 0x20, 0xc4, 0xa5, 0x87, 0x4a, 0x05, 0x09, 0x0e, 0x16, 0x9c, 0x40, 0x5a, return &v.state
0x2d, 0xf2, 0xa8, 0x59, 0xea, 0xac, 0x17, 0xdb, 0x4b, 0x58, 0x1e, 0x94, 0x67, 0xe0, 0x31, 0x90, case 1:
0xff, 0xa5, 0x14, 0x15, 0x38, 0xad, 0xe7, 0xe7, 0xcf, 0xe3, 0x99, 0xf9, 0xbc, 0x30, 0xaa, 0x3a, return &v.sizeCache
0xbb, 0x52, 0xba, 0xfe, 0x4e, 0x8b, 0x56, 0x2b, 0xab, 0xb0, 0xd8, 0x82, 0xd9, 0xcf, 0x1c, 0xc6, case 2:
0xaf, 0xcc, 0x69, 0x8a, 0x05, 0xa7, 0x2f, 0x1d, 0x19, 0x8b, 0x0f, 0x00, 0x3a, 0x43, 0xba, 0xb4, return &v.unknownFields
0xea, 0x92, 0x1a, 0x96, 0x4d, 0xb3, 0x79, 0xc1, 0x0b, 0x47, 0xde, 0x39, 0x80, 0x8f, 0xe1, 0x48, default:
0x07, 0x65, 0xb9, 0x26, 0xbb, 0x52, 0x82, 0xed, 0x78, 0xc9, 0xed, 0x48, 0xdf, 0x78, 0x88, 0x27, return nil
0x30, 0x4c, 0xb2, 0x4e, 0x4b, 0x96, 0x7b, 0x0d, 0x44, 0xf4, 0x5e, 0x4b, 0x7c, 0x04, 0x87, 0x49, }
0xb0, 0x52, 0xc6, 0xb2, 0x5d, 0xaf, 0x48, 0x87, 0xce, 0x95, 0xb1, 0xb8, 0x80, 0x71, 0x92, 0x5c, }
0xe5, 0xaa, 0xd9, 0x9e, 0x57, 0x1e, 0x47, 0xc4, 0x53, 0xca, 0xfa, 0xba, 0x7e, 0xad, 0x2c, 0x95, }
0x95, 0x10, 0x9a, 0x0d, 0xfe, 0xd0, 0xbb, 0x9d, 0x53, 0x21, 0x34, 0x7e, 0x80, 0xd1, 0xb6, 0x04, type x struct{}
0xaa, 0x04, 0x69, 0xc3, 0xf6, 0xa7, 0xf9, 0x7c, 0xb8, 0x5c, 0x2e, 0xae, 0xe6, 0x76, 0xc3, 0x88, out := protoimpl.TypeBuilder{
0x16, 0xf1, 0x7b, 0x1e, 0x0e, 0x9d, 0x35, 0x56, 0xf7, 0x3c, 0x4d, 0x25, 0xc2, 0xc9, 0x09, 0xec, File: protoimpl.DescBuilder{
0xc7, 0x25, 0xde, 0x85, 0xbd, 0xaf, 0x95, 0xec, 0x88, 0x65, 0xd3, 0x7c, 0x5e, 0xf0, 0x10, 0x4c, GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
0x6a, 0x18, 0xdf, 0x90, 0x07, 0xef, 0x40, 0x7e, 0x49, 0x7d, 0x9c, 0xbb, 0x5b, 0xe2, 0xcb, 0x74, RawDescriptor: file_authorize_proto_rawDesc,
0xdc, 0x0d, 0x7a, 0xb8, 0x7c, 0xf2, 0x9f, 0xe2, 0x62, 0xb6, 0x78, 0xcd, 0x8b, 0x9d, 0xe7, 0xd9, NumEnums: 0,
0xec, 0x47, 0x06, 0xc7, 0xd7, 0xa5, 0xad, 0xec, 0x5d, 0x59, 0x95, 0x94, 0x6a, 0xe3, 0xef, 0x3a, NumMessages: 6,
0xe0, 0x21, 0xc0, 0xa7, 0x30, 0x32, 0x64, 0x4c, 0xad, 0x9a, 0x92, 0xbe, 0xb5, 0xb5, 0xa6, 0x60, NumExtensions: 0,
0xf0, 0x01, 0x3f, 0x8a, 0xf8, 0x2c, 0x50, 0x67, 0xa0, 0xa0, 0xa6, 0x2f, 0x35, 0x55, 0x46, 0x35, NumServices: 1,
0x86, 0xe5, 0xbe, 0xb9, 0xa1, 0x63, 0x3c, 0x20, 0xf7, 0x94, 0x4c, 0x7d, 0xd1, 0x90, 0x28, 0x3f, },
0x6f, 0x92, 0xc3, 0x45, 0x20, 0xaf, 0x37, 0x16, 0x11, 0x76, 0xdd, 0xbb, 0x8a, 0x86, 0xfa, 0xb5, GoTypes: file_authorize_proto_goTypes,
0x2b, 0x8a, 0xd6, 0x55, 0x2d, 0xa3, 0x6b, 0x21, 0xc0, 0x7b, 0x30, 0xb8, 0xd0, 0xaa, 0x6b, 0x83, DependencyIndexes: file_authorize_proto_depIdxs,
0x41, 0x05, 0x8f, 0xd1, 0xf2, 0x23, 0xc0, 0xb6, 0x2b, 0x8d, 0x6f, 0xe1, 0xf0, 0xf7, 0x2e, 0xf1, MessageInfos: file_authorize_proto_msgTypes,
0xe1, 0xbf, 0x27, 0x35, 0xb9, 0xff, 0xd7, 0xfd, 0x56, 0xf6, 0xb3, 0x5b, 0x9f, 0x06, 0xfe, 0x9f, }.Build()
0x79, 0xf6, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x10, 0x59, 0xee, 0x46, 0x03, 0x00, 0x00, File_authorize_proto = out.File
file_authorize_proto_rawDesc = nil
file_authorize_proto_goTypes = nil
file_authorize_proto_depIdxs = nil
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -332,7 +573,7 @@ type AuthorizerServer interface {
type UnimplementedAuthorizerServer struct { type UnimplementedAuthorizerServer struct {
} }
func (*UnimplementedAuthorizerServer) IsAuthorized(ctx context.Context, req *IsAuthorizedRequest) (*IsAuthorizedReply, error) { func (*UnimplementedAuthorizerServer) IsAuthorized(context.Context, *IsAuthorizedRequest) (*IsAuthorizedReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsAuthorized not implemented") return nil, status.Errorf(codes.Unimplemented, "method IsAuthorized not implemented")
} }

View file

@ -37,5 +37,11 @@ message IsAuthorizedReply {
string user = 5; string user = 5;
string email = 6; string email = 6;
repeated string groups = 7; repeated string groups = 7;
HTTPStatus http_status = 8;
} }
message HTTPStatus {
int32 code = 1;
string message = 2;
map<string, string> headers = 3;
}

View file

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.21.0 // protoc-gen-go v1.23.0
// protoc v3.11.4 // protoc v3.12.1
// source: cache.proto // source: cache.proto
package cache package cache

View file

@ -0,0 +1,6 @@
package httputil
// StatusInvalidClientCertificate is the status code returned when a
// client's certificate is invalid. This is the same status code used
// by nginx for this purpose.
const StatusInvalidClientCertificate = 495

22
scripts/protoc Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
set -euo pipefail
_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
_protoc_version="3.12.1"
_protoc_path="/tmp/pomerium-protoc/protoc-$_protoc_version"
_os="linux"
if [ "$(uname -s)" == "Darwin" ]; then
_os="osx"
fi
if [ ! -f "$_protoc_path" ]; then
echo "downloading protoc"
mkdir -p "/tmp/pomerium-protoc"
curl -L \
-o protoc.zip \
"https://github.com/protocolbuffers/protobuf/releases/download/v$_protoc_version/protoc-$_protoc_version-$_os-x86_64.zip"
unzip -p protoc.zip bin/protoc >"$_protoc_path"
fi
chmod +x "$_protoc_path"
exec "$_protoc_path" --plugin="protoc-gen-go=$_dir/protoc-gen-go" "$@"

3
scripts/protoc-gen-go Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
set -euo pipefail
exec go run github.com/golang/protobuf/protoc-gen-go "$@"