mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-29 22:48:15 +02:00
Merge remote-tracking branch 'origin/main' into cdoxsey/remove-identity-provider
This commit is contained in:
commit
aada204557
42 changed files with 587 additions and 415 deletions
4
.github/workflows/docker-main.yaml
vendored
4
.github/workflows/docker-main.yaml
vendored
|
@ -83,14 +83,14 @@ jobs:
|
|||
token: ${{ secrets.APPARITOR_GITHUB_TOKEN }}
|
||||
|
||||
- name: Bump psql environment
|
||||
uses: mikefarah/yq@1f0881fb5faf371694bfa108753cda0b824f5037
|
||||
uses: mikefarah/yq@5e490527de24715db37869037083f7f391dde5a6
|
||||
with:
|
||||
cmd:
|
||||
yq eval '.pomerium.image.tag = "${{ needs.publish.outputs.sha-tag }}"' -i
|
||||
projects/pomerium-master-postgres/pomerium/values.yaml
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@fd157da78fa13d9383e5580d1fd1184d89554b51
|
||||
uses: stefanzweifel/git-auto-commit-action@0049e3fa4059ca715255fbbcb7dea4516f02ce0a
|
||||
with:
|
||||
commit_message: |
|
||||
Bump test environment pomerium/pomerium
|
||||
|
|
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
|
@ -122,12 +122,12 @@ jobs:
|
|||
token: ${{ secrets.APPARITOR_GITHUB_TOKEN }}
|
||||
|
||||
- name: Bump test environment
|
||||
uses: mikefarah/yq@1f0881fb5faf371694bfa108753cda0b824f5037
|
||||
uses: mikefarah/yq@5e490527de24715db37869037083f7f391dde5a6
|
||||
with:
|
||||
cmd: yq eval '.pomerium.image.tag = "${{ needs.goreleaser.outputs.tag }}"' -i projects/pomerium-demo/pomerium-demo/values.yaml
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@fd157da78fa13d9383e5580d1fd1184d89554b51
|
||||
uses: stefanzweifel/git-auto-commit-action@0049e3fa4059ca715255fbbcb7dea4516f02ce0a
|
||||
with:
|
||||
commit_message: |
|
||||
Bump test environment pomerium/pomerium
|
||||
|
|
4
.github/workflows/test.yaml
vendored
4
.github/workflows/test.yaml
vendored
|
@ -192,7 +192,7 @@ jobs:
|
|||
make build
|
||||
|
||||
- name: save binary
|
||||
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
|
||||
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
||||
with:
|
||||
path: bin/pomerium*
|
||||
name: pomerium ${{ github.run_id }} ${{ matrix.platform }}
|
||||
|
@ -252,7 +252,7 @@ jobs:
|
|||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
||||
|
||||
- name: retrieve binary
|
||||
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741
|
||||
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7
|
||||
with:
|
||||
name: pomerium ${{ github.run_id }} ${{ matrix.platform }}
|
||||
path: bin/
|
||||
|
|
|
@ -13,7 +13,7 @@ RUN make yarn
|
|||
COPY ./ui/ ./ui/
|
||||
RUN make build-ui
|
||||
|
||||
FROM golang:1.19.2-buster@sha256:403f38941d7643bc91fad0227ebee6ddd80159b79fc339f6702271a2679a5f11 as build
|
||||
FROM golang:1.19.2-buster@sha256:b4480899915b13370161a7e574174212b21baccade35b4df86358d76f83da7f9 as build
|
||||
WORKDIR /go/src/github.com/pomerium/pomerium
|
||||
|
||||
RUN apt-get update \
|
||||
|
@ -30,12 +30,12 @@ RUN make build-go NAME=pomerium
|
|||
RUN touch /config.yaml
|
||||
|
||||
# build our own root trust store from current stable
|
||||
FROM debian:stable@sha256:1b1d158efc589b1eb8858acdc95bd0ff4c5344958f834b7326662da8482b3e7d as casource
|
||||
FROM debian:stable@sha256:9583740c100697a7dd186b80198a66ad24927e03437414559f90e0ed2639346e as casource
|
||||
RUN apt-get update && apt-get install -y ca-certificates
|
||||
# Remove expired root (https://github.com/pomerium/pomerium/issues/2653)
|
||||
RUN rm /usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt && update-ca-certificates
|
||||
|
||||
FROM gcr.io/distroless/base:debug@sha256:9681f07e699fa65958ef9b902399d618cb6a4638868d468cf730a2bafd8f3dcc
|
||||
FROM gcr.io/distroless/base:debug@sha256:856944e81ffb36babf549e52933e1c09379372135a9b73a97f275fa2973de13a
|
||||
ENV AUTOCERT_DIR /data/autocert
|
||||
WORKDIR /pomerium
|
||||
COPY --from=build /go/src/github.com/pomerium/pomerium/bin/* /bin/
|
||||
|
|
|
@ -13,7 +13,7 @@ RUN make yarn
|
|||
COPY ./ui/ ./ui/
|
||||
RUN make build-ui
|
||||
|
||||
FROM golang:1.19.2-buster@sha256:403f38941d7643bc91fad0227ebee6ddd80159b79fc339f6702271a2679a5f11 as build
|
||||
FROM golang:1.19.2-buster@sha256:b4480899915b13370161a7e574174212b21baccade35b4df86358d76f83da7f9 as build
|
||||
WORKDIR /go/src/github.com/pomerium/pomerium
|
||||
|
||||
RUN apt-get update \
|
||||
|
|
|
@ -73,7 +73,6 @@ func (a *Authenticate) Mount(r *mux.Router) {
|
|||
r.Path("/oauth2/callback").Handler(httputil.HandlerFunc(a.OAuthCallback)).Methods(http.MethodGet)
|
||||
|
||||
a.mountDashboard(r)
|
||||
a.mountWellKnown(r)
|
||||
}
|
||||
|
||||
func (a *Authenticate) mountDashboard(r *mux.Router) {
|
||||
|
@ -111,22 +110,9 @@ func (a *Authenticate) mountDashboard(r *mux.Router) {
|
|||
cr.Path("/").Handler(a.requireValidSignature(a.Callback)).Methods(http.MethodGet)
|
||||
}
|
||||
|
||||
func (a *Authenticate) mountWellKnown(r *mux.Router) {
|
||||
r.Path("/.well-known/pomerium/jwks.json").Handler(cors.AllowAll().Handler(httputil.HandlerFunc(a.jwks))).Methods(http.MethodGet)
|
||||
}
|
||||
|
||||
// jwks returns the signing key(s) the client can use to validate signatures
|
||||
// from the authorization server.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc8414
|
||||
func (a *Authenticate) jwks(w http.ResponseWriter, r *http.Request) error {
|
||||
httputil.RenderJSON(w, http.StatusOK, a.state.Load().jwk)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RetrieveSession is the middleware used retrieve session by the sessionLoaders
|
||||
// RetrieveSession is the middleware used retrieve session by the sessionLoader
|
||||
func (a *Authenticate) RetrieveSession(next http.Handler) http.Handler {
|
||||
return sessions.RetrieveSession(a.state.Load().sessionLoaders...)(next)
|
||||
return sessions.RetrieveSession(a.state.Load().sessionLoader)(next)
|
||||
}
|
||||
|
||||
// VerifySession is the middleware used to enforce a valid authentication
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package webauthn
|
||||
|
||||
import "github.com/pomerium/pomerium/pkg/grpc/session"
|
||||
|
||||
func containsString(elements []string, value string) bool {
|
||||
for _, element := range elements {
|
||||
if element == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func removeString(elements []string, value string) []string {
|
||||
dup := make([]string, 0, len(elements))
|
||||
for _, element := range elements {
|
||||
if element != value {
|
||||
dup = append(dup, element)
|
||||
}
|
||||
}
|
||||
return dup
|
||||
}
|
||||
|
||||
func removeSessionDeviceCredential(elements []*session.Session_DeviceCredential, id string) []*session.Session_DeviceCredential {
|
||||
dup := make([]*session.Session_DeviceCredential, 0, len(elements))
|
||||
for _, element := range elements {
|
||||
if element.GetId() != id {
|
||||
dup = append(dup, element)
|
||||
}
|
||||
}
|
||||
return dup
|
||||
}
|
|
@ -324,7 +324,7 @@ func (h *Handler) handleRegister(w http.ResponseWriter, r *http.Request, state *
|
|||
}
|
||||
|
||||
// save the user
|
||||
u.DeviceCredentialIds = append(u.DeviceCredentialIds, deviceCredential.GetId())
|
||||
u.AddDeviceCredentialID(deviceCredential.GetId())
|
||||
_, err = databroker.Put(ctx, state.Client, u)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -356,7 +356,7 @@ func (h *Handler) handleUnregister(w http.ResponseWriter, r *http.Request, state
|
|||
}
|
||||
|
||||
// ensure we only allow removing a device credential the user owns
|
||||
if !containsString(u.GetDeviceCredentialIds(), deviceCredentialID) {
|
||||
if !u.HasDeviceCredentialID(deviceCredentialID) {
|
||||
return errInvalidDeviceCredential
|
||||
}
|
||||
|
||||
|
@ -373,14 +373,14 @@ func (h *Handler) handleUnregister(w http.ResponseWriter, r *http.Request, state
|
|||
}
|
||||
|
||||
// remove the credential from the user
|
||||
u.DeviceCredentialIds = removeString(u.DeviceCredentialIds, deviceCredentialID)
|
||||
u.RemoveDeviceCredentialID(deviceCredentialID)
|
||||
_, err = databroker.Put(ctx, state.Client, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove the credential from the session
|
||||
state.Session.DeviceCredentials = removeSessionDeviceCredential(state.Session.DeviceCredentials, deviceCredentialID)
|
||||
state.Session.RemoveDeviceCredentialID(deviceCredentialID)
|
||||
return h.saveSessionAndRedirect(w, r, state, urlutil.GetAbsoluteURL(r).ResolveReference(&url.URL{
|
||||
Path: "/.pomerium",
|
||||
}).String())
|
||||
|
|
|
@ -289,7 +289,7 @@ func TestAuthenticate_SignOut(t *testing.T) {
|
|||
identity.MockProvider{LogOutResponse: (*uriParseHelper("https://microsoft.com"))},
|
||||
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
||||
http.StatusOK,
|
||||
"{\"Status\":200,\"Error\":\"OK: user logged out\"}\n",
|
||||
"{\"Status\":200}\n",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -587,27 +587,6 @@ func TestAuthenticate_SessionValidatorMiddleware(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestJwksEndpoint(t *testing.T) {
|
||||
o := newTestOptions(t)
|
||||
o.SigningKey = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUpCMFZkbko1VjEvbVlpYUlIWHhnd2Q0Yzd5YWRTeXMxb3Y0bzA1b0F3ekdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUc1eENQMEpUVDFINklvbDhqS3VUSVBWTE0wNENnVzlQbEV5cE5SbVdsb29LRVhSOUhUMwpPYnp6aktZaWN6YjArMUt3VjJmTVRFMTh1dy82MXJVQ0JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
||||
auth, err := New(&config.Config{Options: o})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
return
|
||||
}
|
||||
h := auth.Handler()
|
||||
if h == nil {
|
||||
t.Error("handler cannot be nil")
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/.well-known/pomerium/jwks.json", nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
rr := httptest.NewRecorder()
|
||||
h.ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
expected := "{\"keys\":[{\"use\":\"sig\",\"kty\":\"EC\",\"kid\":\"5b419ade1895fec2d2def6cd33b1b9a018df60db231dc5ecb85cbed6d942813c\",\"crv\":\"P-256\",\"alg\":\"ES256\",\"x\":\"UG5xCP0JTT1H6Iol8jKuTIPVLM04CgW9PlEypNRmWlo\",\"y\":\"KChF0fR09zm884ymInM29PtSsFdnzExNfLsP-ta1AgQ\"}]}\n"
|
||||
assert.Equal(t, expected, body)
|
||||
}
|
||||
|
||||
func TestAuthenticate_userInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ type authenticateState struct {
|
|||
sessionStore sessions.SessionStore
|
||||
// sessionLoaders are a collection of session loaders to attempt to pull
|
||||
// a user's session state from
|
||||
sessionLoaders []sessions.SessionLoader
|
||||
sessionLoader sessions.SessionLoader
|
||||
|
||||
jwk *jose.JSONWebKeySet
|
||||
|
||||
|
@ -118,7 +118,7 @@ func newAuthenticateStateFromConfig(cfg *config.Config) (*authenticateState, err
|
|||
}
|
||||
|
||||
state.sessionStore = cookieStore
|
||||
state.sessionLoaders = []sessions.SessionLoader{cookieStore}
|
||||
state.sessionLoader = cookieStore
|
||||
state.jwk = new(jose.JSONWebKeySet)
|
||||
signingKey, err := cfg.Options.GetSigningKey()
|
||||
if err != nil {
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/pomerium/pomerium/authorize/internal/store"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/atomicutil"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/testutil"
|
||||
"github.com/pomerium/pomerium/pkg/policy/criteria"
|
||||
)
|
||||
|
@ -68,8 +67,6 @@ func TestAuthorize_okResponse(t *testing.T) {
|
|||
JWTClaimsHeaders: config.NewJWTClaimHeaders("email"),
|
||||
}
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
encoder, _ := jws.NewHS256Signer([]byte{0, 0, 0, 0})
|
||||
a.state.Load().encoder = encoder
|
||||
a.currentOptions.Store(opt)
|
||||
a.store = store.New()
|
||||
pe, err := newPolicyEvaluator(opt, a.store)
|
||||
|
@ -124,8 +121,6 @@ func TestAuthorize_okResponse(t *testing.T) {
|
|||
|
||||
func TestAuthorize_deniedResponse(t *testing.T) {
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
encoder, _ := jws.NewHS256Signer([]byte{0, 0, 0, 0})
|
||||
a.state.Load().encoder = encoder
|
||||
a.currentOptions.Store(&config.Options{
|
||||
Policies: []config.Policy{{
|
||||
Source: &config.StringURL{URL: &url.URL{Host: "example.com"}},
|
||||
|
|
|
@ -55,8 +55,7 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v3.CheckRe
|
|||
}
|
||||
}
|
||||
|
||||
rawJWT, _ := loadRawSession(hreq, a.currentOptions.Load(), state.encoder)
|
||||
sessionState, _ := loadSession(state.encoder, rawJWT)
|
||||
sessionState, _ := state.sessionStore.LoadSessionState(hreq)
|
||||
|
||||
var s sessionOrServiceAccount
|
||||
var u *user.User
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/atomicutil"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
|
@ -48,8 +47,6 @@ yE+vPxsiUkvQHdO2fojCkY8jg70jxM+gu59tPDNbw3Uh/2Ij310FgTHsnGQMyA==
|
|||
|
||||
func Test_getEvaluatorRequest(t *testing.T) {
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
encoder, _ := jws.NewHS256Signer([]byte{0, 0, 0, 0})
|
||||
a.state.Load().encoder = encoder
|
||||
a.currentOptions.Store(&config.Options{
|
||||
Policies: []config.Policy{{
|
||||
Source: &config.StringURL{URL: &url.URL{Host: "example.com"}},
|
||||
|
@ -262,8 +259,6 @@ func Test_handleForwardAuth(t *testing.T) {
|
|||
|
||||
func Test_getEvaluatorRequestWithPortInHostHeader(t *testing.T) {
|
||||
a := &Authorize{currentOptions: config.NewAtomicOptions(), state: atomicutil.NewValue(new(authorizeState))}
|
||||
encoder, _ := jws.NewHS256Signer([]byte{0, 0, 0, 0})
|
||||
a.state.Load().encoder = encoder
|
||||
a.currentOptions.Store(&config.Options{
|
||||
Policies: []config.Policy{{
|
||||
Source: &config.StringURL{URL: &url.URL{Host: "example.com"}},
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
package authorize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/encoding"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
||||
"github.com/pomerium/pomerium/internal/sessions/header"
|
||||
"github.com/pomerium/pomerium/internal/sessions/queryparam"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
func loadRawSession(req *http.Request, options *config.Options, encoder encoding.MarshalUnmarshaler) ([]byte, error) {
|
||||
var loaders []sessions.SessionLoader
|
||||
cookieStore, err := getCookieStore(options, encoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loaders = append(loaders,
|
||||
cookieStore,
|
||||
header.NewStore(encoder),
|
||||
queryparam.NewStore(encoder, urlutil.QuerySession),
|
||||
)
|
||||
|
||||
for _, loader := range loaders {
|
||||
sess, err := loader.LoadSession(req)
|
||||
if err != nil && !errors.Is(err, sessions.ErrNoSessionFound) {
|
||||
return nil, err
|
||||
} else if err == nil {
|
||||
return []byte(sess), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, sessions.ErrNoSessionFound
|
||||
}
|
||||
|
||||
func loadSession(encoder encoding.MarshalUnmarshaler, rawJWT []byte) (*sessions.State, error) {
|
||||
var s sessions.State
|
||||
err := encoder.Unmarshal(rawJWT, &s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func getCookieStore(options *config.Options, encoder encoding.MarshalUnmarshaler) (sessions.SessionStore, error) {
|
||||
cookieStore, err := cookie.NewStore(func() cookie.Options {
|
||||
return cookie.Options{
|
||||
Name: options.CookieName,
|
||||
Domain: options.CookieDomain,
|
||||
Secure: options.CookieSecure,
|
||||
HTTPOnly: options.CookieHTTPOnly,
|
||||
Expire: options.CookieExpire,
|
||||
}
|
||||
}, encoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cookieStore, nil
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package authorize
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
)
|
||||
|
||||
func TestLoadSession(t *testing.T) {
|
||||
opts := config.NewDefaultOptions()
|
||||
encoder, err := jws.NewHS256Signer(nil)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
state := &sessions.State{ID: "xyz"}
|
||||
rawjwt, err := encoder.Marshal(state)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
load := func(t *testing.T, hattrs *envoy_service_auth_v3.AttributeContext_HttpRequest) (*sessions.State, error) {
|
||||
req := getHTTPRequestFromCheckRequest(&envoy_service_auth_v3.CheckRequest{
|
||||
Attributes: &envoy_service_auth_v3.AttributeContext{
|
||||
Request: &envoy_service_auth_v3.AttributeContext_Request{
|
||||
Http: hattrs,
|
||||
},
|
||||
},
|
||||
})
|
||||
raw, err := loadRawSession(req, opts, encoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var state sessions.State
|
||||
err = encoder.Unmarshal(raw, &state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
t.Run("header", func(t *testing.T) {
|
||||
hattrs := &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Id: "req-1",
|
||||
Method: "GET",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "Pomerium " + string(rawjwt),
|
||||
},
|
||||
Path: "/hello/world",
|
||||
Host: "example.com",
|
||||
Scheme: "https",
|
||||
}
|
||||
sess, err := load(t, hattrs)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, sess)
|
||||
})
|
||||
t.Run("query param", func(t *testing.T) {
|
||||
hattrs := &envoy_service_auth_v3.AttributeContext_HttpRequest{
|
||||
Id: "req-1",
|
||||
Method: "GET",
|
||||
Path: "/hello/world?" + url.Values{
|
||||
"pomerium_session": []string{string(rawjwt)},
|
||||
}.Encode(),
|
||||
Host: "example.com",
|
||||
Scheme: "https",
|
||||
}
|
||||
sess, err := load(t, hattrs)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, sess)
|
||||
})
|
||||
}
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||
"github.com/pomerium/pomerium/authorize/internal/store"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/encoding"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/pkg/grpc"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
"github.com/pomerium/pomerium/pkg/protoutil"
|
||||
|
@ -21,10 +19,10 @@ var outboundGRPCConnection = new(grpc.CachedOutboundGRPClientConn)
|
|||
type authorizeState struct {
|
||||
sharedKey []byte
|
||||
evaluator *evaluator.Evaluator
|
||||
encoder encoding.MarshalUnmarshaler
|
||||
dataBrokerClientConnection *googlegrpc.ClientConn
|
||||
dataBrokerClient databroker.DataBrokerServiceClient
|
||||
auditEncryptor *protoutil.Encryptor
|
||||
sessionStore *config.SessionStore
|
||||
}
|
||||
|
||||
func newAuthorizeStateFromConfig(cfg *config.Config, store *store.Store) (*authorizeState, error) {
|
||||
|
@ -46,11 +44,6 @@ func newAuthorizeStateFromConfig(cfg *config.Config, store *store.Store) (*autho
|
|||
return nil, err
|
||||
}
|
||||
|
||||
state.encoder, err = jws.NewHS256Signer(state.sharedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sharedKey, err := cfg.Options.GetSharedKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -76,5 +69,10 @@ func newAuthorizeStateFromConfig(cfg *config.Config, store *store.Store) (*autho
|
|||
state.auditEncryptor = protoutil.NewEncryptor(auditKey)
|
||||
}
|
||||
|
||||
state.sessionStore, err = config.NewSessionStore(cfg.Options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("authorize: invalid session store: %w", err)
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
|
|||
}
|
||||
if len(authorizeURLs) > 1 {
|
||||
authorizeCluster.HealthChecks = grpcHealthChecks("pomerium-authorize")
|
||||
authorizeCluster.OutlierDetection = grpcAuthorizeOutlierDetection()
|
||||
authorizeCluster.OutlierDetection = grpcOutlierDetection()
|
||||
}
|
||||
|
||||
databrokerCluster, err := b.buildInternalCluster(ctx, cfg.Options, "pomerium-databroker", databrokerURLs, upstreamProtocolHTTP2)
|
||||
|
@ -75,8 +75,8 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
|
|||
return nil, err
|
||||
}
|
||||
if len(databrokerURLs) > 1 {
|
||||
authorizeCluster.HealthChecks = grpcHealthChecks("pomerium-databroker")
|
||||
authorizeCluster.OutlierDetection = grpcAuthorizeOutlierDetection()
|
||||
databrokerCluster.HealthChecks = grpcHealthChecks("pomerium-databroker")
|
||||
databrokerCluster.OutlierDetection = grpcOutlierDetection()
|
||||
}
|
||||
|
||||
envoyAdminCluster, err := b.buildEnvoyAdminCluster(ctx, cfg)
|
||||
|
@ -406,8 +406,8 @@ func (b *Builder) buildCluster(
|
|||
return cluster.Validate()
|
||||
}
|
||||
|
||||
// grpcAuthorizeOutlierDetection defines slightly more aggressive malfunction detection for authorize endpoints
|
||||
func grpcAuthorizeOutlierDetection() *envoy_config_cluster_v3.OutlierDetection {
|
||||
// grpcOutlierDetection defines slightly more aggressive malfunction detection for grpc endpoints
|
||||
func grpcOutlierDetection() *envoy_config_cluster_v3.OutlierDetection {
|
||||
return &envoy_config_cluster_v3.OutlierDetection{
|
||||
Consecutive_5Xx: wrapperspb.UInt32(5),
|
||||
Interval: durationpb.New(time.Second * 10),
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/identity"
|
||||
)
|
||||
|
||||
// GetIdentityProviderForID returns the identity provider associated with the given IDP id.
|
||||
// If none is found the default provider is returned.
|
||||
func (o *Options) GetIdentityProviderForID(idpID string) (*identity.Provider, error) {
|
||||
for _, policy := range o.GetAllPolicies() {
|
||||
idp, err := o.GetIdentityProviderForPolicy(&policy) //nolint
|
||||
for _, p := range o.GetAllPolicies() {
|
||||
p := p
|
||||
idp, err := o.GetIdentityProviderForPolicy(&p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -47,3 +49,19 @@ func (o *Options) GetIdentityProviderForPolicy(policy *Policy) (*identity.Provid
|
|||
idp.Id = idp.Hash()
|
||||
return idp, nil
|
||||
}
|
||||
|
||||
// GetIdentityProviderForRequestURL gets the identity provider associated with the given request URL.
|
||||
func (o *Options) GetIdentityProviderForRequestURL(requestURL string) (*identity.Provider, error) {
|
||||
u, err := urlutil.ParseAndValidateURL(requestURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range o.GetAllPolicies() {
|
||||
p := p
|
||||
if p.Matches(*u) {
|
||||
return o.GetIdentityProviderForPolicy(&p)
|
||||
}
|
||||
}
|
||||
return o.GetIdentityProviderForPolicy(nil)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -384,10 +385,15 @@ func optionsFromViper(configFile string) (*Options, error) {
|
|||
return o, nil
|
||||
}
|
||||
|
||||
var (
|
||||
// policy's embedded protobuf structs are decoded by separate hook and are unknown to mapstructure
|
||||
routesEmbeddedFieldsRe = regexp.MustCompile(`(routes|policy)\[\.*`)
|
||||
)
|
||||
|
||||
func checkUnusedConfigFields(configFile string, unused []string) {
|
||||
keys := make([]string, 0, len(unused))
|
||||
for _, k := range unused {
|
||||
if !strings.HasPrefix(k, "policy[") { // policy's embedded protobuf structs are decoded by separate hook and are unknown to mapstructure
|
||||
if !routesEmbeddedFieldsRe.MatchString(k) {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
|
|
85
config/session.go
Normal file
85
config/session.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/encoding"
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
||||
"github.com/pomerium/pomerium/internal/sessions/header"
|
||||
"github.com/pomerium/pomerium/internal/sessions/queryparam"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
// A SessionStore saves and loads sessions based on the options.
|
||||
type SessionStore struct {
|
||||
options *Options
|
||||
encoder encoding.MarshalUnmarshaler
|
||||
loader sessions.SessionLoader
|
||||
}
|
||||
|
||||
// NewSessionStore creates a new SessionStore from the Options.
|
||||
func NewSessionStore(options *Options) (*SessionStore, error) {
|
||||
store := &SessionStore{
|
||||
options: options,
|
||||
}
|
||||
|
||||
sharedKey, err := options.GetSharedKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("config/sessions: shared_key is required: %w", err)
|
||||
}
|
||||
|
||||
store.encoder, err = jws.NewHS256Signer(sharedKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("config/sessions: invalid session encoder: %w", err)
|
||||
}
|
||||
|
||||
cookieStore, err := cookie.NewStore(func() cookie.Options {
|
||||
return cookie.Options{
|
||||
Name: options.CookieName,
|
||||
Domain: options.CookieDomain,
|
||||
Secure: options.CookieSecure,
|
||||
HTTPOnly: options.CookieHTTPOnly,
|
||||
Expire: options.CookieExpire,
|
||||
}
|
||||
}, store.encoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headerStore := header.NewStore(store.encoder)
|
||||
queryParamStore := queryparam.NewStore(store.encoder, urlutil.QuerySession)
|
||||
store.loader = sessions.MultiSessionLoader(cookieStore, headerStore, queryParamStore)
|
||||
|
||||
return store, nil
|
||||
}
|
||||
|
||||
// LoadSessionState loads the session state from a request.
|
||||
func (store *SessionStore) LoadSessionState(r *http.Request) (*sessions.State, error) {
|
||||
rawJWT, err := store.loader.LoadSession(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var state sessions.State
|
||||
err = store.encoder.Unmarshal([]byte(rawJWT), &state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// confirm that the identity provider id matches the state
|
||||
if state.IdentityProviderID != "" {
|
||||
idp, err := store.options.GetIdentityProviderForRequestURL(urlutil.GetAbsoluteURL(r).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if idp.GetId() != state.IdentityProviderID {
|
||||
return nil, fmt.Errorf("unexpected session state identity provider id: %s != %s",
|
||||
idp.GetId(), state.IdentityProviderID)
|
||||
}
|
||||
}
|
||||
|
||||
return &state, nil
|
||||
}
|
144
config/session_test.go
Normal file
144
config/session_test.go
Normal file
|
@ -0,0 +1,144 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||
)
|
||||
|
||||
func TestSessionStore_LoadSessionState(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sharedKey := cryptutil.NewKey()
|
||||
options := NewDefaultOptions()
|
||||
options.SharedKey = base64.StdEncoding.EncodeToString(sharedKey)
|
||||
options.Provider = "oidc"
|
||||
options.ProviderURL = "https://oidc.example.com"
|
||||
options.ClientID = "client_id"
|
||||
options.ClientSecret = "client_secret"
|
||||
options.Policies = append(options.Policies,
|
||||
Policy{
|
||||
From: "https://p1.example.com",
|
||||
To: mustParseWeightedURLs(t, "https://p1"),
|
||||
IDPClientID: "client_id_1",
|
||||
IDPClientSecret: "client_secret_1",
|
||||
},
|
||||
Policy{
|
||||
From: "https://p2.example.com",
|
||||
To: mustParseWeightedURLs(t, "https://p2"),
|
||||
IDPClientID: "client_id_2",
|
||||
IDPClientSecret: "client_secret_2",
|
||||
})
|
||||
require.NoError(t, options.Validate())
|
||||
|
||||
store, err := NewSessionStore(options)
|
||||
require.NoError(t, err)
|
||||
|
||||
idp1, err := options.GetIdentityProviderForPolicy(nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, idp1)
|
||||
|
||||
idp2, err := options.GetIdentityProviderForPolicy(&options.Policies[0])
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, idp2)
|
||||
|
||||
idp3, err := options.GetIdentityProviderForPolicy(&options.Policies[1])
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, idp3)
|
||||
|
||||
makeJWS := func(t *testing.T, state *sessions.State) string {
|
||||
e, err := jws.NewHS256Signer(sharedKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
rawJWS, err := e.Marshal(state)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(rawJWS)
|
||||
}
|
||||
|
||||
t.Run("mssing", func(t *testing.T) {
|
||||
r, err := http.NewRequest(http.MethodGet, "https://p1.example.com", nil)
|
||||
require.NoError(t, err)
|
||||
s, err := store.LoadSessionState(r)
|
||||
assert.ErrorIs(t, err, sessions.ErrNoSessionFound)
|
||||
assert.Nil(t, s)
|
||||
})
|
||||
t.Run("query", func(t *testing.T) {
|
||||
rawJWS := makeJWS(t, &sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
IdentityProviderID: idp2.GetId(),
|
||||
})
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "https://p1.example.com?"+url.Values{
|
||||
urlutil.QuerySession: {rawJWS},
|
||||
}.Encode(), nil)
|
||||
require.NoError(t, err)
|
||||
s, err := store.LoadSessionState(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, cmp.Diff(&sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
IdentityProviderID: idp2.GetId(),
|
||||
}, s))
|
||||
})
|
||||
t.Run("header", func(t *testing.T) {
|
||||
rawJWS := makeJWS(t, &sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
IdentityProviderID: idp3.GetId(),
|
||||
})
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "https://p2.example.com", nil)
|
||||
require.NoError(t, err)
|
||||
r.Header.Set(httputil.HeaderPomeriumAuthorization, rawJWS)
|
||||
s, err := store.LoadSessionState(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, cmp.Diff(&sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
IdentityProviderID: idp3.GetId(),
|
||||
}, s))
|
||||
})
|
||||
t.Run("wrong idp", func(t *testing.T) {
|
||||
rawJWS := makeJWS(t, &sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
IdentityProviderID: idp1.GetId(),
|
||||
})
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "https://p2.example.com", nil)
|
||||
require.NoError(t, err)
|
||||
r.Header.Set(httputil.HeaderPomeriumAuthorization, rawJWS)
|
||||
s, err := store.LoadSessionState(r)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, s)
|
||||
})
|
||||
t.Run("blank idp", func(t *testing.T) {
|
||||
rawJWS := makeJWS(t, &sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
})
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "https://p2.example.com", nil)
|
||||
require.NoError(t, err)
|
||||
r.Header.Set(httputil.HeaderPomeriumAuthorization, rawJWS)
|
||||
s, err := store.LoadSessionState(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, cmp.Diff(&sessions.State{
|
||||
Issuer: "authenticate.example.com",
|
||||
ID: "example",
|
||||
}, s))
|
||||
})
|
||||
}
|
48
go.mod
48
go.mod
|
@ -14,19 +14,19 @@ require (
|
|||
github.com/cespare/xxhash/v2 v2.1.2
|
||||
github.com/client9/misspell v0.3.4
|
||||
github.com/coreos/go-oidc/v3 v3.4.0
|
||||
github.com/docker/docker v20.10.19+incompatible
|
||||
github.com/docker/docker v20.10.21+incompatible
|
||||
github.com/envoyproxy/go-control-plane v0.10.3-0.20220819153403-8a9be01c9575
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.13
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
github.com/go-jose/go-jose/v3 v3.0.0
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/golangci/golangci-lint v1.50.0
|
||||
github.com/golangci/golangci-lint v1.50.1
|
||||
github.com/google/btree v1.1.2
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-jsonnet v0.18.0
|
||||
github.com/google/go-jsonnet v0.19.1
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
|
@ -48,26 +48,26 @@ require (
|
|||
github.com/pomerium/csrf v1.7.0
|
||||
github.com/pomerium/webauthn v0.0.0-20211014213840-422c7ce1077f
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/prometheus/client_model v0.3.0
|
||||
github.com/prometheus/common v0.37.0
|
||||
github.com/prometheus/procfs v0.8.0
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/rs/zerolog v1.28.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.9
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tniswong/go.rfcx v0.0.0-20181019234604-07783c52761f
|
||||
github.com/volatiletech/null/v9 v9.0.0
|
||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da
|
||||
go.opencensus.io v0.23.0
|
||||
go.uber.org/zap v1.23.0
|
||||
golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
||||
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458
|
||||
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0
|
||||
google.golang.org/api v0.99.0
|
||||
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
|
||||
golang.org/x/sync v0.1.0
|
||||
google.golang.org/api v0.101.0
|
||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55
|
||||
google.golang.org/grpc v1.50.1
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
@ -82,7 +82,7 @@ require (
|
|||
github.com/Antonboom/errname v0.1.7 // indirect
|
||||
github.com/Antonboom/nilnil v0.1.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/BurntSushi/toml v1.2.0 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/DataDog/datadog-go v3.5.0+incompatible // indirect
|
||||
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
|
||||
github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect
|
||||
|
@ -110,7 +110,7 @@ require (
|
|||
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc // indirect
|
||||
github.com/containerd/continuity v0.3.0 // indirect
|
||||
github.com/curioswitch/go-reassign v0.2.0 // indirect
|
||||
github.com/daixiang0/gci v0.8.0 // indirect
|
||||
github.com/daixiang0/gci v0.8.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/denis-tingaikin/go-header v0.4.3 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
|
@ -168,7 +168,7 @@ require (
|
|||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/iancoleman/strcase v0.2.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
|
@ -181,7 +181,7 @@ require (
|
|||
github.com/julz/importas v0.1.0 // indirect
|
||||
github.com/kisielk/errcheck v1.6.2 // indirect
|
||||
github.com/kisielk/gotool v1.0.0 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.2 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.3 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
||||
github.com/kulti/thelper v0.6.3 // indirect
|
||||
|
@ -246,12 +246,12 @@ require (
|
|||
github.com/sourcegraph/go-diff v0.6.1 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.6.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
|
||||
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
|
||||
github.com/stretchr/objx v0.4.0 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
|
||||
github.com/tdakkota/asciicheck v0.1.1 // indirect
|
||||
|
@ -261,8 +261,8 @@ require (
|
|||
github.com/tinylib/msgp v1.1.2 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/tomarrell/wrapcheck/v2 v2.6.2 // indirect
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.0 // indirect
|
||||
github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
||||
github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
|
||||
github.com/ultraware/funlen v0.0.3 // indirect
|
||||
github.com/ultraware/whitespace v0.0.5 // indirect
|
||||
|
@ -281,10 +281,10 @@ require (
|
|||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.22.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
|
92
go.sum
92
go.sum
|
@ -77,8 +77,8 @@ github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX
|
|||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CAFxX/httpcompression v0.0.8 h1:UBWojERnpCS6X7whJkGGZeCC3ruZBRwkwkcnfGfb0ko=
|
||||
github.com/CAFxX/httpcompression v0.0.8/go.mod h1:bVd1taHK1vYb5SWe9lwNDCqrfj2ka+C1Zx7JHzxuHnU=
|
||||
|
@ -211,8 +211,8 @@ github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBj
|
|||
github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo=
|
||||
github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/daixiang0/gci v0.8.0 h1:DzWYUm4+bc+taVUtuq1tsIMb/QFMMYgDIiykSoO98ZU=
|
||||
github.com/daixiang0/gci v0.8.0/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c=
|
||||
github.com/daixiang0/gci v0.8.1 h1:T4xpSC+hmsi4CSyuYfIJdMZAr9o7xZmHpQVygMghGZ4=
|
||||
github.com/daixiang0/gci v0.8.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -230,8 +230,8 @@ github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32Paq
|
|||
github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v20.10.19+incompatible h1:lzEmjivyNHFHMNAFLXORMBXyGIhw/UP4DvJwvyKYq64=
|
||||
github.com/docker/docker v20.10.19+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog=
|
||||
github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
|
@ -260,7 +260,7 @@ github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStB
|
|||
github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0=
|
||||
github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw=
|
||||
github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
|
@ -275,8 +275,9 @@ github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897 h1:E52jfcE64UG42
|
|||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fxamacker/cbor/v2 v2.3.0 h1:aM45YGMctNakddNNAezPxDUpv38j44Abh+hifNuqXik=
|
||||
github.com/fxamacker/cbor/v2 v2.3.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
||||
|
@ -393,8 +394,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6
|
|||
github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ=
|
||||
github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY=
|
||||
github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs=
|
||||
github.com/golangci/golangci-lint v1.50.0 h1:+Xmyt8rKLauNLp2gzcxKMN8VNGqGc5Avc2ZLTwIOpEA=
|
||||
github.com/golangci/golangci-lint v1.50.0/go.mod h1:UqtDvK24R9OizqRF06foPX8opRMzQB0HQK90uI2JgKc=
|
||||
github.com/golangci/golangci-lint v1.50.1 h1:C829clMcZXEORakZlwpk7M4iDw2XiwxxKaG504SZ9zY=
|
||||
github.com/golangci/golangci-lint v1.50.1/go.mod h1:AQjHBopYS//oB8xs0y0M/dtxdKHkdhl0RvmjUct0/4w=
|
||||
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
|
||||
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
|
||||
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
|
||||
|
@ -428,8 +429,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
|
|||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg=
|
||||
github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0=
|
||||
github.com/google/go-jsonnet v0.19.1 h1:MORxkrG0elylUqh36R4AcSPX0oZQa9hvI3lroN+kDhs=
|
||||
github.com/google/go-jsonnet v0.19.1/go.mod h1:5JVT33JVCoehdTj5Z2KJq1eIdt3Nb8PCmZ+W5D8U350=
|
||||
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
|
||||
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
|
||||
github.com/google/go-tpm v0.3.2 h1:3iQQ2dlEf+1no7CLlfLPYzxhQy7j2G/emBqU5okydaw=
|
||||
|
@ -530,8 +531,9 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
|||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
|
@ -605,8 +607,8 @@ github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7
|
|||
github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkHAIKE/contextcheck v1.1.2 h1:BYUSG/GhMhqVz//yjl8IkBDlMEws+9DtCmkz18QO1gg=
|
||||
github.com/kkHAIKE/contextcheck v1.1.2/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo=
|
||||
github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw=
|
||||
github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo=
|
||||
github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
|
@ -801,8 +803,9 @@ github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5
|
|||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
|
@ -912,8 +915,8 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
|||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
|
||||
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
|
@ -932,8 +935,9 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
@ -942,8 +946,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
|
@ -971,10 +976,10 @@ github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hM
|
|||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tniswong/go.rfcx v0.0.0-20181019234604-07783c52761f h1:C43EMGXFtvYf/zunHR6ivZV7Z6ytg73t0GXwYyicXMQ=
|
||||
github.com/tniswong/go.rfcx v0.0.0-20181019234604-07783c52761f/go.mod h1:N+sR0vLSCTtI6o06PMWsjMB4TVqqDttKNq4iC9wvxVY=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.6.2 h1:3dI6YNcrJTQ/CJQ6M/DUkc0gnqYSIk6o0rChn9E/D0M=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.6.2/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg=
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.0 h1:iAj0a8e6+dXSL7Liq0aXPox36FiN1dBbjA6lt9fl65s=
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.7.0 h1:J/F8DbSKJC83bAvC6FoZaRjZiZ/iKoueSdrEkmGeacA=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.7.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg=
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw=
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw=
|
||||
github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=
|
||||
github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
|
@ -1072,8 +1077,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2 h1:x8vtB3zMecnlqZIwJNUUpwYKYSqCz5jXbiyv0ZJJZeI=
|
||||
golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -1118,8 +1123,9 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -1178,8 +1184,8 @@ golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458 h1:MgJ6t2zo8v0tbmLCueaCbF1RM+TtB0rs3Lv8DGtOIpY=
|
||||
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -1201,8 +1207,8 @@ golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j
|
|||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 h1:3VPzK7eqH25j7GYw5w6g/GzNRc0/fYtrxz27z1gD4W0=
|
||||
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -1216,8 +1222,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -1318,8 +1324,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908150016-7ac13a9a928d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -1332,8 +1339,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -1429,8 +1436,9 @@ golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlz
|
|||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -1480,8 +1488,8 @@ google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69
|
|||
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
||||
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
|
||||
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
|
||||
google.golang.org/api v0.99.0 h1:tsBtOIklCE2OFxhmcYSVqGwSAN/Y897srxmcvAQnwK8=
|
||||
google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08=
|
||||
google.golang.org/api v0.101.0 h1:lJPPeEBIRxGpGLwnBTam1NPEM8Z2BmmXEd3z812pjwM=
|
||||
google.golang.org/api v0.101.0/go.mod h1:CjxAAWWt3A3VrUE2IGDY2bgK5qhoG/OkyWVlYcP05MY=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -1571,8 +1579,8 @@ google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP
|
|||
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e h1:halCgTFuLWDRD61piiNSxPsARANGD3Xl16hPrLgLiIg=
|
||||
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
|
||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg=
|
||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
|
|
|
@ -2,15 +2,14 @@
|
|||
package controlplane
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/CAFxX/httpcompression"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/pomerium/csrf"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
|
@ -47,32 +46,23 @@ func (srv *Server) addHTTPMiddleware(root *mux.Router, cfg *config.Config) {
|
|||
root.Use(telemetry.HTTPStatsHandler(func() string {
|
||||
return srv.currentConfig.Load().Options.InstallationID
|
||||
}, srv.name))
|
||||
root.HandleFunc("/healthz", httputil.HealthCheck)
|
||||
root.HandleFunc("/ping", httputil.HealthCheck)
|
||||
root.Handle("/.well-known/pomerium", httputil.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||
return wellKnownPomerium(w, r, cfg)
|
||||
}))
|
||||
root.Handle("/.well-known/pomerium/", httputil.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||
return wellKnownPomerium(w, r, cfg)
|
||||
}))
|
||||
}
|
||||
|
||||
func wellKnownPomerium(w http.ResponseWriter, r *http.Request, cfg *config.Config) error {
|
||||
func (srv *Server) mountCommonEndpoints(root *mux.Router, cfg *config.Config) error {
|
||||
authenticateURL, err := cfg.Options.GetAuthenticateURL()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid authenticate URL: %w", err)
|
||||
}
|
||||
|
||||
wellKnownURLs := struct {
|
||||
OAuth2Callback string `json:"authentication_callback_endpoint"` // RFC6749
|
||||
JSONWebKeySetURL string `json:"jwks_uri"` // RFC7517
|
||||
FrontchannelLogoutURI string `json:"frontchannel_logout_uri"` // https://openid.net/specs/openid-connect-frontchannel-1_0.html
|
||||
}{
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/oauth2/callback"}).String(),
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/.well-known/pomerium/jwks.json"}).String(),
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/.pomerium/sign_out"}).String(),
|
||||
rawSigningKey, err := cfg.Options.GetSigningKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid signing key: %w", err)
|
||||
}
|
||||
w.Header().Set("X-CSRF-Token", csrf.Token(r))
|
||||
httputil.RenderJSON(w, http.StatusOK, wellKnownURLs)
|
||||
|
||||
root.HandleFunc("/healthz", httputil.HealthCheck)
|
||||
root.HandleFunc("/ping", httputil.HealthCheck)
|
||||
root.Handle("/.well-known/pomerium", httputil.WellKnownPomeriumHandler(authenticateURL))
|
||||
root.Handle("/.well-known/pomerium/", httputil.WellKnownPomeriumHandler(authenticateURL))
|
||||
root.Path("/.well-known/pomerium/jwks.json").Methods(http.MethodGet).Handler(httputil.JWKSHandler(rawSigningKey))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -285,6 +285,9 @@ func (srv *Server) EnableProxy(svc Service) error {
|
|||
func (srv *Server) updateRouter(cfg *config.Config) error {
|
||||
httpRouter := mux.NewRouter()
|
||||
srv.addHTTPMiddleware(httpRouter, cfg)
|
||||
if err := srv.mountCommonEndpoints(httpRouter, cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
if srv.authenticateSvc != nil {
|
||||
authenticateURL, err := cfg.Options.GetInternalAuthenticateURL()
|
||||
if err != nil {
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
"github.com/pomerium/pomerium/pkg/netutil"
|
||||
)
|
||||
|
||||
func TestServerWellKnown(t *testing.T) {
|
||||
func TestServerHTTP(t *testing.T) {
|
||||
ports, err := netutil.AllocatePorts(5)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -33,23 +33,49 @@ func TestServerWellKnown(t *testing.T) {
|
|||
Options: config.NewDefaultOptions(),
|
||||
}
|
||||
cfg.Options.AuthenticateURLString = "https://authenticate.localhost.pomerium.io"
|
||||
cfg.Options.SigningKey = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUpCMFZkbko1VjEvbVlpYUlIWHhnd2Q0Yzd5YWRTeXMxb3Y0bzA1b0F3ekdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUc1eENQMEpUVDFINklvbDhqS3VUSVBWTE0wNENnVzlQbEV5cE5SbVdsb29LRVhSOUhUMwpPYnp6aktZaWN6YjArMUt3VjJmTVRFMTh1dy82MXJVQ0JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
||||
|
||||
src := config.NewStaticSource(cfg)
|
||||
srv, err := NewServer(cfg, config.NewMetricsManager(ctx, src), events.New())
|
||||
require.NoError(t, err)
|
||||
go srv.Run(ctx)
|
||||
|
||||
res, err := http.Get(fmt.Sprintf("http://localhost:%s/.well-known/pomerium", src.GetConfig().HTTPPort))
|
||||
require.NoError(t, err)
|
||||
defer res.Body.Close()
|
||||
t.Run("well-known", func(t *testing.T) {
|
||||
res, err := http.Get(fmt.Sprintf("http://localhost:%s/.well-known/pomerium", src.GetConfig().HTTPPort))
|
||||
require.NoError(t, err)
|
||||
defer res.Body.Close()
|
||||
|
||||
var actual map[string]any
|
||||
err = json.NewDecoder(res.Body).Decode(&actual)
|
||||
require.NoError(t, err)
|
||||
var actual map[string]any
|
||||
err = json.NewDecoder(res.Body).Decode(&actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
expect := map[string]any{
|
||||
"authentication_callback_endpoint": "https://authenticate.localhost.pomerium.io/oauth2/callback",
|
||||
"frontchannel_logout_uri": "https://authenticate.localhost.pomerium.io/.pomerium/sign_out",
|
||||
"jwks_uri": "https://authenticate.localhost.pomerium.io/.well-known/pomerium/jwks.json",
|
||||
}
|
||||
assert.Equal(t, expect, actual)
|
||||
expect := map[string]any{
|
||||
"authentication_callback_endpoint": "https://authenticate.localhost.pomerium.io/oauth2/callback",
|
||||
"frontchannel_logout_uri": "https://authenticate.localhost.pomerium.io/.pomerium/sign_out",
|
||||
"jwks_uri": "https://authenticate.localhost.pomerium.io/.well-known/pomerium/jwks.json",
|
||||
}
|
||||
assert.Equal(t, expect, actual)
|
||||
})
|
||||
t.Run("jwks", func(t *testing.T) {
|
||||
res, err := http.Get(fmt.Sprintf("http://localhost:%s/.well-known/pomerium/jwks.json", src.GetConfig().HTTPPort))
|
||||
require.NoError(t, err)
|
||||
defer res.Body.Close()
|
||||
|
||||
var actual map[string]any
|
||||
err = json.NewDecoder(res.Body).Decode(&actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
expect := map[string]any{
|
||||
"keys": []any{map[string]any{
|
||||
"alg": "ES256",
|
||||
"crv": "P-256",
|
||||
"kid": "5b419ade1895fec2d2def6cd33b1b9a018df60db231dc5ecb85cbed6d942813c",
|
||||
"kty": "EC",
|
||||
"use": "sig",
|
||||
"x": "UG5xCP0JTT1H6Iol8jKuTIPVLM04CgW9PlEypNRmWlo",
|
||||
"y": "KChF0fR09zm884ymInM29PtSsFdnzExNfLsP-ta1AgQ",
|
||||
}},
|
||||
}
|
||||
assert.Equal(t, expect, actual)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
||||
"github.com/pomerium/pomerium/pkg/contextutil"
|
||||
"github.com/pomerium/pomerium/ui"
|
||||
|
@ -52,7 +53,6 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
|
|||
}
|
||||
response := struct {
|
||||
Status int
|
||||
Error string
|
||||
StatusText string `json:"-"`
|
||||
RequestID string `json:",omitempty"`
|
||||
CanDebug bool `json:"-"`
|
||||
|
@ -61,7 +61,6 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
|
|||
}{
|
||||
Status: e.Status,
|
||||
StatusText: StatusText(e.Status),
|
||||
Error: e.Error(),
|
||||
RequestID: reqID,
|
||||
CanDebug: e.Status/100 == 4 && (e.DebugURL != nil || reqID != ""),
|
||||
DebugURL: e.DebugURL,
|
||||
|
@ -70,6 +69,13 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
|
|||
// indicate to clients that the error originates from Pomerium, not the app
|
||||
w.Header().Set(HeaderPomeriumResponse, "true")
|
||||
|
||||
log.Error(ctx).
|
||||
Err(e.Err).
|
||||
Int("status", e.Status).
|
||||
Str("status-text", StatusText(e.Status)).
|
||||
Str("request-id", reqID).
|
||||
Msg("httputil: error")
|
||||
|
||||
if r.Header.Get("Accept") == "application/json" {
|
||||
RenderJSON(w, e.Status, response)
|
||||
return
|
||||
|
@ -77,7 +83,6 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
|
|||
|
||||
m := map[string]any{
|
||||
"canDebug": response.CanDebug,
|
||||
"error": response.Error,
|
||||
"requestId": response.RequestID,
|
||||
"status": response.Status,
|
||||
"statusText": response.StatusText,
|
||||
|
|
|
@ -19,7 +19,7 @@ func TestHTTPError_ErrorResponse(t *testing.T) {
|
|||
wantStatus int
|
||||
wantBody string
|
||||
}{
|
||||
{"404 json", http.StatusNotFound, errors.New("route not known"), "application/json", http.StatusNotFound, "{\"Status\":404,\"Error\":\"Not Found: route not known\"}\n"},
|
||||
{"404 json", http.StatusNotFound, errors.New("route not known"), "application/json", http.StatusNotFound, "{\"Status\":404}\n"},
|
||||
{"404 html", http.StatusNotFound, errors.New("route not known"), "", http.StatusNotFound, ""},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -2,10 +2,17 @@ package httputil
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
|
||||
"github.com/pomerium/csrf"
|
||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||
)
|
||||
|
||||
// HealthCheck is a simple healthcheck handler that responds to GET and HEAD
|
||||
|
@ -64,3 +71,41 @@ func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
e.ErrorResponse(r.Context(), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// JWKSHandler returns the /.well-known/pomerium/jwks.json handler.
|
||||
func JWKSHandler(rawSigningKey string) http.Handler {
|
||||
return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||
var jwks jose.JSONWebKeySet
|
||||
if rawSigningKey != "" {
|
||||
decodedCert, err := base64.StdEncoding.DecodeString(rawSigningKey)
|
||||
if err != nil {
|
||||
return NewError(http.StatusInternalServerError, errors.New("bad signing key"))
|
||||
}
|
||||
jwk, err := cryptutil.PublicJWKFromBytes(decodedCert)
|
||||
if err != nil {
|
||||
return NewError(http.StatusInternalServerError, errors.New("bad signing key"))
|
||||
}
|
||||
jwks.Keys = append(jwks.Keys, *jwk)
|
||||
}
|
||||
RenderJSON(w, http.StatusOK, jwks)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// WellKnownPomeriumHandler returns the /.well-known/pomerium handler.
|
||||
func WellKnownPomeriumHandler(authenticateURL *url.URL) http.Handler {
|
||||
return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||
wellKnownURLs := struct {
|
||||
OAuth2Callback string `json:"authentication_callback_endpoint"` // RFC6749
|
||||
JSONWebKeySetURL string `json:"jwks_uri"` // RFC7517
|
||||
FrontchannelLogoutURI string `json:"frontchannel_logout_uri"` // https://openid.net/specs/openid-connect-frontchannel-1_0.html
|
||||
}{
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/oauth2/callback"}).String(),
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/.well-known/pomerium/jwks.json"}).String(),
|
||||
authenticateURL.ResolveReference(&url.URL{Path: "/.pomerium/sign_out"}).String(),
|
||||
}
|
||||
w.Header().Set("X-CSRF-Token", csrf.Token(r))
|
||||
RenderJSON(w, http.StatusOK, wellKnownURLs)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
|
@ -75,8 +75,8 @@ func TestHandlerFunc_ServeHTTP(t *testing.T) {
|
|||
f HandlerFunc
|
||||
wantBody string
|
||||
}{
|
||||
{"good http error", func(w http.ResponseWriter, r *http.Request) error { return NewError(404, errors.New("404")) }, "{\"Status\":404,\"Error\":\"Not Found: 404\"}\n"},
|
||||
{"good std error", func(w http.ResponseWriter, r *http.Request) error { return errors.New("404") }, "{\"Status\":500,\"Error\":\"Internal Server Error: 404\"}\n"},
|
||||
{"good http error", func(w http.ResponseWriter, r *http.Request) error { return NewError(404, errors.New("404")) }, "{\"Status\":404}\n"},
|
||||
{"good std error", func(w http.ResponseWriter, r *http.Request) error { return errors.New("404") }, "{\"Status\":500}\n"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -55,7 +55,7 @@ func TestValidateSignature(t *testing.T) {
|
|||
wantBody string
|
||||
}{
|
||||
{"good", []byte("secret"), []byte("secret"), http.StatusOK, http.StatusText(http.StatusOK)},
|
||||
{"secret mistmatch", []byte("secret"), []byte("hunter42"), http.StatusBadRequest, "{\"Status\":400,\"Error\":\"Bad Request: internal/urlutil: hmac failed\"}\n"},
|
||||
{"secret mistmatch", []byte("secret"), []byte("hunter42"), http.StatusBadRequest, "{\"Status\":400}\n"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -2,7 +2,6 @@ package sessions
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -14,17 +13,17 @@ var (
|
|||
|
||||
// RetrieveSession takes a slice of session loaders and tries to find a valid
|
||||
// session in the order they were supplied and is added to the request's context
|
||||
func RetrieveSession(s ...SessionLoader) func(http.Handler) http.Handler {
|
||||
func RetrieveSession(s SessionLoader) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return retrieve(s...)(next)
|
||||
return retrieve(s)(next)
|
||||
}
|
||||
}
|
||||
|
||||
func retrieve(s ...SessionLoader) func(http.Handler) http.Handler {
|
||||
func retrieve(s SessionLoader) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
hfn := func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
jwt, err := retrieveFromRequest(r, s...)
|
||||
jwt, err := s.LoadSession(r)
|
||||
ctx = NewContext(ctx, jwt, err)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
}
|
||||
|
@ -32,21 +31,6 @@ func retrieve(s ...SessionLoader) func(http.Handler) http.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
// retrieveFromRequest extracts sessions state from the request by calling
|
||||
// token find functions in the order they where provided.
|
||||
func retrieveFromRequest(r *http.Request, sessions ...SessionLoader) (string, error) {
|
||||
for _, s := range sessions {
|
||||
jwt, err := s.LoadSession(r)
|
||||
if err != nil && !errors.Is(err, ErrNoSessionFound) {
|
||||
return "", err
|
||||
} else if err == nil {
|
||||
return jwt, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", ErrNoSessionFound
|
||||
}
|
||||
|
||||
// NewContext sets context values for the user session state and error.
|
||||
func NewContext(ctx context.Context, jwt string, err error) context.Context {
|
||||
ctx = context.WithValue(ctx, SessionCtxKey, jwt)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package sessions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -17,3 +18,21 @@ type SessionStore interface {
|
|||
type SessionLoader interface {
|
||||
LoadSession(*http.Request) (string, error)
|
||||
}
|
||||
|
||||
type multiSessionLoader []SessionLoader
|
||||
|
||||
func (l multiSessionLoader) LoadSession(r *http.Request) (string, error) {
|
||||
for _, ll := range l {
|
||||
s, err := ll.LoadSession(r)
|
||||
if errors.Is(err, ErrNoSessionFound) {
|
||||
continue
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
return "", ErrNoSessionFound
|
||||
}
|
||||
|
||||
// MultiSessionLoader returns a session loader that returns the first session available.
|
||||
func MultiSessionLoader(loaders ...SessionLoader) SessionLoader {
|
||||
return multiSessionLoader(loaders)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/pomerium/pomerium/internal/identity"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
"github.com/pomerium/pomerium/pkg/protoutil"
|
||||
"github.com/pomerium/pomerium/pkg/slices"
|
||||
)
|
||||
|
||||
// Delete deletes a session from the databroker.
|
||||
|
@ -78,3 +79,10 @@ func (x *Session) SetRawIDToken(rawIDToken string) {
|
|||
}
|
||||
x.IdToken.Raw = rawIDToken
|
||||
}
|
||||
|
||||
// RemoveDeviceCredentialID removes a device credential id.
|
||||
func (x *Session) RemoveDeviceCredentialID(deviceCredentialID string) {
|
||||
x.DeviceCredentials = slices.Filter(x.DeviceCredentials, func(el *Session_DeviceCredential) bool {
|
||||
return el.GetId() != deviceCredentialID
|
||||
})
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/pomerium/pomerium/internal/identity"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
"github.com/pomerium/pomerium/pkg/slices"
|
||||
)
|
||||
|
||||
// Get gets a user from the databroker.
|
||||
|
@ -47,3 +48,18 @@ func (x *User) GetClaim(claim string) []interface{} {
|
|||
}
|
||||
return vs
|
||||
}
|
||||
|
||||
// AddDeviceCredentialID adds a device credential id to the list of device credential ids.
|
||||
func (x *User) AddDeviceCredentialID(deviceCredentialID string) {
|
||||
x.DeviceCredentialIds = slices.Unique(append(x.DeviceCredentialIds, deviceCredentialID))
|
||||
}
|
||||
|
||||
// HasDeviceCredentialID returns true if the user has the device credential id.
|
||||
func (x *User) HasDeviceCredentialID(deviceCredentialID string) bool {
|
||||
return slices.Contains(x.DeviceCredentialIds, deviceCredentialID)
|
||||
}
|
||||
|
||||
// RemoveDeviceCredentialID removes the device credential id from the list of device credential ids.
|
||||
func (x *User) RemoveDeviceCredentialID(deviceCredentialID string) {
|
||||
x.DeviceCredentialIds = slices.Remove(x.DeviceCredentialIds, deviceCredentialID)
|
||||
}
|
||||
|
|
47
pkg/slices/slices.go
Normal file
47
pkg/slices/slices.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Package slices contains functions for working with slices.
|
||||
package slices
|
||||
|
||||
// Contains returns true if e is in s.
|
||||
func Contains[S ~[]E, E comparable](s S, e E) bool {
|
||||
for _, el := range s {
|
||||
if el == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Filter returns a new slice containing only those elements for which f(element) is true.
|
||||
func Filter[S ~[]E, E any](s S, f func(E) bool) S {
|
||||
var ns S
|
||||
for _, el := range s {
|
||||
if f(el) {
|
||||
ns = append(ns, el)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// Remove removes e from s.
|
||||
func Remove[S ~[]E, E comparable](s S, e E) S {
|
||||
var ns S
|
||||
for _, el := range s {
|
||||
if el != e {
|
||||
ns = append(ns, el)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// Unique returns the unique elements of s.
|
||||
func Unique[S ~[]E, E comparable](s S) S {
|
||||
var ns S
|
||||
h := map[E]struct{}{}
|
||||
for _, el := range s {
|
||||
if _, ok := h[el]; !ok {
|
||||
h[el] = struct{}{}
|
||||
ns = append(ns, el)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/pomerium/pomerium/pkg/storage"
|
||||
)
|
||||
|
||||
const recordBatchSize = 64
|
||||
const recordBatchSize = 4 * 1024
|
||||
|
||||
type recordStream struct {
|
||||
backend *Backend
|
||||
|
|
|
@ -63,9 +63,9 @@ func TestProxy_ForwardAuth(t *testing.T) {
|
|||
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,\"Error\":\"Bad Request: https: url does contain a valid hostname\"}\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,\"Error\":\"Bad Request: a.naked.domain url does contain a valid scheme\"}\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,\"Error\":\"Bad Request: %20 url does contain a valid scheme\"}\n"},
|
||||
{"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, ""},
|
||||
|
|
|
@ -331,14 +331,14 @@ func TestProxy_ProgrammaticLogin(t *testing.T) {
|
|||
opts, http.MethodGet, "https", "corp.example.example", "/.pomerium/api/v1/login", nil,
|
||||
map[string]string{urlutil.QueryRedirectURI: "localhost"},
|
||||
http.StatusBadRequest,
|
||||
"{\"Status\":400,\"Error\":\"Bad Request: localhost url does contain a valid scheme\"}\n",
|
||||
"{\"Status\":400}\n",
|
||||
},
|
||||
{
|
||||
"bad redirect_uri not whitelisted",
|
||||
opts, http.MethodGet, "https", "corp.example.example", "/.pomerium/api/v1/login", nil,
|
||||
map[string]string{urlutil.QueryRedirectURI: "https://example.com"},
|
||||
http.StatusBadRequest,
|
||||
"{\"Status\":400,\"Error\":\"Bad Request: invalid redirect uri\"}\n",
|
||||
"{\"Status\":400}\n",
|
||||
},
|
||||
{
|
||||
"bad http method",
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/pomerium/pomerium/internal/encoding/jws"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
||||
"github.com/pomerium/pomerium/internal/sessions/header"
|
||||
"github.com/pomerium/pomerium/internal/sessions/queryparam"
|
||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||
)
|
||||
|
||||
|
@ -26,7 +24,6 @@ type proxyState struct {
|
|||
encoder encoding.MarshalUnmarshaler
|
||||
cookieSecret []byte
|
||||
sessionStore sessions.SessionStore
|
||||
sessionLoaders []sessions.SessionLoader
|
||||
jwtClaimHeaders config.JWTClaimHeaders
|
||||
|
||||
programmaticRedirectDomainWhitelist []string
|
||||
|
@ -84,11 +81,6 @@ func newProxyStateFromConfig(cfg *config.Config) (*proxyState, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
state.sessionLoaders = []sessions.SessionLoader{
|
||||
state.sessionStore,
|
||||
header.NewStore(state.encoder),
|
||||
queryparam.NewStore(state.encoder, "pomerium_session"),
|
||||
}
|
||||
state.programmaticRedirectDomainWhitelist = cfg.Options.ProgrammaticRedirectDomainWhitelist
|
||||
|
||||
return state, nil
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
import {ErrorPageData, PolicyEvaluationTrace} from "../types";
|
||||
import SectionFooter from "./SectionFooter";
|
||||
import { ListItemProps, TableCell } from "@mui/material";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import AlertTitle from "@mui/material/AlertTitle";
|
||||
import Box from "@mui/material/Box";
|
||||
import Container from "@mui/material/Container";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import React, { FC } from "react";
|
||||
import Markdown from "markdown-to-jsx";
|
||||
import {ListItemProps, TableCell} from "@mui/material";
|
||||
import {CheckCircle, MinusCircle, XCircle} from "react-feather";
|
||||
import Table from "@mui/material/Table";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import TableHead from "@mui/material/TableHead";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Markdown from "markdown-to-jsx";
|
||||
import React, { FC } from "react";
|
||||
import { CheckCircle, MinusCircle, XCircle } from "react-feather";
|
||||
|
||||
import { ErrorPageData, PolicyEvaluationTrace } from "../types";
|
||||
import SectionFooter from "./SectionFooter";
|
||||
|
||||
type PolicyEvaluationTraceDetailsProps = {
|
||||
trace: PolicyEvaluationTrace;
|
||||
} & ListItemProps;
|
||||
const PolicyEvaluationTraceDetails: FC<PolicyEvaluationTraceDetailsProps> = ({
|
||||
trace,
|
||||
...props
|
||||
trace,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell align={'center'}>
|
||||
<TableCell align={"center"}>
|
||||
{trace.deny ? (
|
||||
<XCircle color="red" />
|
||||
) : trace.allow ? (
|
||||
|
@ -34,9 +35,7 @@ const PolicyEvaluationTraceDetails: FC<PolicyEvaluationTraceDetailsProps> = ({
|
|||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Markdown>
|
||||
{trace.explanation || trace.id}
|
||||
</Markdown>
|
||||
<Markdown>{trace.explanation || trace.id}</Markdown>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Markdown>
|
||||
|
@ -63,14 +62,11 @@ export const ErrorPage: FC<ErrorPageProps> = ({ data }) => {
|
|||
{data?.status || 500}{" "}
|
||||
{data?.statusText || "Internal Server Error"}
|
||||
</AlertTitle>
|
||||
{data?.error || "Internal Server Error"}
|
||||
</Alert>
|
||||
</Box>
|
||||
{!!data?.errorMessageFirstParagraph && (
|
||||
<Box sx={{p: 4}}>
|
||||
<Markdown>
|
||||
{data.errorMessageFirstParagraph}
|
||||
</Markdown>
|
||||
<Box sx={{ p: 4 }}>
|
||||
<Markdown>{data.errorMessageFirstParagraph}</Markdown>
|
||||
</Box>
|
||||
)}
|
||||
{traces?.length > 0 && (
|
||||
|
|
|
@ -92,7 +92,6 @@ export type ErrorPageData = BasePageData & {
|
|||
|
||||
canDebug?: boolean;
|
||||
debugUrl?: string;
|
||||
error?: string;
|
||||
requestId?: string;
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue