reorganize federation domain packages to be more intuitive
Co-authored-by: Benjamin A. Petersen <ben@benjaminapetersen.me>
This commit is contained in:
parent
3160b5bad1
commit
86c791b8a6
@ -26,7 +26,7 @@ import (
|
||||
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/upstreamldap"
|
||||
)
|
||||
|
@ -29,9 +29,9 @@ import (
|
||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/endpointaddr"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/mocks/mockldapconn"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/upstreamldap"
|
||||
)
|
||||
@ -2010,7 +2010,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
pinnipedInformers := pinnipedinformers.NewSharedInformerFactory(fakePinnipedClient, 0)
|
||||
fakeKubeClient := fake.NewSimpleClientset(tt.inputSecrets...)
|
||||
kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||
cache := provider.NewDynamicUpstreamIDPProvider()
|
||||
cache := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
cache.SetActiveDirectoryIdentityProviders([]upstreamprovider.UpstreamLDAPIdentityProviderI{
|
||||
upstreamldap.New(upstreamldap.ProviderConfig{Name: "initial-entry"}),
|
||||
})
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
"go.pinniped.dev/internal/celtransformer"
|
||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
|
@ -27,8 +27,8 @@ import (
|
||||
pinnipedfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
pinnipedinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/upstreamldap"
|
||||
)
|
||||
|
@ -28,9 +28,9 @@ import (
|
||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/endpointaddr"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/mocks/mockldapconn"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/upstreamldap"
|
||||
)
|
||||
@ -1139,7 +1139,7 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
||||
pinnipedInformers := pinnipedinformers.NewSharedInformerFactory(fakePinnipedClient, 0)
|
||||
fakeKubeClient := fake.NewSimpleClientset(tt.inputSecrets...)
|
||||
kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||
cache := provider.NewDynamicUpstreamIDPProvider()
|
||||
cache := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
cache.SetLDAPIdentityProviders([]upstreamprovider.UpstreamLDAPIdentityProviderI{
|
||||
upstreamldap.New(upstreamldap.ProviderConfig{Name: "initial-entry"}),
|
||||
})
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
@ -34,8 +34,8 @@ import (
|
||||
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/net/phttp"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/upstreamoidc"
|
||||
)
|
||||
@ -94,7 +94,7 @@ type UpstreamOIDCIdentityProviderICache interface {
|
||||
SetOIDCIdentityProviders([]upstreamprovider.UpstreamOIDCIdentityProviderI)
|
||||
}
|
||||
|
||||
// lruValidatorCache caches the *oidc.Provider associated with a particular issuer/TLS configuration.
|
||||
// lruValidatorCache caches the *coreosoidc.Provider associated with a particular issuer/TLS configuration.
|
||||
type lruValidatorCache struct{ cache *cache.Expiring }
|
||||
|
||||
type lruValidatorCacheEntry struct {
|
||||
|
@ -28,8 +28,8 @@ import (
|
||||
pinnipedinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions"
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
@ -81,7 +81,7 @@ func TestOIDCUpstreamWatcherControllerFilterSecret(t *testing.T) {
|
||||
pinnipedInformers := pinnipedinformers.NewSharedInformerFactory(fakePinnipedClient, 0)
|
||||
fakeKubeClient := fake.NewSimpleClientset()
|
||||
kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||
cache := provider.NewDynamicUpstreamIDPProvider()
|
||||
cache := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
cache.SetOIDCIdentityProviders([]upstreamprovider.UpstreamOIDCIdentityProviderI{
|
||||
&upstreamoidc.ProviderConfig{Name: "initial-entry"},
|
||||
})
|
||||
@ -1416,7 +1416,7 @@ oidc: issuer did not match the issuer returned by provider, expected "` + testIs
|
||||
fakeKubeClient := fake.NewSimpleClientset(tt.inputSecrets...)
|
||||
kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||
testLog := testlogger.NewLegacy(t) //nolint:staticcheck // old test with lots of log statements
|
||||
cache := provider.NewDynamicUpstreamIDPProvider()
|
||||
cache := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
cache.SetOIDCIdentityProviders([]upstreamprovider.UpstreamOIDCIdentityProviderI{
|
||||
&upstreamoidc.ProviderConfig{Name: "initial-entry"},
|
||||
})
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/upstreamldap"
|
||||
)
|
||||
|
@ -21,13 +21,13 @@ import (
|
||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/fositestorage/accesstoken"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/fositestorage/openidconnect"
|
||||
"go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestorage/refreshtoken"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
@ -144,7 +144,7 @@ func (c *garbageCollectorController) Sync(ctx controllerlib.Context) error {
|
||||
// cleaning them out of etcd storage.
|
||||
fourHoursAgo := frozenClock.Now().Add(-4 * time.Hour)
|
||||
nowIsLessThanFourHoursBeyondSecretGCTime := garbageCollectAfterTime.After(fourHoursAgo)
|
||||
if errors.As(revokeErr, &provider.RetryableRevocationError{}) && nowIsLessThanFourHoursBeyondSecretGCTime {
|
||||
if errors.As(revokeErr, &dynamicupstreamprovider.RetryableRevocationError{}) && nowIsLessThanFourHoursBeyondSecretGCTime {
|
||||
// Hasn't been very long since secret expired, so skip deletion to try revocation again later.
|
||||
plog.Trace("garbage collector keeping Secret to retry upstream OIDC token revocation later", logKV(secret)...)
|
||||
continue
|
||||
|
@ -25,12 +25,12 @@ import (
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/fositestorage/accesstoken"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/fositestorage/refreshtoken"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
@ -138,7 +138,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
|
||||
// Defer starting the informers until the last possible moment so that the
|
||||
// nested Before's can keep adding things to the informer caches.
|
||||
var startInformersAndController = func(idpCache provider.DynamicUpstreamIDPProvider) {
|
||||
var startInformersAndController = func(idpCache dynamicupstreamprovider.DynamicUpstreamIDPProvider) {
|
||||
// Set this at the last second to allow for injection of server override.
|
||||
subject = GarbageCollectorController(
|
||||
idpCache,
|
||||
@ -774,7 +774,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
WithName("upstream-oidc-provider-name").
|
||||
WithResourceUID("upstream-oidc-provider-uid").
|
||||
// make the upstream revocation fail in a retryable way
|
||||
WithRevokeTokenError(provider.NewRetryableRevocationError(errors.New("some retryable upstream revocation error")))
|
||||
WithRevokeTokenError(dynamicupstreamprovider.NewRetryableRevocationError(errors.New("some retryable upstream revocation error")))
|
||||
idpListerBuilder := oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream.Build())
|
||||
|
||||
startInformersAndController(idpListerBuilder.BuildDynamicUpstreamIDPProvider())
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package clientregistry defines Pinniped's OAuth2/OIDC clients.
|
||||
@ -18,7 +18,7 @@ import (
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
supervisorclient "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clientregistry
|
||||
@ -21,7 +21,7 @@ import (
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package csp defines helpers related to HTML Content Security Policies.
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package csp
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package csrftoken
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package csrftoken
|
@ -20,9 +20,9 @@ import (
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/authenticators"
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package dynamiccodec provides a type that can encode information using a just-in-time signing and
|
||||
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/gorilla/securecookie"
|
||||
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
)
|
||||
|
||||
var _ oidc.Codec = &Codec{}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package dynamiccodec
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package provider
|
||||
package dynamictlscertprovider
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
@ -1,13 +1,13 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package provider
|
||||
package dynamicupstreamprovider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
)
|
||||
|
||||
type DynamicUpstreamIDPProvider interface {
|
@ -16,17 +16,17 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/csrftoken"
|
||||
"go.pinniped.dev/internal/federationdomain/downstreamsession"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/login"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/formposthtml"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/resolvedprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/csrftoken"
|
||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||
"go.pinniped.dev/internal/oidc/login"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/oidc/provider/formposthtml"
|
||||
"go.pinniped.dev/internal/oidc/provider/resolvedprovider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
@ -30,11 +30,12 @@ import (
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/authenticators"
|
||||
"go.pinniped.dev/internal/federationdomain/csrftoken"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/csrftoken"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
@ -232,18 +233,18 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
jwksProviderIsUnused := jwks.NewDynamicJWKSProvider()
|
||||
timeoutsConfiguration := oidc.DefaultOIDCTimeoutsConfiguration()
|
||||
|
||||
createOauthHelperWithRealStorage := func(secretsClient v1.SecretInterface, oidcClientsClient v1alpha1.OIDCClientInterface) (fosite.OAuth2Provider, *oidc.KubeStorage) {
|
||||
createOauthHelperWithRealStorage := func(secretsClient v1.SecretInterface, oidcClientsClient v1alpha1.OIDCClientInterface) (fosite.OAuth2Provider, *storage.KubeStorage) {
|
||||
// Configure fosite the same way that the production code would when using Kube storage.
|
||||
// Inject this into our test subject at the last second so we get a fresh storage for every test.
|
||||
// Use lower minimum required bcrypt cost than we would use in production to keep unit the tests fast.
|
||||
kubeOauthStore := oidc.NewKubeStorage(secretsClient, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
kubeOauthStore := storage.NewKubeStorage(secretsClient, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
return oidc.FositeOauth2Helper(kubeOauthStore, downstreamIssuer, hmacSecretFunc, jwksProviderIsUnused, timeoutsConfiguration), kubeOauthStore
|
||||
}
|
||||
|
||||
createOauthHelperWithNullStorage := func(secretsClient v1.SecretInterface, oidcClientsClient v1alpha1.OIDCClientInterface) (fosite.OAuth2Provider, *oidc.NullStorage) {
|
||||
createOauthHelperWithNullStorage := func(secretsClient v1.SecretInterface, oidcClientsClient v1alpha1.OIDCClientInterface) (fosite.OAuth2Provider, *storage.NullStorage) {
|
||||
// Configure fosite the same way that the production code would, using NullStorage to turn off storage.
|
||||
// Use lower minimum required bcrypt cost than we would use in production to keep unit the tests fast.
|
||||
nullOauthStore := oidc.NewNullStorage(secretsClient, oidcClientsClient, bcrypt.MinCost)
|
||||
nullOauthStore := storage.NewNullStorage(secretsClient, oidcClientsClient, bcrypt.MinCost)
|
||||
return oidc.FositeOauth2Helper(nullOauthStore, downstreamIssuer, hmacSecretFunc, jwksProviderIsUnused, timeoutsConfiguration), nullOauthStore
|
||||
}
|
||||
|
||||
@ -3175,7 +3176,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
runOneTestCase := func(t *testing.T, test testCase, subject http.Handler, kubeOauthStore *oidc.KubeStorage, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset, secretsClient v1.SecretInterface) {
|
||||
runOneTestCase := func(t *testing.T, test testCase, subject http.Handler, kubeOauthStore *storage.KubeStorage, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset, secretsClient v1.SecretInterface) {
|
||||
if test.kubeResources != nil {
|
||||
test.kubeResources(t, supervisorClient, kubeClient)
|
||||
}
|
@ -10,12 +10,12 @@ import (
|
||||
|
||||
"github.com/ory/fosite"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/downstreamsession"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/formposthtml"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/oidc/provider/formposthtml"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
@ -21,9 +21,10 @@ import (
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
@ -1451,7 +1452,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
// Inject this into our test subject at the last second so we get a fresh storage for every test.
|
||||
timeoutsConfiguration := oidc.DefaultOIDCTimeoutsConfiguration()
|
||||
// Use lower minimum required bcrypt cost than we would use in production to keep unit the tests fast.
|
||||
oauthStore := oidc.NewKubeStorage(secrets, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
oauthStore := storage.NewKubeStorage(secrets, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
hmacSecretFunc := func() []byte { return []byte("some secret - must have at least 32 bytes") }
|
||||
require.GreaterOrEqual(t, len(hmacSecretFunc()), 32, "fosite requires that hmac secrets have at least 32 bytes")
|
||||
jwksProviderIsUnused := jwks.NewDynamicJWKSProvider()
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
)
|
||||
|
||||
// Metadata holds all fields (that we care about) from the OpenID Provider Metadata section in the
|
@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
)
|
||||
|
||||
func TestDiscovery(t *testing.T) {
|
@ -11,7 +11,7 @@ import (
|
||||
"sort"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
)
|
||||
|
||||
// NewHandler returns an http.Handler that serves the upstream IDP discovery endpoint.
|
@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jwks
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package discovery provides a handler for the OIDC discovery endpoint.
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jwks
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package login
|
||||
@ -6,8 +6,8 @@ package login
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/login/loginhtml"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/login/loginhtml"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
)
|
||||
|
||||
const (
|
@ -10,9 +10,9 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/idplister"
|
||||
"go.pinniped.dev/internal/oidc/login/loginhtml"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/login/loginhtml"
|
||||
"go.pinniped.dev/internal/federationdomain/idplister"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package login
|
||||
@ -8,11 +8,11 @@ import (
|
||||
"net/url"
|
||||
|
||||
idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/login/loginhtml"
|
||||
"go.pinniped.dev/internal/federationdomain/formposthtml"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/login/loginhtml"
|
||||
"go.pinniped.dev/internal/oidc/provider/formposthtml"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package login
|
||||
@ -13,8 +13,8 @@ import (
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2022 the Pinniped contributors. All Rights Reserved. */
|
||||
/* Copyright 2022-2023 the Pinniped contributors. All Rights Reserved. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
html {
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
Notes:
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package loginhtml defines HTML templates used by the Supervisor.
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/tdewolff/minify/v2/minify"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/provider/csp"
|
||||
"go.pinniped.dev/internal/federationdomain/csp"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // This package uses globals to ensure that all parsing and minifying happens at init.
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package loginhtml
|
||||
@ -8,9 +8,9 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
||||
var (
|
@ -9,10 +9,10 @@ import (
|
||||
|
||||
"github.com/ory/fosite"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/downstreamsession"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
@ -20,9 +20,10 @@ import (
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/internal/authenticators"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
@ -978,7 +979,7 @@ func TestPostLoginEndpoint(t *testing.T) {
|
||||
// Inject this into our test subject at the last second so we get a fresh storage for every test.
|
||||
timeoutsConfiguration := oidc.DefaultOIDCTimeoutsConfiguration()
|
||||
// Use lower minimum required bcrypt cost than we would use in production to keep unit the tests fast.
|
||||
kubeOauthStore := oidc.NewKubeStorage(secretsClient, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
kubeOauthStore := storage.NewKubeStorage(secretsClient, oidcClientsClient, timeoutsConfiguration, bcrypt.MinCost)
|
||||
hmacSecretFunc := func() []byte { return []byte("some secret - must have at least 32 bytes") }
|
||||
require.GreaterOrEqual(t, len(hmacSecretFunc()), 32, "fosite requires that hmac secrets have at least 32 bytes")
|
||||
jwksProviderIsUnused := jwks.NewDynamicJWKSProvider()
|
@ -18,13 +18,13 @@ import (
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/downstreamsession"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/resolvedprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/oidc/provider/resolvedprovider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
@ -24,7 +24,7 @@ import (
|
||||
"github.com/ory/fosite"
|
||||
fositeoauth2 "github.com/ory/fosite/handler/oauth2"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/handler/pkce"
|
||||
fositepkce "github.com/ory/fosite/handler/pkce"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -42,19 +42,20 @@ import (
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/fositestorage/accesstoken"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/fositestorage/openidconnect"
|
||||
storagepkce "go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestorage/refreshtoken"
|
||||
"go.pinniped.dev/internal/fositestoragei"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
@ -955,7 +956,7 @@ func TestTokenEndpointWhenAuthcodeIsUsedTwice(t *testing.T) {
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: openidconnect.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: accesstoken.TypeLabelValue}, 0)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: refreshtoken.TypeLabelValue}, 0)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: storagepkce.TypeLabelValue}, 0)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: pkce.TypeLabelValue}, 0)
|
||||
// Assert the number of all secrets, excluding any OIDCClient's storage secret, since those are not related to session storage.
|
||||
testutil.RequireNumberOfSecretsExcludingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: oidcclientsecretstorage.TypeLabelValue}, 2)
|
||||
})
|
||||
@ -1005,7 +1006,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn
|
||||
authcodeExchange authcodeExchangeInputs
|
||||
modifyRequestParams func(t *testing.T, params url.Values)
|
||||
modifyRequestHeaders func(r *http.Request)
|
||||
modifyStorage func(t *testing.T, storage *oidc.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request)
|
||||
modifyStorage func(t *testing.T, storage *storage.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request)
|
||||
requestedAudience string
|
||||
kubeResources func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset)
|
||||
|
||||
@ -1452,7 +1453,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn
|
||||
name: "valid access token, but it was already deleted from storage",
|
||||
authcodeExchange: doValidAuthCodeExchange,
|
||||
requestedAudience: "some-workload-cluster",
|
||||
modifyStorage: func(t *testing.T, storage *oidc.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request) {
|
||||
modifyStorage: func(t *testing.T, storage *storage.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request) {
|
||||
parts := strings.Split(pendingRequest.Form.Get("subject_token"), ".")
|
||||
require.Len(t, parts, 2)
|
||||
require.NoError(t, storage.DeleteAccessTokenSession(context.Background(), parts[1]))
|
||||
@ -1465,7 +1466,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn
|
||||
name: "valid access token, but it has already expired",
|
||||
authcodeExchange: doValidAuthCodeExchange,
|
||||
requestedAudience: "some-workload-cluster",
|
||||
modifyStorage: func(t *testing.T, storage *oidc.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request) {
|
||||
modifyStorage: func(t *testing.T, storage *storage.KubeStorage, secrets v1.SecretInterface, pendingRequest *http.Request) {
|
||||
// The fosite storage APIs don't offer a way to update an access token, so we will instead find the underlying
|
||||
// storage Secret and update it in a more manual way. First get the access token's signature.
|
||||
parts := strings.Split(pendingRequest.Form.Get("subject_token"), ".")
|
||||
@ -1955,7 +1956,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
kubeResources func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset)
|
||||
authcodeExchange authcodeExchangeInputs
|
||||
refreshRequest refreshRequestInputs
|
||||
modifyRefreshTokenStorage func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string)
|
||||
modifyRefreshTokenStorage func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string)
|
||||
}{
|
||||
{
|
||||
name: "happy path refresh grant with openid scope granted (id token returned)",
|
||||
@ -2869,7 +2870,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
name: "when a valid refresh token is sent in the refresh request, but the token has already expired",
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(upstreamOIDCIdentityProviderBuilder().Build()),
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
// The fosite storage APIs don't offer a way to update a refresh token, so we will instead find the underlying
|
||||
// storage Secret and update it in a more manual way. First get the refresh token's signature.
|
||||
refreshTokenSignature := getFositeDataSignature(t, refreshToken)
|
||||
@ -3832,7 +3833,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
Build(),
|
||||
),
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForLDAPUpstream,
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
refreshTokenSignature := getFositeDataSignature(t, refreshToken)
|
||||
firstRequester, err := oauthStore.GetRefreshTokenSession(context.Background(), refreshTokenSignature, nil)
|
||||
require.NoError(t, err)
|
||||
@ -3870,7 +3871,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
happyLDAPCustomSessionData,
|
||||
),
|
||||
},
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
refreshTokenSignature := getFositeDataSignature(t, refreshToken)
|
||||
firstRequester, err := oauthStore.GetRefreshTokenSession(context.Background(), refreshTokenSignature, nil)
|
||||
require.NoError(t, err)
|
||||
@ -3908,7 +3909,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
happyLDAPCustomSessionData,
|
||||
),
|
||||
},
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
refreshTokenSignature := getFositeDataSignature(t, refreshToken)
|
||||
firstRequester, err := oauthStore.GetRefreshTokenSession(context.Background(), refreshTokenSignature, nil)
|
||||
require.NoError(t, err)
|
||||
@ -3988,7 +3989,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
Build(),
|
||||
),
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForLDAPUpstream,
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *oidc.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
modifyRefreshTokenStorage: func(t *testing.T, oauthStore *storage.KubeStorage, secrets v1.SecretInterface, refreshToken string) {
|
||||
refreshTokenSignature := getFositeDataSignature(t, refreshToken)
|
||||
firstRequester, err := oauthStore.GetRefreshTokenSession(context.Background(), refreshTokenSignature, nil)
|
||||
require.NoError(t, err)
|
||||
@ -4178,7 +4179,7 @@ func exchangeAuthcodeForTokens(
|
||||
authCode string,
|
||||
jwtSigningKey *ecdsa.PrivateKey,
|
||||
secrets v1.SecretInterface,
|
||||
oauthStore *oidc.KubeStorage,
|
||||
oauthStore *storage.KubeStorage,
|
||||
) {
|
||||
authRequest := deepCopyRequestForm(happyAuthRequest)
|
||||
if test.modifyAuthRequest != nil {
|
||||
@ -4196,7 +4197,7 @@ func exchangeAuthcodeForTokens(
|
||||
|
||||
var oauthHelper fosite.OAuth2Provider
|
||||
// Use lower minimum required bcrypt cost than we would use in production to keep unit the tests fast.
|
||||
oauthStore = oidc.NewKubeStorage(secrets, oidcClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), bcrypt.MinCost)
|
||||
oauthStore = storage.NewKubeStorage(secrets, oidcClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), bcrypt.MinCost)
|
||||
|
||||
if test.makeJwksSigningKeyAndProvider == nil {
|
||||
test.makeJwksSigningKeyAndProvider = generateJWTSigningKeyAndJWKSProvider
|
||||
@ -4214,7 +4215,7 @@ func exchangeAuthcodeForTokens(
|
||||
}
|
||||
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: authorizationcode.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: storagepkce.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: pkce.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: openidconnect.TypeLabelValue}, expectedNumberOfIDSessionsStored)
|
||||
// Assert the number of all secrets, excluding any OIDCClient's storage secret, since those are not related to session storage.
|
||||
testutil.RequireNumberOfSecretsExcludingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: oidcclientsecretstorage.TypeLabelValue}, 2+expectedNumberOfIDSessionsStored)
|
||||
@ -4259,7 +4260,7 @@ func requireTokenEndpointBehavior(
|
||||
wantNonceValueInIDToken bool,
|
||||
tokenEndpointResponse *httptest.ResponseRecorder,
|
||||
authCode string,
|
||||
oauthStore *oidc.KubeStorage,
|
||||
oauthStore *storage.KubeStorage,
|
||||
jwtSigningKey *ecdsa.PrivateKey,
|
||||
secrets v1.SecretInterface,
|
||||
requestTime time.Time,
|
||||
@ -4298,7 +4299,7 @@ func requireTokenEndpointBehavior(
|
||||
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: authorizationcode.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: accesstoken.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: storagepkce.TypeLabelValue}, 0)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: pkce.TypeLabelValue}, 0)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: refreshtoken.TypeLabelValue}, expectedNumberOfRefreshTokenSessionsStored)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: openidconnect.TypeLabelValue}, expectedNumberOfIDSessionsStored)
|
||||
// Assert the number of all secrets, excluding any OIDCClient's storage secret, since those are not related to session storage.
|
||||
@ -4650,7 +4651,7 @@ func requireInvalidAccessTokenStorage(
|
||||
func requireInvalidPKCEStorage(
|
||||
t *testing.T,
|
||||
code string,
|
||||
storage pkce.PKCERequestStorage,
|
||||
storage fositepkce.PKCERequestStorage,
|
||||
) {
|
||||
t.Helper()
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package tokenexchange
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -27,8 +27,8 @@ type stsParams struct {
|
||||
requestedAudience string
|
||||
}
|
||||
|
||||
func TokenExchangeFactory(config fosite.Configurator, storage interface{}, strategy interface{}) interface{} {
|
||||
return &TokenExchangeHandler{
|
||||
func HandlerFactory(config fosite.Configurator, storage interface{}, strategy interface{}) interface{} {
|
||||
return &tokenExchangeHandler{
|
||||
idTokenStrategy: strategy.(openid.OpenIDConnectTokenStrategy),
|
||||
accessTokenStrategy: strategy.(oauth2.AccessTokenStrategy),
|
||||
accessTokenStorage: storage.(oauth2.AccessTokenStorage),
|
||||
@ -36,23 +36,23 @@ func TokenExchangeFactory(config fosite.Configurator, storage interface{}, strat
|
||||
}
|
||||
}
|
||||
|
||||
type TokenExchangeHandler struct {
|
||||
type tokenExchangeHandler struct {
|
||||
idTokenStrategy openid.OpenIDConnectTokenStrategy
|
||||
accessTokenStrategy oauth2.AccessTokenStrategy
|
||||
accessTokenStorage oauth2.AccessTokenStorage
|
||||
fositeConfig fosite.Configurator
|
||||
}
|
||||
|
||||
var _ fosite.TokenEndpointHandler = (*TokenExchangeHandler)(nil)
|
||||
var _ fosite.TokenEndpointHandler = (*tokenExchangeHandler)(nil)
|
||||
|
||||
func (t *TokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error {
|
||||
func (t *tokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error {
|
||||
if !t.CanHandleTokenEndpointRequest(ctx, requester) {
|
||||
return errors.WithStack(fosite.ErrUnknownRequest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
|
||||
func (t *tokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
|
||||
// Skip this request if it's for a different grant type.
|
||||
if err := t.HandleTokenEndpointRequest(ctx, requester); err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -108,7 +108,7 @@ func (t *TokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) mintJWT(ctx context.Context, requester fosite.Requester, audience string) (string, error) {
|
||||
func (t *tokenExchangeHandler) mintJWT(ctx context.Context, requester fosite.Requester, audience string) (string, error) {
|
||||
downscoped := fosite.NewAccessRequest(requester.GetSession())
|
||||
downscoped.Client.(*fosite.DefaultClient).ID = audience
|
||||
|
||||
@ -119,7 +119,7 @@ func (t *TokenExchangeHandler) mintJWT(ctx context.Context, requester fosite.Req
|
||||
return t.idTokenStrategy.GenerateIDToken(ctx, idTokenLifespan, downscoped)
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) validateSession(requester fosite.Requester) error {
|
||||
func (t *tokenExchangeHandler) validateSession(requester fosite.Requester) error {
|
||||
pSession, ok := requester.GetSession().(*psession.PinnipedSession)
|
||||
if !ok {
|
||||
// This shouldn't really happen.
|
||||
@ -135,7 +135,7 @@ func (t *TokenExchangeHandler) validateSession(requester fosite.Requester) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) validateParams(params url.Values) (*stsParams, error) {
|
||||
func (t *tokenExchangeHandler) validateParams(params url.Values) (*stsParams, error) {
|
||||
var result stsParams
|
||||
|
||||
// Validate some required parameters.
|
||||
@ -189,7 +189,7 @@ func (t *TokenExchangeHandler) validateParams(params url.Values) (*stsParams, er
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) validateAccessToken(ctx context.Context, requester fosite.AccessRequester, accessToken string) (fosite.Requester, error) {
|
||||
func (t *tokenExchangeHandler) validateAccessToken(ctx context.Context, requester fosite.AccessRequester, accessToken string) (fosite.Requester, error) {
|
||||
// Look up the access token's stored session data.
|
||||
signature := t.accessTokenStrategy.AccessTokenSignature(ctx, accessToken)
|
||||
originalRequester, err := t.accessTokenStorage.GetAccessTokenSession(ctx, signature, requester.GetSession())
|
||||
@ -204,10 +204,10 @@ func (t *TokenExchangeHandler) validateAccessToken(ctx context.Context, requeste
|
||||
return originalRequester, nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) CanSkipClientAuth(_ context.Context, _ fosite.AccessRequester) bool {
|
||||
func (t *tokenExchangeHandler) CanSkipClientAuth(_ context.Context, _ fosite.AccessRequester) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) CanHandleTokenEndpointRequest(_ context.Context, requester fosite.AccessRequester) bool {
|
||||
func (t *tokenExchangeHandler) CanHandleTokenEndpointRequest(_ context.Context, requester fosite.AccessRequester) bool {
|
||||
return requester.GetGrantTypes().ExactOne(oidcapi.GrantTypeTokenExchange)
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package manager
|
||||
package endpointsmanager
|
||||
|
||||
import (
|
||||
"go.pinniped.dev/internal/httputil/requestutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -11,20 +12,20 @@ import (
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
"go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/httputil/requestutil"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/auth"
|
||||
"go.pinniped.dev/internal/oidc/callback"
|
||||
"go.pinniped.dev/internal/oidc/csrftoken"
|
||||
"go.pinniped.dev/internal/oidc/discovery"
|
||||
"go.pinniped.dev/internal/oidc/dynamiccodec"
|
||||
"go.pinniped.dev/internal/oidc/idpdiscovery"
|
||||
"go.pinniped.dev/internal/oidc/idplister"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/login"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/oidc/token"
|
||||
"go.pinniped.dev/internal/federationdomain/csrftoken"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamiccodec"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/auth"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/callback"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/discovery"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/idpdiscovery"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/login"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/token"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/idplister"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/secret"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
@ -101,7 +102,7 @@ func (m *Manager) SetFederationDomains(federationDomains ...*federationdomainpro
|
||||
// Use NullStorage for the authorize endpoint because we do not actually want to store anything until
|
||||
// the upstream callback endpoint is called later.
|
||||
oauthHelperWithNullStorage := oidc.FositeOauth2Helper(
|
||||
oidc.NewNullStorage(m.secretsClient, m.oidcClientsClient, oidcclientvalidator.DefaultMinBcryptCost),
|
||||
storage.NewNullStorage(m.secretsClient, m.oidcClientsClient, oidcclientvalidator.DefaultMinBcryptCost),
|
||||
issuerURL,
|
||||
tokenHMACKeyGetter,
|
||||
nil,
|
||||
@ -110,7 +111,7 @@ func (m *Manager) SetFederationDomains(federationDomains ...*federationdomainpro
|
||||
|
||||
// For all the other endpoints, make another oauth helper with exactly the same settings except use real storage.
|
||||
oauthHelperWithKubeStorage := oidc.FositeOauth2Helper(
|
||||
oidc.NewKubeStorage(m.secretsClient, m.oidcClientsClient, timeoutsConfiguration, oidcclientvalidator.DefaultMinBcryptCost),
|
||||
storage.NewKubeStorage(m.secretsClient, m.oidcClientsClient, timeoutsConfiguration, oidcclientvalidator.DefaultMinBcryptCost),
|
||||
issuerURL,
|
||||
tokenHMACKeyGetter,
|
||||
m.dynamicJWKSProvider,
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package manager
|
||||
package endpointsmanager
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
@ -20,12 +20,12 @@ import (
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
supervisorfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/discovery"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/discovery"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/provider/federationdomainproviders"
|
||||
"go.pinniped.dev/internal/secret"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
@ -9,9 +9,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/idplister"
|
||||
"go.pinniped.dev/internal/federationdomain/resolvedprovider"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc/idplister"
|
||||
"go.pinniped.dev/internal/oidc/provider/resolvedprovider"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2021 the Pinniped contributors. All Rights Reserved. */
|
||||
/* Copyright 2021-2023 the Pinniped contributors. All Rights Reserved. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
body {
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||
Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
--><!DOCTYPE html>
|
||||
<html lang="en">
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
window.onload = () => {
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package formposthtml defines HTML templates used by the Supervisor.
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/tdewolff/minify/v2/minify"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/provider/csp"
|
||||
"go.pinniped.dev/internal/federationdomain/csp"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // This package uses globals to ensure that all parsing and minifying happens at init.
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package formposthtml
|
@ -4,7 +4,7 @@
|
||||
package idplister
|
||||
|
||||
import (
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
)
|
||||
|
||||
type UpstreamOIDCIdentityProvidersLister interface {
|
@ -1,7 +1,8 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package oidc contains common OIDC functionality needed by Pinniped.
|
||||
// Package oidc contains common OIDC functionality needed by FederationDomains to implement
|
||||
// downstream OIDC functionality.
|
||||
package oidc
|
||||
|
||||
import (
|
||||
@ -18,10 +19,13 @@ import (
|
||||
errorsx "github.com/pkg/errors"
|
||||
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/csrftoken"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/tokenexchange"
|
||||
"go.pinniped.dev/internal/federationdomain/formposthtml"
|
||||
"go.pinniped.dev/internal/federationdomain/strategy"
|
||||
"go.pinniped.dev/internal/federationdomain/timeouts"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc/csrftoken"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/provider/formposthtml"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
@ -99,81 +103,13 @@ type UpstreamStateParamData struct {
|
||||
FormatVersion string `json:"v"`
|
||||
}
|
||||
|
||||
type TimeoutsConfiguration struct {
|
||||
// The length of time that our state param that we encrypt and pass to the upstream OIDC IDP should be considered
|
||||
// valid. If a state param generated by the authorize endpoint is sent to the callback endpoint after this much
|
||||
// time has passed, then the callback endpoint should reject it. This allows us to set a limit on how long
|
||||
// the end user has to finish their login with the upstream IDP, including the time that it takes to fumble
|
||||
// with password manager and two-factor authenticator apps, and also accounting for taking a coffee break while
|
||||
// the browser is sitting at the upstream IDP's login page.
|
||||
UpstreamStateParamLifespan time.Duration
|
||||
|
||||
// How long an authcode issued by the callback endpoint is valid. This determines how much time the end user
|
||||
// has to come back to exchange the authcode for tokens at the token endpoint.
|
||||
AuthorizeCodeLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream access token issued by the token endpoint. Access tokens should generally
|
||||
// be fairly short-lived.
|
||||
AccessTokenLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream ID token issued by the token endpoint. This should generally be the same
|
||||
// as the AccessTokenLifespan, or longer if it would be useful for the user's proof of identity to be valid
|
||||
// for longer than their proof of authorization.
|
||||
IDTokenLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream refresh token issued by the token endpoint. This should generally be
|
||||
// significantly longer than the access token lifetime, so it can be used to refresh the access token
|
||||
// multiple times. Once the refresh token expires, the user's session is over and they will need
|
||||
// to start a new authorization request, which will require them to log in again with the upstream IDP
|
||||
// in their web browser.
|
||||
RefreshTokenLifespan time.Duration
|
||||
|
||||
// AuthorizationCodeSessionStorageLifetime is the length of time after which an authcode is allowed to be garbage
|
||||
// collected from storage. Authcodes are kept in storage after they are redeemed to allow the system to mark the
|
||||
// authcode as already used, so it can reject any future uses of the same authcode with special case handling which
|
||||
// include revoking the access and refresh tokens associated with the session. Therefore, this should be
|
||||
// significantly longer than the AuthorizeCodeLifespan, and there is probably no reason to make it longer than
|
||||
// the sum of the AuthorizeCodeLifespan and the RefreshTokenLifespan.
|
||||
AuthorizationCodeSessionStorageLifetime time.Duration
|
||||
|
||||
// PKCESessionStorageLifetime is the length of time after which PKCE data is allowed to be garbage collected from
|
||||
// storage. PKCE sessions are closely related to authorization code sessions. After the authcode is successfully
|
||||
// redeemed, the PKCE session is explicitly deleted. After the authcode expires, the PKCE session is no longer needed,
|
||||
// but it is not explicitly deleted. Therefore, this can be just slightly longer than the AuthorizeCodeLifespan. We'll
|
||||
// avoid making it exactly the same as AuthorizeCodeLifespan to avoid any chance of the garbage collector deleting it
|
||||
// while it is being used.
|
||||
PKCESessionStorageLifetime time.Duration
|
||||
|
||||
// OIDCSessionStorageLifetime is the length of time after which the OIDC session data related to an authcode
|
||||
// is allowed to be garbage collected from storage. Due to a bug in an underlying library, these are not explicitly
|
||||
// deleted. Similar to the PKCE session, they are not needed anymore after the corresponding authcode has expired.
|
||||
// Therefore, this can be just slightly longer than the AuthorizeCodeLifespan. We'll avoid making it exactly the same
|
||||
// as AuthorizeCodeLifespan to avoid any chance of the garbage collector deleting it while it is being used.
|
||||
OIDCSessionStorageLifetime time.Duration
|
||||
|
||||
// AccessTokenSessionStorageLifetime is the length of time after which an access token's session data is allowed
|
||||
// to be garbage collected from storage. These must exist in storage for as long as the refresh token is valid
|
||||
// or else the refresh flow will not work properly. So this must be longer than RefreshTokenLifespan.
|
||||
AccessTokenSessionStorageLifetime time.Duration
|
||||
|
||||
// RefreshTokenSessionStorageLifetime is the length of time after which a refresh token's session data is allowed
|
||||
// to be garbage collected from storage. These must exist in storage for as long as the refresh token is valid.
|
||||
// Therefore, this can be just slightly longer than the RefreshTokenLifespan. We'll avoid making it exactly the same
|
||||
// as RefreshTokenLifespan to avoid any chance of the garbage collector deleting it while it is being used.
|
||||
// If an expired token is still stored when the user tries to refresh it, then they will get a more specific
|
||||
// error message telling them that the token is expired, rather than a more generic error that is returned
|
||||
// when the token does not exist. If this is desirable, then the RefreshTokenSessionStorageLifetime can be made
|
||||
// to be significantly larger than RefreshTokenLifespan, at the cost of slower cleanup.
|
||||
RefreshTokenSessionStorageLifetime time.Duration
|
||||
}
|
||||
|
||||
// Get the defaults for the Supervisor server.
|
||||
func DefaultOIDCTimeoutsConfiguration() TimeoutsConfiguration {
|
||||
func DefaultOIDCTimeoutsConfiguration() timeouts.Configuration {
|
||||
accessTokenLifespan := 2 * time.Minute
|
||||
authorizationCodeLifespan := 10 * time.Minute
|
||||
refreshTokenLifespan := 9 * time.Hour
|
||||
|
||||
return TimeoutsConfiguration{
|
||||
return timeouts.Configuration{
|
||||
UpstreamStateParamLifespan: 90 * time.Minute,
|
||||
AuthorizeCodeLifespan: authorizationCodeLifespan,
|
||||
AccessTokenLifespan: accessTokenLifespan,
|
||||
@ -192,7 +128,7 @@ func FositeOauth2Helper(
|
||||
issuer string,
|
||||
hmacSecretOfLengthAtLeast32Func func() []byte,
|
||||
jwksProvider jwks.DynamicJWKSProvider,
|
||||
timeoutsConfiguration TimeoutsConfiguration,
|
||||
timeoutsConfiguration timeouts.Configuration,
|
||||
) fosite.OAuth2Provider {
|
||||
isRedirectURISecureStrict := func(_ context.Context, uri *url.URL) bool {
|
||||
return fosite.IsRedirectURISecureStrict(uri)
|
||||
@ -234,15 +170,15 @@ func FositeOauth2Helper(
|
||||
oauthStore,
|
||||
&compose.CommonStrategy{
|
||||
// Note that Fosite requires the HMAC secret to be at least 32 bytes.
|
||||
CoreStrategy: newDynamicOauth2HMACStrategy(oauthConfig, hmacSecretOfLengthAtLeast32Func),
|
||||
OpenIDConnectTokenStrategy: newDynamicOpenIDConnectECDSAStrategy(oauthConfig, jwksProvider),
|
||||
CoreStrategy: strategy.NewDynamicOauth2HMACStrategy(oauthConfig, hmacSecretOfLengthAtLeast32Func),
|
||||
OpenIDConnectTokenStrategy: strategy.NewDynamicOpenIDConnectECDSAStrategy(oauthConfig, jwksProvider),
|
||||
},
|
||||
compose.OAuth2AuthorizeExplicitFactory,
|
||||
compose.OAuth2RefreshTokenGrantFactory,
|
||||
compose.OpenIDConnectExplicitFactory,
|
||||
compose.OpenIDConnectRefreshFactory,
|
||||
compose.OAuth2PKCEFactory,
|
||||
TokenExchangeFactory, // handle the "urn:ietf:params:oauth:grant-type:token-exchange" grant type
|
||||
tokenexchange.HandlerFactory, // handle the "urn:ietf:params:oauth:grant-type:token-exchange" grant type
|
||||
)
|
||||
|
||||
return oAuth2Provider
|
@ -1,8 +1,11 @@
|
||||
// Copyright 2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package resolvedprovider
|
||||
|
||||
import (
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -14,13 +14,14 @@ import (
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
"go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/timeouts"
|
||||
"go.pinniped.dev/internal/fositestorage/accesstoken"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/fositestorage/openidconnect"
|
||||
"go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestorage/refreshtoken"
|
||||
"go.pinniped.dev/internal/fositestoragei"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
)
|
||||
|
||||
@ -38,7 +39,7 @@ var _ fositestoragei.AllFositeStorage = &KubeStorage{}
|
||||
func NewKubeStorage(
|
||||
secrets corev1client.SecretInterface,
|
||||
oidcClientsClient v1alpha1.OIDCClientInterface,
|
||||
timeoutsConfiguration TimeoutsConfiguration,
|
||||
timeoutsConfiguration timeouts.Configuration,
|
||||
minBcryptCost int,
|
||||
) *KubeStorage {
|
||||
nowFunc := time.Now
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,8 +11,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestoragei"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/oidcclientsecretstorage"
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"github.com/ory/fosite/compose"
|
||||
"github.com/ory/fosite/handler/oauth2"
|
||||
errorsx "github.com/pkg/errors"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -24,7 +26,7 @@ const (
|
||||
oryAuthcodePrefix = "ory_ac_"
|
||||
)
|
||||
|
||||
// dynamicOauth2HMACStrategy is an oauth2.CoreStrategy that can dynamically load an HMAC key to sign
|
||||
// DynamicOauth2HMACStrategy is an oauth2.CoreStrategy that can dynamically load an HMAC key to sign
|
||||
// stuff (access tokens, refresh tokens, and auth codes). We want this dynamic capability since our
|
||||
// controllers for loading FederationDomain's and signing keys run in parallel, and thus the signing key
|
||||
// might not be ready when an FederationDomain is otherwise ready.
|
||||
@ -37,18 +39,18 @@ const (
|
||||
// out of context, such as when accidentally committed to a GitHub repo. After we implemented the
|
||||
// custom prefix feature, fosite later added the same feature, but did not make the prefix customizable.
|
||||
// Therefore, this code has been updated to replace the fosite prefix with our custom prefix.
|
||||
type dynamicOauth2HMACStrategy struct {
|
||||
type DynamicOauth2HMACStrategy struct {
|
||||
fositeConfig *fosite.Config
|
||||
keyFunc func() []byte
|
||||
}
|
||||
|
||||
var _ oauth2.CoreStrategy = &dynamicOauth2HMACStrategy{}
|
||||
var _ oauth2.CoreStrategy = &DynamicOauth2HMACStrategy{}
|
||||
|
||||
func newDynamicOauth2HMACStrategy(
|
||||
func NewDynamicOauth2HMACStrategy(
|
||||
fositeConfig *fosite.Config,
|
||||
keyFunc func() []byte,
|
||||
) *dynamicOauth2HMACStrategy {
|
||||
return &dynamicOauth2HMACStrategy{
|
||||
) *DynamicOauth2HMACStrategy {
|
||||
return &DynamicOauth2HMACStrategy{
|
||||
fositeConfig: fositeConfig,
|
||||
keyFunc: keyFunc,
|
||||
}
|
||||
@ -58,11 +60,11 @@ func replacePrefix(s, prefixToReplace, newPrefix string) string {
|
||||
return newPrefix + strings.TrimPrefix(s, prefixToReplace)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) AccessTokenSignature(ctx context.Context, token string) string {
|
||||
func (s *DynamicOauth2HMACStrategy) AccessTokenSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().AccessTokenSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateAccessToken(
|
||||
func (s *DynamicOauth2HMACStrategy) GenerateAccessToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (string, string, error) {
|
||||
@ -78,7 +80,7 @@ func (s *dynamicOauth2HMACStrategy) GenerateAccessToken(
|
||||
return token, sig, err
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) ValidateAccessToken(
|
||||
func (s *DynamicOauth2HMACStrategy) ValidateAccessToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
@ -90,11 +92,11 @@ func (s *dynamicOauth2HMACStrategy) ValidateAccessToken(
|
||||
return s.delegate().ValidateAccessToken(ctx, requester, replacePrefix(token, pinAccessTokenPrefix, oryAccessTokenPrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) RefreshTokenSignature(ctx context.Context, token string) string {
|
||||
func (s *DynamicOauth2HMACStrategy) RefreshTokenSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().RefreshTokenSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateRefreshToken(
|
||||
func (s *DynamicOauth2HMACStrategy) GenerateRefreshToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (string, string, error) {
|
||||
@ -110,7 +112,7 @@ func (s *dynamicOauth2HMACStrategy) GenerateRefreshToken(
|
||||
return token, sig, err
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) ValidateRefreshToken(
|
||||
func (s *DynamicOauth2HMACStrategy) ValidateRefreshToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
@ -122,11 +124,11 @@ func (s *dynamicOauth2HMACStrategy) ValidateRefreshToken(
|
||||
return s.delegate().ValidateRefreshToken(ctx, requester, replacePrefix(token, pinRefreshTokenPrefix, oryRefreshTokenPrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) AuthorizeCodeSignature(ctx context.Context, token string) string {
|
||||
func (s *DynamicOauth2HMACStrategy) AuthorizeCodeSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().AuthorizeCodeSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateAuthorizeCode(
|
||||
func (s *DynamicOauth2HMACStrategy) GenerateAuthorizeCode(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (string, string, error) {
|
||||
@ -142,7 +144,7 @@ func (s *dynamicOauth2HMACStrategy) GenerateAuthorizeCode(
|
||||
return authcode, sig, err
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) ValidateAuthorizeCode(
|
||||
func (s *DynamicOauth2HMACStrategy) ValidateAuthorizeCode(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
@ -154,6 +156,6 @@ func (s *dynamicOauth2HMACStrategy) ValidateAuthorizeCode(
|
||||
return s.delegate().ValidateAuthorizeCode(ctx, requester, replacePrefix(token, pinAuthcodePrefix, oryAuthcodePrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) delegate() *oauth2.HMACSHAStrategy {
|
||||
return compose.NewOAuth2HMACStrategy(NewDynamicGlobalSecretConfig(s.fositeConfig, s.keyFunc))
|
||||
func (s *DynamicOauth2HMACStrategy) delegate() *oauth2.HMACSHAStrategy {
|
||||
return compose.NewOAuth2HMACStrategy(storage.NewDynamicGlobalSecretConfig(s.fositeConfig, s.keyFunc))
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Signatures(t *testing.T) {
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
s := NewDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
||||
@ -57,12 +57,12 @@ func TestDynamicOauth2HMACStrategy_Signatures(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Generate(t *testing.T) {
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
s := NewDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
||||
|
||||
generateTokenErrorCausingStrategy := newDynamicOauth2HMACStrategy(
|
||||
generateTokenErrorCausingStrategy := NewDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{},
|
||||
func() []byte { return []byte("too_short_causes_error") }, // secret key is below required 32 characters
|
||||
)
|
||||
@ -134,7 +134,7 @@ func TestDynamicOauth2HMACStrategy_Generate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Validate(t *testing.T) {
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
s := NewDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -14,11 +14,11 @@ import (
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
// dynamicOpenIDConnectECDSAStrategy is an openid.OpenIDConnectTokenStrategy that can dynamically
|
||||
// DynamicOpenIDConnectECDSAStrategy is an openid.OpenIDConnectTokenStrategy that can dynamically
|
||||
// load a signing key to issue ID tokens. We want this dynamic capability since our controllers for
|
||||
// loading FederationDomain's and signing keys run in parallel, and thus the signing key might not be
|
||||
// ready when an FederationDomain is otherwise ready.
|
||||
@ -26,24 +26,24 @@ import (
|
||||
// If we ever update FederationDomain's to hold their signing key, we might not need this type, since we
|
||||
// could have an invariant that routes to an FederationDomain's endpoints are only wired up if an
|
||||
// FederationDomain has a valid signing key.
|
||||
type dynamicOpenIDConnectECDSAStrategy struct {
|
||||
type DynamicOpenIDConnectECDSAStrategy struct {
|
||||
fositeConfig *fosite.Config
|
||||
jwksProvider jwks.DynamicJWKSProvider
|
||||
}
|
||||
|
||||
var _ openid.OpenIDConnectTokenStrategy = &dynamicOpenIDConnectECDSAStrategy{}
|
||||
var _ openid.OpenIDConnectTokenStrategy = &DynamicOpenIDConnectECDSAStrategy{}
|
||||
|
||||
func newDynamicOpenIDConnectECDSAStrategy(
|
||||
func NewDynamicOpenIDConnectECDSAStrategy(
|
||||
fositeConfig *fosite.Config,
|
||||
jwksProvider jwks.DynamicJWKSProvider,
|
||||
) *dynamicOpenIDConnectECDSAStrategy {
|
||||
return &dynamicOpenIDConnectECDSAStrategy{
|
||||
) *DynamicOpenIDConnectECDSAStrategy {
|
||||
return &DynamicOpenIDConnectECDSAStrategy{
|
||||
fositeConfig: fositeConfig,
|
||||
jwksProvider: jwksProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *dynamicOpenIDConnectECDSAStrategy) GenerateIDToken(
|
||||
func (s *DynamicOpenIDConnectECDSAStrategy) GenerateIDToken(
|
||||
ctx context.Context,
|
||||
lifespan time.Duration,
|
||||
requester fosite.Requester,
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -20,7 +20,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||
)
|
||||
|
||||
@ -94,7 +94,7 @@ func TestDynamicOpenIDConnectECDSAStrategy(t *testing.T) {
|
||||
if test.jwksProvider != nil {
|
||||
test.jwksProvider(jwksProvider)
|
||||
}
|
||||
s := newDynamicOpenIDConnectECDSAStrategy(
|
||||
s := NewDynamicOpenIDConnectECDSAStrategy(
|
||||
&fosite.Config{IDTokenIssuer: test.issuer},
|
||||
jwksProvider,
|
||||
)
|
74
internal/federationdomain/timeouts/timeouts_configuration.go
Normal file
74
internal/federationdomain/timeouts/timeouts_configuration.go
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package timeouts
|
||||
|
||||
import "time"
|
||||
|
||||
type Configuration struct {
|
||||
// The length of time that our state param that we encrypt and pass to the upstream OIDC IDP should be considered
|
||||
// valid. If a state param generated by the authorize endpoint is sent to the callback endpoint after this much
|
||||
// time has passed, then the callback endpoint should reject it. This allows us to set a limit on how long
|
||||
// the end user has to finish their login with the upstream IDP, including the time that it takes to fumble
|
||||
// with password manager and two-factor authenticator apps, and also accounting for taking a coffee break while
|
||||
// the browser is sitting at the upstream IDP's login page.
|
||||
UpstreamStateParamLifespan time.Duration
|
||||
|
||||
// How long an authcode issued by the callback endpoint is valid. This determines how much time the end user
|
||||
// has to come back to exchange the authcode for tokens at the token endpoint.
|
||||
AuthorizeCodeLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream access token issued by the token endpoint. Access tokens should generally
|
||||
// be fairly short-lived.
|
||||
AccessTokenLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream ID token issued by the token endpoint. This should generally be the same
|
||||
// as the AccessTokenLifespan, or longer if it would be useful for the user's proof of identity to be valid
|
||||
// for longer than their proof of authorization.
|
||||
IDTokenLifespan time.Duration
|
||||
|
||||
// The lifetime of an downstream refresh token issued by the token endpoint. This should generally be
|
||||
// significantly longer than the access token lifetime, so it can be used to refresh the access token
|
||||
// multiple times. Once the refresh token expires, the user's session is over and they will need
|
||||
// to start a new authorization request, which will require them to log in again with the upstream IDP
|
||||
// in their web browser.
|
||||
RefreshTokenLifespan time.Duration
|
||||
|
||||
// AuthorizationCodeSessionStorageLifetime is the length of time after which an authcode is allowed to be garbage
|
||||
// collected from storage. Authcodes are kept in storage after they are redeemed to allow the system to mark the
|
||||
// authcode as already used, so it can reject any future uses of the same authcode with special case handling which
|
||||
// include revoking the access and refresh tokens associated with the session. Therefore, this should be
|
||||
// significantly longer than the AuthorizeCodeLifespan, and there is probably no reason to make it longer than
|
||||
// the sum of the AuthorizeCodeLifespan and the RefreshTokenLifespan.
|
||||
AuthorizationCodeSessionStorageLifetime time.Duration
|
||||
|
||||
// PKCESessionStorageLifetime is the length of time after which PKCE data is allowed to be garbage collected from
|
||||
// storage. PKCE sessions are closely related to authorization code sessions. After the authcode is successfully
|
||||
// redeemed, the PKCE session is explicitly deleted. After the authcode expires, the PKCE session is no longer needed,
|
||||
// but it is not explicitly deleted. Therefore, this can be just slightly longer than the AuthorizeCodeLifespan. We'll
|
||||
// avoid making it exactly the same as AuthorizeCodeLifespan to avoid any chance of the garbage collector deleting it
|
||||
// while it is being used.
|
||||
PKCESessionStorageLifetime time.Duration
|
||||
|
||||
// OIDCSessionStorageLifetime is the length of time after which the OIDC session data related to an authcode
|
||||
// is allowed to be garbage collected from storage. Due to a bug in an underlying library, these are not explicitly
|
||||
// deleted. Similar to the PKCE session, they are not needed anymore after the corresponding authcode has expired.
|
||||
// Therefore, this can be just slightly longer than the AuthorizeCodeLifespan. We'll avoid making it exactly the same
|
||||
// as AuthorizeCodeLifespan to avoid any chance of the garbage collector deleting it while it is being used.
|
||||
OIDCSessionStorageLifetime time.Duration
|
||||
|
||||
// AccessTokenSessionStorageLifetime is the length of time after which an access token's session data is allowed
|
||||
// to be garbage collected from storage. These must exist in storage for as long as the refresh token is valid
|
||||
// or else the refresh flow will not work properly. So this must be longer than RefreshTokenLifespan.
|
||||
AccessTokenSessionStorageLifetime time.Duration
|
||||
|
||||
// RefreshTokenSessionStorageLifetime is the length of time after which a refresh token's session data is allowed
|
||||
// to be garbage collected from storage. These must exist in storage for as long as the refresh token is valid.
|
||||
// Therefore, this can be just slightly longer than the RefreshTokenLifespan. We'll avoid making it exactly the same
|
||||
// as RefreshTokenLifespan to avoid any chance of the garbage collector deleting it while it is being used.
|
||||
// If an expired token is still stored when the user tries to refresh it, then they will get a more specific
|
||||
// error message telling them that the token is expired, rather than a more generic error that is returned
|
||||
// when the token does not exist. If this is desirable, then the RefreshTokenSessionStorageLifetime can be made
|
||||
// to be significantly larger than RefreshTokenLifespan, at the cost of slower cleanup.
|
||||
RefreshTokenSessionStorageLifetime time.Duration
|
||||
}
|
@ -16,8 +16,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -17,8 +17,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -34,8 +34,8 @@ import (
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package fositestorage
|
||||
@ -7,7 +7,7 @@ import (
|
||||
"github.com/ory/fosite"
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package issuermocks
|
||||
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=issuermocks.go -package=issuermocks -copyright_file=../../../hack/header.txt go.pinniped.dev/internal/issuer ClientCertIssuer
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=issuermocks.go -package=issuermocks -copyright_file=../../../hack/header.txt go.pinniped.dev/internal/clientcertissuer ClientCertIssuer
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: go.pinniped.dev/internal/issuer (interfaces: ClientCertIssuer)
|
||||
// Source: go.pinniped.dev/internal/clientcertissuer (interfaces: ClientCertIssuer)
|
||||
|
||||
// Package issuermocks is a generated GoMock package.
|
||||
package issuermocks
|
||||
|
@ -3,4 +3,4 @@
|
||||
|
||||
package mockupstreamoidcidentityprovider
|
||||
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=mockupstreamoidcidentityprovider.go -package=mockupstreamoidcidentityprovider -copyright_file=../../../hack/header.txt go.pinniped.dev/internal/oidc/provider/upstreamprovider UpstreamOIDCIdentityProviderI
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=mockupstreamoidcidentityprovider.go -package=mockupstreamoidcidentityprovider -copyright_file=../../../hack/header.txt go.pinniped.dev/internal/federationdomain/upstreamprovider UpstreamOIDCIdentityProviderI
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: go.pinniped.dev/internal/oidc/provider/upstreamprovider (interfaces: UpstreamOIDCIdentityProviderI)
|
||||
// Source: go.pinniped.dev/internal/federationdomain/upstreamprovider (interfaces: UpstreamOIDCIdentityProviderI)
|
||||
|
||||
// Package mockupstreamoidcidentityprovider is a generated GoMock package.
|
||||
package mockupstreamoidcidentityprovider
|
||||
@ -14,7 +14,7 @@ import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
upstreamprovider "go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
upstreamprovider "go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
nonce "go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
oidctypes "go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
pkce "go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
|
@ -58,12 +58,13 @@ import (
|
||||
"go.pinniped.dev/internal/deploymentref"
|
||||
"go.pinniped.dev/internal/downward"
|
||||
"go.pinniped.dev/internal/dynamiccert"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamictlscertprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/endpoints/jwks"
|
||||
"go.pinniped.dev/internal/federationdomain/endpointsmanager"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/kubeclient"
|
||||
"go.pinniped.dev/internal/leaderelection"
|
||||
"go.pinniped.dev/internal/oidc/jwks"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/manager"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/pversion"
|
||||
"go.pinniped.dev/internal/secret"
|
||||
@ -129,10 +130,10 @@ func signalCtx() context.Context {
|
||||
//nolint:funlen
|
||||
func prepareControllers(
|
||||
cfg *supervisor.Config,
|
||||
issuerManager *manager.Manager,
|
||||
issuerManager *endpointsmanager.Manager,
|
||||
dynamicJWKSProvider jwks.DynamicJWKSProvider,
|
||||
dynamicTLSCertProvider provider.DynamicTLSCertProvider,
|
||||
dynamicUpstreamIDPProvider provider.DynamicUpstreamIDPProvider,
|
||||
dynamicTLSCertProvider dynamictlscertprovider.DynamicTLSCertProvider,
|
||||
dynamicUpstreamIDPProvider dynamicupstreamprovider.DynamicUpstreamIDPProvider,
|
||||
dynamicServingCertProvider dynamiccert.Private,
|
||||
secretCache *secret.Cache,
|
||||
supervisorDeployment *appsv1.Deployment,
|
||||
@ -436,12 +437,12 @@ func runSupervisor(ctx context.Context, podInfo *downward.PodInfo, cfg *supervis
|
||||
dynamicServingCertProvider := dynamiccert.NewServingCert("supervisor-serving-cert")
|
||||
|
||||
dynamicJWKSProvider := jwks.NewDynamicJWKSProvider()
|
||||
dynamicTLSCertProvider := provider.NewDynamicTLSCertProvider()
|
||||
dynamicUpstreamIDPProvider := provider.NewDynamicUpstreamIDPProvider()
|
||||
dynamicTLSCertProvider := dynamictlscertprovider.NewDynamicTLSCertProvider()
|
||||
dynamicUpstreamIDPProvider := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
secretCache := secret.Cache{}
|
||||
|
||||
// OIDC endpoints will be served by the oidProvidersManager, and any non-OIDC paths will fallback to the healthMux.
|
||||
oidProvidersManager := manager.NewManager(
|
||||
oidProvidersManager := endpointsmanager.NewManager(
|
||||
healthMux,
|
||||
dynamicJWKSProvider,
|
||||
dynamicUpstreamIDPProvider,
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package testutil
|
||||
@ -6,10 +6,10 @@ package testutil
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
)
|
||||
|
||||
func TestBcryptConstants(t *testing.T) {
|
||||
|
@ -30,19 +30,19 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/authenticators"
|
||||
"go.pinniped.dev/internal/crud"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/resolvedprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/fositestorage/openidconnect"
|
||||
pkce2 "go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestorage/pkce"
|
||||
"go.pinniped.dev/internal/fositestoragei"
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/resolvedprovider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
oidcpkce "go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
)
|
||||
|
||||
// Test helpers for the OIDC package.
|
||||
@ -52,7 +52,7 @@ import (
|
||||
type ExchangeAuthcodeAndValidateTokenArgs struct {
|
||||
Ctx context.Context
|
||||
Authcode string
|
||||
PKCECodeVerifier pkce.Code
|
||||
PKCECodeVerifier oidcpkce.Code
|
||||
ExpectedIDTokenNonce nonce.Nonce
|
||||
RedirectURI string
|
||||
}
|
||||
@ -267,7 +267,7 @@ type TestUpstreamOIDCIdentityProvider struct {
|
||||
ExchangeAuthcodeAndValidateTokensFunc func(
|
||||
ctx context.Context,
|
||||
authcode string,
|
||||
pkceCodeVerifier pkce.Code,
|
||||
pkceCodeVerifier oidcpkce.Code,
|
||||
expectedIDTokenNonce nonce.Nonce,
|
||||
) (*oidctypes.Token, error)
|
||||
|
||||
@ -358,7 +358,7 @@ func (u *TestUpstreamOIDCIdentityProvider) PasswordCredentialsGrantAndValidateTo
|
||||
func (u *TestUpstreamOIDCIdentityProvider) ExchangeAuthcodeAndValidateTokens(
|
||||
ctx context.Context,
|
||||
authcode string,
|
||||
pkceCodeVerifier pkce.Code,
|
||||
pkceCodeVerifier oidcpkce.Code,
|
||||
expectedIDTokenNonce nonce.Nonce,
|
||||
redirectURI string,
|
||||
) (*oidctypes.Token, error) {
|
||||
@ -595,8 +595,8 @@ func (b *UpstreamIDPListerBuilder) BuildFederationDomainIdentityProvidersListerF
|
||||
}
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) BuildDynamicUpstreamIDPProvider() provider.DynamicUpstreamIDPProvider {
|
||||
idpProvider := provider.NewDynamicUpstreamIDPProvider()
|
||||
func (b *UpstreamIDPListerBuilder) BuildDynamicUpstreamIDPProvider() dynamicupstreamprovider.DynamicUpstreamIDPProvider {
|
||||
idpProvider := dynamicupstreamprovider.NewDynamicUpstreamIDPProvider()
|
||||
|
||||
oidcUpstreams := make([]upstreamprovider.UpstreamOIDCIdentityProviderI, len(b.upstreamOIDCIdentityProviders))
|
||||
for i := range b.upstreamOIDCIdentityProviders {
|
||||
@ -1038,7 +1038,7 @@ func (u *TestUpstreamOIDCIdentityProviderBuilder) Build() *TestUpstreamOIDCIdent
|
||||
AdditionalClaimMappings: u.additionalClaimMappings,
|
||||
DisplayNameForFederationDomain: u.displayNameForFederationDomain,
|
||||
TransformsForFederationDomain: u.transformsForFederationDomain,
|
||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
|
||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier oidcpkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
|
||||
if u.authcodeExchangeErr != nil {
|
||||
return nil, u.authcodeExchangeErr
|
||||
}
|
||||
@ -1223,7 +1223,7 @@ func RequireAuthCodeRegexpMatch(
|
||||
)
|
||||
|
||||
// One PKCE should have been stored.
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secretsClient, labels.Set{crud.SecretLabelKey: pkce2.TypeLabelValue}, 1)
|
||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secretsClient, labels.Set{crud.SecretLabelKey: pkce.TypeLabelValue}, 1)
|
||||
|
||||
validatePKCEStorage(
|
||||
t,
|
||||
|
@ -27,8 +27,8 @@ import (
|
||||
"go.pinniped.dev/internal/authenticators"
|
||||
"go.pinniped.dev/internal/crypto/ptls"
|
||||
"go.pinniped.dev/internal/endpointaddr"
|
||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/downstreamsession"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/crypto/ptls"
|
||||
"go.pinniped.dev/internal/endpointaddr"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/mocks/mockldapconn"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/tlsassertions"
|
||||
"go.pinniped.dev/internal/testutil/tlsserver"
|
||||
|
@ -21,9 +21,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
@ -221,7 +221,7 @@ func (p *ProviderConfig) tryRevokeToken(
|
||||
if err != nil {
|
||||
// Couldn't connect to the server or some similar error.
|
||||
// Could be a temporary network problem, so it might be worth retrying.
|
||||
return false, provider.NewRetryableRevocationError(err)
|
||||
return false, dynamicupstreamprovider.NewRetryableRevocationError(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
@ -271,7 +271,7 @@ func (p *ProviderConfig) tryRevokeToken(
|
||||
// be caused by an underlying problem which could potentially become resolved in the near future. We'll be
|
||||
// optimistic and call all 5xx errors retryable.
|
||||
plog.Trace("RevokeToken() got unexpected error response from provider's revocation endpoint", "providerName", p.Name, "usedBasicAuth", useBasicAuth, "statusCode", status)
|
||||
return false, provider.NewRetryableRevocationError(fmt.Errorf("server responded with status %d", status))
|
||||
return false, dynamicupstreamprovider.NewRetryableRevocationError(fmt.Errorf("server responded with status %d", status))
|
||||
default:
|
||||
// Any other error is probably not due to failed client auth, and is probably not worth retrying later.
|
||||
plog.Trace("RevokeToken() got unexpected error response from provider's revocation endpoint", "providerName", p.Name, "usedBasicAuth", useBasicAuth, "statusCode", status)
|
||||
|
@ -23,9 +23,9 @@ import (
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/dynamicupstreamprovider"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/mocks/mockkeyset"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
@ -715,8 +715,8 @@ func TestProviderConfig(t *testing.T) {
|
||||
testutil.RequireErrorStringFromErr(t, err, tt.wantErr)
|
||||
|
||||
if tt.wantRetryableErrType {
|
||||
require.ErrorAs(t, err, &provider.RetryableRevocationError{})
|
||||
} else if errors.As(err, &provider.RetryableRevocationError{}) {
|
||||
require.ErrorAs(t, err, &dynamicupstreamprovider.RetryableRevocationError{})
|
||||
} else if errors.As(err, &dynamicupstreamprovider.RetryableRevocationError{}) {
|
||||
// There is no NotErrorAs() assertion available in the current version of testify, so do the equivalent.
|
||||
require.Fail(t, "error should not be As RetryableRevocationError")
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ import (
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/internal/net/phttp"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/upstreamoidc"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
|
@ -28,11 +28,11 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/upstreamprovider"
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/roundtripper"
|
||||
"go.pinniped.dev/internal/mocks/mockupstreamoidcidentityprovider"
|
||||
"go.pinniped.dev/internal/net/phttp"
|
||||
"go.pinniped.dev/internal/oidc/provider/upstreamprovider"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/internal/testutil/testlogger"
|
||||
|
@ -160,7 +160,7 @@ Once dynamic clients are implemented:
|
||||
#### New Dependencies
|
||||
This should be kept to a very simple HTML page with minimal, clean CSS styling.
|
||||
Javascript should be avoided.
|
||||
The styling should match the [form post html page](https://github.com/vmware-tanzu/pinniped/tree/main/internal/oidc/provider/formposthtml)
|
||||
The styling should match the [form post html page](https://github.com/vmware-tanzu/pinniped/tree/main/internal/federationdomain/formposthtml)
|
||||
as much as possible, we should reuse some of the existing css and add to it to keep the style consistent.
|
||||
|
||||
#### Observability Considerations
|
||||
|
@ -192,28 +192,28 @@ The Supervisor's endpoints are:
|
||||
Each FederationDomain's endpoints are mounted under the path of the FederationDomain's `spec.issuer`,
|
||||
if the `spec.issuer` URL has a path component specified. If the issuer has no path, then they are mounted under `/`.
|
||||
These per-FederationDomain endpoint are all mounted by the code in
|
||||
[internal/oidc/provider/manager/manager.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/provider/manager/manager.go).
|
||||
[internal/federationdomain/endpointsmanager/manager.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpointsmanager/manager.go).
|
||||
|
||||
The per-FederationDomain endpoints are:
|
||||
|
||||
- `<issuer_path>/.well-known/openid-configuration` is the standard OIDC discovery endpoint, which can be used to discover all the other endpoints listed here.
|
||||
See [internal/oidc/discovery/discovery_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/discovery/discovery_handler.go).
|
||||
See [internal/federationdomain/endpoints/discovery/discovery_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/discovery/discovery_handler.go).
|
||||
- `<issuer_path>/jwks.json` is the standard OIDC JWKS discovery endpoint.
|
||||
See [internal/oidc/jwks/jwks_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/jwks/jwks_handler.go).
|
||||
See [internal/federationdomain/endpoints/jwks/jwks_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/jwks/jwks_handler.go).
|
||||
- `<issuer_path>/oauth2/authorize` is the standard OIDC authorize endpoint.
|
||||
See [internal/oidc/auth/auth_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/auth/auth_handler.go).
|
||||
See [internal/federationdomain/endpoints/auth/auth_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/auth/auth_handler.go).
|
||||
- `<issuer_path>/oauth2/token` is the standard OIDC token endpoint.
|
||||
See [internal/oidc/token/token_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/token/token_handler.go).
|
||||
See [internal/federationdomain/endpoints/token/token_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/token/token_handler.go).
|
||||
The token endpoint can handle the standard OIDC `authorization_code` and `refresh_token` grant types, and has also been
|
||||
extended in [internal/oidc/token_exchange.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/token_exchange.go)
|
||||
extended in [internal/federationdomain/endpoints/tokenexchange/token_exchange.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/tokenexchange/token_exchange.go)
|
||||
to handle an additional grant type for [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) token exchanges to
|
||||
reduce the applicable scope (technically, the `aud` claim) of ID tokens.
|
||||
- `<issuer_path>/callback` is a special endpoint that is used as the redirect URL when performing an OIDC authcode flow against an upstream OIDC identity provider as configured by an OIDCIdentityProvider custom resource.
|
||||
See [internal/oidc/callback/callback_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/callback/callback_handler.go).
|
||||
See [internal/federationdomain/endpoints/callback/callback_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/callback/callback_handler.go).
|
||||
- `<issuer_path>/v1alpha1/pinniped_identity_providers` is a custom discovery endpoint for clients to learn about available upstream identity providers.
|
||||
See [internal/oidc/idpdiscovery/idp_discovery_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/idpdiscovery/idp_discovery_handler.go).
|
||||
See [internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler.go).
|
||||
- `<issuer_path>/login` is a login UI page to support the optional browser-based login flow for LDAP and Active Directory identity providers.
|
||||
See [internal/oidc/login/login_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/oidc/login/login_handler.go).
|
||||
See [internal/federationdomain/endpoints/login/login_handler.go](https://github.com/vmware-tanzu/pinniped/blob/main/internal/federationdomain/endpoints/login/login_handler.go).
|
||||
|
||||
The OIDC specifications implemented by the Supervisor can be found at [openid.net](https://openid.net/connect).
|
||||
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/formposthtml"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/internal/oidc/provider/formposthtml"
|
||||
"go.pinniped.dev/test/testlib"
|
||||
"go.pinniped.dev/test/testlib/browsertest"
|
||||
)
|
||||
|
@ -31,8 +31,9 @@ import (
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
idpv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/oidc"
|
||||
"go.pinniped.dev/internal/federationdomain/oidcclientvalidator"
|
||||
"go.pinniped.dev/internal/federationdomain/storage"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
@ -2240,7 +2241,7 @@ func testSupervisorLogin(
|
||||
// First use the latest downstream refresh token to look up the corresponding session in the Supervisor's storage.
|
||||
supervisorSecretsClient := testlib.NewKubernetesClientset(t).CoreV1().Secrets(env.SupervisorNamespace)
|
||||
supervisorOIDCClientsClient := testlib.NewSupervisorClientset(t).ConfigV1alpha1().OIDCClients(env.SupervisorNamespace)
|
||||
oauthStore := oidc.NewKubeStorage(supervisorSecretsClient, supervisorOIDCClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), oidcclientvalidator.DefaultMinBcryptCost)
|
||||
oauthStore := storage.NewKubeStorage(supervisorSecretsClient, supervisorOIDCClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), oidcclientvalidator.DefaultMinBcryptCost)
|
||||
storedRefreshSession, err := oauthStore.GetRefreshTokenSession(ctx, signatureOfLatestRefreshToken, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -2302,7 +2303,7 @@ func testSupervisorLogin(
|
||||
// First use the latest downstream refresh token to look up the corresponding session in the Supervisor's storage.
|
||||
supervisorSecretsClient := testlib.NewKubernetesClientset(t).CoreV1().Secrets(env.SupervisorNamespace)
|
||||
supervisorOIDCClientsClient := testlib.NewSupervisorClientset(t).ConfigV1alpha1().OIDCClients(env.SupervisorNamespace)
|
||||
oauthStore := oidc.NewKubeStorage(supervisorSecretsClient, supervisorOIDCClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), oidcclientvalidator.DefaultMinBcryptCost)
|
||||
oauthStore := storage.NewKubeStorage(supervisorSecretsClient, supervisorOIDCClientsClient, oidc.DefaultOIDCTimeoutsConfiguration(), oidcclientvalidator.DefaultMinBcryptCost)
|
||||
storedRefreshSession, err := oauthStore.GetRefreshTokenSession(ctx, signatureOfLatestRefreshToken, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package integration
|
||||
@ -17,8 +17,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/internal/federationdomain/clientregistry"
|
||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/test/testlib"
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user