stub out HPKE public key fetch for self-hosted authenticate (#4360)

Fetch the HPKE public key only when configured to use the hosted
authenticate service. Determine whether we are using the hosted
authenticate service by comparing the resolved authenticate domain with
a hard-coded list of hosted authenticate domains.

Extract this list of hosted authenticate domains to the internal/urlutil
package in order to keep a single source of truth for this data.
This commit is contained in:
Kenneth Jenkins 2023-07-13 10:04:34 -07:00 committed by GitHub
parent 4674b98cfb
commit a1388592d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 6 deletions

View file

@ -237,10 +237,22 @@ func (cfg *Config) GetAuthenticateKeyFetcher() (hpke.KeyFetcher, error) {
if err != nil {
return nil, err
}
jwksURL := authenticateURL.ResolveReference(&url.URL{
// For hosted authenticate, we need to fetch the HPKE public key.
if urlutil.IsHostedAuthenticateDomain(authenticateURL.Hostname()) {
hpkeURL := authenticateURL.ResolveReference(&url.URL{
Path: urlutil.HPKEPublicKeyPath,
}).String()
return hpke.NewKeyFetcher(jwksURL, transport), nil
return hpke.NewKeyFetcher(hpkeURL, transport), nil
}
// Otherwise we can use our own HPKE public key.
privKey, err := cfg.Options.GetHPKEPrivateKey()
if err != nil {
return nil, err
}
pubKey := privKey.PublicKey()
return hpke.NewStubKeyFetcher(pubKey), nil
}
func (cfg *Config) resolveAuthenticateURL() (*url.URL, *http.Transport, error) {

View file

@ -458,8 +458,9 @@ func sourceHostnames(cfg *config.Config) []string {
}
// remove any hosted authenticate URLs
delete(dedupe, "authenticate.pomerium.app")
delete(dedupe, "authenticate.staging.pomerium.app")
for _, domain := range urlutil.HostedAuthenticateDomains {
delete(dedupe, domain)
}
var h []string
for k := range dedupe {

View file

@ -0,0 +1,25 @@
package urlutil
// HostedAuthenticateDomains is a list of all known domains associated with the
// hosted authenticate service.
var HostedAuthenticateDomains = []string{
"authenticate.pomerium.app",
"authenticate.staging.pomerium.app",
}
var hostedAuthenticateDomainSet = initHostedAuthenticateDomainSet()
func initHostedAuthenticateDomainSet() map[string]struct{} {
s := make(map[string]struct{})
for _, domain := range HostedAuthenticateDomains {
s[domain] = struct{}{}
}
return s
}
// IsHostedAuthenticateDomain indicates whether the given domain is associated
// with the hosted authenticate service.
func IsHostedAuthenticateDomain(domain string) bool {
_, isHostedAuthenticate := hostedAuthenticateDomainSet[domain]
return isHostedAuthenticate
}

View file

@ -0,0 +1,19 @@
package urlutil
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsHostedAuthenticateDomain(t *testing.T) {
t.Parallel()
for _, domain := range HostedAuthenticateDomains {
assert.True(t, IsHostedAuthenticateDomain(domain), domain)
}
for _, domain := range []string{"authenticate.example.com", "foo.bar"} {
assert.False(t, IsHostedAuthenticateDomain(domain), domain)
}
}

18
pkg/hpke/stub.go Normal file
View file

@ -0,0 +1,18 @@
package hpke
import (
"context"
)
type stubFetcher struct {
key *PublicKey
}
func (f stubFetcher) FetchPublicKey(_ context.Context) (*PublicKey, error) {
return f.key, nil
}
// NewStubKeyFetcher returns a new KeyFetcher which returns a fixed key.
func NewStubKeyFetcher(key *PublicKey) KeyFetcher {
return stubFetcher{key}
}

26
pkg/hpke/stub_test.go Normal file
View file

@ -0,0 +1,26 @@
package hpke_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/pomerium/pomerium/pkg/hpke"
)
func TestStubFetcher(t *testing.T) {
t.Parallel()
hpkePrivateKey, err := hpke.GeneratePrivateKey()
require.NoError(t, err)
expected := hpkePrivateKey.PublicKey()
f := hpke.NewStubKeyFetcher(expected)
actual, err := f.FetchPublicKey(context.Background())
require.NoError(t, err)
assert.Equal(t, expected.String(), actual.String())
}