mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-10 15:47:36 +02:00
envoy: implement refresh session (#674)
* authorize: refresh session WIP * remove upstream cookie with lua * only refresh session on expired * authorize: handle session expiration * authorize: add refresh test, fix isExpired check * proxy: implement preserve host header option * authorize: allow CORS preflight requests * proxy: add request headers * authenticate: use id token expiry
This commit is contained in:
parent
ae3049baca
commit
0d9a372182
7 changed files with 284 additions and 27 deletions
|
@ -12,6 +12,8 @@ import (
|
|||
"github.com/pomerium/pomerium/authorize/evaluator/opa"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/cryptutil"
|
||||
"github.com/pomerium/pomerium/internal/encoding"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/telemetry/metrics"
|
||||
"github.com/pomerium/pomerium/internal/telemetry/trace"
|
||||
|
@ -31,11 +33,24 @@ func (a *atomicOptions) Store(options config.Options) {
|
|||
a.value.Store(options)
|
||||
}
|
||||
|
||||
type atomicMarshalUnmarshaler struct {
|
||||
value atomic.Value
|
||||
}
|
||||
|
||||
func (a *atomicMarshalUnmarshaler) Load() encoding.MarshalUnmarshaler {
|
||||
return a.value.Load().(encoding.MarshalUnmarshaler)
|
||||
}
|
||||
|
||||
func (a *atomicMarshalUnmarshaler) Store(encoder encoding.MarshalUnmarshaler) {
|
||||
a.value.Store(encoder)
|
||||
}
|
||||
|
||||
// Authorize struct holds
|
||||
type Authorize struct {
|
||||
pe evaluator.Evaluator
|
||||
|
||||
currentOptions atomicOptions
|
||||
currentEncoder atomicMarshalUnmarshaler
|
||||
}
|
||||
|
||||
// New validates and creates a new Authorize service from a set of config options.
|
||||
|
@ -44,8 +59,19 @@ func New(opts config.Options) (*Authorize, error) {
|
|||
return nil, fmt.Errorf("authorize: bad options: %w", err)
|
||||
}
|
||||
var a Authorize
|
||||
|
||||
var host string
|
||||
if opts.AuthenticateURL != nil {
|
||||
host = opts.AuthenticateURL.Host
|
||||
}
|
||||
encoder, err := jws.NewHS256Signer([]byte(opts.SharedKey), host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.currentEncoder.Store(encoder)
|
||||
|
||||
a.currentOptions.Store(config.Options{})
|
||||
err := a.UpdateOptions(opts)
|
||||
err = a.UpdateOptions(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -2,13 +2,17 @@ package authorize
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
||||
|
@ -35,10 +39,26 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
|
|||
hattrs := in.GetAttributes().GetRequest().GetHttp()
|
||||
|
||||
hdrs := getCheckRequestHeaders(in)
|
||||
|
||||
var requestHeaders []*envoy_api_v2_core.HeaderValueOption
|
||||
sess, sesserr := a.loadSessionFromCheckRequest(in)
|
||||
if a.isExpired(sess) {
|
||||
log.Info().Msg("refreshing session")
|
||||
if newSession, err := a.refreshSession(ctx, sess); err == nil {
|
||||
sess = newSession
|
||||
sesserr = nil
|
||||
requestHeaders, err = a.getEnvoyRequestHeaders(sess)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("authorize: error generating new request headers")
|
||||
}
|
||||
} else {
|
||||
log.Warn().Err(err).Msg("authorize: error refreshing session")
|
||||
}
|
||||
}
|
||||
|
||||
requestURL := getCheckRequestURL(in)
|
||||
req := &evaluator.Request{
|
||||
User: sess,
|
||||
User: string(sess),
|
||||
Header: hdrs,
|
||||
Host: hattrs.GetHost(),
|
||||
Method: hattrs.GetMethod(),
|
||||
|
@ -65,12 +85,17 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
|
|||
evt = evt.Strs("deny-reasons", reply.GetDenyReasons())
|
||||
evt = evt.Str("email", reply.GetEmail())
|
||||
evt = evt.Strs("groups", reply.GetGroups())
|
||||
evt = evt.Str("session", string(sess))
|
||||
evt.Msg("authorize check")
|
||||
|
||||
if reply.Allow {
|
||||
return &envoy_service_auth_v2.CheckResponse{
|
||||
Status: &status.Status{Code: int32(codes.OK), Message: "OK"},
|
||||
HttpResponse: &envoy_service_auth_v2.CheckResponse_OkResponse{OkResponse: &envoy_service_auth_v2.OkHttpResponse{}},
|
||||
HttpResponse: &envoy_service_auth_v2.CheckResponse_OkResponse{
|
||||
OkResponse: &envoy_service_auth_v2.OkHttpResponse{
|
||||
Headers: requestHeaders,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -136,15 +161,100 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v2.CheckRe
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (a *Authorize) loadSessionFromCheckRequest(req *envoy_service_auth_v2.CheckRequest) (string, error) {
|
||||
opts := a.currentOptions.Load()
|
||||
|
||||
// used to load and verify JWT tokens signed by the authenticate service
|
||||
encoder, err := jws.NewHS256Signer([]byte(opts.SharedKey), opts.AuthenticateURL.Host)
|
||||
func (a *Authorize) getEnvoyRequestHeaders(rawSession []byte) ([]*envoy_api_v2_core.HeaderValueOption, error) {
|
||||
cookieStore, err := a.getCookieStore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
err = cookieStore.SaveSession(recorder, nil /* unused by cookie store */, string(rawSession))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("authorize: error saving cookie: %w", err)
|
||||
}
|
||||
|
||||
var hvos []*envoy_api_v2_core.HeaderValueOption
|
||||
for k, vs := range recorder.Header() {
|
||||
for _, v := range vs {
|
||||
hvos = append(hvos, &envoy_api_v2_core.HeaderValueOption{
|
||||
Header: &envoy_api_v2_core.HeaderValue{
|
||||
Key: "x-pomerium-" + k,
|
||||
Value: v,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return hvos, nil
|
||||
}
|
||||
|
||||
func (a *Authorize) refreshSession(ctx context.Context, rawSession []byte) (newSession []byte, err error) {
|
||||
options := a.currentOptions.Load()
|
||||
encoder := a.currentEncoder.Load()
|
||||
|
||||
var state sessions.State
|
||||
if err := encoder.Unmarshal(rawSession, &state); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling raw session: %w", err)
|
||||
}
|
||||
|
||||
// 1 - build a signed url to call refresh on authenticate service
|
||||
refreshURI := options.AuthenticateURL.ResolveReference(&url.URL{Path: "/.pomerium/refresh"})
|
||||
q := refreshURI.Query()
|
||||
q.Set(urlutil.QueryAccessTokenID, state.AccessTokenID) // hash value points to parent token
|
||||
q.Set(urlutil.QueryAudience, strings.Join(state.Audience, ",")) // request's audience, this route
|
||||
refreshURI.RawQuery = q.Encode()
|
||||
signedRefreshURL := urlutil.NewSignedURL(options.SharedKey, refreshURI).String()
|
||||
|
||||
// 2 - http call to authenticate service
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, signedRefreshURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("authorize: refresh request: %w", err)
|
||||
}
|
||||
req.Header.Set("X-Requested-With", "XmlHttpRequest")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
res, err := httputil.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("authorize: client err %s: %w", signedRefreshURL, err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
newJwt, err := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// auth couldn't refresh the session, delete the session and reload via 302
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("authorize: backend refresh failed: %s", newJwt)
|
||||
}
|
||||
return newJwt, nil
|
||||
}
|
||||
|
||||
func (a *Authorize) loadSessionFromCheckRequest(req *envoy_service_auth_v2.CheckRequest) ([]byte, error) {
|
||||
cookieStore, err := a.getCookieStore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sess, err := cookieStore.LoadSession(&http.Request{
|
||||
Header: getCheckRequestHeaders(req),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []byte(sess), nil
|
||||
}
|
||||
|
||||
func (a *Authorize) isExpired(rawSession []byte) bool {
|
||||
state := sessions.State{}
|
||||
err := a.currentEncoder.Load().Unmarshal(rawSession, &state)
|
||||
return err == nil && state.IsExpired()
|
||||
}
|
||||
|
||||
func (a *Authorize) getCookieStore() (sessions.SessionStore, error) {
|
||||
opts := a.currentOptions.Load()
|
||||
encoder := a.currentEncoder.Load()
|
||||
|
||||
cookieOptions := &cookie.Options{
|
||||
Name: opts.CookieName,
|
||||
Domain: opts.CookieDomain,
|
||||
|
@ -155,13 +265,9 @@ func (a *Authorize) loadSessionFromCheckRequest(req *envoy_service_auth_v2.Check
|
|||
|
||||
cookieStore, err := cookie.NewStore(cookieOptions, encoder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sess, err := cookieStore.LoadSession(&http.Request{
|
||||
Header: http.Header(getCheckRequestHeaders(req)),
|
||||
})
|
||||
return sess, err
|
||||
return cookieStore, nil
|
||||
}
|
||||
|
||||
func getFullURL(rawurl, host string) string {
|
||||
|
|
|
@ -7,8 +7,9 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/integration/internal/flows"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/pomerium/pomerium/integration/internal/flows"
|
||||
)
|
||||
|
||||
func TestAuthorization(t *testing.T) {
|
||||
|
@ -34,14 +35,16 @@ func TestAuthorization(t *testing.T) {
|
|||
t.Run("domains", func(t *testing.T) {
|
||||
t.Run("allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"), "bob@dogs.test", []string{"user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||
flows.WithEmail("bob@dogs.test"), flows.WithGroups("user"))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for dogs.test")
|
||||
}
|
||||
})
|
||||
t.Run("not allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"), "joe@cats.test", []string{"user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||
flows.WithEmail("joe@cats.test"), flows.WithGroups("user"))
|
||||
if assert.NoError(t, err) {
|
||||
assertDeniedAccess(t, res, "expected Forbidden for cats.test")
|
||||
}
|
||||
|
@ -50,14 +53,16 @@ func TestAuthorization(t *testing.T) {
|
|||
t.Run("users", func(t *testing.T) {
|
||||
t.Run("allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-user"), "bob@dogs.test", []string{"user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-user"),
|
||||
flows.WithEmail("bob@dogs.test"), flows.WithGroups("user"))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for bob@dogs.test")
|
||||
}
|
||||
})
|
||||
t.Run("not allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-user"), "joe@cats.test", []string{"user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-user"),
|
||||
flows.WithEmail("joe@cats.test"), flows.WithGroups("user"))
|
||||
if assert.NoError(t, err) {
|
||||
assertDeniedAccess(t, res, "expected Forbidden for joe@cats.test")
|
||||
}
|
||||
|
@ -66,19 +71,61 @@ func TestAuthorization(t *testing.T) {
|
|||
t.Run("groups", func(t *testing.T) {
|
||||
t.Run("allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"), "bob@dogs.test", []string{"admin", "user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"),
|
||||
flows.WithEmail("bob@dogs.test"), flows.WithGroups("admin", "user"))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for admin")
|
||||
}
|
||||
})
|
||||
t.Run("not allowed", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"), "joe@cats.test", []string{"user"})
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"),
|
||||
flows.WithEmail("joe@cats.test"), flows.WithGroups("user"))
|
||||
if assert.NoError(t, err) {
|
||||
assertDeniedAccess(t, res, "expected Forbidden for user, but got %d", res.StatusCode)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("refresh", func(t *testing.T) {
|
||||
client := testcluster.NewHTTPClient()
|
||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||
flows.WithEmail("bob@dogs.test"), flows.WithGroups("user"), flows.WithTokenExpiration(time.Second))
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for dogs.test")
|
||||
res.Body.Close()
|
||||
|
||||
// poll till we get a new cookie because of a refreshed session
|
||||
ticker := time.NewTicker(time.Millisecond * 500)
|
||||
defer ticker.Stop()
|
||||
deadline := time.NewTimer(time.Second * 10)
|
||||
defer deadline.Stop()
|
||||
for i := 0; ; i++ {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-deadline.C:
|
||||
t.Fatal("timed out waiting for refreshed session")
|
||||
return
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timed out waiting for refreshed session")
|
||||
return
|
||||
}
|
||||
|
||||
res, err = client.Get(mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain").String())
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
res.Body.Close()
|
||||
if !assert.Equal(t, http.StatusOK, res.StatusCode, "failed after %d times", i+1) {
|
||||
return
|
||||
}
|
||||
if res.Header.Get("Set-Cookie") != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func mustParseURL(str string) *url.URL {
|
||||
|
|
|
@ -6,7 +6,9 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/integration/internal/forms"
|
||||
)
|
||||
|
@ -17,9 +19,50 @@ const (
|
|||
pomeriumCallbackPath = "/.pomerium/callback/"
|
||||
)
|
||||
|
||||
type authenticateConfig struct {
|
||||
email string
|
||||
groups []string
|
||||
tokenExpiration time.Duration
|
||||
}
|
||||
|
||||
// An AuthenticateOption is an option for authentication.
|
||||
type AuthenticateOption func(cfg *authenticateConfig)
|
||||
|
||||
func getAuthenticateConfig(options ...AuthenticateOption) *authenticateConfig {
|
||||
cfg := &authenticateConfig{
|
||||
tokenExpiration: time.Hour * 24,
|
||||
}
|
||||
for _, option := range options {
|
||||
option(cfg)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
// WithEmail sets the email to use.
|
||||
func WithEmail(email string) AuthenticateOption {
|
||||
return func(cfg *authenticateConfig) {
|
||||
cfg.email = email
|
||||
}
|
||||
}
|
||||
|
||||
// WithGroups sets the groups to use.
|
||||
func WithGroups(groups ...string) AuthenticateOption {
|
||||
return func(cfg *authenticateConfig) {
|
||||
cfg.groups = groups
|
||||
}
|
||||
}
|
||||
|
||||
// WithTokenExpiration sets the token expiration.
|
||||
func WithTokenExpiration(tokenExpiration time.Duration) AuthenticateOption {
|
||||
return func(cfg *authenticateConfig) {
|
||||
cfg.tokenExpiration = tokenExpiration
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate submits a request to a URL, expects a redirect to authenticate and then openid and logs in.
|
||||
// Finally it expects to redirect back to the original page.
|
||||
func Authenticate(ctx context.Context, client *http.Client, url *url.URL, email string, groups []string) (*http.Response, error) {
|
||||
func Authenticate(ctx context.Context, client *http.Client, url *url.URL, options ...AuthenticateOption) (*http.Response, error) {
|
||||
cfg := getAuthenticateConfig(options...)
|
||||
originalHostname := url.Hostname()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url.String(), nil)
|
||||
|
@ -68,8 +111,11 @@ func Authenticate(ctx context.Context, client *http.Client, url *url.URL, email
|
|||
forms := forms.Parse(res.Body)
|
||||
if len(forms) > 0 {
|
||||
f := forms[0]
|
||||
f.Inputs["email"] = email
|
||||
f.Inputs["groups"] = strings.Join(groups, ",")
|
||||
f.Inputs["email"] = cfg.email
|
||||
if len(cfg.groups) > 0 {
|
||||
f.Inputs["groups"] = strings.Join(cfg.groups, ",")
|
||||
}
|
||||
f.Inputs["token_expiration"] = strconv.Itoa(int(cfg.tokenExpiration.Seconds()))
|
||||
req, err = f.NewRequestWithContext(ctx, req.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -178,6 +178,7 @@ local PomeriumDeployment = function(svc) {
|
|||
ip: '10.96.1.1',
|
||||
hostnames: [
|
||||
'openid.localhost.pomerium.io',
|
||||
'authenticate.localhost.pomerium.io'
|
||||
],
|
||||
}],
|
||||
initContainers: [{
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
envoy_config_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
|
|
@ -9,11 +9,13 @@ import (
|
|||
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
||||
envoy_extensions_filters_http_lua_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3"
|
||||
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
@ -99,6 +101,28 @@ func (srv *Server) buildHTTPListener(options config.Options) *envoy_config_liste
|
|||
},
|
||||
})
|
||||
|
||||
luaConfig, _ := ptypes.MarshalAny(&envoy_extensions_filters_http_lua_v3.Lua{
|
||||
InlineCode: `
|
||||
function envoy_on_request(request_handle)
|
||||
local headers = request_handle:headers()
|
||||
local dynamic_meta = request_handle:streamInfo():dynamicMetadata()
|
||||
if headers:get("x-pomerium-set-cookie") ~= nil then
|
||||
dynamic_meta:set("envoy.filters.http.lua", "pomerium_set_cookie", headers:get("x-pomerium-set-cookie"))
|
||||
headers:remove("x-pomerium-set-cookie")
|
||||
end
|
||||
end
|
||||
|
||||
function envoy_on_response(response_handle)
|
||||
local headers = response_handle:headers()
|
||||
local dynamic_meta = response_handle:streamInfo():dynamicMetadata()
|
||||
local tbl = dynamic_meta:get("envoy.filters.http.lua")
|
||||
if tbl ~= nil and tbl["pomerium_set_cookie"] ~= nil then
|
||||
headers:add("set-cookie", tbl["pomerium_set_cookie"])
|
||||
end
|
||||
end
|
||||
`,
|
||||
})
|
||||
|
||||
tc, _ := ptypes.MarshalAny(&envoy_http_connection_manager.HttpConnectionManager{
|
||||
CodecType: envoy_http_connection_manager.HttpConnectionManager_AUTO,
|
||||
StatPrefix: "ingress",
|
||||
|
@ -115,6 +139,12 @@ func (srv *Server) buildHTTPListener(options config.Options) *envoy_config_liste
|
|||
TypedConfig: extAuthZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "envoy.filters.http.lua",
|
||||
ConfigType: &envoy_http_connection_manager.HttpFilter_TypedConfig{
|
||||
TypedConfig: luaConfig,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "envoy.filters.http.router",
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue