Compare commits

...

34 Commits

Author SHA1 Message Date
Joshua Casey
1d99889418 Backfill test to show that the IDP chooser page is shown when only one IDP is on the FederationDomain 2025-02-11 16:41:52 -06:00
Joshua Casey
876f626e7d Merge pull request #2196 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m23s
CodeQL / Analyze (javascript) (push) Failing after 41s
Bump dependencies
2025-02-10 09:47:12 -06:00
Pinny
0dc704be9c Bump dependencies 2025-02-10 14:01:28 +00:00
Joshua Casey
e437832698 Merge pull request #2195 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m24s
CodeQL / Analyze (javascript) (push) Failing after 42s
Bump dependencies
2025-02-06 10:26:31 -06:00
Pinny
274ca4cb73 Bump dependencies 2025-02-06 14:03:20 +00:00
Ryan Richard
a99ff646a0 Merge pull request #2193 from vmware-tanzu/rr/ca_bundle_discovery
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m20s
CodeQL / Analyze (javascript) (push) Failing after 40s
"pinniped get kubeconfig" discovers CA bundle from JWTAuthenticator's spec.TLS.CertificateAuthorityDataSource
2025-02-05 12:47:42 -08:00
Ryan Richard
02eb26f135 "pinniped get kubeconfig" discovers CA bundle from CertificateAuthorityDataSource 2025-02-05 10:59:02 -08:00
Joshua Casey
e90f19f8ab Merge pull request #2192 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 49s
CodeQL / Analyze (javascript) (push) Failing after 35s
Bump dependencies
2025-02-04 10:06:44 -06:00
Pinny
00c2c5cf6e Bump dependencies 2025-02-04 14:08:31 +00:00
Joshua Casey
3386774f5f Merge pull request #2191 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m34s
CodeQL / Analyze (javascript) (push) Failing after 45s
Bump dependencies
2025-02-03 13:47:48 -06:00
Joshua Casey
7e4330be93 Bump codegen to latest k8s.io versions for 1.29, 1.30, and 1.31 2025-02-03 10:28:43 -06:00
Joshua Casey
f5b3e6da93 Bump to k8s.io@v0.31.5 libs 2025-02-03 10:28:42 -06:00
Joshua Casey
5c39374915 Update code for fosite changes 2025-02-03 10:28:42 -06:00
Pinny
4fdb931141 Bump dependencies 2025-02-03 14:06:25 +00:00
Ryan Richard
3a02854192 Merge pull request #2190 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m30s
CodeQL / Analyze (javascript) (push) Failing after 41s
Bump dependencies
2025-01-31 09:30:28 -08:00
Pinny
63c071d6ea Bump dependencies 2025-01-31 14:05:01 +00:00
Ryan Richard
6dc96f4224 Merge pull request #2189 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m33s
CodeQL / Analyze (javascript) (push) Failing after 42s
Bump dependencies
2025-01-30 10:33:40 -08:00
Pinny
aa8f8f7fda Bump dependencies 2025-01-30 14:10:37 +00:00
Joshua Casey
f5167bb279 Merge pull request #2188 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m24s
CodeQL / Analyze (javascript) (push) Failing after 43s
Bump dependencies
2025-01-29 13:10:25 -06:00
Pinny
b84eafc173 Bump dependencies 2025-01-29 14:04:56 +00:00
Ryan Richard
50ed1b0cf9 Merge pull request #2167 from vmware-tanzu/jtc/federation-domain-issuer-must-be-https-url
Some checks failed
CodeQL / Analyze (go) (push) Failing after 56s
CodeQL / Analyze (javascript) (push) Failing after 45s
Federation domain issuer must be https url
2025-01-28 10:56:35 -08:00
Joshua Casey
1d873be184 Make sure that CEL errors are checked for the appropriate Kube version 2025-01-27 10:46:55 -06:00
Joshua Casey
5a0d6eddb1 Make sure each FederationDomain has a unique name, and skip CEL tests for old K8s versions 2025-01-27 10:46:55 -06:00
Joshua Casey
31b45525ce Remove deprecated CredentialIssuer.status.kubeConfigInfo 2025-01-27 10:46:55 -06:00
Joshua Casey
430c73b903 FederationDomain.spec.issuer must now be an HTTPS URL 2025-01-27 10:46:55 -06:00
Joshua Casey
cc1befbc57 Allow for multiple error messages 2025-01-27 10:46:55 -06:00
Joshua Casey
68a0ad4112 Extract common prefix from error messages 2025-01-27 10:46:55 -06:00
Joshua Casey
9aca187559 Merge pull request #2187 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m27s
CodeQL / Analyze (javascript) (push) Failing after 44s
Bump dependencies
2025-01-27 10:18:30 -06:00
Pinny
d0fb9f3637 Bump dependencies 2025-01-27 14:05:17 +00:00
Joshua Casey
51d1bc32e8 Merge pull request #2186 from vmware-tanzu/pinny/bump-deps
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m23s
CodeQL / Analyze (javascript) (push) Failing after 35s
Bump dependencies
2025-01-24 17:00:25 -06:00
Ryan Richard
e9b9dd6fa3 update generated code for 1.26 and 1.29 2025-01-24 13:15:39 -08:00
Joshua Casey
7e43aa4e12 Bump dependencies and codgen 2025-01-24 13:56:57 -06:00
Pinny
de509db7be Bump dependencies 2025-01-24 14:01:08 +00:00
Pinny
69c6676d8f Updated versions in docs for v0.37.0 release
Some checks failed
CodeQL / Analyze (go) (push) Failing after 1m25s
CodeQL / Analyze (javascript) (push) Failing after 41s
2025-01-15 20:53:32 +00:00
86 changed files with 1317 additions and 1170 deletions

View File

