Merge branch 'main' into upstream_refresh
This commit is contained in:
commit
d68bebeb49
@ -3,7 +3,7 @@
|
|||||||
# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
FROM golang:1.17.1 as build-env
|
FROM golang:1.17.2 as build-env
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
COPY . .
|
COPY . .
|
||||||
@ -24,7 +24,7 @@ RUN \
|
|||||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
||||||
|
|
||||||
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
|
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
|
||||||
FROM gcr.io/distroless/static:nonroot@sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4
|
FROM gcr.io/distroless/static:nonroot@sha256:07869abb445859465749913267a8c7b3b02dc4236fbc896e29ae859e4b360851
|
||||||
|
|
||||||
# Copy the server binary from the build-env stage.
|
# Copy the server binary from the build-env stage.
|
||||||
COPY --from=build-env /usr/local/bin /usr/local/bin
|
COPY --from=build-env /usr/local/bin /usr/local/bin
|
||||||
|
@ -36,9 +36,10 @@ The following table includes the current roadmap for Pinniped. If you have any q
|
|||||||
Last Updated: Sept 2021
|
Last Updated: Sept 2021
|
||||||
|Theme|Description|Timeline|
|
|Theme|Description|Timeline|
|
||||||
|--|--|--|
|
|--|--|--|
|
||||||
|Improving Security Posture|Supervisor token refresh fails when the upstream refresh token no longer works|Sept 2021|
|
|Improving Security Posture|Supervisor token refresh fails when the upstream refresh token no longer works for OIDC |Oct 2021|
|
||||||
|Wider Concierge cluster support|Support for OpenShift cluster types in the Concierge|Sept 2021|
|
|Improving Security Posture|Supervisor token refresh fails when the upstream refresh token no longer works for LDAP/AD |Nov 2021|
|
||||||
|Multiple IDP support|Support multiple IDPs configured on a single Supervisor|Exploring/Ongoing|
|
|Multiple IDP support|Support multiple IDPs configured on a single Supervisor|Exploring/Ongoing|
|
||||||
|
|Wider Concierge cluster support|Support for OpenShift cluster types in the Concierge|Exploring/Ongoing|
|
||||||
|Identity transforms|Support prefixing, filtering, or performing coarse-grained checks on upstream users and groups|Exploring/Ongoing|
|
|Identity transforms|Support prefixing, filtering, or performing coarse-grained checks on upstream users and groups|Exploring/Ongoing|
|
||||||
|CLI SSO|Support Kerberos based authentication on CLI |Exploring/Ongoing|
|
|CLI SSO|Support Kerberos based authentication on CLI |Exploring/Ongoing|
|
||||||
|Extended IDP support|Support more types of identity providers on the Supervisor|Exploring/Ongoing|
|
|Extended IDP support|Support more types of identity providers on the Supervisor|Exploring/Ongoing|
|
||||||
|
@ -14,11 +14,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog/v2"
|
|
||||||
|
|
||||||
"go.pinniped.dev/internal/constable"
|
"go.pinniped.dev/internal/constable"
|
||||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
|
"go.pinniped.dev/internal/plog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type certsExpirerController struct {
|
type certsExpirerController struct {
|
||||||
@ -74,7 +74,13 @@ func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
|||||||
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
||||||
}
|
}
|
||||||
if notFound {
|
if notFound {
|
||||||
klog.Info("certsExpirerController Sync found that the secret does not exist yet or was deleted")
|
plog.Info("secret does not exist yet or was deleted",
|
||||||
|
"controller", ctx.Name,
|
||||||
|
"namespace", c.namespace,
|
||||||
|
"name", c.certsSecretResourceName,
|
||||||
|
"key", c.secretKey,
|
||||||
|
"renewBefore", c.renewBefore.String(),
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +91,17 @@ func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
|||||||
|
|
||||||
certAge := time.Since(notBefore)
|
certAge := time.Since(notBefore)
|
||||||
renewDelta := certAge - c.renewBefore
|
renewDelta := certAge - c.renewBefore
|
||||||
klog.Infof("certsExpirerController Sync found a renew delta of %s", renewDelta)
|
plog.Debug("found renew delta",
|
||||||
|
"controller", ctx.Name,
|
||||||
|
"namespace", c.namespace,
|
||||||
|
"name", c.certsSecretResourceName,
|
||||||
|
"key", c.secretKey,
|
||||||
|
"renewBefore", c.renewBefore.String(),
|
||||||
|
"notBefore", notBefore.String(),
|
||||||
|
"notAfter", notAfter.String(),
|
||||||
|
"certAge", certAge.String(),
|
||||||
|
"renewDelta", renewDelta.String(),
|
||||||
|
)
|
||||||
if renewDelta >= 0 || time.Now().After(notAfter) {
|
if renewDelta >= 0 || time.Now().After(notAfter) {
|
||||||
err := c.k8sClient.
|
err := c.k8sClient.
|
||||||
CoreV1().
|
CoreV1().
|
||||||
@ -107,9 +123,7 @@ func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getCertBounds returns the NotBefore and NotAfter fields of the TLS
|
// getCertBounds returns the NotBefore and NotAfter fields of the TLS
|
||||||
// certificate in the provided secret, or an error. Not that it expects the
|
// certificate in the provided secret, or an error.
|
||||||
// provided secret to contain the well-known data keys from this package (see
|
|
||||||
// certs_manager.go).
|
|
||||||
func (c *certsExpirerController) getCertBounds(secret *corev1.Secret) (time.Time, time.Time, error) {
|
func (c *certsExpirerController) getCertBounds(secret *corev1.Secret) (time.Time, time.Time, error) {
|
||||||
certPEM := secret.Data[c.secretKey]
|
certPEM := secret.Data[c.secretKey]
|
||||||
if certPEM == nil {
|
if certPEM == nil {
|
||||||
|
@ -51,7 +51,7 @@ const (
|
|||||||
impersonationProxyPort = 8444
|
impersonationProxyPort = 8444
|
||||||
defaultHTTPSPort = 443
|
defaultHTTPSPort = 443
|
||||||
approximatelyOneHundredYears = 100 * 365 * 24 * time.Hour
|
approximatelyOneHundredYears = 100 * 365 * 24 * time.Hour
|
||||||
caCommonName = "Pinniped Impersonation Proxy CA"
|
caCommonName = "Pinniped Impersonation Proxy Serving CA"
|
||||||
caCrtKey = "ca.crt"
|
caCrtKey = "ca.crt"
|
||||||
caKeyKey = "ca.key"
|
caKeyKey = "ca.key"
|
||||||
appLabelKey = "app"
|
appLabelKey = "app"
|
||||||
|
@ -1055,7 +1055,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
|||||||
require.NotNil(t, block)
|
require.NotNil(t, block)
|
||||||
caCert, err := x509.ParseCertificate(block.Bytes)
|
caCert, err := x509.ParseCertificate(block.Bytes)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "Pinniped Impersonation Proxy CA", caCert.Subject.CommonName)
|
require.Equal(t, "Pinniped Impersonation Proxy Serving CA", caCert.Subject.CommonName)
|
||||||
require.WithinDuration(t, time.Now().Add(-5*time.Minute), caCert.NotBefore, 10*time.Second)
|
require.WithinDuration(t, time.Now().Add(-5*time.Minute), caCert.NotBefore, 10*time.Second)
|
||||||
require.WithinDuration(t, time.Now().Add(100*time.Hour*24*365), caCert.NotAfter, 10*time.Second)
|
require.WithinDuration(t, time.Now().Add(100*time.Hour*24*365), caCert.NotAfter, 10*time.Second)
|
||||||
return createdCertPEM
|
return createdCertPEM
|
||||||
|
@ -148,7 +148,7 @@ func PrepareControllers(c *Config) (controllerinit.RunnerBuilder, error) {
|
|||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
controllerlib.WithInitialEvent,
|
controllerlib.WithInitialEvent,
|
||||||
c.ServingCertDuration,
|
c.ServingCertDuration,
|
||||||
"Pinniped CA",
|
"Pinniped Aggregation CA",
|
||||||
c.NamesConfig.APIService,
|
c.NamesConfig.APIService,
|
||||||
),
|
),
|
||||||
singletonWorker,
|
singletonWorker,
|
||||||
@ -285,7 +285,7 @@ func PrepareControllers(c *Config) (controllerinit.RunnerBuilder, error) {
|
|||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
controllerlib.WithInitialEvent,
|
controllerlib.WithInitialEvent,
|
||||||
365*24*time.Hour, // 1 year hard coded value
|
365*24*time.Hour, // 1 year hard coded value
|
||||||
"Pinniped Impersonation Proxy CA",
|
"Pinniped Impersonation Proxy Signer CA",
|
||||||
"", // optional, means do not give me a serving cert
|
"", // optional, means do not give me a serving cert
|
||||||
),
|
),
|
||||||
singletonWorker,
|
singletonWorker,
|
||||||
@ -297,7 +297,7 @@ func PrepareControllers(c *Config) (controllerinit.RunnerBuilder, error) {
|
|||||||
client.Kubernetes,
|
client.Kubernetes,
|
||||||
informers.installationNamespaceK8s.Core().V1().Secrets(),
|
informers.installationNamespaceK8s.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
c.ServingCertRenewBefore,
|
365*24*time.Hour-time.Hour, // 1 year minus 1 hour hard coded value (i.e. wait until the last moment to break the signer)
|
||||||
apicerts.CACertificateSecretKey,
|
apicerts.CACertificateSecretKey,
|
||||||
),
|
),
|
||||||
singletonWorker,
|
singletonWorker,
|
||||||
|
@ -27,8 +27,10 @@ The Pinniped Concierge has two strategies available to support clusters, under t
|
|||||||
This type of cluster is typically called "self-hosted" because the cluster's control plane is running on nodes that are part of the cluster itself.
|
This type of cluster is typically called "self-hosted" because the cluster's control plane is running on nodes that are part of the cluster itself.
|
||||||
Most managed Kubernetes services do not support this.
|
Most managed Kubernetes services do not support this.
|
||||||
|
|
||||||
2. Impersonation Proxy: Can be run on any Kubernetes cluster where a `LoadBalancer` service can be created. Most cloud-hosted Kubernetes environments have this
|
2. Impersonation Proxy: Can be run on any Kubernetes cluster. Default configuration requires that a `LoadBalancer` service can be created. Most cloud-hosted Kubernetes environments have this
|
||||||
capability. The Impersonation Proxy automatically provisions a `LoadBalancer` for ingress to the impersonation endpoint.
|
capability. The Impersonation Proxy automatically provisions (when `spec.impersonationProxy.mode` is set to `auto`) a `LoadBalancer` for ingress to the impersonation endpoint. Users who wish to use the impersonation proxy without an automatically
|
||||||
|
configured `LoadBalancer` can do so with an automatically provisioned `ClusterIP` or with a Service that they provision themselves. These options
|
||||||
|
can be configured in the spec of the [`CredentialIssuer`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#credentialissuer).
|
||||||
|
|
||||||
If a cluster is capable of supporting both strategies, the Pinniped CLI will use the
|
If a cluster is capable of supporting both strategies, the Pinniped CLI will use the
|
||||||
token credential request API strategy by default.
|
token credential request API strategy by default.
|
||||||
|
Loading…
Reference in New Issue
Block a user