databroker: support rotating shared secret (#3502)

* databroker: support rotating shared secret

* fix test

* run tests on linux

* fix tests

* fix typo

* increase timeout
This commit is contained in:
Caleb Doxsey 2022-07-26 10:59:54 -06:00 committed by GitHub
parent f0745f0626
commit 0b48da1e2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 118 additions and 69 deletions

View file

@ -16,28 +16,30 @@ jobs:
platform: [ubuntu-latest, macos-latest] platform: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # pin@v3 - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: set env vars - name: set env vars
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
- name: cache go binaries - name: cache go binaries
uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
id: cache-go-bin id: cache-go-bin
with: with:
path: ~/go/bin path: ~/go/bin
key: ${{ runner.os }}-${{ hashFiles('**/go.mod') }} key: ${{ runner.os }}-${{ hashFiles('**/go.mod') }}
restore-keys: ${{ runner.os }}-go-bin restore-keys: ${{ runner.os }}-go-bin
- uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 - uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
with: with:
path: | path: |
~/go/pkg/mod ~/go/pkg/mod
@ -45,12 +47,12 @@ jobs:
~/Library/Caches/go-build ~/Library/Caches/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go- restore-keys: ${{ runner.os }}-go-
- run: make deps-build - run: make deps-build
- name: Lint - name: Lint
if: runner.os == 'Linux' if: runner.os == 'Linux'
run: make lint run: make lint
- name: test - name: test
if: runner.os != 'Linux'
run: make test run: make test
cover: cover:
@ -60,15 +62,15 @@ jobs:
go-version: [1.18.x] go-version: [1.18.x]
node-version: [16.x] node-version: [16.x]
steps: steps:
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # pin@v3 - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
@ -76,14 +78,14 @@ jobs:
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- name: cache go binaries - name: cache go binaries
uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
id: cache-go-bin id: cache-go-bin
with: with:
path: ~/go/bin path: ~/go/bin
key: ${{ runner.os }}-${{ hashFiles('**/go.mod') }} key: ${{ runner.os }}-${{ hashFiles('**/go.mod') }}
restore-keys: ${{ runner.os }}-go-bin restore-keys: ${{ runner.os }}-go-bin
- uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 - uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
with: with:
path: | path: |
~/go/pkg/mod ~/go/pkg/mod
@ -95,14 +97,14 @@ jobs:
- name: cover - name: cover
run: make cover run: make cover
- uses: jandelgado/gcov2lcov-action@c680c0f7c7442485f1749eb2a13e54a686e76eb5 # pin@v1.0.8 - uses: jandelgado/gcov2lcov-action@c680c0f7c7442485f1749eb2a13e54a686e76eb5
name: convert coverage to lcov name: convert coverage to lcov
with: with:
infile: coverage.txt infile: coverage.txt
outfile: coverage.lcov outfile: coverage.lcov
- name: upload to coveralls - name: upload to coveralls
uses: coverallsapp/github-action@9ba913c152ae4be1327bfb9085dc806cedb44057 # pin@1.1.3 uses: coverallsapp/github-action@9ba913c152ae4be1327bfb9085dc806cedb44057
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: coverage.lcov path-to-lcov: coverage.lcov
@ -118,20 +120,20 @@ jobs:
idp: [auth0, azure, github, gitlab, google, oidc, okta, onelogin, ping] idp: [auth0, azure, github, gitlab, google, oidc, okta, onelogin, ping]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # pin@v3 - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: set env vars - name: set env vars
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 - uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
with: with:
path: | path: |
~/go/pkg ~/go/pkg
@ -164,18 +166,18 @@ jobs:
platform: [ubuntu-latest, macos-latest] platform: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # pin@v3 - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129 # pin@v3 - uses: actions/cache@0865c47f36e68161719c5b124609996bb5c40129
with: with:
path: | path: |
~/go/pkg/mod ~/go/pkg/mod
@ -191,7 +193,7 @@ jobs:
make build make build
- name: save binary - name: save binary
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # pin@v2 uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with: with:
path: bin/pomerium* path: bin/pomerium*
name: pomerium ${{ github.run_id }} ${{ matrix.platform }} name: pomerium ${{ github.run_id }} ${{ matrix.platform }}
@ -200,15 +202,15 @@ jobs:
build-docker: build-docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # pin@v1 uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6
- name: Docker Build - name: Docker Build
uses: docker/build-push-action@1cb9d22b932e4832bb29793b7777ec860fc1cde0 # pin@v2 uses: docker/build-push-action@1cb9d22b932e4832bb29793b7777ec860fc1cde0
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
@ -218,16 +220,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
steps: steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: 1.18.x go-version: 1.18.x
- uses: actions/setup-python@c4e89fac7e8767b327bbad6cb4d859eda999cf08 # pin@v3 - uses: actions/setup-python@c4e89fac7e8767b327bbad6cb4d859eda999cf08
with: with:
python-version: "3.x" python-version: "3.x"
- uses: pre-commit/action@876132a3c26aa072b09eab6c5395b4749eeb2435 # pin@release - uses: pre-commit/action@876132a3c26aa072b09eab6c5395b4749eeb2435
with: with:
extra_args: --show-diff-on-failure --from-ref ${{ extra_args: --show-diff-on-failure --from-ref ${{
github.event.pull_request.base.sha }} --to-ref ${{ github.event.pull_request.base.sha }} --to-ref ${{
@ -244,14 +246,14 @@ jobs:
needs: needs:
- build - build
steps: steps:
- uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # pin@v2 - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a
with: with:
go-version: 1.18.x go-version: 1.18.x
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3 - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: retrieve binary - name: retrieve binary
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # pin@v2 uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741
with: with:
name: pomerium ${{ github.run_id }} ${{ matrix.platform }} name: pomerium ${{ github.run_id }} ${{ matrix.platform }}
path: bin/ path: bin/
@ -260,6 +262,6 @@ jobs:
run: make get-envoy run: make get-envoy
- name: FOSSA Scan - name: FOSSA Scan
uses: fossa-contrib/fossa-action@6cffaa064112e1cf9b5798c6224f9487dc1ec316 # pin@v1 uses: fossa-contrib/fossa-action@6cffaa064112e1cf9b5798c6224f9487dc1ec316
with: with:
fossa-api-key: 18f4ef488f514d06874b75f5809cea93 fossa-api-key: 18f4ef488f514d06874b75f5809cea93

View file

@ -103,7 +103,7 @@ test: get-envoy ## Runs the go tests.
.PHONY: cover .PHONY: cover
cover: get-envoy ## Runs go test with coverage cover: get-envoy ## Runs go test with coverage
@echo "==> $@" @echo "==> $@"
$(GO) test -race -coverprofile=coverage.txt -tags "$(BUILDTAGS)" $(shell $(GO) list ./... | grep -v vendor | grep -v github.com/pomerium/pomerium/integration | grep -v github.com/pomerium/pomerium/pkg/storage/postgres) $(GO) test -race -coverprofile=coverage.txt -tags "$(BUILDTAGS)" $(shell $(GO) list ./... | grep -v vendor | grep -v github.com/pomerium/pomerium/integration)
@sed -i.bak '/\.pb\.go\:/d' coverage.txt @sed -i.bak '/\.pb\.go\:/d' coverage.txt
@sed -i.bak '/\/mock\.go\:/d' coverage.txt @sed -i.bak '/\/mock\.go\:/d' coverage.txt
@sort -o coverage.txt coverage.txt @sort -o coverage.txt coverage.txt

View file

@ -15,6 +15,7 @@ import (
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/atomicutil"
"github.com/pomerium/pomerium/internal/directory" "github.com/pomerium/pomerium/internal/directory"
"github.com/pomerium/pomerium/internal/events" "github.com/pomerium/pomerium/internal/events"
"github.com/pomerium/pomerium/internal/identity" "github.com/pomerium/pomerium/internal/identity"
@ -36,11 +37,10 @@ type DataBroker struct {
manager *manager.Manager manager *manager.Manager
eventsMgr *events.Manager eventsMgr *events.Manager
localListener net.Listener localListener net.Listener
localGRPCServer *grpc.Server localGRPCServer *grpc.Server
localGRPCConnection *grpc.ClientConn localGRPCConnection *grpc.ClientConn
dataBrokerStorageType string // TODO remove in v0.11 sharedKey *atomicutil.Value[[]byte]
deprecatedCacheClusterDomain string // TODO: remove in v0.11
mu sync.Mutex mu sync.Mutex
directoryProvider directory.Provider directoryProvider directory.Provider
@ -53,8 +53,6 @@ func New(cfg *config.Config, eventsMgr *events.Manager) (*DataBroker, error) {
return nil, err return nil, err
} }
sharedKey, _ := cfg.Options.GetSharedKey()
ui, si := grpcutil.AttachMetadataInterceptors( ui, si := grpcutil.AttachMetadataInterceptors(
metadata.Pairs( metadata.Pairs(
grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(), grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(),
@ -69,11 +67,17 @@ func New(cfg *config.Config, eventsMgr *events.Manager) (*DataBroker, error) {
grpc.UnaryInterceptor(ui), grpc.UnaryInterceptor(ui),
) )
sharedKey, err := cfg.Options.GetSharedKey()
if err != nil {
return nil, err
}
sharedKeyValue := atomicutil.NewValue(sharedKey)
clientStatsHandler := telemetry.NewGRPCClientStatsHandler(cfg.Options.Services) clientStatsHandler := telemetry.NewGRPCClientStatsHandler(cfg.Options.Services)
clientDialOptions := []grpc.DialOption{ clientDialOptions := []grpc.DialOption{
grpc.WithInsecure(), grpc.WithInsecure(),
grpc.WithChainUnaryInterceptor(clientStatsHandler.UnaryInterceptor, grpcutil.WithUnarySignedJWT(sharedKey)), grpc.WithChainUnaryInterceptor(clientStatsHandler.UnaryInterceptor, grpcutil.WithUnarySignedJWT(sharedKeyValue.Load)),
grpc.WithChainStreamInterceptor(grpcutil.WithStreamSignedJWT(sharedKey)), grpc.WithChainStreamInterceptor(grpcutil.WithStreamSignedJWT(sharedKeyValue.Load)),
grpc.WithStatsHandler(clientStatsHandler.Handler), grpc.WithStatsHandler(clientStatsHandler.Handler),
} }
@ -90,19 +94,14 @@ func New(cfg *config.Config, eventsMgr *events.Manager) (*DataBroker, error) {
} }
dataBrokerServer := newDataBrokerServer(cfg) dataBrokerServer := newDataBrokerServer(cfg)
dataBrokerURLs, err := cfg.Options.GetInternalDataBrokerURLs()
if err != nil {
return nil, err
}
c := &DataBroker{ c := &DataBroker{
dataBrokerServer: dataBrokerServer, dataBrokerServer: dataBrokerServer,
localListener: localListener, localListener: localListener,
localGRPCServer: localGRPCServer, localGRPCServer: localGRPCServer,
localGRPCConnection: localGRPCConnection, localGRPCConnection: localGRPCConnection,
deprecatedCacheClusterDomain: dataBrokerURLs[0].Hostname(), sharedKey: sharedKeyValue,
dataBrokerStorageType: cfg.Options.DataBrokerStorageType, eventsMgr: eventsMgr,
eventsMgr: eventsMgr,
} }
c.Register(c.localGRPCServer) c.Register(c.localGRPCServer)
@ -153,6 +152,12 @@ func (c *DataBroker) update(ctx context.Context, cfg *config.Config) error {
return fmt.Errorf("databroker: bad option: %w", err) return fmt.Errorf("databroker: bad option: %w", err)
} }
sharedKey, err := cfg.Options.GetSharedKey()
if err != nil {
return fmt.Errorf("databroker: invalid shared key: %w", err)
}
c.sharedKey.Store(sharedKey)
oauthOptions, err := cfg.Options.GetOauthOptions() oauthOptions, err := cfg.Options.GetOauthOptions()
if err != nil { if err != nil {
return fmt.Errorf("databroker: invalid oauth options: %w", err) return fmt.Errorf("databroker: invalid oauth options: %w", err)

View file

@ -24,7 +24,6 @@ func TestNew(t *testing.T) {
}{ }{
{"good", config.Options{SharedKey: cryptutil.NewBase64Key(), DataBrokerURLString: "http://example"}, false}, {"good", config.Options{SharedKey: cryptutil.NewBase64Key(), DataBrokerURLString: "http://example"}, false},
{"bad shared secret", config.Options{SharedKey: string([]byte(cryptutil.NewBase64Key())[:31]), DataBrokerURLString: "http://example"}, true}, {"bad shared secret", config.Options{SharedKey: string([]byte(cryptutil.NewBase64Key())[:31]), DataBrokerURLString: "http://example"}, true},
{"bad databroker url", config.Options{SharedKey: cryptutil.NewBase64Key(), DataBrokerURLString: "BAD"}, true},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

View file

@ -0,0 +1,26 @@
// Package atomicutil contains functions for working with the atomic package.
package atomicutil
import "sync/atomic"
// Value is a generic atomic.Value.
type Value[T any] struct {
value atomic.Value
}
// NewValue creates a new Value.
func NewValue[T any](init T) *Value[T] {
v := new(Value[T])
v.value.Store(init)
return v
}
// Load loads the value atomically.
func (v *Value[T]) Load() T {
return v.value.Load().(T)
}
// Store stores the value atomically.
func (v *Value[T]) Store(val T) {
v.value.Store(val)
}

View file

@ -18,7 +18,7 @@ import (
"github.com/pomerium/pomerium/pkg/cryptutil" "github.com/pomerium/pomerium/pkg/cryptutil"
) )
const maxWait = time.Minute const maxWait = 20 * time.Minute
// WithTestRedis creates a test a test redis instance using docker. // WithTestRedis creates a test a test redis instance using docker.
func WithTestRedis(useTLS bool, handler func(rawURL string) error) error { func WithTestRedis(useTLS bool, handler func(rawURL string) error) error {

View file

@ -43,8 +43,8 @@ func NewGRPCClientConn(ctx context.Context, opts *Options, other ...grpc.DialOpt
requestid.StreamClientInterceptor(), requestid.StreamClientInterceptor(),
} }
if opts.SignedJWTKey != nil { if opts.SignedJWTKey != nil {
unaryClientInterceptors = append(unaryClientInterceptors, grpcutil.WithUnarySignedJWT(opts.SignedJWTKey)) unaryClientInterceptors = append(unaryClientInterceptors, grpcutil.WithUnarySignedJWT(func() []byte { return opts.SignedJWTKey }))
streamClientInterceptors = append(streamClientInterceptors, grpcutil.WithStreamSignedJWT(opts.SignedJWTKey)) streamClientInterceptors = append(streamClientInterceptors, grpcutil.WithStreamSignedJWT(func() []byte { return opts.SignedJWTKey }))
} }
dialOptions := []grpc.DialOption{ dialOptions := []grpc.DialOption{

View file

@ -63,8 +63,8 @@ func NewGRPCClientConn(ctx context.Context, opts *Options, other ...grpc.DialOpt
} }
streamClientInterceptors := []grpc.StreamClientInterceptor{} streamClientInterceptors := []grpc.StreamClientInterceptor{}
if opts.SignedJWTKey != nil { if opts.SignedJWTKey != nil {
unaryClientInterceptors = append(unaryClientInterceptors, WithUnarySignedJWT(opts.SignedJWTKey)) unaryClientInterceptors = append(unaryClientInterceptors, WithUnarySignedJWT(func() []byte { return opts.SignedJWTKey }))
streamClientInterceptors = append(streamClientInterceptors, WithStreamSignedJWT(opts.SignedJWTKey)) streamClientInterceptors = append(streamClientInterceptors, WithStreamSignedJWT(func() []byte { return opts.SignedJWTKey }))
} }
dialOptions := []grpc.DialOption{ dialOptions := []grpc.DialOption{

View file

@ -13,7 +13,7 @@ import (
) )
// WithStreamSignedJWT returns a StreamClientInterceptor that adds a JWT to requests. // WithStreamSignedJWT returns a StreamClientInterceptor that adds a JWT to requests.
func WithStreamSignedJWT(key []byte) grpc.StreamClientInterceptor { func WithStreamSignedJWT(getKey func() []byte) grpc.StreamClientInterceptor {
return func( return func(
ctx context.Context, ctx context.Context,
desc *grpc.StreamDesc, desc *grpc.StreamDesc,
@ -21,7 +21,7 @@ func WithStreamSignedJWT(key []byte) grpc.StreamClientInterceptor {
method string, streamer grpc.Streamer, method string, streamer grpc.Streamer,
opts ...grpc.CallOption, opts ...grpc.CallOption,
) (grpc.ClientStream, error) { ) (grpc.ClientStream, error) {
ctx, err := withSignedJWT(ctx, key) ctx, err := withSignedJWT(ctx, getKey())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -31,9 +31,9 @@ func WithStreamSignedJWT(key []byte) grpc.StreamClientInterceptor {
} }
// WithUnarySignedJWT returns a UnaryClientInterceptor that adds a JWT to requests. // WithUnarySignedJWT returns a UnaryClientInterceptor that adds a JWT to requests.
func WithUnarySignedJWT(key []byte) grpc.UnaryClientInterceptor { func WithUnarySignedJWT(getKey func() []byte) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx, err := withSignedJWT(ctx, key) ctx, err := withSignedJWT(ctx, getKey())
if err != nil { if err != nil {
return err return err
} }

View file

@ -74,8 +74,8 @@ func TestSignedJWT(t *testing.T) {
}) })
t.Run("authenticated", func(t *testing.T) { t.Run("authenticated", func(t *testing.T) {
cc, err := grpc.Dial(li.Addr().String(), cc, err := grpc.Dial(li.Addr().String(),
grpc.WithUnaryInterceptor(WithUnarySignedJWT(key)), grpc.WithUnaryInterceptor(WithUnarySignedJWT(func() []byte { return key })),
grpc.WithStreamInterceptor(WithStreamSignedJWT(key)), grpc.WithStreamInterceptor(WithStreamSignedJWT(func() []byte { return key })),
grpc.WithInsecure()) grpc.WithInsecure())
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
return return

View file

@ -20,12 +20,16 @@ import (
"github.com/pomerium/pomerium/pkg/storage" "github.com/pomerium/pomerium/pkg/storage"
) )
const maxWait = time.Minute * 10
func TestBackend(t *testing.T) { func TestBackend(t *testing.T) {
if os.Getenv("GITHUB_ACTION") != "" && runtime.GOOS == "darwin" { if os.Getenv("GITHUB_ACTION") != "" && runtime.GOOS == "darwin" {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10) t.Parallel()
ctx, clearTimeout := context.WithTimeout(context.Background(), maxWait)
defer clearTimeout() defer clearTimeout()
require.NoError(t, testutil.WithTestPostgres(func(dsn string) error { require.NoError(t, testutil.WithTestPostgres(func(dsn string) error {

View file

@ -7,7 +7,6 @@ import (
"os" "os"
"runtime" "runtime"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -36,7 +35,9 @@ func TestRegistry(t *testing.T) {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10) t.Parallel()
ctx, clearTimeout := context.WithTimeout(context.Background(), maxWait)
defer clearTimeout() defer clearTimeout()
require.NoError(t, testutil.WithTestPostgres(func(dsn string) error { require.NoError(t, testutil.WithTestPostgres(func(dsn string) error {

View file

@ -79,12 +79,14 @@ func TestBackend(t *testing.T) {
} }
t.Run("no-tls", func(t *testing.T) { t.Run("no-tls", func(t *testing.T) {
t.Parallel()
require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error { require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error {
return handler(t, false, rawURL) return handler(t, false, rawURL)
})) }))
}) })
t.Run("tls", func(t *testing.T) { t.Run("tls", func(t *testing.T) {
t.Parallel()
require.NoError(t, testutil.WithTestRedis(true, func(rawURL string) error { require.NoError(t, testutil.WithTestRedis(true, func(rawURL string) error {
return handler(t, true, rawURL) return handler(t, true, rawURL)
})) }))
@ -92,12 +94,14 @@ func TestBackend(t *testing.T) {
if runtime.GOOS == "linux" { if runtime.GOOS == "linux" {
t.Run("cluster", func(t *testing.T) { t.Run("cluster", func(t *testing.T) {
t.Parallel()
require.NoError(t, testutil.WithTestRedisCluster(func(rawURL string) error { require.NoError(t, testutil.WithTestRedisCluster(func(rawURL string) error {
return handler(t, false, rawURL) return handler(t, false, rawURL)
})) }))
}) })
t.Run("sentinel", func(t *testing.T) { t.Run("sentinel", func(t *testing.T) {
t.Parallel()
require.NoError(t, testutil.WithTestRedisSentinel(func(rawURL string) error { require.NoError(t, testutil.WithTestRedisSentinel(func(rawURL string) error {
return handler(t, false, rawURL) return handler(t, false, rawURL)
})) }))
@ -110,6 +114,8 @@ func TestChangeSignal(t *testing.T) {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
t.Parallel()
ctx := context.Background() ctx := context.Background()
require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error { require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error {
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30) ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
@ -174,6 +180,8 @@ func TestExpiry(t *testing.T) {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
t.Parallel()
ctx := context.Background() ctx := context.Background()
require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error { require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error {
backend, err := New(rawURL, WithExpiry(0)) backend, err := New(rawURL, WithExpiry(0))
@ -219,6 +227,8 @@ func TestCapacity(t *testing.T) {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
t.Parallel()
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10) ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10)
defer clearTimeout() defer clearTimeout()
@ -263,6 +273,8 @@ func TestLease(t *testing.T) {
t.Skip("Github action can not run docker on MacOS") t.Skip("Github action can not run docker on MacOS")
} }
t.Parallel()
ctx := context.Background() ctx := context.Background()
require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error { require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error {
backend, err := New(rawURL) backend, err := New(rawURL)