@@ -3,7 +3,7 @@
# Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
ARG BUILD_IMAGE=golang:1.23.4@sha256:585103a29aa6d4c98bbb45d2446e1fdf41441698bbdf707d1801f5708e479f04
ARG BUILD_IMAGE=golang:1.23.6@sha256:927112936d6b496ed95f55f362cc09da6e3e624ef868814c56d55bd7323e0959
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:6ec5aa99dc335666e79dc64e4a6c8b89c33a543a1967f20d360922a80dd21f02
# Prepare to cross-compile by always running the build stage in the build platform, not the target platform.

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -1,34 +1,36 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
"go.pinniped.dev/internal/groupsuffix"
"go.pinniped.dev/internal/kubeclient"
)
// getConciergeClientsetFunc is a function that can return a clientset for the Concierge API given a
// getClientsetsFunc is a function that can return clients for the Concierge and Kubernetes APIs given a
// clientConfig and the apiGroupSuffix with which the API is running.
type getConciergeClientsetFunc func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error)
type getClientsetsFunc func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error)
// getRealConciergeClientset returns a real implementation of a conciergeclientset.Interface.
func getRealConciergeClientset(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
// getRealClientsets returns real implementations of the Concierge and Kubernetes client interfaces.
func getRealClientsets(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
restConfig, err := clientConfig.ClientConfig()
if err != nil {
return nil, err
return nil, nil, nil, err
}
client, err := kubeclient.New(
kubeclient.WithConfig(restConfig),
kubeclient.WithMiddleware(groupsuffix.New(apiGroupSuffix)),
)
if err != nil {
return nil, err
return nil, nil, nil, err
}
return client.PinnipedConcierge, nil
return client.PinnipedConcierge, client.Kubernetes, client.Aggregation, nil
}
// newClientConfig returns a clientcmd.ClientConfig given an optional kubeconfig path override and

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd
@@ -20,10 +20,12 @@ import (
coreosoidc "github.com/coreos/go-oidc/v3/oidc"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
conciergeconfigv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
@@ -38,7 +40,7 @@ import (
type kubeconfigDeps struct {
getenv func(key string) string
getPathToSelf func() (string, error)
getClientset getConciergeClientsetFunc
getClientsets getClientsetsFunc
log plog.MinLogger
}
@@ -46,7 +48,7 @@ func kubeconfigRealDeps() kubeconfigDeps {
return kubeconfigDeps{
getenv: os.Getenv,
getPathToSelf: os.Executable,
getClientset: getRealConciergeClientset,
getClientsets: getRealClientsets,
log: plog.New(),
}
}
@@ -215,7 +217,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
return fmt.Errorf("could not load --kubeconfig/--kubeconfig-context: %w", err)
}
cluster := currentKubeConfig.Clusters[currentKubeconfigNames.ClusterName]
clientset, err := deps.getClientset(clientConfig, flags.concierge.apiGroupSuffix)
conciergeClient, kubeClient, aggregatorClient, err := deps.getClientsets(clientConfig, flags.concierge.apiGroupSuffix)
if err != nil {
return fmt.Errorf("could not configure Kubernetes client: %w", err)
}
@@ -228,13 +230,15 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
}
if !flags.concierge.disabled {
credentialIssuer, err := waitForCredentialIssuer(ctx, clientset, flags, deps)
// Look up the Concierge's CredentialIssuer, and optionally wait for it to have no pending strategies showing in its status.
credentialIssuer, err := waitForCredentialIssuer(ctx, conciergeClient, flags, deps)
if err != nil {
return err
}
// Decide which Concierge authenticator should be used in the resulting kubeconfig.
authenticator, err := lookupAuthenticator(
clientset,
conciergeClient,
flags.concierge.authenticatorType,
flags.concierge.authenticatorName,
deps.log,
@@ -242,10 +246,15 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
if err != nil {
return err
}
// Discover from the CredentialIssuer how the resulting kubeconfig should be configured to talk to this Concierge.
if err := discoverConciergeParams(credentialIssuer, &flags, cluster, deps.log); err != nil {
return err
}
if err := discoverAuthenticatorParams(authenticator, &flags, deps.log); err != nil {
// Discover how the resulting kubeconfig should interact with the selected authenticator.
// For a JWTAuthenticator, this includes discovering how to talk to the OIDC issuer configured in its spec fields.
if err := discoverAuthenticatorParams(ctx, authenticator, &flags, kubeClient, aggregatorClient, deps.log); err != nil {
return err
}
@@ -255,6 +264,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
}
if len(flags.oidc.issuer) > 0 {
// The OIDC provider may or may not be a Pinniped Supervisor. Find out.
err = pinnipedSupervisorDiscovery(ctx, &flags, deps.log)
if err != nil {
return err
@@ -488,7 +498,14 @@ func logStrategies(credentialIssuer *conciergeconfigv1alpha1.CredentialIssuer, l
}
}
func discoverAuthenticatorParams(authenticator metav1.Object, flags *getKubeconfigParams, log plog.MinLogger) error {
func discoverAuthenticatorParams(
ctx context.Context,
authenticator metav1.Object,
flags *getKubeconfigParams,
kubeClient kubernetes.Interface,
aggregatorClient aggregatorclient.Interface,
log plog.MinLogger,
) error {
switch auth := authenticator.(type) {
case *authenticationv1alpha1.WebhookAuthenticator:
// If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set
@@ -520,19 +537,130 @@ func discoverAuthenticatorParams(authenticator metav1.Object, flags *getKubeconf
}
// If the --oidc-ca-bundle flags was not set explicitly, default it to the
// spec.tls.certificateAuthorityData field of the JWTAuthenticator.
if len(flags.oidc.caBundle) == 0 && auth.Spec.TLS != nil && auth.Spec.TLS.CertificateAuthorityData != "" {
decoded, err := base64.StdEncoding.DecodeString(auth.Spec.TLS.CertificateAuthorityData)
// spec.tls.certificateAuthorityData field of the JWTAuthenticator, if that field is set, or else
// try to discover it from the spec.tls.certificateAuthorityDataSource, if that field is set.
if len(flags.oidc.caBundle) == 0 && auth.Spec.TLS != nil {
err := discoverOIDCCABundle(ctx, auth, flags, kubeClient, aggregatorClient, log)
if err != nil {
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", auth.Name, err)
return err
}
log.Info("discovered OIDC CA bundle", "roots", countCACerts(decoded))
flags.oidc.caBundle = decoded
}
}
return nil
}
func discoverOIDCCABundle(
ctx context.Context,
jwtAuthenticator *authenticationv1alpha1.JWTAuthenticator,
flags *getKubeconfigParams,
kubeClient kubernetes.Interface,
aggregatorClient aggregatorclient.Interface,
log plog.MinLogger,
) error {
if jwtAuthenticator.Spec.TLS.CertificateAuthorityData != "" {
decodedCABundleData, err := base64.StdEncoding.DecodeString(jwtAuthenticator.Spec.TLS.CertificateAuthorityData)
if err != nil {
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", jwtAuthenticator.Name, err)
}
log.Info("discovered OIDC CA bundle", "roots", countCACerts(decodedCABundleData))
flags.oidc.caBundle = decodedCABundleData
} else if jwtAuthenticator.Spec.TLS.CertificateAuthorityDataSource != nil {
caBundleData, err := discoverOIDCCABundleFromCertificateAuthorityDataSource(
ctx, jwtAuthenticator, flags.concierge.apiGroupSuffix, kubeClient, aggregatorClient, log)
if err != nil {
return err
}
flags.oidc.caBundle = caBundleData
}
return nil
}
func discoverOIDCCABundleFromCertificateAuthorityDataSource(
ctx context.Context,
jwtAuthenticator *authenticationv1alpha1.JWTAuthenticator,
apiGroupSuffix string,
kubeClient kubernetes.Interface,
aggregatorClient aggregatorclient.Interface,
log plog.MinLogger,
) ([]byte, error) {
conciergeNamespace, err := discoverConciergeNamespace(ctx, apiGroupSuffix, aggregatorClient)
if err != nil {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator %s: %w", jwtAuthenticator.Name, err)
}
log.Info("discovered Concierge namespace for API group suffix", "apiGroupSuffix", apiGroupSuffix)
var caBundleData []byte
var keyExisted bool
caSource := jwtAuthenticator.Spec.TLS.CertificateAuthorityDataSource
// Note that the Kind, Name, and Key fields must all be non-empty, and Kind must be Secret or ConfigMap, due to CRD validations.
switch caSource.Kind {
case authenticationv1alpha1.CertificateAuthorityDataSourceKindConfigMap:
caBundleConfigMap, err := kubeClient.CoreV1().ConfigMaps(conciergeNamespace).Get(ctx, caSource.Name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error getting %s %s/%s specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource: %w",
caSource.Kind, conciergeNamespace, caSource.Name, jwtAuthenticator.Name, err)
}
var caBundleDataStr string
caBundleDataStr, keyExisted = caBundleConfigMap.Data[caSource.Key]
caBundleData = []byte(caBundleDataStr)
case authenticationv1alpha1.CertificateAuthorityDataSourceKindSecret:
caBundleSecret, err := kubeClient.CoreV1().Secrets(conciergeNamespace).Get(ctx, caSource.Name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error getting %s %s/%s specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource: %w",
caSource.Kind, conciergeNamespace, caSource.Name, jwtAuthenticator.Name, err)
}
caBundleData, keyExisted = caBundleSecret.Data[caSource.Key]
default:
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.Kind value %q is not supported by this CLI version",
jwtAuthenticator.Name, caSource.Kind)
}
if !keyExisted {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key does not exist in %s %s/%s",
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
}
if len(caBundleData) == 0 {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key exists but has empty value in %s %s/%s",
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
}
numCACerts := countCACerts(caBundleData)
if numCACerts == 0 {
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but value at key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key does not contain any CA certificates in %s %s/%s",
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
}
log.Info("discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource", "roots", numCACerts)
return caBundleData, nil
}
func discoverConciergeNamespace(ctx context.Context, apiGroupSuffix string, aggregatorClient aggregatorclient.Interface) (string, error) {
// Let's look for the APIService for the API group of the Concierge's TokenCredentialRequest aggregated API.
apiGroup := "login.concierge." + apiGroupSuffix
// List all APIServices.
apiServiceList, err := aggregatorClient.ApiregistrationV1().APIServices().List(ctx, metav1.ListOptions{})
if err != nil {
return "", fmt.Errorf("error listing APIServices: %w", err)
}
// Find one with the expected API group name.
for _, apiService := range apiServiceList.Items {
if apiService.Spec.Group == apiGroup {
if apiService.Spec.Service.Namespace != "" {
// We are assuming that all API versions (e.g. v1alpha1) of this API group are backed by service(s)
// in the same namespace, which is the namespace of the Concierge hosting this API suffix.
return apiService.Spec.Service.Namespace, nil
}
}
}
// Couldn't find any APIService for the expected API group name which contained a namespace reference in its spec.
return "", fmt.Errorf("could not find APIService with non-empty spec.service.namespace for API group %s", apiGroup)
}
func getConciergeFrontend(credentialIssuer *conciergeconfigv1alpha1.CredentialIssuer, mode conciergeModeFlag) (*conciergeconfigv1alpha1.CredentialIssuerFrontend, error) {
for _, strategy := range credentialIssuer.Status.Strategies {
// Skip unhealthy strategies.
@@ -540,26 +668,15 @@ func getConciergeFrontend(credentialIssuer *conciergeconfigv1alpha1.CredentialIs
continue
}
// Backfill the .status.strategies[].frontend field from .status.kubeConfigInfo for backwards compatibility.
if strategy.Type == conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType && strategy.Frontend == nil && credentialIssuer.Status.KubeConfigInfo != nil {
strategy = *strategy.DeepCopy()
strategy.Frontend = &conciergeconfigv1alpha1.CredentialIssuerFrontend{
Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{
Server: credentialIssuer.Status.KubeConfigInfo.Server,
CertificateAuthorityData: credentialIssuer.Status.KubeConfigInfo.CertificateAuthorityData,
},
}
}
// If the strategy frontend is still nil, skip.
// If the strategy frontend is nil, skip.
if strategy.Frontend == nil {
continue
}
// Skip any unknown frontend types.
switch strategy.Frontend.Type {
case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, conciergeconfigv1alpha1.ImpersonationProxyFrontendType:
case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
conciergeconfigv1alpha1.ImpersonationProxyFrontendType:
default:
continue
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd
@@ -15,10 +15,16 @@ import (
"time"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
kubetesting "k8s.io/client-go/testing"
"k8s.io/client-go/tools/clientcmd"
v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
aggregatorfake "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
"k8s.io/utils/ptr"
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
@@ -64,14 +70,69 @@ func TestGetKubeconfig(t *testing.T) {
}
}
jwtAuthenticator := func(issuerCABundle string, issuerURL string) runtime.Object {
caBundleInSecret := func(issuerCABundle, secretName, secretNamespace, secretDataKey string) runtime.Object {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: secretNamespace,
},
Data: map[string][]byte{
secretDataKey: []byte(issuerCABundle),
"other": []byte("unrelated"),
},
}
}
caBundleInConfigmap := func(issuerCABundle, cmName, cmNamespace, cmDataKey string) runtime.Object {
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: cmName,
Namespace: cmNamespace,
},
Data: map[string]string{
cmDataKey: issuerCABundle,
"other": "unrelated",
},
}
}
jwtAuthenticator := func(issuerCABundle, issuerURL string) *authenticationv1alpha1.JWTAuthenticator {
encodedCABundle := ""
if issuerCABundle != "" {
encodedCABundle = base64.StdEncoding.EncodeToString([]byte(issuerCABundle))
}
return &authenticationv1alpha1.JWTAuthenticator{
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
Spec: authenticationv1alpha1.JWTAuthenticatorSpec{
Issuer: issuerURL,
Audience: "test-audience",
TLS: &authenticationv1alpha1.TLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(issuerCABundle)),
CertificateAuthorityData: encodedCABundle,
},
},
}
}
jwtAuthenticatorWithCABundleDataSource := func(sourceKind, sourceName, sourceKey, issuerURL string) runtime.Object {
authenticator := jwtAuthenticator("", issuerURL)
authenticator.Spec.TLS.CertificateAuthorityDataSource = &authenticationv1alpha1.CertificateAuthorityDataSourceSpec{
Kind: authenticationv1alpha1.CertificateAuthorityDataSourceKind(sourceKind),
Name: sourceName,
Key: sourceKey,
}
return authenticator
}
apiService := func(group, version, serviceNamespace string) *v1.APIService {
return &v1.APIService{
ObjectMeta: metav1.ObjectMeta{
Name: version + "." + group,
},
Spec: v1.APIServiceSpec{
Group: group,
Version: version,
Service: &v1.ServiceReference{
Namespace: serviceNamespace,
},
},
}
@@ -144,7 +205,11 @@ func TestGetKubeconfig(t *testing.T) {
getPathToSelfErr error
getClientsetErr error
conciergeObjects func(string, string) []runtime.Object
kubeObjects func(string) []runtime.Object
apiServiceObjects []runtime.Object
conciergeReactions []kubetesting.Reactor
kubeReactions []kubetesting.Reactor
apiServiceReactions []kubetesting.Reactor
oidcDiscoveryResponse func(string) string
oidcDiscoveryStatusCode int
idpsDiscoveryResponse string
@@ -613,18 +678,18 @@ func TestGetKubeconfig(t *testing.T) {
&conciergeconfigv1alpha1.CredentialIssuer{
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
Status: conciergeconfigv1alpha1.CredentialIssuerStatus{
KubeConfigInfo: &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{
Server: "https://concierge-endpoint",
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
},
Strategies: []conciergeconfigv1alpha1.CredentialIssuerStrategy{{
Type: conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType,
Status: conciergeconfigv1alpha1.SuccessStrategyStatus,
Reason: conciergeconfigv1alpha1.FetchedKeyStrategyReason,
Message: "Successfully fetched key",
LastUpdateTime: metav1.Now(),
// Simulate a previous version of CredentialIssuer that's missing this Frontend field.
Frontend: nil,
Frontend: &conciergeconfigv1alpha1.CredentialIssuerFrontend{
Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{
Server: "https://concierge-endpoint.example.com",
},
},
}},
},
},
@@ -656,6 +721,321 @@ func TestGetKubeconfig(t *testing.T) {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator has invalid spec.tls.certificateAuthorityData: illegal base64 data at input byte 7` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but Secret not found",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error getting Secret test-concierge-namespace/my-ca-secret specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource: secrets "my-ca-secret" not found` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in ConfigMap, but ConfigMap not found",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error getting ConfigMap test-concierge-namespace/my-ca-configmap specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource: configmaps "my-ca-configmap" not found` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but invalid TLS bundle found in Secret",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInSecret("invalid CA bundle data", "my-ca-secret", "test-concierge-namespace", "ca.crt"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but value at key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key does not contain any CA certificates in Secret test-concierge-namespace/my-ca-secret` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but specified key not found in Secret",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInSecret(issuerCABundle, "my-ca-secret", "test-concierge-namespace", "wrong_key_name"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key does not exist in Secret test-concierge-namespace/my-ca-secret` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but specified key has empty value in Secret",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInSecret("", "my-ca-secret", "test-concierge-namespace", "ca.crt"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key exists but has empty value in Secret test-concierge-namespace/my-ca-secret` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle source, but source's Kind is not supported",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Unsupported-Value", "my-ca-secret", "ca.crt", issuerURL),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.Kind value "Unsupported-Value" is not supported by this CLI version` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but no related APIService found",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
apiServiceObjects: []runtime.Object{
apiService("unrelated.example.com", "v1alpha1", "test-concierge-namespace"),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: could not find APIService with non-empty spec.service.namespace for API group login.concierge.pinniped.dev` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but related APIService has empty namespace in spec",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", ""),
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: could not find APIService with non-empty spec.service.namespace for API group login.concierge.pinniped.dev` + "\n")
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret, but error when listing APIServices",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
apiServiceReactions: []kubetesting.Reactor{
&kubetesting.SimpleReactor{
Verb: "*",
Resource: "apiservices",
Reaction: func(kubetesting.Action) (bool, runtime.Object, error) {
return true, nil, fmt.Errorf("some list error")
},
},
},
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
}
},
wantError: true,
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: error listing APIServices: some list error` + "\n")
},
},
{
name: "autodetect JWT authenticator, invalid substring in audience",
args: func(issuerCABundle string, issuerURL string) []string {
@@ -1600,6 +1980,257 @@ func TestGetKubeconfig(t *testing.T) {
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
},
},
{
name: "autodetect JWT authenticator with CA bundle in Secret",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
"--skip-validation",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInSecret(issuerCABundle, "my-ca-secret", "test-concierge-namespace", "ca.crt"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
apiService("login.concierge.pinniped.dev", "v1alpha2", "test-concierge-namespace"),
},
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
}
},
wantStdout: func(issuerCABundle string, issuerURL string) string {
return here.Docf(`
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
server: https://fake-server-url-value
name: kind-cluster-pinniped
contexts:
- context:
cluster: kind-cluster-pinniped
user: kind-user-pinniped
name: kind-context-pinniped
current-context: kind-context-pinniped
kind: Config
preferences: {}
users:
- name: kind-user-pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- login
- oidc
- --enable-concierge
- --concierge-api-group-suffix=pinniped.dev
- --concierge-authenticator-name=test-authenticator
- --concierge-authenticator-type=jwt
- --concierge-endpoint=https://fake-server-url-value
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
- --issuer=%s
- --client-id=pinniped-cli
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
- --ca-bundle-data=%s
- --request-audience=test-audience
command: '.../path/to/pinniped'
env: []
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
for more details
provideClusterInfo: true
`,
issuerURL,
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
},
},
{
name: "autodetect JWT authenticator with CA bundle in ConfigMap",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
"--skip-validation",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInConfigmap(issuerCABundle, "my-ca-configmap", "test-concierge-namespace", "ca.crt"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
apiService("login.concierge.pinniped.dev", "v1alpha2", "test-concierge-namespace"),
},
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
}
},
wantStdout: func(issuerCABundle string, issuerURL string) string {
return here.Docf(`
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
server: https://fake-server-url-value
name: kind-cluster-pinniped
contexts:
- context:
cluster: kind-cluster-pinniped
user: kind-user-pinniped
name: kind-context-pinniped
current-context: kind-context-pinniped
kind: Config
preferences: {}
users:
- name: kind-user-pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- login
- oidc
- --enable-concierge
- --concierge-api-group-suffix=pinniped.dev
- --concierge-authenticator-name=test-authenticator
- --concierge-authenticator-type=jwt
- --concierge-endpoint=https://fake-server-url-value
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
- --issuer=%s
- --client-id=pinniped-cli
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
- --ca-bundle-data=%s
- --request-audience=test-audience
command: '.../path/to/pinniped'
env: []
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
for more details
provideClusterInfo: true
`,
issuerURL,
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
},
},
{
name: "autodetect JWT authenticator with CA bundle in ConfigMap with a custom API group suffix",
args: func(issuerCABundle string, issuerURL string) []string {
return []string{
"--kubeconfig", "./testdata/kubeconfig.yaml",
"--concierge-api-group-suffix=acme.com",
"--skip-validation",
}
},
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
return []runtime.Object{
credentialIssuer(),
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
}
},
kubeObjects: func(issuerCABundle string) []runtime.Object {
return []runtime.Object{
caBundleInConfigmap(issuerCABundle, "my-ca-configmap", "test-concierge-namespace", "ca.crt"),
}
},
apiServiceObjects: []runtime.Object{
apiService("login.concierge.acme.com", "v1alpha1", "test-concierge-namespace"),
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
apiService("login.concierge.pinniped.dev", "v1alpha2", "another-unrelated-namespace"),
},
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
wantLogs: func(issuerCABundle string, issuerURL string) []string {
return []string{
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "acme.com"}`,
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
}
},
wantAPIGroupSuffix: "acme.com",
wantStdout: func(issuerCABundle string, issuerURL string) string {
return here.Docf(`
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
server: https://fake-server-url-value
name: kind-cluster-pinniped
contexts:
- context:
cluster: kind-cluster-pinniped
user: kind-user-pinniped
name: kind-context-pinniped
current-context: kind-context-pinniped
kind: Config
preferences: {}
users:
- name: kind-user-pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- login
- oidc
- --enable-concierge
- --concierge-api-group-suffix=acme.com
- --concierge-authenticator-name=test-authenticator
- --concierge-authenticator-type=jwt
- --concierge-endpoint=https://fake-server-url-value
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
- --issuer=%s
- --client-id=pinniped-cli
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
- --ca-bundle-data=%s
- --request-audience=test-audience
command: '.../path/to/pinniped'
env: []
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
for more details
provideClusterInfo: true
`,
issuerURL,
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
},
},
{
name: "autodetect nothing, set a bunch of options",
args: func(issuerCABundle string, issuerURL string) []string {
@@ -3211,6 +3842,7 @@ func TestGetKubeconfig(t *testing.T) {
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var issuerEndpointPtr *string
@@ -3245,6 +3877,37 @@ func TestGetKubeconfig(t *testing.T) {
}), nil)
issuerEndpointPtr = ptr.To(testServer.URL)
getClientsetFunc := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
if tt.wantAPIGroupSuffix == "" {
require.Equal(t, "pinniped.dev", apiGroupSuffix) // "pinniped.dev" = api group suffix default
} else {
require.Equal(t, tt.wantAPIGroupSuffix, apiGroupSuffix)
}
if tt.getClientsetErr != nil {
return nil, nil, nil, tt.getClientsetErr
}
fakeAggregatorClient := aggregatorfake.NewSimpleClientset(tt.apiServiceObjects...)
fakeKubeClient := fake.NewClientset()
if tt.kubeObjects != nil {
kubeObjects := tt.kubeObjects(string(testServerCA))
fakeKubeClient = fake.NewClientset(kubeObjects...)
}
fakeConciergeClient := conciergefake.NewSimpleClientset()
if tt.conciergeObjects != nil {
fakeConciergeClient = conciergefake.NewSimpleClientset(tt.conciergeObjects(string(testServerCA), testServer.URL)...)
}
if len(tt.conciergeReactions) > 0 {
fakeConciergeClient.ReactionChain = slices.Concat(tt.conciergeReactions, fakeConciergeClient.ReactionChain)
}
if len(tt.kubeReactions) > 0 {
fakeKubeClient.ReactionChain = slices.Concat(tt.kubeReactions, fakeKubeClient.ReactionChain)
}
if len(tt.apiServiceReactions) > 0 {
fakeAggregatorClient.ReactionChain = slices.Concat(tt.apiServiceReactions, fakeAggregatorClient.ReactionChain)
}
return fakeConciergeClient, fakeKubeClient, fakeAggregatorClient, nil
}
var log bytes.Buffer
cmd := kubeconfigCommand(kubeconfigDeps{
@@ -3257,25 +3920,8 @@ func TestGetKubeconfig(t *testing.T) {
}
return ".../path/to/pinniped", nil
},
getClientset: func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
if tt.wantAPIGroupSuffix == "" {
require.Equal(t, "pinniped.dev", apiGroupSuffix) // "pinniped.dev" = api group suffix default
} else {
require.Equal(t, tt.wantAPIGroupSuffix, apiGroupSuffix)
}
if tt.getClientsetErr != nil {
return nil, tt.getClientsetErr
}
fake := conciergefake.NewSimpleClientset()
if tt.conciergeObjects != nil {
fake = conciergefake.NewSimpleClientset(tt.conciergeObjects(string(testServerCA), testServer.URL)...)
}
if len(tt.conciergeReactions) > 0 {
fake.ReactionChain = slices.Concat(tt.conciergeReactions, fake.ReactionChain)
}
return fake, nil
},
log: plog.TestConsoleLogger(t, &log),
getClientsets: getClientsetFunc,
log: plog.TestConsoleLogger(t, &log),
})
require.NotNil(t, cmd)

