mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-09-20 15:04:34 +00:00
Supervisor controllers apply custom labels to JWKS secrets
Signed-off-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
committed by
Ryan Richard
parent
f8e461dfc3
commit
617c5608ca
@@ -17,13 +17,13 @@ import (
|
||||
loginv1alpha1 "go.pinniped.dev/generated/1.19/apis/login/v1alpha1"
|
||||
"go.pinniped.dev/internal/certauthority/dynamiccertauthority"
|
||||
"go.pinniped.dev/internal/concierge/apiserver"
|
||||
"go.pinniped.dev/internal/config/concierge"
|
||||
"go.pinniped.dev/internal/controller/identityprovider/idpcache"
|
||||
"go.pinniped.dev/internal/controllermanager"
|
||||
"go.pinniped.dev/internal/downward"
|
||||
"go.pinniped.dev/internal/dynamiccert"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||
"go.pinniped.dev/pkg/config"
|
||||
)
|
||||
|
||||
// App is an object that represents the pinniped-concierge application.
|
||||
@@ -92,7 +92,7 @@ func addCommandlineFlagsToCommand(cmd *cobra.Command, app *App) {
|
||||
// Boot the aggregated API server, which will in turn boot the controllers.
|
||||
func (a *App) runServer(ctx context.Context) error {
|
||||
// Read the server config file.
|
||||
cfg, err := config.FromPath(a.configPath)
|
||||
cfg, err := concierge.FromPath(a.configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not load config: %w", err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package concierge contains functionality to load/store Config's from/to
|
||||
// some source.
|
||||
package concierge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
)
|
||||
|
||||
const (
|
||||
aboutAYear = 60 * 60 * 24 * 365
|
||||
about9Months = 60 * 60 * 24 * 30 * 9
|
||||
)
|
||||
|
||||
// FromPath loads an Config from a provided local file path, inserts any
|
||||
// defaults (from the Config documentation), and verifies that the config is
|
||||
// valid (per the Config documentation).
|
||||
//
|
||||
// Note! The Config file should contain base64-encoded WebhookCABundle data.
|
||||
// This function will decode that base64-encoded data to PEM bytes to be stored
|
||||
// in the Config.
|
||||
func FromPath(path string) (*Config, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read file: %w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("decode yaml: %w", err)
|
||||
}
|
||||
|
||||
maybeSetAPIDefaults(&config.APIConfig)
|
||||
maybeSetKubeCertAgentDefaults(&config.KubeCertAgentConfig)
|
||||
|
||||
if err := validateAPI(&config.APIConfig); err != nil {
|
||||
return nil, fmt.Errorf("validate api: %w", err)
|
||||
}
|
||||
|
||||
if err := validateNames(&config.NamesConfig); err != nil {
|
||||
return nil, fmt.Errorf("validate names: %w", err)
|
||||
}
|
||||
|
||||
if config.Labels == nil {
|
||||
config.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func maybeSetAPIDefaults(apiConfig *APIConfigSpec) {
|
||||
if apiConfig.ServingCertificateConfig.DurationSeconds == nil {
|
||||
apiConfig.ServingCertificateConfig.DurationSeconds = int64Ptr(aboutAYear)
|
||||
}
|
||||
|
||||
if apiConfig.ServingCertificateConfig.RenewBeforeSeconds == nil {
|
||||
apiConfig.ServingCertificateConfig.RenewBeforeSeconds = int64Ptr(about9Months)
|
||||
}
|
||||
}
|
||||
|
||||
func maybeSetKubeCertAgentDefaults(cfg *KubeCertAgentSpec) {
|
||||
if cfg.NamePrefix == nil {
|
||||
cfg.NamePrefix = stringPtr("pinniped-kube-cert-agent-")
|
||||
}
|
||||
|
||||
if cfg.Image == nil {
|
||||
cfg.Image = stringPtr("debian:latest")
|
||||
}
|
||||
}
|
||||
|
||||
func validateNames(names *NamesConfigSpec) error {
|
||||
missingNames := []string{}
|
||||
if names == nil {
|
||||
missingNames = append(missingNames, "servingCertificateSecret", "credentialIssuerConfig", "apiService")
|
||||
} else {
|
||||
if names.ServingCertificateSecret == "" {
|
||||
missingNames = append(missingNames, "servingCertificateSecret")
|
||||
}
|
||||
if names.CredentialIssuerConfig == "" {
|
||||
missingNames = append(missingNames, "credentialIssuerConfig")
|
||||
}
|
||||
if names.APIService == "" {
|
||||
missingNames = append(missingNames, "apiService")
|
||||
}
|
||||
}
|
||||
if len(missingNames) > 0 {
|
||||
return constable.Error("missing required names: " + strings.Join(missingNames, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAPI(apiConfig *APIConfigSpec) error {
|
||||
if *apiConfig.ServingCertificateConfig.DurationSeconds < *apiConfig.ServingCertificateConfig.RenewBeforeSeconds {
|
||||
return constable.Error("durationSeconds cannot be smaller than renewBeforeSeconds")
|
||||
}
|
||||
|
||||
if *apiConfig.ServingCertificateConfig.RenewBeforeSeconds <= 0 {
|
||||
return constable.Error("renewBefore must be positive")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package concierge
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
)
|
||||
|
||||
func TestFromPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
yaml string
|
||||
wantConfig *Config
|
||||
wantError string
|
||||
}{
|
||||
{
|
||||
name: "Happy",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
discovery:
|
||||
url: https://some.discovery/url
|
||||
api:
|
||||
servingCertificate:
|
||||
durationSeconds: 3600
|
||||
renewBeforeSeconds: 2400
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
kubeCertAgentPrefix: kube-cert-agent-prefix
|
||||
labels:
|
||||
myLabelKey1: myLabelValue1
|
||||
myLabelKey2: myLabelValue2
|
||||
KubeCertAgent:
|
||||
namePrefix: kube-cert-agent-name-prefix-
|
||||
image: kube-cert-agent-image
|
||||
imagePullSecrets: [kube-cert-agent-image-pull-secret]
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: stringPtr("https://some.discovery/url"),
|
||||
},
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: int64Ptr(3600),
|
||||
RenewBeforeSeconds: int64Ptr(2400),
|
||||
},
|
||||
},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
|
||||
CredentialIssuerConfig: "pinniped-config",
|
||||
APIService: "pinniped-api",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: stringPtr("kube-cert-agent-name-prefix-"),
|
||||
Image: stringPtr("kube-cert-agent-image"),
|
||||
ImagePullSecrets: []string{"kube-cert-agent-image-pull-secret"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "When only the required fields are present, causes other fields to be defaulted",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: nil,
|
||||
},
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: int64Ptr(60 * 60 * 24 * 365), // about a year
|
||||
RenewBeforeSeconds: int64Ptr(60 * 60 * 24 * 30 * 9), // about 9 months
|
||||
},
|
||||
},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
|
||||
CredentialIssuerConfig: "pinniped-config",
|
||||
APIService: "pinniped-api",
|
||||
},
|
||||
Labels: map[string]string{},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: stringPtr("pinniped-kube-cert-agent-"),
|
||||
Image: stringPtr("debian:latest"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Empty",
|
||||
yaml: here.Doc(``),
|
||||
wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuerConfig, apiService",
|
||||
},
|
||||
{
|
||||
name: "Missing apiService name",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
`),
|
||||
wantError: "validate names: missing required names: apiService",
|
||||
},
|
||||
{
|
||||
name: "Missing credentialIssuerConfig name",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantError: "validate names: missing required names: credentialIssuerConfig",
|
||||
},
|
||||
{
|
||||
name: "Missing servingCertificateSecret name",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
names:
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantError: "validate names: missing required names: servingCertificateSecret",
|
||||
},
|
||||
{
|
||||
name: "InvalidDurationRenewBefore",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
api:
|
||||
servingCertificate:
|
||||
durationSeconds: 2400
|
||||
renewBeforeSeconds: 3600
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantError: "validate api: durationSeconds cannot be smaller than renewBeforeSeconds",
|
||||
},
|
||||
{
|
||||
name: "NegativeRenewBefore",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
api:
|
||||
servingCertificate:
|
||||
durationSeconds: 2400
|
||||
renewBeforeSeconds: -10
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantError: "validate api: renewBefore must be positive",
|
||||
},
|
||||
{
|
||||
name: "ZeroRenewBefore",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
api:
|
||||
servingCertificate:
|
||||
durationSeconds: 2400
|
||||
renewBeforeSeconds: -10
|
||||
names:
|
||||
servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
|
||||
credentialIssuerConfig: pinniped-config
|
||||
apiService: pinniped-api
|
||||
`),
|
||||
wantError: "validate api: renewBefore must be positive",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Write yaml to temp file
|
||||
f, err := ioutil.TempFile("", "pinniped-test-config-yaml-*")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
err := os.Remove(f.Name())
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
_, err = f.WriteString(test.yaml)
|
||||
require.NoError(t, err)
|
||||
err = f.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test FromPath()
|
||||
config, err := FromPath(f.Name())
|
||||
|
||||
if test.wantError != "" {
|
||||
require.EqualError(t, err, test.wantError)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.wantConfig, config)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package concierge
|
||||
|
||||
// Config contains knobs to setup an instance of the Pinniped Concierge.
|
||||
type Config struct {
|
||||
DiscoveryInfo DiscoveryInfoSpec `json:"discovery"`
|
||||
APIConfig APIConfigSpec `json:"api"`
|
||||
NamesConfig NamesConfigSpec `json:"names"`
|
||||
KubeCertAgentConfig KubeCertAgentSpec `json:"kubeCertAgent"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
|
||||
// DiscoveryInfoSpec contains configuration knobs specific to
|
||||
// pinniped's publishing of discovery information. These values can be
|
||||
// viewed as overrides, i.e., if these are set, then Pinniped will
|
||||
// publish these values in its discovery document instead of the ones it finds.
|
||||
type DiscoveryInfoSpec struct {
|
||||
// URL contains the URL at which pinniped can be contacted.
|
||||
URL *string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// APIConfigSpec contains configuration knobs for the Pinniped API.
|
||||
//nolint: golint
|
||||
type APIConfigSpec struct {
|
||||
ServingCertificateConfig ServingCertificateConfigSpec `json:"servingCertificate"`
|
||||
}
|
||||
|
||||
// NamesConfigSpec configures the names of some Kubernetes resources for the Concierge.
|
||||
type NamesConfigSpec struct {
|
||||
ServingCertificateSecret string `json:"servingCertificateSecret"`
|
||||
CredentialIssuerConfig string `json:"credentialIssuerConfig"`
|
||||
APIService string `json:"apiService"`
|
||||
}
|
||||
|
||||
// ServingCertificateConfigSpec contains the configuration knobs for the API's
|
||||
// serving certificate, i.e., the x509 certificate that it uses for the server
|
||||
// certificate in inbound TLS connections.
|
||||
type ServingCertificateConfigSpec struct {
|
||||
// DurationSeconds is the validity period, in seconds, of the API serving
|
||||
// certificate. By default, the serving certificate is issued for 31536000
|
||||
// seconds (1 year). This value is also used for the serving certificate's
|
||||
// CA certificate.
|
||||
DurationSeconds *int64 `json:"durationSeconds,omitempty"`
|
||||
|
||||
// RenewBeforeSeconds is the period of time, in seconds, that Pinniped will
|
||||
// wait before rotating the serving certificate. This period of time starts
|
||||
// upon issuance of the serving certificate. This must be less than
|
||||
// DurationSeconds. By default, Pinniped begins rotation after 23328000
|
||||
// seconds (about 9 months).
|
||||
RenewBeforeSeconds *int64 `json:"renewBeforeSeconds,omitempty"`
|
||||
}
|
||||
|
||||
type KubeCertAgentSpec struct {
|
||||
// NamePrefix is the prefix of the name of the kube-cert-agent pods. For example, if this field is
|
||||
// set to "some-prefix-", then the name of the pods will look like "some-prefix-blah". The default
|
||||
// for this value is "pinniped-kube-cert-agent-".
|
||||
NamePrefix *string `json:"namePrefix,omitempty"`
|
||||
|
||||
// Image is the container image that will be used by the kube-cert-agent pod. The container image
|
||||
// should contain at least 2 binaries: /bin/sleep and cat (somewhere on the $PATH). The default
|
||||
// for this value is "debian:latest".
|
||||
Image *string `json:"image"`
|
||||
|
||||
// ImagePullSecrets is a list of names of Kubernetes Secret objects that will be used as
|
||||
// ImagePullSecrets on the kube-cert-agent pods.
|
||||
ImagePullSecrets []string
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package supervisor contains functionality to load/store Config's from/to
|
||||
// some source.
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// FromPath loads an Config from a provided local file path, inserts any
|
||||
// defaults (from the Config documentation), and verifies that the config is
|
||||
// valid (Config documentation).
|
||||
func FromPath(path string) (*Config, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read file: %w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("decode yaml: %w", err)
|
||||
}
|
||||
|
||||
if config.Labels == nil {
|
||||
config.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
)
|
||||
|
||||
func TestFromPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
yaml string
|
||||
wantConfig *Config
|
||||
}{
|
||||
{
|
||||
name: "Happy",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
labels:
|
||||
myLabelKey1: myLabelValue1
|
||||
myLabelKey2: myLabelValue2
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "When only the required fields are present, causes other fields to be defaulted",
|
||||
yaml: here.Doc(`
|
||||
---
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
Labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Write yaml to temp file
|
||||
f, err := ioutil.TempFile("", "pinniped-test-config-yaml-*")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
err := os.Remove(f.Name())
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
_, err = f.WriteString(test.yaml)
|
||||
require.NoError(t, err)
|
||||
err = f.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test FromPath()
|
||||
config, err := FromPath(f.Name())
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.wantConfig, config)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package supervisor
|
||||
|
||||
// Config contains knobs to setup an instance of the Pinniped Supervisor.
|
||||
type Config struct {
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
@@ -56,15 +56,17 @@ func generateECKey(r io.Reader) (interface{}, error) {
|
||||
// jwkController holds the fields necessary for the JWKS controller to communicate with OPC's and
|
||||
// secrets, both via a cache and via the API.
|
||||
type jwksController struct {
|
||||
pinnipedClient pinnipedclientset.Interface
|
||||
kubeClient kubernetes.Interface
|
||||
opcInformer configinformers.OIDCProviderConfigInformer
|
||||
secretInformer corev1informers.SecretInformer
|
||||
jwksSecretLabels map[string]string
|
||||
pinnipedClient pinnipedclientset.Interface
|
||||
kubeClient kubernetes.Interface
|
||||
opcInformer configinformers.OIDCProviderConfigInformer
|
||||
secretInformer corev1informers.SecretInformer
|
||||
}
|
||||
|
||||
// NewJWKSController returns a controllerlib.Controller that ensures an OPC has a corresponding
|
||||
// Secret that contains a valid active JWK and JWKS.
|
||||
func NewJWKSController(
|
||||
jwksSecretLabels map[string]string,
|
||||
kubeClient kubernetes.Interface,
|
||||
pinnipedClient pinnipedclientset.Interface,
|
||||
secretInformer corev1informers.SecretInformer,
|
||||
@@ -75,10 +77,11 @@ func NewJWKSController(
|
||||
controllerlib.Config{
|
||||
Name: "JWKSController",
|
||||
Syncer: &jwksController{
|
||||
kubeClient: kubeClient,
|
||||
pinnipedClient: pinnipedClient,
|
||||
secretInformer: secretInformer,
|
||||
opcInformer: opcInformer,
|
||||
jwksSecretLabels: jwksSecretLabels,
|
||||
kubeClient: kubeClient,
|
||||
pinnipedClient: pinnipedClient,
|
||||
secretInformer: secretInformer,
|
||||
opcInformer: opcInformer,
|
||||
},
|
||||
},
|
||||
// We want to be notified when a OPC's secret gets updated or deleted. When this happens, we
|
||||
@@ -234,6 +237,7 @@ func (c *jwksController) generateSecret(opc *configv1alpha1.OIDCProviderConfig)
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: opc.Name + "-jwks",
|
||||
Namespace: opc.Namespace,
|
||||
Labels: c.jwksSecretLabels,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(opc, schema.GroupVersionKind{
|
||||
Group: configv1alpha1.SchemeGroupVersion.Group,
|
||||
@@ -241,7 +245,6 @@ func (c *jwksController) generateSecret(opc *configv1alpha1.OIDCProviderConfig)
|
||||
Kind: opcKind,
|
||||
}),
|
||||
},
|
||||
// TODO: custom labels.
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
activeJWKKey: jwkData,
|
||||
|
||||
@@ -151,6 +151,7 @@ func TestJWKSControllerFilterSecret(t *testing.T) {
|
||||
).Config().V1alpha1().OIDCProviderConfigs()
|
||||
withInformer := testutil.NewObservableWithInformerOption()
|
||||
_ = NewJWKSController(
|
||||
nil, // labels, not needed
|
||||
nil, // kubeClient, not needed
|
||||
nil, // pinnipedClient, not needed
|
||||
secretInformer,
|
||||
@@ -204,6 +205,7 @@ func TestJWKSControllerFilterOPC(t *testing.T) {
|
||||
).Config().V1alpha1().OIDCProviderConfigs()
|
||||
withInformer := testutil.NewObservableWithInformerOption()
|
||||
_ = NewJWKSController(
|
||||
nil, // labels, not needed
|
||||
nil, // kubeClient, not needed
|
||||
nil, // pinnipedClient, not needed
|
||||
secretInformer,
|
||||
@@ -264,6 +266,10 @@ func TestJWKSControllerSync(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: goodOPCWithStatus.Status.JWKSSecret.Name,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: opcGVR.GroupVersion().String(),
|
||||
@@ -648,6 +654,10 @@ func TestJWKSControllerSync(t *testing.T) {
|
||||
)
|
||||
|
||||
c := NewJWKSController(
|
||||
map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
kubeAPIClient,
|
||||
pinnipedAPIClient,
|
||||
kubeInformers.Core().V1().Secrets(),
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
loginv1alpha1 "go.pinniped.dev/generated/1.19/apis/login/v1alpha1"
|
||||
pinnipedclientset "go.pinniped.dev/generated/1.19/client/clientset/versioned"
|
||||
pinnipedinformers "go.pinniped.dev/generated/1.19/client/informers/externalversions"
|
||||
"go.pinniped.dev/internal/config/concierge"
|
||||
"go.pinniped.dev/internal/controller/apicerts"
|
||||
"go.pinniped.dev/internal/controller/identityprovider/idpcache"
|
||||
"go.pinniped.dev/internal/controller/identityprovider/webhookcachecleaner"
|
||||
@@ -30,7 +31,6 @@ import (
|
||||
"go.pinniped.dev/internal/controller/kubecertagent"
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/dynamiccert"
|
||||
"go.pinniped.dev/pkg/config/api"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -47,11 +47,11 @@ type Config struct {
|
||||
|
||||
// NamesConfig comes from the Pinniped config API (see api.Config). It specifies how Kubernetes
|
||||
// objects should be named.
|
||||
NamesConfig *api.NamesConfigSpec
|
||||
NamesConfig *concierge.NamesConfigSpec
|
||||
|
||||
// KubeCertAgentConfig comes from the Pinniped config API (see api.Config). It configures how
|
||||
// the kubecertagent package's controllers should manage the agent pods.
|
||||
KubeCertAgentConfig *api.KubeCertAgentSpec
|
||||
KubeCertAgentConfig *concierge.KubeCertAgentSpec
|
||||
|
||||
// DiscoveryURLOverride allows a caller to inject a hardcoded discovery URL into Pinniped
|
||||
// discovery document.
|
||||
|
||||
Reference in New Issue
Block a user