View File

@@ -1,4 +1,4 @@
// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd
@@ -25,14 +25,14 @@ import (
)
type whoamiDeps struct {
getenv func(key string) string
getClientset getConciergeClientsetFunc
getenv func(key string) string
getClientsets getClientsetsFunc
}
func whoamiRealDeps() whoamiDeps {
return whoamiDeps{
getenv: os.Getenv,
getClientset: getRealConciergeClientset,
getenv: os.Getenv,
getClientsets: getRealClientsets,
}
}
@@ -82,7 +82,7 @@ func newWhoamiCommand(deps whoamiDeps) *cobra.Command {
func runWhoami(output io.Writer, deps whoamiDeps, flags *whoamiFlags) error {
clientConfig := newClientConfig(flags.kubeconfigPath, flags.kubeconfigContextOverride)
clientset, err := deps.getClientset(clientConfig, flags.apiGroupSuffix)
conciergeClient, _, _, err := deps.getClientsets(clientConfig, flags.apiGroupSuffix)
if err != nil {
return fmt.Errorf("could not configure Kubernetes client: %w", err)
}
@@ -108,7 +108,7 @@ func runWhoami(output io.Writer, deps whoamiDeps, flags *whoamiFlags) error {
defer cancelFunc()
}
whoAmI, err := clientset.IdentityV1alpha1().WhoAmIRequests().Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
whoAmI, err := conciergeClient.IdentityV1alpha1().WhoAmIRequests().Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
if err != nil {
hint := ""
if apierrors.IsNotFound(err) {

View File

@@ -1,4 +1,4 @@
// Copyright 2023-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2023-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd
@@ -11,8 +11,10 @@ import (
"github.com/stretchr/testify/require"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
kubetesting "k8s.io/client-go/testing"
"k8s.io/client-go/tools/clientcmd"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
@@ -290,14 +292,15 @@ func TestWhoami(t *testing.T) {
wantStderr: "Error: could not complete WhoAmIRequest (is the Pinniped WhoAmI API running and healthy?): whoamirequests.identity.concierge.pinniped.dev \"whatever\" not found\n",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
getClientset := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
getClientsetFunc := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
if test.gettingClientsetErr != nil {
return nil, test.gettingClientsetErr
return nil, nil, nil, test.gettingClientsetErr
}
clientset := conciergefake.NewSimpleClientset()
clientset.PrependReactor("create", "whoamirequests", func(_ kubetesting.Action) (bool, runtime.Object, error) {
conciergeClient := conciergefake.NewSimpleClientset()
conciergeClient.PrependReactor("create", "whoamirequests", func(_ kubetesting.Action) (bool, runtime.Object, error) {
if test.callingAPIErr != nil {
return true, nil, test.callingAPIErr
}
@@ -316,13 +319,14 @@ func TestWhoami(t *testing.T) {
},
}, nil
})
return clientset, nil
return conciergeClient, nil, nil, nil
}
cmd := newWhoamiCommand(whoamiDeps{
getenv: func(key string) string {
return test.env[key]
},
getClientset: getClientset,
getClientsets: getClientsetFunc,
})
stdout, stderr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -4,8 +4,8 @@ module go.pinniped.dev/generated/1.29/apis
go 1.21
require (
k8s.io/api v0.29.12
k8s.io/apimachinery v0.29.12
k8s.io/api v0.29.13
k8s.io/apimachinery v0.29.13
)
require (

View File

@@ -75,10 +75,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.12 h1:SsEEMtFupOAt3pAAtAz0PDu+54g3L5rwbSCi0xQzAJM=
k8s.io/api v0.29.12/go.mod h1:QFwqOP+7LNoAG1RI3vKAFxjKSLQTCamcPzAQ0Z/Yhuk=
k8s.io/apimachinery v0.29.12 h1:k6OdfK9xaNANQvWkl1pSICJGLjB4jSuJ3gGP9hBKOhE=
k8s.io/apimachinery v0.29.12/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/api v0.29.13 h1:VkMIbjJw1t2VgTatg8ggzI93LOfFa8z8SzAYzXtWuEg=
k8s.io/api v0.29.13/go.mod h1:fBWhXqqE25b46PZEVA2DXN2EuhNg1ZT3VRyb5JitLG8=
k8s.io/apimachinery v0.29.13 h1:a7I4uQtlfaL+UTRGFhl8lLd2nHBR7qt+axhQLtpLYMg=
k8s.io/apimachinery v0.29.13/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -7,8 +7,8 @@ replace go.pinniped.dev/generated/1.29/apis => ../apis
require (
go.pinniped.dev/generated/1.29/apis v0.0.0
k8s.io/apimachinery v0.29.12
k8s.io/client-go v0.29.12
k8s.io/apimachinery v0.29.13
k8s.io/client-go v0.29.13
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
)
@@ -44,7 +44,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.29.12 // indirect
k8s.io/api v0.29.13 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

View File

@@ -134,12 +134,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.12 h1:SsEEMtFupOAt3pAAtAz0PDu+54g3L5rwbSCi0xQzAJM=
k8s.io/api v0.29.12/go.mod h1:QFwqOP+7LNoAG1RI3vKAFxjKSLQTCamcPzAQ0Z/Yhuk=
k8s.io/apimachinery v0.29.12 h1:k6OdfK9xaNANQvWkl1pSICJGLjB4jSuJ3gGP9hBKOhE=
k8s.io/apimachinery v0.29.12/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/client-go v0.29.12 h1:PjwJXavmpAqOWBRy4U5V/g3JQBpclIHEn5dvfTfsY+w=
k8s.io/client-go v0.29.12/go.mod h1:hRHG6tAKxaLVKF5SlMqgXrbqPEoUcUpJGFFrC3jU69A=
k8s.io/api v0.29.13 h1:VkMIbjJw1t2VgTatg8ggzI93LOfFa8z8SzAYzXtWuEg=
k8s.io/api v0.29.13/go.mod h1:fBWhXqqE25b46PZEVA2DXN2EuhNg1ZT3VRyb5JitLG8=
k8s.io/apimachinery v0.29.13 h1:a7I4uQtlfaL+UTRGFhl8lLd2nHBR7qt+axhQLtpLYMg=
k8s.io/apimachinery v0.29.13/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/client-go v0.29.13 h1:M2scR9NWGlzI2YoIxTgwx2N3OA+dXqN87zsM4tvewmA=
k8s.io/client-go v0.29.13/go.mod h1:BBzF0Pr78Y8DM20j22E6tOMwTBpFaKnSnn6N0pNe4VE=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -3,11 +3,11 @@ module go.pinniped.dev/generated/1.30/apis
go 1.22.0
toolchain go1.23.4
toolchain go1.23.6
require (
k8s.io/api v0.30.8
k8s.io/apimachinery v0.30.8
k8s.io/api v0.30.9
k8s.io/apimachinery v0.30.9
)
require (

View File

@@ -75,10 +75,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.30.8 h1:Y+yZRF3c1WC0MTkLe0qBkiLCquRNa4I21/iDioGMCbo=
k8s.io/api v0.30.8/go.mod h1:89IE5MzirZ5HHxU/Hq1/KWGqXkhXClu/FHGesFhQ0A4=
k8s.io/apimachinery v0.30.8 h1:9jyTItYzmJc00cBDxZC5ArFNxUeKCwbw0m760iFUMKY=
k8s.io/apimachinery v0.30.8/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/api v0.30.9 h1:yojLzwl7TBV3XusCHXvR2AnowQFVnL9Ui3/wAga3pv4=
k8s.io/api v0.30.9/go.mod h1:FGOLP66cj572P8rjO1H5x5+0vzmvf3bLc8pQlyQeBqk=
k8s.io/apimachinery v0.30.9 h1:wDbY7vSPd3ALl5Fpw0yEiDyW5ozMyCpqsQ6anaCkpII=
k8s.io/apimachinery v0.30.9/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -3,14 +3,14 @@ module go.pinniped.dev/generated/1.30/client
go 1.22.0
toolchain go1.23.4
toolchain go1.23.6
replace go.pinniped.dev/generated/1.30/apis => ../apis
require (
go.pinniped.dev/generated/1.30/apis v0.0.0
k8s.io/apimachinery v0.30.8
k8s.io/client-go v0.30.8
k8s.io/apimachinery v0.30.9
k8s.io/client-go v0.30.9
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
)
@@ -46,7 +46,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.30.8 // indirect
k8s.io/api v0.30.9 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

View File

@@ -134,12 +134,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.30.8 h1:Y+yZRF3c1WC0MTkLe0qBkiLCquRNa4I21/iDioGMCbo=
k8s.io/api v0.30.8/go.mod h1:89IE5MzirZ5HHxU/Hq1/KWGqXkhXClu/FHGesFhQ0A4=
k8s.io/apimachinery v0.30.8 h1:9jyTItYzmJc00cBDxZC5ArFNxUeKCwbw0m760iFUMKY=
k8s.io/apimachinery v0.30.8/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.8 h1:fC1SQMZm7bSWiVv9ydN+nv+sqGVAxMdf/5eKUVffNJE=
k8s.io/client-go v0.30.8/go.mod h1:daF3UcGVqGPHvH5mn/ESkp/VoR8i9tg9IBfKr+AeFYo=
k8s.io/api v0.30.9 h1:yojLzwl7TBV3XusCHXvR2AnowQFVnL9Ui3/wAga3pv4=
k8s.io/api v0.30.9/go.mod h1:FGOLP66cj572P8rjO1H5x5+0vzmvf3bLc8pQlyQeBqk=
k8s.io/apimachinery v0.30.9 h1:wDbY7vSPd3ALl5Fpw0yEiDyW5ozMyCpqsQ6anaCkpII=
k8s.io/apimachinery v0.30.9/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.9 h1:nIO9MJIWK/H/rDHT0PikZhEmK0MSK5hyfdT9YMTMMC0=
k8s.io/client-go v0.30.9/go.mod h1:JObO2rfBeqrWn45GNMNnDReUfa6lgP4p+RjRLPJMaE8=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -3,11 +3,11 @@ module go.pinniped.dev/generated/1.31/apis
go 1.22.0
toolchain go1.23.4
toolchain go1.23.6
require (
k8s.io/api v0.31.4
k8s.io/apimachinery v0.31.4
k8s.io/api v0.31.5
k8s.io/apimachinery v0.31.5
)
require (

View File

@@ -81,10 +81,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM=
k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw=
k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM=
k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/api v0.31.5 h1:7jP74egbPUOCLJV5KheUnwo9gz3zzUsMIj2EPkuYK1E=
k8s.io/api v0.31.5/go.mod h1:RMyMdZG1kJjou2ng5buEti0OHlo0uFXgSzTZ/k5LeVk=
k8s.io/apimachinery v0.31.5 h1:NxhAVGcfrSdTMx3M2v1OnvcMS7h1ZnWyt2x2z8CJJBU=
k8s.io/apimachinery v0.31.5/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

View File

@@ -3,15 +3,15 @@ module go.pinniped.dev/generated/1.31/client
go 1.22.0
toolchain go1.23.4
toolchain go1.23.6
replace go.pinniped.dev/generated/1.31/apis => ../apis
require (
go.pinniped.dev/generated/1.31/apis v0.0.0
k8s.io/api v0.31.4
k8s.io/apimachinery v0.31.4
k8s.io/client-go v0.31.4
k8s.io/api v0.31.5
k8s.io/apimachinery v0.31.5
k8s.io/client-go v0.31.5
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
)

View File

@@ -136,12 +136,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM=
k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw=
k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM=
k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ=
k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg=
k8s.io/api v0.31.5 h1:7jP74egbPUOCLJV5KheUnwo9gz3zzUsMIj2EPkuYK1E=
k8s.io/api v0.31.5/go.mod h1:RMyMdZG1kJjou2ng5buEti0OHlo0uFXgSzTZ/k5LeVk=
k8s.io/apimachinery v0.31.5 h1:NxhAVGcfrSdTMx3M2v1OnvcMS7h1ZnWyt2x2z8CJJBU=
k8s.io/apimachinery v0.31.5/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/client-go v0.31.5 h1:rmDswcUaIFAJ5vJaB82pjyqc52DgHCPv0G6af3OupO0=
k8s.io/client-go v0.31.5/go.mod h1:js93IlRSzRHql9o9zP54N56rMR249uH4+srnSOcFLsU=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=

View File

@@ -134,24 +134,6 @@ spec:
status:
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: |-
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This field is deprecated and will be removed in a future version.
properties:
certificateAuthorityData:
description: The K8s API server CA bundle.
minLength: 1
type: string
server:
description: The K8s API server URL.
minLength: 1
pattern: ^https://|^http://
type: string
required:
- certificateAuthorityData
- server
type: object
strategies:
description: List of integration strategies that were attempted by
Pinniped.

View File

@@ -289,6 +289,9 @@ spec:
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
minLength: 1
type: string
x-kubernetes-validations:
- message: issuer must be an HTTPS URL
rule: isURL(self) && url(self).getScheme() == 'https'
tls:
description: TLS specifies a secret which will contain Transport Layer
Security (TLS) configuration for the FederationDomain.

View File

@@ -428,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
==== CredentialIssuerKubeConfigInfo
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
This type is deprecated and will be removed in a future version.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`server`* __string__ | The K8s API server URL. +
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerspec"]
@@ -480,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|===
| Field | Description
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
This field is deprecated and will be removed in a future version. +
|===

View File

@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This field is deprecated and will be removed in a future version.
// +optional
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// This type is deprecated and will be removed in a future version.
type CredentialIssuerKubeConfigInfo struct {
// The K8s API server URL.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^https://|^http://`
Server string `json:"server"`
// The K8s API server CA bundle.
// +kubebuilder:validation:MinLength=1
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.

View File

@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
if in == nil {
return nil
}
out := new(CredentialIssuerKubeConfigInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
*out = *in
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeConfigInfo != nil {
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
*out = new(CredentialIssuerKubeConfigInfo)
**out = **in
}
return
}

View File

@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
// See
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
Issuer string `json:"issuer"`
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.

50
go.mod
View File

@@ -2,16 +2,17 @@ module go.pinniped.dev
go 1.23.0
toolchain go1.23.4
toolchain go1.23.6
// When using v0.31.4, need to use this version of structured-merge-diff.
// See https://github.com/kubernetes/apimachinery/blob/v0.31.4/go.mod#L30
// When using v0.31.5, need to use this version of structured-merge-diff.
// See https://github.com/kubernetes/apimachinery/blob/v0.31.5/go.mod#L30
// This replace must be in the go.mod, not overrides.conf, because it is an "indirect" dependency.
replace sigs.k8s.io/structured-merge-diff/v4 => sigs.k8s.io/structured-merge-diff/v4 v4.4.1
require (
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/chromedp/cdproto v0.0.0-20250113203156-3ff4b409e0d4
github.com/chromedp/chromedp v0.11.2
github.com/chromedp/cdproto v0.0.0-20250208210249-fa305b1d5b8a
github.com/chromedp/chromedp v0.12.1
github.com/coreos/go-oidc/v3 v3.12.0
github.com/coreos/go-semver v0.3.1
github.com/creack/pty v1.1.24
@@ -24,7 +25,7 @@ require (
github.com/go-logr/stdr v1.2.2
github.com/go-logr/zapr v1.3.0
github.com/gofrs/flock v0.12.1
github.com/google/cel-go v0.22.1
github.com/google/cel-go v0.23.2
github.com/google/go-cmp v0.6.0
github.com/google/go-github/v68 v68.0.0
github.com/google/gofuzz v1.2.0
@@ -34,38 +35,38 @@ require (
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531
github.com/migueleliasweb/go-github-mock v1.1.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/ory/fosite v0.49.1-0.20250102135636-049ed1924cd0
github.com/ory/fosite v0.49.1-0.20250203124447-75b904ddbee4
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/pkg/errors v0.9.1
github.com/sclevine/spec v1.4.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
github.com/tdewolff/minify/v2 v2.21.3
go.uber.org/mock v0.5.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.32.0
golang.org/x/crypto v0.33.0
golang.org/x/net v0.34.0
golang.org/x/oauth2 v0.25.0
golang.org/x/sync v0.10.0
golang.org/x/term v0.28.0
golang.org/x/text v0.21.0
k8s.io/api v0.31.4
k8s.io/apiextensions-apiserver v0.31.4
k8s.io/apimachinery v0.31.4
k8s.io/apiserver v0.31.4
k8s.io/client-go v0.31.4
k8s.io/component-base v0.31.4
k8s.io/gengo v0.0.0-20250106234829-0359904fc2a6
golang.org/x/oauth2 v0.26.0
golang.org/x/sync v0.11.0
golang.org/x/term v0.29.0
golang.org/x/text v0.22.0
k8s.io/api v0.31.5
k8s.io/apiextensions-apiserver v0.31.5
k8s.io/apimachinery v0.31.5
k8s.io/apiserver v0.31.5
k8s.io/client-go v0.31.5
k8s.io/component-base v0.31.5
k8s.io/gengo v0.0.0-20250207200755-1244d31929d7
k8s.io/klog/v2 v2.130.1
k8s.io/kube-aggregator v0.31.4
k8s.io/kube-aggregator v0.31.5
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
k8s.io/utils v0.0.0-20241210054802-24370beab758
sigs.k8s.io/yaml v1.4.0
)
require (
cel.dev/expr v0.18.0 // indirect
cel.dev/expr v0.19.1 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
@@ -94,7 +95,6 @@ require (
github.com/gobwas/ws v1.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-github/v64 v64.0.0 // indirect
@@ -111,7 +111,7 @@ require (
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/goveralls v0.0.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect
@@ -163,7 +163,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.26.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect

90
go.sum
View File

@@ -1,5 +1,5 @@
cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=
cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -65,10 +65,10 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chromedp/cdproto v0.0.0-20250113203156-3ff4b409e0d4 h1:xO38R20PvryeuBgQYnRU3WsNXFtr/iMyQVJednQVoZw=
github.com/chromedp/cdproto v0.0.0-20250113203156-3ff4b409e0d4/go.mod h1:4XqMl3iIW08jtieURWL6Tt5924w21pxirC6th662XUM=
github.com/chromedp/chromedp v0.11.2 h1:ZRHTh7DjbNTlfIv3NFTbB7eVeu5XCNkgrpcGSpn2oX0=
github.com/chromedp/chromedp v0.11.2/go.mod h1:lr8dFRLKsdTTWb75C/Ttol2vnBKOSnt0BW8R9Xaupi8=
github.com/chromedp/cdproto v0.0.0-20250208210249-fa305b1d5b8a h1:AfyrGZiCnK66SBxtNhrTWzGEoheSOV3K1wrnPLqaTT8=
github.com/chromedp/cdproto v0.0.0-20250208210249-fa305b1d5b8a/go.mod h1:RTGuBeCeabAJGi3OZf71a6cGa7oYBfBP75VJZFLv6SU=
github.com/chromedp/chromedp v0.12.1 h1:kBMblXk7xH5/6j3K9uk8d7/c+fzXWiUsCsPte0VMwOA=
github.com/chromedp/chromedp v0.12.1/go.mod h1:F6+wdq9LKFDMoyxhq46ZLz4VLXrsrCAR3sFqJz4Nqc0=
github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -206,8 +206,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -228,8 +226,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cel-go v0.22.1 h1:AfVXx3chM2qwoSbM7Da8g8hX8OVSkBFwX+rz2+PcK40=
github.com/google/cel-go v0.22.1/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
github.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=
github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -412,8 +410,8 @@ github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/luna-duclos/instrumentedsql v1.1.3/go.mod h1:9J1njvFds+zN7y85EDhN9XNQLANWwZt2ULeIC8yMNYs=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@@ -464,8 +462,8 @@ github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7s
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/ory/fosite v0.49.1-0.20250102135636-049ed1924cd0 h1:/nSkF1lW5wwD2bfUy8PRPVoFTLl1am/sZlX2gkgnepA=
github.com/ory/fosite v0.49.1-0.20250102135636-049ed1924cd0/go.mod h1:6XCoaTdHP3fF76sy6uLFfUCTjgJNdNspjny7azuTxoQ=
github.com/ory/fosite v0.49.1-0.20250203124447-75b904ddbee4 h1:VnazT+N30kfg5TxJQ2bg4Fa1pCWT7A1i3FffmX0fhAA=
github.com/ory/fosite v0.49.1-0.20250203124447-75b904ddbee4/go.mod h1:IhAwHrxwNgB3smKB75jkMVQjFTHq9HveITItLGX8/GU=
github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe h1:rvu4obdvqR0fkSIJ8IfgzKOWwZ5kOT2UNfLq81Qk7rc=
github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe/go.mod h1:z4n3u6as84LbV4YmgjHhnwtccQqzf4cZlSk9f1FhygI=
github.com/ory/go-convenience v0.1.0 h1:zouLKfF2GoSGnJwGq+PE/nJAE6dj2Zj5QlTgmMTsTS8=
@@ -534,8 +532,9 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
@@ -588,7 +587,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
@@ -682,8 +680,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -719,7 +717,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -760,7 +757,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
@@ -784,8 +780,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -796,15 +792,15 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -844,10 +840,8 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -863,8 +857,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -877,8 +871,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -892,8 +886,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -954,7 +949,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
@@ -1099,27 +1093,27 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM=
k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw=
k8s.io/apiextensions-apiserver v0.31.4 h1:FxbqzSvy92Ca9DIs5jqot883G0Ln/PGXfm/07t39LS0=
k8s.io/apiextensions-apiserver v0.31.4/go.mod h1:hIW9YU8UsqZqIWGG99/gsdIU0Ar45Qd3A12QOe/rvpg=
k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM=
k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.4 h1:JbtnTaXVYEAYIHJil6Wd74Wif9sd8jVcBw84kwEmp7o=
k8s.io/apiserver v0.31.4/go.mod h1:JJjoTjZ9PTMLdIFq7mmcJy2B9xLN3HeAUebW6xZyIP0=
k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ=
k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg=
k8s.io/component-base v0.31.4 h1:wCquJh4ul9O8nNBSB8N/o8+gbfu3BVQkVw9jAUY/Qtw=
k8s.io/component-base v0.31.4/go.mod h1:G4dgtf5BccwiDT9DdejK0qM6zTK0jwDGEKnCmb9+u/s=
k8s.io/gengo v0.0.0-20250106234829-0359904fc2a6 h1:1+JP7kneHC0+mprySiI1c9c9QsBsXMMaozt6+asWx3Y=
k8s.io/gengo v0.0.0-20250106234829-0359904fc2a6/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/api v0.31.5 h1:7jP74egbPUOCLJV5KheUnwo9gz3zzUsMIj2EPkuYK1E=
k8s.io/api v0.31.5/go.mod h1:RMyMdZG1kJjou2ng5buEti0OHlo0uFXgSzTZ/k5LeVk=
k8s.io/apiextensions-apiserver v0.31.5 h1:50+b/hHx4nyvQ+gaFH7p5myPEZyekGhGGAQb4vnBUlQ=
k8s.io/apiextensions-apiserver v0.31.5/go.mod h1:6vZ7IIlk3l7GSFcbaNz5CEYpUBLsQ0ee+LgLGOsExWQ=
k8s.io/apimachinery v0.31.5 h1:NxhAVGcfrSdTMx3M2v1OnvcMS7h1ZnWyt2x2z8CJJBU=
k8s.io/apimachinery v0.31.5/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.5 h1:n0daI1zIb+G2Jkzqjm2NQJSJfTKccgFeHHQM4LYsz7E=
k8s.io/apiserver v0.31.5/go.mod h1:SboTZ2NHCsXjAHqTrE/kDTnrzquVY5mDKNnoCdRFLJw=
k8s.io/client-go v0.31.5 h1:rmDswcUaIFAJ5vJaB82pjyqc52DgHCPv0G6af3OupO0=
k8s.io/client-go v0.31.5/go.mod h1:js93IlRSzRHql9o9zP54N56rMR249uH4+srnSOcFLsU=
k8s.io/component-base v0.31.5 h1:kpFiy1hI7F4Owp+o59H2CVLzmN94qwcPz+2L6wRhkqM=
k8s.io/component-base v0.31.5/go.mod h1:OiiusrmcLz42i9VvcAd94yQIN7UzQHJxN/hXxwYzj6E=
k8s.io/gengo v0.0.0-20250207200755-1244d31929d7 h1:iOdAjO5OsCszwPG5xNcJJL+rKaMUogk5fx9HsYZJxQM=
k8s.io/gengo v0.0.0-20250207200755-1244d31929d7/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kms v0.32.0 h1:jwOfunHIrcdYl5FRcA+uUKKtg6qiqoPCwmS2T3XTYL4=
k8s.io/kms v0.32.0/go.mod h1:Bk2evz/Yvk0oVrvm4MvZbgq8BD34Ksxs2SRHn4/UiOM=
k8s.io/kube-aggregator v0.31.4 h1:4hWVeNo4vLWstckMCo223cb9j7cCt7KD6b+RhQ8hTNE=
k8s.io/kube-aggregator v0.31.4/go.mod h1:R1wXjopE/VgW947R1axTzwEmyuatUp/a2lKn/ZGo2yo=
k8s.io/kube-aggregator v0.31.5 h1:ibCqykJwv7Ht4tgwd1793N6h444gf5m7ZH2dpJ0r4yI=
k8s.io/kube-aggregator v0.31.5/go.mod h1:bWajrGqcljoq5w1zWwj1qU34VoKfZeMZSCbK/vp127s=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=

View File

@@ -16,7 +16,7 @@
# See https://go.googlesource.com/go/+/dev.boringcrypto/README.boringcrypto.md
# and https://kupczynski.info/posts/fips-golang/ for details.
ARG BUILD_IMAGE=golang:1.23.4@sha256:585103a29aa6d4c98bbb45d2446e1fdf41441698bbdf707d1801f5708e479f04
ARG BUILD_IMAGE=golang:1.23.6@sha256:927112936d6b496ed95f55f362cc09da6e3e624ef868814c56d55bd7323e0959
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:6ec5aa99dc335666e79dc64e4a6c8b89c33a543a1967f20d360922a80dd21f02
# This is not currently using --platform to prepare to cross-compile because we use gcc below to build

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright 2022-2024 the Pinniped contributors. All Rights Reserved.
# Copyright 2022-2025 the Pinniped contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
@@ -13,7 +13,11 @@ go version
lint_version="v$(cat hack/lib/lint-version.txt)"
echo "Installing golangci-lint@${lint_version}"
# Find the toolchain version from our go.mod file. "go install" pays attention to $GOTOOLCHAIN.
GOTOOLCHAIN=$(sed -rn 's/^toolchain (go[0-9\.]+)$/\1/p' go.mod)
export GOTOOLCHAIN
echo "Installing golangci-lint@${lint_version} using toolchain ${GOTOOLCHAIN}"
# Install the same version of the linter that the pipelines will use
# so you can get the same results when running the linter locally.

View File

@@ -12,9 +12,9 @@
# Whenever a new version is added to this file, or when a version number
# is edited in this file, please run hack/update.sh.
#
1.31.4
1.30.8
1.29.12
1.31.5
1.30.9
1.29.13
1.28.15
1.27.16
1.26.15

View File

@@ -2,6 +2,6 @@ module go.pinniped.dev/update-go-mod
go 1.22.0
toolchain go1.23.4
toolchain go1.23.6
require golang.org/x/mod v0.22.0

View File

@@ -8,13 +8,13 @@ github.com/ory/fosite github.com/ory/fosite@master
# causes the race detector to fail our unit tests. We hope to remove these
# version locks as soon as possible.
# See https://github.com/vmware-tanzu/pinniped/issues/2157.
k8s.io/api k8s.io/api@v0.31.4
k8s.io/apiextensions-apiserver k8s.io/apiextensions-apiserver@v0.31.4
k8s.io/apimachinery k8s.io/apimachinery@v0.31.4
k8s.io/apiserver k8s.io/apiserver@v0.31.4
k8s.io/client-go k8s.io/client-go@v0.31.4
k8s.io/component-base k8s.io/component-base@v0.31.4
k8s.io/kube-aggregator k8s.io/kube-aggregator@v0.31.4
# When using v0.31.4, need to use this version of kube-openapi.
# See https://github.com/kubernetes/apiserver/blob/v0.31.4/go.mod#L54
k8s.io/api k8s.io/api@v0.31.5
k8s.io/apiextensions-apiserver k8s.io/apiextensions-apiserver@v0.31.5
k8s.io/apimachinery k8s.io/apimachinery@v0.31.5
k8s.io/apiserver k8s.io/apiserver@v0.31.5
k8s.io/client-go k8s.io/client-go@v0.31.5
k8s.io/component-base k8s.io/component-base@v0.31.5
k8s.io/kube-aggregator k8s.io/kube-aggregator@v0.31.5
# When using v0.31.5, need to use this version of kube-openapi.
# See https://github.com/kubernetes/apiserver/blob/v0.31.5/go.mod#L54
k8s.io/kube-openapi k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340

View File

@@ -49,14 +49,6 @@ func mergeStrategy(configToUpdate *conciergeconfigv1alpha1.CredentialIssuerStatu
configToUpdate.Strategies = append(configToUpdate.Strategies, strategy)
}
sort.Stable(sortableStrategies(configToUpdate.Strategies))
// Special case: the "TokenCredentialRequestAPI" data is mirrored into the deprecated status.kubeConfigInfo field.
if strategy.Frontend != nil && strategy.Frontend.Type == conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType {
configToUpdate.KubeConfigInfo = &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{
Server: strategy.Frontend.TokenCredentialRequestAPIInfo.Server,
CertificateAuthorityData: strategy.Frontend.TokenCredentialRequestAPIInfo.CertificateAuthorityData,
}
}
}
// weights are a set of priorities for each strategy type.

View File

@@ -87,10 +87,6 @@ func TestMergeStrategy(t *testing.T) {
},
},
},
KubeConfigInfo: &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{
Server: "https://test-server",
CertificateAuthorityData: "test-ca-bundle",
},
},
},
{

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package auth
@@ -993,7 +993,45 @@ func TestAuthorizationEndpoint(t *testing.T) { //nolint:gocyclo
},
},
{
name: "with multiple IDPs available, request does not choose which IDP to use",
name: "with one IDP available, request does not choose which IDP to use, will redirect to the IDP chooser",
idps: testidplister.NewUpstreamIDPListerBuilder().
WithLDAP(upstreamLDAPIdentityProviderBuilder().Build()),
generateCSRF: happyCSRFGenerator,
generatePKCE: happyPKCEGenerator,
generateNonce: happyNonceGenerator,
stateEncoder: happyStateEncoder,
cookieEncoder: happyCookieEncoder,
method: http.MethodGet,
path: happyGetRequestPath, // does not include pinniped_idp_name param
wantStatus: http.StatusSeeOther,
wantContentType: htmlContentType,
wantCSRFValueInCookieHeader: "", // there should not be a CSRF cookie set on the response
wantLocationHeader: urlWithQuery(downstreamIssuer+"/choose_identity_provider", happyGetRequestQueryMap),
wantUpstreamStateParamInLocationHeader: false, // it should copy the params of the original request, not add a new state param
wantBodyStringWithLocationInHref: true,
wantAuditLogs: func(_ stateparam.Encoded, sessionID string) []testutil.WantedAuditLog {
return []testutil.WantedAuditLog{
testutil.WantAuditLog("HTTP Request Parameters", map[string]any{
"params": map[string]any{
"client_id": "pinniped-cli",
"code_challenge": "redacted",
"code_challenge_method": "S256",
"nonce": "redacted",
"redirect_uri": "http://127.0.0.1/callback",
"response_type": "code",
"scope": "openid profile email username groups",
"state": "redacted",
},
}),
testutil.WantAuditLog("HTTP Request Custom Headers Used", map[string]any{
"Pinniped-Username": false,
"Pinniped-Password": false,
}),
}
},
},
{
name: "with multiple IDPs available, request does not choose which IDP to use, will redirect to the IDP chooser",
idps: testidplister.NewUpstreamIDPListerBuilder().
WithOIDC(upstreamOIDCIdentityProviderBuilder().Build()).
WithLDAP(upstreamLDAPIdentityProviderBuilder().Build()),

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package storage
@@ -61,3 +61,7 @@ func (d *DynamicGlobalSecretConfig) GetRotatedGlobalSecrets(_ctx context.Context
// We don't support having multiple global secrets yet, but when we do we will need to implement this.
return nil, nil
}
func (d *DynamicGlobalSecretConfig) GetDeviceAndUserCodeLifespan(_ctx context.Context) time.Duration {
return d.fositeConfig.DeviceAndUserCodeLifespan
}

View File

@@ -1,4 +1,4 @@
// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package testutil
@@ -45,7 +45,7 @@ func KubeServerMinorVersionAtLeastInclusive(t *testing.T, discoveryClient discov
return !KubeServerMinorVersionInBetweenInclusive(t, discoveryClient, 0, min-1)
}
func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient discovery.DiscoveryInterface, min, max int) bool {
func KubeServerMinorVersion(t *testing.T, discoveryClient discovery.DiscoveryInterface) int {
t.Helper()
version, err := discoveryClient.ServerVersion()
@@ -56,6 +56,12 @@ func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient disc
minor, err := strconv.Atoi(strings.TrimSuffix(version.Minor, "+"))
require.NoError(t, err)
return minor
}
func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient discovery.DiscoveryInterface, min, max int) bool {
minor := KubeServerMinorVersion(t, discoveryClient)
return minor >= min && minor <= max
}

View File

@@ -7,7 +7,7 @@ params:
github_url: "https://github.com/vmware-tanzu/pinniped"
slack_url: "https://go.pinniped.dev/community/slack"
community_url: "https://go.pinniped.dev/community"
latest_version: v0.36.0
latest_version: v0.37.0
latest_codegen_version: 1.31
pygmentsCodefences: true
pygmentsStyle: "pygments"

View File

@@ -36,7 +36,6 @@ func TestCredentialIssuer(t *testing.T) {
require.Len(t, actualConfigList.Items, 1)
actualConfig := actualConfigList.Items[0]
actualStatusKubeConfigInfo := actualConfigList.Items[0].Status.KubeConfigInfo
for k, v := range env.ConciergeCustomLabels {
require.Equalf(t, v, actualConfig.Labels[k], "expected ci to have label `%s: %s`", k, v)
@@ -77,22 +76,11 @@ func TestCredentialIssuer(t *testing.T) {
CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData),
}
require.Equal(t, &expectedTokenRequestAPIInfo, actualStatusStrategy.Frontend.TokenCredentialRequestAPIInfo)
// Verify the published kube config info.
require.Equal(
t,
&conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{
Server: expectedTokenRequestAPIInfo.Server,
CertificateAuthorityData: expectedTokenRequestAPIInfo.CertificateAuthorityData,
},
actualStatusKubeConfigInfo,
)
} else {
require.Equal(t, conciergeconfigv1alpha1.ErrorStrategyStatus, actualStatusStrategy.Status)
require.Equal(t, conciergeconfigv1alpha1.CouldNotFetchKeyStrategyReason, actualStatusStrategy.Reason)
require.Contains(t, actualStatusStrategy.Message, "could not find a healthy kube-controller-manager pod (0 candidates): "+
"note that this error is the expected behavior for some cluster types, including most cloud provider clusters (e.g. GKE, AKS, EKS)")
require.Nil(t, actualStatusKubeConfigInfo)
}
})
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration
@@ -174,7 +174,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes
@@ -276,7 +275,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
"--oidc-scopes", "offline_access,openid,pinniped:request-audience", // does not request username or groups
@@ -379,7 +377,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-skip-listen",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes
@@ -517,7 +514,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-skip-listen",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes
@@ -651,7 +647,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--oidc-skip-browser",
"--oidc-skip-listen",
"--upstream-identity-provider-flow", "cli_password", // create a kubeconfig configured to use the cli_password flow
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes
@@ -731,7 +726,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--upstream-identity-provider-name", oidcIdentityProvider.Name,
"--upstream-identity-provider-type", "oidc",
"--upstream-identity-provider-flow", "cli_password",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes
@@ -1118,7 +1112,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--upstream-identity-provider-flow", "browser_authcode",
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
@@ -1174,7 +1167,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--upstream-identity-provider-flow", "browser_authcode",
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
@@ -1230,7 +1222,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--upstream-identity-provider-flow", "cli_password", // put cli_password in the kubeconfig, so we can override it with the env var
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
@@ -1319,7 +1310,6 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", authenticator.Name,
"--oidc-skip-browser",
"--oidc-ca-bundle", federationDomainCABundlePath,
"--oidc-session-cache", sessionCachePath,
"--credential-cache", credentialCachePath,
// use default for --oidc-scopes, which is to request all relevant scopes

View File

@@ -452,7 +452,7 @@ func TestGetAPIResourceList(t *testing.T) { //nolint:gocyclo // each t.Run is pr
}
// manually update this value whenever you add additional fields to an API resource and then run the generator
totalExpectedAPIFields := 313
totalExpectedAPIFields := 310
// Because we are parsing text from `kubectl explain` and because the format of that text can change
// over time, make a rudimentary assertion that this test exercised the whole tree of all fields of all

View File

@@ -1,4 +1,4 @@
// Copyright 2023-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2023-2025 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration
@@ -563,311 +563,263 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) {
t.Cleanup(cancel)
adminClient := testlib.NewKubernetesClientset(t)
usingKubeVersionInCluster23OrOlder := testutil.KubeServerMinorVersionInBetweenInclusive(t, adminClient.Discovery(), 0, 23)
usingKubeVersionInCluster24Through31Inclusive := testutil.KubeServerMinorVersionInBetweenInclusive(t, adminClient.Discovery(), 24, 31)
usingKubeVersionInCluster32OrNewer := !usingKubeVersionInCluster23OrOlder && !usingKubeVersionInCluster24Through31Inclusive
objectMeta := testlib.ObjectMetaWithRandomName(t, "federation-domain")
// Certain non-CEL validation failures will prevent CEL validations from running,
// and the Kubernetes API server will return this error message for those cases.
const couldNotRunCELValidationsErrMessage = `<nil>: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`
tests := []struct {
name string
fd *supervisorconfigv1alpha1.FederationDomain
wantErr string
name string
spec *supervisorconfigv1alpha1.FederationDomainSpec
wantErrs []string
// optionally override wantErr for one or more specific versions of Kube, due to changing validation error text
wantKube23OrOlderErr string
wantKube24Through31InclusiveErr string
wantKube32OrNewerErr string
wantKube23OrOlderErrs []string
wantKube24Through31InclusiveErrs []string
wantKube32OrNewerErrs []string
// These errors are appended to any other wanted errors when k8sAPIServerSupportsCEL is true
wantCELErrorsForKube25Through28Inclusive []string
wantCELErrorsForKube29OrNewer []string
}{
{
name: "issuer cannot be empty",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "",
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "",
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`},
wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
},
{
name: "issuer must be a URL",
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "foo",
},
wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
},
{
name: "issuer URL scheme must be 'https'",
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "http://example.com",
},
wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`},
},
{
name: "IDP display names cannot be empty",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].displayName: Invalid value: "": `+
"spec.identityProviders[0].displayName in body should be at least 1 chars long",
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].displayName: Invalid value: "": spec.identityProviders[0].displayName in body should be at least 1 chars long`},
},
{
name: "IDP transform constants must have unique names",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "notUnique", Type: "string", StringValue: "foo"},
{Name: "notUnique", Type: "string", StringValue: "bar"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "notUnique", Type: "string", StringValue: "foo"},
{Name: "notUnique", Type: "string", StringValue: "bar"},
},
},
},
},
},
wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`,
env.APIGroupSuffix, objectMeta.Name),
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`,
env.APIGroupSuffix, objectMeta.Name),
// For some unknown reason, Kubernetes versions 1.23 and older return errors *with indices* for this test case only.
wantKube23OrOlderErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`},
wantErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`},
},
{
name: "IDP transform constant names cannot be empty",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "", Type: "string"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "", Type: "string"},
},
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": `+
`spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`},
},
{
name: "IDP transform constant names cannot be more than 64 characters",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "12345678901234567890123456789012345678901234567890123456789012345", Type: "string"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "12345678901234567890123456789012345678901234567890123456789012345", Type: "string"},
},
},
},
},
},
wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": `+
`spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`,
env.APIGroupSuffix, objectMeta.Name),
wantKube24Through31InclusiveErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`,
env.APIGroupSuffix, objectMeta.Name),
wantKube32OrNewerErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`,
env.APIGroupSuffix, objectMeta.Name),
wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`},
wantKube24Through31InclusiveErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`},
wantKube32OrNewerErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`},
wantCELErrorsForKube25Through28Inclusive: []string{couldNotRunCELValidationsErrMessage},
wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage},
},
{
name: "IDP transform constant names must be a legal CEL variable name",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "cannot have spaces", Type: "string"},
{Name: "1mustStartWithLetter", Type: "string"},
{Name: "_mustStartWithLetter", Type: "string"},
{Name: "canOnlyIncludeLettersAndNumbersAnd_", Type: "string"},
{Name: "CanStart1_withUpperCase", Type: "string"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "cannot have spaces", Type: "string"},
{Name: "1mustStartWithLetter", Type: "string"},
{Name: "_mustStartWithLetter", Type: "string"},
{Name: "canOnlyIncludeLettersAndNumbersAnd_", Type: "string"},
{Name: "CanStart1_withUpperCase", Type: "string"},
},
},
},
},
},
wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": `+
`spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`,
env.APIGroupSuffix, objectMeta.Name),
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`[spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": `+
`spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', `+
`spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": `+
`spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', `+
`spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": `+
`spec.identityProviders[0].transforms.constants[2].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$']`,
env.APIGroupSuffix, objectMeta.Name),
wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`},
wantErrs: []string{
`spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`,
`spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`,
`spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": spec.identityProviders[0].transforms.constants[2].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`},
},
{
name: "IDP transform constant types must be one of the allowed enum strings",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "a", Type: "this is invalid"},
{Name: "b", Type: "string"},
{Name: "c", Type: "stringList"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "a", Type: "this is invalid"},
{Name: "b", Type: "string"},
{Name: "c", Type: "stringList"},
},
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": `+
`supported values: "string", "stringList"`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`},
wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage}, // this should not be checked on kind 1.25, 1.26, 1.27, 1.28
},
{
name: "IDP transform expression types must be one of the allowed enum strings",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "this is invalid", Expression: "foo"},
{Type: "policy/v1", Expression: "foo"},
{Type: "username/v1", Expression: "foo"},
{Type: "groups/v1", Expression: "foo"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "this is invalid", Expression: "foo"},
{Type: "policy/v1", Expression: "foo"},
{Type: "username/v1", Expression: "foo"},
{Type: "groups/v1", Expression: "foo"},
},
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": `+
`supported values: "policy/v1", "username/v1", "groups/v1"`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`},
wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage}, // this should not be checked on kind 1.25, 1.26, 1.27, 1.28
},
{
name: "IDP transform expressions cannot be empty",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "username/v1", Expression: ""},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "username/v1", Expression: ""},
},
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": `+
`spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`},
},
{
name: "IDP transform example usernames cannot be empty",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: objectMeta,
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{
{Username: ""},
{Username: "non-empty"},
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{
{Username: ""},
{Username: "non-empty"},
},
},
},
},
},
wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+
`spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": `+
`spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`,
env.APIGroupSuffix, objectMeta.Name),
wantErrs: []string{`spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`},
},
{
name: "minimum valid",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"),
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
},
},
{
name: "minimum valid when IDPs are included",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"),
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
},
},
@@ -875,26 +827,23 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) {
},
{
name: "minimum valid when IDP has transform constants, expressions, and examples",
fd: &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"),
Spec: supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
spec: &supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: "https://example.com",
IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{
{
DisplayName: "foo",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"),
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "foo", Type: "string"},
},
Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{
Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{
{Name: "foo", Type: "string"},
},
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "username/v1", Expression: "foo"},
},
Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{
{Username: "foo"},
},
Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{
{Type: "username/v1", Expression: "foo"},
},
Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{
{Username: "foo"},
},
},
},
@@ -908,50 +857,76 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
_, createErr := fdClient.Create(ctx, tt.fd, metav1.CreateOptions{})
fd := &supervisorconfigv1alpha1.FederationDomain{
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "federation-domain"),
Spec: *tt.spec,
}
_, actualCreateErr := fdClient.Create(ctx, fd, metav1.CreateOptions{})
t.Cleanup(func() {
// Delete it if it exists.
delErr := fdClient.Delete(ctx, tt.fd.Name, metav1.DeleteOptions{})
delErr := fdClient.Delete(ctx, fd.Name, metav1.DeleteOptions{})
if !apierrors.IsNotFound(delErr) {
require.NoError(t, delErr)
}
})
if tt.wantErr != "" && tt.wantKube23OrOlderErr != "" && tt.wantKube24Through31InclusiveErr != "" && tt.wantKube32OrNewerErr != "" {
if len(tt.wantErrs) > 0 && len(tt.wantKube23OrOlderErrs) > 0 && len(tt.wantKube24Through31InclusiveErrs) > 0 && len(tt.wantKube32OrNewerErrs) > 0 {
require.Fail(t, "test setup problem: wanted every possible kind of error, which would cause tt.wantErr to be unused")
}
if tt.wantErr == "" && tt.wantKube23OrOlderErr == "" && tt.wantKube24Through31InclusiveErr == "" && tt.wantKube32OrNewerErr == "" { //nolint:nestif
// Did not want any error.
require.NoError(t, createErr)
} else {
wantErr := tt.wantErr
if usingKubeVersionInCluster23OrOlder {
// Old versions of Kubernetes did not show the index where the error occurred in some of the messages,
// so remove the indices from the expected messages when running against an old version of Kube.
// For the above tests, it should be enough to assume that there will only be indices up to 10.
// This is useful when the only difference in the message between old and new is the missing indices.
// Otherwise, use wantKube23OrOlderErr to say what the expected message should be for old versions.
for i := range 10 {
wantErr = strings.ReplaceAll(wantErr, fmt.Sprintf("[%d]", i), "")
minor := testutil.KubeServerMinorVersion(t, adminClient.Discovery())
wantErr := tt.wantErrs
if minor <= 23 {
// Old versions of Kubernetes did not show the index where the error occurred in some of the messages,
// so remove the indices from the expected messages when running against an old version of Kube.
// For the above tests, it should be enough to assume that there will only be indices up to 10.
// This is useful when the only difference in the message between old and new is the missing indices.
// Otherwise, use wantKube23OrOlderErr to say what the expected message should be for old versions.
for i := range wantErr {
for j := range 10 {
wantErr[i] = strings.ReplaceAll(wantErr[i], fmt.Sprintf("[%d]", j), "")
}
}
if usingKubeVersionInCluster23OrOlder && tt.wantKube23OrOlderErr != "" {
// Sometimes there are other difference in older Kubernetes messages, so also allow exact
// expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters.
wantErr = tt.wantKube23OrOlderErr
}
if usingKubeVersionInCluster24Through31Inclusive && tt.wantKube24Through31InclusiveErr != "" {
// Also allow overriding with an exact expected error for these Kube versions.
wantErr = tt.wantKube24Through31InclusiveErr
}
if usingKubeVersionInCluster32OrNewer && tt.wantKube32OrNewerErr != "" {
// Also allow overriding with an exact expected error for these Kube versions.
wantErr = tt.wantKube32OrNewerErr
}
require.EqualError(t, createErr, wantErr)
}
if minor <= 23 && len(tt.wantKube23OrOlderErrs) > 0 {
// Sometimes there are other difference in older Kubernetes messages, so also allow exact
// expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters.
wantErr = tt.wantKube23OrOlderErrs
}
if minor >= 24 && minor <= 31 && len(tt.wantKube24Through31InclusiveErrs) > 0 {
// Also allow overriding with an exact expected error for these Kube versions.
wantErr = tt.wantKube24Through31InclusiveErrs
}
if minor >= 32 && len(tt.wantKube32OrNewerErrs) > 0 {
// Also allow overriding with an exact expected error for these Kube versions.
wantErr = tt.wantKube32OrNewerErrs
}
if minor >= 25 && minor <= 28 && len(tt.wantCELErrorsForKube25Through28Inclusive) > 0 {
wantErr = append(wantErr, tt.wantCELErrorsForKube25Through28Inclusive...)
} else if minor >= 29 && len(tt.wantCELErrorsForKube29OrNewer) > 0 {
wantErr = append(wantErr, tt.wantCELErrorsForKube29OrNewer...)
}
// Did not want any error.
if len(wantErr) == 0 {
require.NoError(t, actualCreateErr)
return
}
wantErrStr := fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: ",
env.APIGroupSuffix, fd.Name)
if len(wantErr) == 1 {
wantErrStr += wantErr[0]
} else {
wantErrStr += "[" + strings.Join(wantErr, ", ") + "]"
}
require.EqualError(t, actualCreateErr, wantErrStr)
})
}
}

View File

@@ -31,7 +31,7 @@ func TestSupervisorSecrets_Parallel(t *testing.T) {
// Create our FederationDomain under test.
federationDomain := testlib.CreateTestFederationDomain(ctx, t,
supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: fmt.Sprintf("http://test-issuer-%s.pinniped.dev", testlib.RandHex(t, 8)),
Issuer: fmt.Sprintf("https://test-issuer-%s.pinniped.dev", testlib.RandHex(t, 8)),
},
supervisorconfigv1alpha1.FederationDomainPhaseError, // in phase error until there is an IDP created, but this test does not care
)