Compare commits
32 Commits
main
...
ben/carvel
Author | SHA1 | Date | |
---|---|---|---|
|
96c094c901 | ||
|
6a847aaec7 | ||
|
65a54d39a5 | ||
|
d99a43bd87 | ||
|
3a71252167 | ||
|
ead2b3ce08 | ||
|
1ec75ba8ca | ||
|
e297f05603 | ||
|
233e382579 | ||
|
c82b14179a | ||
|
1688210630 | ||
|
296f09ed85 | ||
|
e873f11284 | ||
|
3097a263cd | ||
|
8bea59139d | ||
|
02ac4d26af | ||
|
af04f331f3 | ||
|
9b8addef00 | ||
|
c8ec432eef | ||
|
109cf0cd28 | ||
|
562f11d034 | ||
|
1938b2df73 | ||
|
c1a9fb60d0 | ||
|
a801a93411 | ||
|
b861fdc148 | ||
|
0c60e31d86 | ||
|
1d1b98f9a1 | ||
|
9657719f9f | ||
|
5c75734112 | ||
|
aceef06873 | ||
|
550673b8dd | ||
|
715a93d64a |
@ -21,6 +21,3 @@
|
|||||||
|
|
||||||
# MacOS Desktop Services Store
|
# MacOS Desktop Services Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Hugo temp file
|
|
||||||
.hugo_build.lock
|
|
||||||
|
19
.drone.yml
19
.drone.yml
@ -1,19 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: kubernetes
|
|
||||||
name: Container
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build & publish
|
|
||||||
image: spritsail/docker-build
|
|
||||||
context: .
|
|
||||||
settings:
|
|
||||||
repo: bv11-cr01.bessems.eu/library/pinniped-server
|
|
||||||
registry: bv11-cr01.bessems.eu
|
|
||||||
tags: latest
|
|
||||||
build_args:
|
|
||||||
- BUILDPLATFORM=linux/amd64
|
|
||||||
mtu: 1450
|
|
||||||
username:
|
|
||||||
from_secret: harbor_username
|
|
||||||
password:
|
|
||||||
from_secret: harbor_password
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -19,6 +19,3 @@
|
|||||||
|
|
||||||
# MacOS Desktop Services Store
|
# MacOS Desktop Services Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Hugo temp file
|
|
||||||
.hugo_build.lock
|
|
||||||
|
23
Dockerfile
23
Dockerfile
@ -3,29 +3,23 @@
|
|||||||
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Prepare to cross-compile by always running the build stage in the build platform, not the target platform.
|
FROM golang:1.20.7 as build-env
|
||||||
FROM --platform=linux/amd64 golang:1.21.3 as build-env
|
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
COPY . .
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
|
|
||||||
ARG KUBE_GIT_VERSION
|
ARG KUBE_GIT_VERSION
|
||||||
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
||||||
|
|
||||||
# These will be set by buildkit automatically, e.g. TARGETOS set to "linux" and TARGETARCH set to "amd64" or "arm64".
|
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
||||||
# Useful for building multi-arch container images.
|
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
||||||
ARG TARGETOS
|
# can be re-used between image builds.
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
# Build the statically linked (CGO_ENABLED=0) binary.
|
|
||||||
# Mount source, build cache, and module cache for performance reasons.
|
|
||||||
# See https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
|
|
||||||
RUN \
|
RUN \
|
||||||
--mount=target=. \
|
|
||||||
--mount=type=cache,target=/cache/gocache \
|
--mount=type=cache,target=/cache/gocache \
|
||||||
--mount=type=cache,target=/cache/gomodcache \
|
--mount=type=cache,target=/cache/gomodcache \
|
||||||
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH && \
|
mkdir out && \
|
||||||
|
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=linux GOARCH=amd64 && \
|
||||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/... && \
|
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/... && \
|
||||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/... && \
|
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/... && \
|
||||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
||||||
@ -33,9 +27,6 @@ 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.
|
||||||
# Note that we are not using --platform here, so it will choose the base image for the target platform, not the build platform.
|
|
||||||
# By using "distroless/static" instead of "distroless/static-debianXX" we can float on the latest stable version of debian.
|
|
||||||
# See https://github.com/GoogleContainerTools/distroless#base-operating-system
|
|
||||||
FROM gcr.io/distroless/static:nonroot@sha256:2a9e2b4fa771d31fe3346a873be845bfc2159695b9f90ca08e950497006ccc2e
|
FROM gcr.io/distroless/static:nonroot@sha256:2a9e2b4fa771d31fe3346a873be845bfc2159695b9f90ca08e950497006ccc2e
|
||||||
|
|
||||||
# Copy the server binary from the build-env stage.
|
# Copy the server binary from the build-env stage.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a JWT authenticator.
|
// Spec for configuring a JWT authenticator.
|
||||||
|
75
apis/concierge/authentication/v1alpha1/types_meta.go.tmpl
Normal file
75
apis/concierge/authentication/v1alpha1/types_meta.go.tmpl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a webhook authenticator.
|
// Spec for configuring a webhook authenticator.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,17 +8,14 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FederationDomainPhase string
|
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||||
|
type FederationDomainStatusCondition string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FederationDomainPhasePending is the default phase for newly-created FederationDomain resources.
|
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||||
FederationDomainPhasePending FederationDomainPhase = "Pending"
|
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||||
|
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||||
// FederationDomainPhaseReady is the phase for an FederationDomain resource in a healthy state.
|
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||||
FederationDomainPhaseReady FederationDomainPhase = "Ready"
|
|
||||||
|
|
||||||
// FederationDomainPhaseError is the phase for an FederationDomain in an unhealthy state.
|
|
||||||
FederationDomainPhaseError FederationDomainPhase = "Error"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||||
@ -45,157 +42,6 @@ type FederationDomainTLSSpec struct {
|
|||||||
SecretName string `json:"secretName,omitempty"`
|
SecretName string `json:"secretName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainTransformsConstant defines a constant variable and its value which will be made available to
|
|
||||||
// the transform expressions. This is a union type, and Type is the discriminator field.
|
|
||||||
type FederationDomainTransformsConstant struct {
|
|
||||||
// Name determines the name of the constant. It must be a valid identifier name.
|
|
||||||
// +kubebuilder:validation:Pattern=`^[a-zA-Z][_a-zA-Z0-9]*$`
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
// +kubebuilder:validation:MaxLength=64
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Type determines the type of the constant, and indicates which other field should be non-empty.
|
|
||||||
// +kubebuilder:validation:Enum=string;stringList
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// StringValue should hold the value when Type is "string", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringValue string `json:"stringValue,omitempty"`
|
|
||||||
|
|
||||||
// StringListValue should hold the value when Type is "stringList", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringListValue []string `json:"stringListValue,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExpression defines a transform expression.
|
|
||||||
type FederationDomainTransformsExpression struct {
|
|
||||||
// Type determines the type of the expression. It must be one of the supported types.
|
|
||||||
// +kubebuilder:validation:Enum=policy/v1;username/v1;groups/v1
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// Expression is a CEL expression that will be evaluated based on the Type during an authentication.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Expression string `json:"expression"`
|
|
||||||
|
|
||||||
// Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects
|
|
||||||
// an authentication attempt. When empty, a default message will be used.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExample defines a transform example.
|
|
||||||
type FederationDomainTransformsExample struct {
|
|
||||||
// Username is the input username.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Username string `json:"username"`
|
|
||||||
|
|
||||||
// Groups is the input list of group names.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Expects is the expected output of the entire sequence of transforms when they are run against the
|
|
||||||
// input Username and Groups.
|
|
||||||
Expects FederationDomainTransformsExampleExpects `json:"expects"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExampleExpects defines the expected result for a transforms example.
|
|
||||||
type FederationDomainTransformsExampleExpects struct {
|
|
||||||
// Username is the expected username after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
|
|
||||||
// Groups is the expected list of group names after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression
|
|
||||||
// after the transformations have been applied. True means that it is expected that the authentication would be
|
|
||||||
// rejected. The default value of false means that it is expected that the authentication would not be rejected
|
|
||||||
// by any policy expression.
|
|
||||||
// +optional
|
|
||||||
Rejected bool `json:"rejected,omitempty"`
|
|
||||||
|
|
||||||
// Message is the expected error message of the transforms. When Rejected is true, then Message is the expected
|
|
||||||
// message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank,
|
|
||||||
// then Message will be treated as the default error message for authentication attempts which are rejected by a
|
|
||||||
// policy. When Rejected is false, then Message is the expected error message for some other non-policy
|
|
||||||
// transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransforms defines identity transformations for an identity provider's usage on a FederationDomain.
|
|
||||||
type FederationDomainTransforms struct {
|
|
||||||
// Constants defines constant variables and their values which will be made available to the transform expressions.
|
|
||||||
// +patchMergeKey=name
|
|
||||||
// +patchStrategy=merge
|
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=name
|
|
||||||
// +optional
|
|
||||||
Constants []FederationDomainTransformsConstant `json:"constants,omitempty"`
|
|
||||||
|
|
||||||
// Expressions are an optional list of transforms and policies to be executed in the order given during every
|
|
||||||
// authentication attempt, including during every session refresh.
|
|
||||||
// Each is a CEL expression. It may use the basic CEL language as defined in
|
|
||||||
// https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in
|
|
||||||
// https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
//
|
|
||||||
// The username and groups extracted from the identity provider, and the constants defined in this CR, are
|
|
||||||
// available as variables in all expressions. The username is provided via a variable called `username` and
|
|
||||||
// the list of group names is provided via a variable called `groups` (which may be an empty list).
|
|
||||||
// Each user-provided constants is provided via a variable named `strConst.varName` for string constants
|
|
||||||
// and `strListConst.varName` for string list constants.
|
|
||||||
//
|
|
||||||
// The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1.
|
|
||||||
// Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated
|
|
||||||
// and the authentication attempt is rejected.
|
|
||||||
// Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the
|
|
||||||
// username or group names.
|
|
||||||
// Each username/v1 transform must return the new username (a string), which can be the same as the old username.
|
|
||||||
// Transformations of type username/v1 do not return group names, and therefore cannot change the group names.
|
|
||||||
// Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old
|
|
||||||
// groups list.
|
|
||||||
// Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames.
|
|
||||||
// After each expression, the new (potentially changed) username or groups get passed to the following expression.
|
|
||||||
//
|
|
||||||
// Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain.
|
|
||||||
// During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the
|
|
||||||
// authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username
|
|
||||||
// and group names have been decided for that authentication attempt.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
Expressions []FederationDomainTransformsExpression `json:"expressions,omitempty"`
|
|
||||||
|
|
||||||
// Examples can optionally be used to ensure that the sequence of transformation expressions are working as
|
|
||||||
// expected. Examples define sample input identities which are then run through the expression list, and the
|
|
||||||
// results are compared to the expected results. If any example in this list fails, then this
|
|
||||||
// identity provider will not be available for use within this FederationDomain, and the error(s) will be
|
|
||||||
// added to the FederationDomain status. This can be used to help guard against programming mistakes in the
|
|
||||||
// expressions, and also act as living documentation for other administrators to better understand the expressions.
|
|
||||||
// +optional
|
|
||||||
Examples []FederationDomainTransformsExample `json:"examples,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainIdentityProvider describes how an identity provider is made available in this FederationDomain.
|
|
||||||
type FederationDomainIdentityProvider struct {
|
|
||||||
// DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the
|
|
||||||
// kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a
|
|
||||||
// disruptive change for those users.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
|
|
||||||
// ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required.
|
|
||||||
// If the reference cannot be resolved then the identity provider will not be made available.
|
|
||||||
// Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider,
|
|
||||||
// LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
|
||||||
ObjectRef corev1.TypedLocalObjectReference `json:"objectRef"`
|
|
||||||
|
|
||||||
// Transforms is an optional way to specify transformations to be applied during user authentication and
|
|
||||||
// session refresh.
|
|
||||||
// +optional
|
|
||||||
Transforms FederationDomainTransforms `json:"transforms,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||||
type FederationDomainSpec struct {
|
type FederationDomainSpec struct {
|
||||||
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||||
@ -209,35 +55,9 @@ type FederationDomainSpec struct {
|
|||||||
// +kubebuilder:validation:MinLength=1
|
// +kubebuilder:validation:MinLength=1
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
|
|
||||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||||
// +optional
|
// +optional
|
||||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||||
|
|
||||||
// IdentityProviders is the list of identity providers available for use by this FederationDomain.
|
|
||||||
//
|
|
||||||
// An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server,
|
|
||||||
// how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to
|
|
||||||
// extract a normalized user identity. Normalized user identities include a username and a list of group names.
|
|
||||||
// In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which
|
|
||||||
// belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations
|
|
||||||
// on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid
|
|
||||||
// accidental conflicts when multiple identity providers have different users with the same username (e.g.
|
|
||||||
// "idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication
|
|
||||||
// rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow
|
|
||||||
// the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could
|
|
||||||
// disallow the authentication unless the user belongs to a specific group in the identity provider.
|
|
||||||
//
|
|
||||||
// For backwards compatibility with versions of Pinniped which predate support for multiple identity providers,
|
|
||||||
// an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which
|
|
||||||
// exist in the same namespace, but also to reject all authentication requests when there is more than one identity
|
|
||||||
// provider currently defined. In this backwards compatibility mode, the name of the identity provider resource
|
|
||||||
// (e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this
|
|
||||||
// FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of
|
|
||||||
// relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead
|
|
||||||
// explicitly list the identity provider using this IdentityProviders field.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
IdentityProviders []FederationDomainIdentityProvider `json:"identityProviders,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||||
@ -266,17 +86,20 @@ type FederationDomainSecrets struct {
|
|||||||
|
|
||||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||||
type FederationDomainStatus struct {
|
type FederationDomainStatus struct {
|
||||||
// Phase summarizes the overall status of the FederationDomain.
|
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||||
// +kubebuilder:default=Pending
|
// represent success or failure.
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +optional
|
||||||
Phase FederationDomainPhase `json:"phase,omitempty"`
|
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||||
|
|
||||||
// Conditions represent the observations of an FederationDomain's current state.
|
// Message provides human-readable details about the Status.
|
||||||
// +patchMergeKey=type
|
// +optional
|
||||||
// +patchStrategy=merge
|
Message string `json:"message,omitempty"`
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=type
|
// LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
// around some undesirable behavior with respect to the empty metav1.Time value (see
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
|
// +optional
|
||||||
|
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||||
|
|
||||||
// Secrets contains information about this OIDC Provider's secrets.
|
// Secrets contains information about this OIDC Provider's secrets.
|
||||||
// +optional
|
// +optional
|
||||||
@ -288,7 +111,7 @@ type FederationDomainStatus struct {
|
|||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
// +kubebuilder:resource:categories=pinniped
|
// +kubebuilder:resource:categories=pinniped
|
||||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
type FederationDomain struct {
|
type FederationDomain struct {
|
||||||
|
75
apis/supervisor/config/v1alpha1/types_meta.go.tmpl
Normal file
75
apis/supervisor/config/v1alpha1/types_meta.go.tmpl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|||||||
type OIDCClientPhase string
|
type OIDCClientPhase string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
PhasePending OIDCClientPhase = "Pending"
|
||||||
|
|
||||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
PhaseReady OIDCClientPhase = "Ready"
|
||||||
|
|
||||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
PhaseError OIDCClientPhase = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||||
@ -85,7 +85,7 @@ type OIDCClientStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -32,7 +32,7 @@ type ActiveDirectoryIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActiveDirectoryIdentityProviderBind struct {
|
type ActiveDirectoryIdentityProviderBind struct {
|
||||||
|
@ -32,7 +32,7 @@ type LDAPIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LDAPIdentityProviderBind struct {
|
type LDAPIdentityProviderBind struct {
|
||||||
|
75
apis/supervisor/idp/v1alpha1/types_meta.go.tmpl
Normal file
75
apis/supervisor/idp/v1alpha1/types_meta.go.tmpl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -32,7 +32,7 @@ type OIDCIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConciergeModeFlag(t *testing.T) {
|
func TestConciergeModeFlag(t *testing.T) {
|
||||||
@ -51,7 +52,7 @@ func TestConciergeModeFlag(t *testing.T) {
|
|||||||
func TestCABundleFlag(t *testing.T) {
|
func TestCABundleFlag(t *testing.T) {
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
emptyFilePath := filepath.Join(tmpdir, "empty")
|
emptyFilePath := filepath.Join(tmpdir, "empty")
|
||||||
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
||||||
|
|
||||||
|
@ -96,7 +96,6 @@ type getKubeconfigParams struct {
|
|||||||
credentialCachePath string
|
credentialCachePath string
|
||||||
credentialCachePathSet bool
|
credentialCachePathSet bool
|
||||||
installHint string
|
installHint string
|
||||||
pinnipedCliPath string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type discoveryResponseScopesSupported struct {
|
type discoveryResponseScopesSupported struct {
|
||||||
@ -152,16 +151,14 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
|||||||
f.StringVarP(&flags.outputPath, "output", "o", "", "Output file path (default: stdout)")
|
f.StringVarP(&flags.outputPath, "output", "o", "", "Output file path (default: stdout)")
|
||||||
f.StringVar(&flags.generatedNameSuffix, "generated-name-suffix", "-pinniped", "Suffix to append to generated cluster, context, user kubeconfig entries")
|
f.StringVar(&flags.generatedNameSuffix, "generated-name-suffix", "-pinniped", "Suffix to append to generated cluster, context, user kubeconfig entries")
|
||||||
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
|
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
|
||||||
f.StringVar(&flags.pinnipedCliPath, "pinniped-cli-path", "", "Full path or executable name for the Pinniped CLI binary to be embedded in the resulting kubeconfig output (e.g. 'pinniped') (default: full path of the binary used to execute this command)")
|
|
||||||
f.StringVar(&flags.installHint, "install-hint", "The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli for more details", "This text is shown to the user when the pinniped CLI is not installed.")
|
f.StringVar(&flags.installHint, "install-hint", "The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli for more details", "This text is shown to the user when the pinniped CLI is not installed.")
|
||||||
|
mustMarkHidden(cmd, "oidc-debug-session-cache")
|
||||||
|
|
||||||
mustMarkHidden(cmd,
|
// --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
||||||
"oidc-debug-session-cache",
|
mustMarkHidden(cmd, "oidc-skip-listen")
|
||||||
"oidc-skip-listen", // --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
|
||||||
"concierge-namespace",
|
|
||||||
)
|
|
||||||
|
|
||||||
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
||||||
|
mustMarkHidden(cmd, "concierge-namespace")
|
||||||
|
|
||||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
if flags.outputPath != "" {
|
if flags.outputPath != "" {
|
||||||
@ -271,12 +268,7 @@ func newExecConfig(deps kubeconfigDeps, flags getKubeconfigParams) (*clientcmdap
|
|||||||
|
|
||||||
execConfig.InstallHint = flags.installHint
|
execConfig.InstallHint = flags.installHint
|
||||||
var err error
|
var err error
|
||||||
execConfig.Command, err = func() (string, error) {
|
execConfig.Command, err = deps.getPathToSelf()
|
||||||
if flags.pinnipedCliPath != "" {
|
|
||||||
return flags.pinnipedCliPath, nil
|
|
||||||
}
|
|
||||||
return deps.getPathToSelf()
|
|
||||||
}()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
func TestGetKubeconfig(t *testing.T) {
|
func TestGetKubeconfig(t *testing.T) {
|
||||||
testOIDCCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testOIDCCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
testOIDCCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testOIDCCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, os.WriteFile(testOIDCCABundlePath, testOIDCCA.Bundle(), 0600))
|
require.NoError(t, os.WriteFile(testOIDCCABundlePath, testOIDCCA.Bundle(), 0600))
|
||||||
|
|
||||||
@ -147,7 +147,6 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
--oidc-session-cache string Path to OpenID Connect session cache file
|
--oidc-session-cache string Path to OpenID Connect session cache file
|
||||||
--oidc-skip-browser During OpenID Connect login, skip opening the browser (just print the URL)
|
--oidc-skip-browser During OpenID Connect login, skip opening the browser (just print the URL)
|
||||||
-o, --output string Output file path (default: stdout)
|
-o, --output string Output file path (default: stdout)
|
||||||
--pinniped-cli-path string Full path or executable name for the Pinniped CLI binary to be embedded in the resulting kubeconfig output (e.g. 'pinniped') (default: full path of the binary used to execute this command)
|
|
||||||
--skip-validation Skip final validation of the kubeconfig (default: false)
|
--skip-validation Skip final validation of the kubeconfig (default: false)
|
||||||
--static-token string Instead of doing an OIDC-based login, specify a static token
|
--static-token string Instead of doing an OIDC-based login, specify a static token
|
||||||
--static-token-env string Instead of doing an OIDC-based login, read a static token from the environment
|
--static-token-env string Instead of doing an OIDC-based login, read a static token from the environment
|
||||||
@ -1584,6 +1583,7 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
name: "autodetect nothing, set a bunch of options",
|
name: "autodetect nothing, set a bunch of options",
|
||||||
args: func(issuerCABundle string, issuerURL string) []string {
|
args: func(issuerCABundle string, issuerURL string) []string {
|
||||||
f := testutil.WriteStringToTempFile(t, "testca-*.pem", issuerCABundle)
|
f := testutil.WriteStringToTempFile(t, "testca-*.pem", issuerCABundle)
|
||||||
@ -1607,7 +1607,6 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
"--skip-validation",
|
"--skip-validation",
|
||||||
"--generated-name-suffix", "-sso",
|
"--generated-name-suffix", "-sso",
|
||||||
"--credential-cache", "/path/to/cache/dir/credentials.yaml",
|
"--credential-cache", "/path/to/cache/dir/credentials.yaml",
|
||||||
"--pinniped-cli-path", "/some/path/to/command-exe",
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||||
@ -1659,7 +1658,7 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
- --session-cache=/path/to/cache/dir/sessions.yaml
|
- --session-cache=/path/to/cache/dir/sessions.yaml
|
||||||
- --debug-session-cache
|
- --debug-session-cache
|
||||||
- --request-audience=test-audience
|
- --request-audience=test-audience
|
||||||
command: /some/path/to/command-exe
|
command: '.../path/to/pinniped'
|
||||||
env: []
|
env: []
|
||||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||||
for more details
|
for more details
|
||||||
|
@ -164,7 +164,7 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
|||||||
// Initialize the login handler.
|
// Initialize the login handler.
|
||||||
opts := []oidcclient.Option{
|
opts := []oidcclient.Option{
|
||||||
oidcclient.WithContext(cmd.Context()),
|
oidcclient.WithContext(cmd.Context()),
|
||||||
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
||||||
oidcclient.WithScopes(flags.scopes),
|
oidcclient.WithScopes(flags.scopes),
|
||||||
oidcclient.WithSessionCache(sessionCache),
|
oidcclient.WithSessionCache(sessionCache),
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient"
|
"go.pinniped.dev/pkg/oidcclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||||
@ -33,7 +34,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
|
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||||
|
|
||||||
@ -512,7 +513,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
"--concierge-endpoint", "https://127.0.0.1:1234/",
|
"--concierge-endpoint", "https://127.0.0.1:1234/",
|
||||||
"--concierge-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
|
"--concierge-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
|
||||||
"--concierge-api-group-suffix", "some.suffix.com",
|
"--concierge-api-group-suffix", "some.suffix.com",
|
||||||
"--credential-cache", t.TempDir() + "/credentials.yaml", // must specify --credential-cache or else the cache file on disk causes test pollution
|
"--credential-cache", testutil.TempDir(t) + "/credentials.yaml", // must specify --credential-cache or else the cache file on disk causes test pollution
|
||||||
"--upstream-identity-provider-name", "some-upstream-name",
|
"--upstream-identity-provider-name", "some-upstream-name",
|
||||||
"--upstream-identity-provider-type", "ldap",
|
"--upstream-identity-provider-type", "ldap",
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
|||||||
|
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -96,15 +97,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -173,3 +168,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -69,15 +70,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -146,3 +141,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: credentialissuers.config.concierge.pinniped.dev
|
name: credentialissuers.config.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.concierge.pinniped.dev
|
group: config.concierge.pinniped.dev
|
||||||
@ -255,3 +256,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -134,6 +134,8 @@ spec:
|
|||||||
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||||
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
||||||
_: #@ template.replace(deploymentPodLabel())
|
_: #@ template.replace(deploymentPodLabel())
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: #@ data.values.run_as_user
|
runAsUser: #@ data.values.run_as_user
|
||||||
@ -245,14 +247,9 @@ spec:
|
|||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
- key: kubernetes.io/arch
|
#! "system-cluster-critical" cannot be used outside the kube-system namespace until Kubernetes >= 1.17,
|
||||||
effect: NoSchedule
|
#! so we skip setting this for now (see https://github.com/kubernetes/kubernetes/issues/60596).
|
||||||
operator: Equal
|
#!priorityClassName: system-cluster-critical
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
#! This will help make sure our multiple pods run on different nodes, making
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
#! our deployment "more" "HA".
|
#! our deployment "more" "HA".
|
||||||
affinity:
|
affinity:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -76,15 +76,6 @@ spec:
|
|||||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: "RuntimeDefault"
|
type: "RuntimeDefault"
|
||||||
tolerations:
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: federationdomains.config.supervisor.pinniped.dev
|
name: federationdomains.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -20,7 +21,7 @@ spec:
|
|||||||
- jsonPath: .spec.issuer
|
- jsonPath: .spec.issuer
|
||||||
name: Issuer
|
name: Issuer
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .status.phase
|
- jsonPath: .status.status
|
||||||
name: Status
|
name: Status
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .metadata.creationTimestamp
|
- jsonPath: .metadata.creationTimestamp
|
||||||
@ -46,264 +47,6 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
description: Spec of the OIDC provider.
|
description: Spec of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
identityProviders:
|
|
||||||
description: "IdentityProviders is the list of identity providers
|
|
||||||
available for use by this FederationDomain. \n An identity provider
|
|
||||||
CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes
|
|
||||||
how to connect to a server, how to talk in a specific protocol for
|
|
||||||
authentication, and how to use the schema of that server/protocol
|
|
||||||
to extract a normalized user identity. Normalized user identities
|
|
||||||
include a username and a list of group names. In contrast, IdentityProviders
|
|
||||||
describes how to use that normalized identity in those Kubernetes
|
|
||||||
clusters which belong to this FederationDomain. Each entry in IdentityProviders
|
|
||||||
can be configured with arbitrary transformations on that normalized
|
|
||||||
identity. For example, a transformation can add a prefix to all
|
|
||||||
usernames to help avoid accidental conflicts when multiple identity
|
|
||||||
providers have different users with the same username (e.g. \"idp1:ryan\"
|
|
||||||
versus \"idp2:ryan\"). Each entry in IdentityProviders can also
|
|
||||||
implement arbitrary authentication rejection policies. Even though
|
|
||||||
a user was able to authenticate with the identity provider, a policy
|
|
||||||
can disallow the authentication to the Kubernetes clusters that
|
|
||||||
belong to this FederationDomain. For example, a policy could disallow
|
|
||||||
the authentication unless the user belongs to a specific group in
|
|
||||||
the identity provider. \n For backwards compatibility with versions
|
|
||||||
of Pinniped which predate support for multiple identity providers,
|
|
||||||
an empty IdentityProviders list will cause the FederationDomain
|
|
||||||
to use all available identity providers which exist in the same
|
|
||||||
namespace, but also to reject all authentication requests when there
|
|
||||||
is more than one identity provider currently defined. In this backwards
|
|
||||||
compatibility mode, the name of the identity provider resource (e.g.
|
|
||||||
the Name of an OIDCIdentityProvider resource) will be used as the
|
|
||||||
name of the identity provider in this FederationDomain. This mode
|
|
||||||
is provided to make upgrading from older versions easier. However,
|
|
||||||
instead of relying on this backwards compatibility mode, please
|
|
||||||
consider this mode to be deprecated and please instead explicitly
|
|
||||||
list the identity provider using this IdentityProviders field."
|
|
||||||
items:
|
|
||||||
description: FederationDomainIdentityProvider describes how an identity
|
|
||||||
provider is made available in this FederationDomain.
|
|
||||||
properties:
|
|
||||||
displayName:
|
|
||||||
description: DisplayName is the name of this identity provider
|
|
||||||
as it will appear to clients. This name ends up in the kubeconfig
|
|
||||||
of end users, so changing the name of an identity provider
|
|
||||||
that is in use by end users will be a disruptive change for
|
|
||||||
those users.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
objectRef:
|
|
||||||
description: ObjectRef is a reference to a Pinniped identity
|
|
||||||
provider resource. A valid reference is required. If the reference
|
|
||||||
cannot be resolved then the identity provider will not be
|
|
||||||
made available. Must refer to a resource of one of the Pinniped
|
|
||||||
identity provider types, e.g. OIDCIdentityProvider, LDAPIdentityProvider,
|
|
||||||
ActiveDirectoryIdentityProvider.
|
|
||||||
properties:
|
|
||||||
apiGroup:
|
|
||||||
description: APIGroup is the group for the resource being
|
|
||||||
referenced. If APIGroup is not specified, the specified
|
|
||||||
Kind must be in the core API group. For any other third-party
|
|
||||||
types, APIGroup is required.
|
|
||||||
type: string
|
|
||||||
kind:
|
|
||||||
description: Kind is the type of resource being referenced
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
description: Name is the name of resource being referenced
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
transforms:
|
|
||||||
description: Transforms is an optional way to specify transformations
|
|
||||||
to be applied during user authentication and session refresh.
|
|
||||||
properties:
|
|
||||||
constants:
|
|
||||||
description: Constants defines constant variables and their
|
|
||||||
values which will be made available to the transform expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsConstant defines
|
|
||||||
a constant variable and its value which will be made
|
|
||||||
available to the transform expressions. This is a union
|
|
||||||
type, and Type is the discriminator field.
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name determines the name of the constant.
|
|
||||||
It must be a valid identifier name.
|
|
||||||
maxLength: 64
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[a-zA-Z][_a-zA-Z0-9]*$
|
|
||||||
type: string
|
|
||||||
stringListValue:
|
|
||||||
description: StringListValue should hold the value
|
|
||||||
when Type is "stringList", and is otherwise ignored.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
stringValue:
|
|
||||||
description: StringValue should hold the value when
|
|
||||||
Type is "string", and is otherwise ignored.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the constant,
|
|
||||||
and indicates which other field should be non-empty.
|
|
||||||
enum:
|
|
||||||
- string
|
|
||||||
- stringList
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- name
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
examples:
|
|
||||||
description: Examples can optionally be used to ensure that
|
|
||||||
the sequence of transformation expressions are working
|
|
||||||
as expected. Examples define sample input identities which
|
|
||||||
are then run through the expression list, and the results
|
|
||||||
are compared to the expected results. If any example in
|
|
||||||
this list fails, then this identity provider will not
|
|
||||||
be available for use within this FederationDomain, and
|
|
||||||
the error(s) will be added to the FederationDomain status.
|
|
||||||
This can be used to help guard against programming mistakes
|
|
||||||
in the expressions, and also act as living documentation
|
|
||||||
for other administrators to better understand the expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExample defines
|
|
||||||
a transform example.
|
|
||||||
properties:
|
|
||||||
expects:
|
|
||||||
description: Expects is the expected output of the
|
|
||||||
entire sequence of transforms when they are run
|
|
||||||
against the input Username and Groups.
|
|
||||||
properties:
|
|
||||||
groups:
|
|
||||||
description: Groups is the expected list of group
|
|
||||||
names after the transformations have been applied.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
message:
|
|
||||||
description: Message is the expected error message
|
|
||||||
of the transforms. When Rejected is true, then
|
|
||||||
Message is the expected message for the policy
|
|
||||||
which rejected the authentication attempt. When
|
|
||||||
Rejected is true and Message is blank, then
|
|
||||||
Message will be treated as the default error
|
|
||||||
message for authentication attempts which are
|
|
||||||
rejected by a policy. When Rejected is false,
|
|
||||||
then Message is the expected error message for
|
|
||||||
some other non-policy transformation error,
|
|
||||||
such as a runtime error. When Rejected is false,
|
|
||||||
there is no default expected Message.
|
|
||||||
type: string
|
|
||||||
rejected:
|
|
||||||
description: Rejected is a boolean that indicates
|
|
||||||
whether authentication is expected to be rejected
|
|
||||||
by a policy expression after the transformations
|
|
||||||
have been applied. True means that it is expected
|
|
||||||
that the authentication would be rejected. The
|
|
||||||
default value of false means that it is expected
|
|
||||||
that the authentication would not be rejected
|
|
||||||
by any policy expression.
|
|
||||||
type: boolean
|
|
||||||
username:
|
|
||||||
description: Username is the expected username
|
|
||||||
after the transformations have been applied.
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
groups:
|
|
||||||
description: Groups is the input list of group names.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
username:
|
|
||||||
description: Username is the input username.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expects
|
|
||||||
- username
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
expressions:
|
|
||||||
description: "Expressions are an optional list of transforms
|
|
||||||
and policies to be executed in the order given during
|
|
||||||
every authentication attempt, including during every session
|
|
||||||
refresh. Each is a CEL expression. It may use the basic
|
|
||||||
CEL language as defined in https://github.com/google/cel-spec/blob/master/doc/langdef.md
|
|
||||||
plus the CEL string extensions defined in https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
\n The username and groups extracted from the identity
|
|
||||||
provider, and the constants defined in this CR, are available
|
|
||||||
as variables in all expressions. The username is provided
|
|
||||||
via a variable called `username` and the list of group
|
|
||||||
names is provided via a variable called `groups` (which
|
|
||||||
may be an empty list). Each user-provided constants is
|
|
||||||
provided via a variable named `strConst.varName` for string
|
|
||||||
constants and `strListConst.varName` for string list constants.
|
|
||||||
\n The only allowed types for expressions are currently
|
|
||||||
policy/v1, username/v1, and groups/v1. Each policy/v1
|
|
||||||
must return a boolean, and when it returns false, no more
|
|
||||||
expressions from the list are evaluated and the authentication
|
|
||||||
attempt is rejected. Transformations of type policy/v1
|
|
||||||
do not return usernames or group names, and therefore
|
|
||||||
cannot change the username or group names. Each username/v1
|
|
||||||
transform must return the new username (a string), which
|
|
||||||
can be the same as the old username. Transformations of
|
|
||||||
type username/v1 do not return group names, and therefore
|
|
||||||
cannot change the group names. Each groups/v1 transform
|
|
||||||
must return the new groups list (list of strings), which
|
|
||||||
can be the same as the old groups list. Transformations
|
|
||||||
of type groups/v1 do not return usernames, and therefore
|
|
||||||
cannot change the usernames. After each expression, the
|
|
||||||
new (potentially changed) username or groups get passed
|
|
||||||
to the following expression. \n Any compilation or static
|
|
||||||
type-checking failure of any expression will cause an
|
|
||||||
error status on the FederationDomain. During an authentication
|
|
||||||
attempt, any unexpected runtime evaluation errors (e.g.
|
|
||||||
division by zero) cause the authentication attempt to
|
|
||||||
fail. When all expressions evaluate successfully, then
|
|
||||||
the (potentially changed) username and group names have
|
|
||||||
been decided for that authentication attempt."
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExpression defines
|
|
||||||
a transform expression.
|
|
||||||
properties:
|
|
||||||
expression:
|
|
||||||
description: Expression is a CEL expression that will
|
|
||||||
be evaluated based on the Type during an authentication.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: Message is only used when Type is policy/v1.
|
|
||||||
It defines an error message to be used when the
|
|
||||||
policy rejects an authentication attempt. When empty,
|
|
||||||
a default message will be used.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the expression.
|
|
||||||
It must be one of the supported types.
|
|
||||||
enum:
|
|
||||||
- policy/v1
|
|
||||||
- username/v1
|
|
||||||
- groups/v1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expression
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- displayName
|
|
||||||
- objectRef
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
issuer:
|
issuer:
|
||||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||||
Metadata document, as well as the identifier that it will use for
|
Metadata document, as well as the identifier that it will use for
|
||||||
@ -316,8 +59,8 @@ spec:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
type: string
|
type: string
|
||||||
tls:
|
tls:
|
||||||
description: TLS specifies a secret which will contain Transport Layer
|
description: TLS configures how this FederationDomain is served over
|
||||||
Security (TLS) configuration for the FederationDomain.
|
Transport Layer Security (TLS).
|
||||||
properties:
|
properties:
|
||||||
secretName:
|
secretName:
|
||||||
description: "SecretName is an optional name of a Secret in the
|
description: "SecretName is an optional name of a Secret in the
|
||||||
@ -348,86 +91,14 @@ spec:
|
|||||||
status:
|
status:
|
||||||
description: Status of the OIDC provider.
|
description: Status of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
lastUpdateTime:
|
||||||
description: Conditions represent the observations of an FederationDomain's
|
description: LastUpdateTime holds the time at which the Status was
|
||||||
current state.
|
last updated. It is a pointer to get around some undesirable behavior
|
||||||
items:
|
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
description: "Condition contains details for one aspect of the current
|
format: date-time
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type: string
|
||||||
use as an array at the field path .status.conditions. For example,
|
message:
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
description: Message provides human-readable details about the Status.
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
|
||||||
lastTransitionTime:
|
|
||||||
description: lastTransitionTime is the last time the condition
|
|
||||||
transitioned from one status to another. This should be when
|
|
||||||
the underlying condition changed. If that is not known, then
|
|
||||||
using the time when the API field changed is acceptable.
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: message is a human readable message indicating
|
|
||||||
details about the transition. This may be an empty string.
|
|
||||||
maxLength: 32768
|
|
||||||
type: string
|
|
||||||
observedGeneration:
|
|
||||||
description: observedGeneration represents the .metadata.generation
|
|
||||||
that the condition was set based upon. For instance, if .metadata.generation
|
|
||||||
is currently 12, but the .status.conditions[x].observedGeneration
|
|
||||||
is 9, the condition is out of date with respect to the current
|
|
||||||
state of the instance.
|
|
||||||
format: int64
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
reason:
|
|
||||||
description: reason contains a programmatic identifier indicating
|
|
||||||
the reason for the condition's last transition. Producers
|
|
||||||
of specific condition types may define expected values and
|
|
||||||
meanings for this field, and whether the values are considered
|
|
||||||
a guaranteed API. The value should be a CamelCase string.
|
|
||||||
This field may not be empty.
|
|
||||||
maxLength: 1024
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: status of the condition, one of True, False, Unknown.
|
|
||||||
enum:
|
|
||||||
- "True"
|
|
||||||
- "False"
|
|
||||||
- Unknown
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
|
||||||
--- Many .condition.type values are consistent across resources
|
|
||||||
like Available, but because arbitrary conditions can be useful
|
|
||||||
(see .node.status.conditions), the ability to deconflict is
|
|
||||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
|
||||||
maxLength: 316
|
|
||||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- lastTransitionTime
|
|
||||||
- message
|
|
||||||
- reason
|
|
||||||
- status
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- type
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
phase:
|
|
||||||
default: Pending
|
|
||||||
description: Phase summarizes the overall status of the FederationDomain.
|
|
||||||
enum:
|
|
||||||
- Pending
|
|
||||||
- Ready
|
|
||||||
- Error
|
|
||||||
type: string
|
type: string
|
||||||
secrets:
|
secrets:
|
||||||
description: Secrets contains information about this OIDC Provider's
|
description: Secrets contains information about this OIDC Provider's
|
||||||
@ -444,7 +115,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
stateEncryptionKey:
|
stateEncryptionKey:
|
||||||
description: StateSigningKey holds the name of the corev1.Secret
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for encrypting state parameters
|
in which this OIDC Provider's key for encrypting state parameters
|
||||||
@ -455,7 +125,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
stateSigningKey:
|
stateSigningKey:
|
||||||
description: StateSigningKey holds the name of the corev1.Secret
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for signing state parameters
|
in which this OIDC Provider's key for signing state parameters
|
||||||
@ -466,7 +135,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
tokenSigningKey:
|
tokenSigningKey:
|
||||||
description: TokenSigningKey holds the name of the corev1.Secret
|
description: TokenSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for signing tokens is stored.
|
in which this OIDC Provider's key for signing tokens is stored.
|
||||||
@ -476,8 +144,16 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
type: object
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status holds an enum that describes the state of this
|
||||||
|
OIDC Provider. Note that this Status can represent success or failure.
|
||||||
|
enum:
|
||||||
|
- Success
|
||||||
|
- Duplicate
|
||||||
|
- Invalid
|
||||||
|
- SameIssuerHostMustUseSameSecret
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
@ -486,3 +162,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcclients.config.supervisor.pinniped.dev
|
name: oidcclients.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -128,15 +129,9 @@ spec:
|
|||||||
description: conditions represent the observations of an OIDCClient's
|
description: conditions represent the observations of an OIDCClient's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -218,3 +213,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -190,15 +190,6 @@ spec:
|
|||||||
- name: socket
|
- name: socket
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
#@ end
|
#@ end
|
||||||
tolerations:
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
#! This will help make sure our multiple pods run on different nodes, making
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
#! our deployment "more" "HA".
|
#! our deployment "more" "HA".
|
||||||
affinity:
|
affinity:
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -231,15 +232,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -316,3 +311,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -228,15 +229,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -313,3 +308,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -258,15 +259,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -343,3 +338,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
190
deploy_carvel/build.sh
Executable file
190
deploy_carvel/build.sh
Executable file
@ -0,0 +1,190 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e # immediately exit
|
||||||
|
set -u # error if variables undefined
|
||||||
|
set -o pipefail # prevent masking errors in a pipeline
|
||||||
|
# set -x # print all executed commands to terminal
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# NOTES:
|
||||||
|
# - on images
|
||||||
|
# prepare-for-integration-tests.sh simply creates images with a "docker build" call.
|
||||||
|
# then it loads them into the kind cluster via kind load docker-image ....
|
||||||
|
# nothing fancy here.
|
||||||
|
# so, in this script, we ought be able to do the same, build images and imgpkg bundles
|
||||||
|
# and push or load them into a kind cluster.
|
||||||
|
|
||||||
|
# ./prepare-for-integration-tests.sh will pass each of these.
|
||||||
|
# optionally could be user defined.
|
||||||
|
# app is currently ignored, tag is necessary.
|
||||||
|
app="${1:-undefined}"
|
||||||
|
tag="${2:-$(uuidgen)}" # always a new tag to force K8s to reload the image on redeploy
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: final resting place for these images (PackageRepository, Packge) will need to be in the same plate as our regular images:
|
||||||
|
# https://github.com/vmware-tanzu/pinniped/releases/tag/v0.25.0
|
||||||
|
#
|
||||||
|
# from prepare-for-integration-tests.sh
|
||||||
|
# registry="pinniped.local"
|
||||||
|
# repo="test/build"
|
||||||
|
registry="docker.io/benjaminapetersen" # docker.io default
|
||||||
|
repo="pinniped-package-repo"
|
||||||
|
registry_repo="$registry/$repo"
|
||||||
|
tag=$(uuidgen) # always a new tag to force K8s to reload the image on redeploy
|
||||||
|
# can't use this straight from prepare-for-integration-tests.sh as we build several images in this file
|
||||||
|
# registry_repo_tag="${registry_repo}:${tag}"
|
||||||
|
|
||||||
|
PACKAGE_REPO_HOST="${registry_repo}"
|
||||||
|
# TODO: this variable is currently a little quirky as our values.yaml files do NOT pin pinniped to a specific
|
||||||
|
# hard-coded version. Rather, Pinniped's values.yaml allows for a passed-in version.
|
||||||
|
PINNIPED_PACKAGE_VERSION="0.25.0"
|
||||||
|
|
||||||
|
# TODO: should we copy these directories:
|
||||||
|
# - ../deploy/supervisor/config/*
|
||||||
|
# - ../deploy/concierge/config/*
|
||||||
|
# rather than duplicating the files?
|
||||||
|
# in this exercise, I have transformed the values.yaml into a "values schema" so this would have to be
|
||||||
|
# migrated up. There are some incompatibilities here, in that a values schema assesses the type of value
|
||||||
|
# by the default. currently many of the values have no actual default.
|
||||||
|
|
||||||
|
log_note "Cleaning ./package-repository to generate new..."
|
||||||
|
PACKAGE_REPOSITORY_DIR="package-repository"
|
||||||
|
rm -rf "./${PACKAGE_REPOSITORY_DIR}"
|
||||||
|
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/.imgpkg"
|
||||||
|
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/packages/concierge.pinniped.dev"
|
||||||
|
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/packages/supervisor.pinniped.dev"
|
||||||
|
|
||||||
|
|
||||||
|
log_note "Generating PackageRepository and Packages for Pinniped version ${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
declare -a arr=("supervisor" "concierge")
|
||||||
|
for resource_name in "${arr[@]}"
|
||||||
|
do
|
||||||
|
log_note "Generating for ${resource_name}..."
|
||||||
|
RESOURCE_DIR="${SCRIPT_DIR}/${resource_name}"
|
||||||
|
CONFIG_DIR="${RESOURCE_DIR}/config"
|
||||||
|
VALUES_FILE="${CONFIG_DIR}/values.yaml"
|
||||||
|
IMGPKG_IMAGES_FILE="${RESOURCE_DIR}/.imgpkg/images.yml"
|
||||||
|
SCHEMA_OPENAPI_FILE="${RESOURCE_DIR}/schema-openapi.yaml"
|
||||||
|
|
||||||
|
log_note "Generating ${resource_name} imgpkg lock file... ${IMGPKG_IMAGES_FILE}"
|
||||||
|
kbld --file "${CONFIG_DIR}" --imgpkg-lock-output "${IMGPKG_IMAGES_FILE}"
|
||||||
|
|
||||||
|
# generate a schema in each package directory
|
||||||
|
log_note "Generating ${resource_name} OpenAPIv3 Schema... ${SCHEMA_OPENAPI_FILE}"
|
||||||
|
ytt \
|
||||||
|
--file "${VALUES_FILE}" \
|
||||||
|
--data-values-schema-inspect --output openapi-v3 > "${SCHEMA_OPENAPI_FILE}"
|
||||||
|
|
||||||
|
# TODO: this is not the pattern we want.
|
||||||
|
# final resting place should be with our primary Pinniped image at:
|
||||||
|
# - projects.registry.vmware.com/pinniped/pinniped-server:v0.25.0 VMware Harbor
|
||||||
|
# - docker.io/getpinniped/pinniped-server:v0.25.0 DockerHub
|
||||||
|
package_push_repo_location="${PACKAGE_REPO_HOST}-package-${resource_name}:${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
package_repo_pull_location=""
|
||||||
|
log_note "Pushing ${resource_name} package image: ${package_push_repo_location} ..."
|
||||||
|
|
||||||
|
# need to push and then pull in order to kind load it later
|
||||||
|
# imgpkg does not support a "build it locally and keep the image in your docker registry"
|
||||||
|
imgpkg push --bundle "${package_push_repo_location}" --file "${RESOURCE_DIR}"
|
||||||
|
docker pull "${package_push_repo_location}"
|
||||||
|
# TODO:
|
||||||
|
# - match prepare-for-integration-tests.sh
|
||||||
|
# - do we want this in this script, or do we want to split things apart into several scripts?
|
||||||
|
log_note "Loading Package image ${resource_name} into kind from repo ${package_push_repo_location}..."
|
||||||
|
kind load docker-image "${package_push_repo_location}" --name "${resource_name}"
|
||||||
|
|
||||||
|
resource_package_version="${resource_name}.pinniped.dev"
|
||||||
|
PACKAGE_REPO_PACKGE_FILE="${RSOURCE_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/${PINNIPED_PACKAGE_VERSION}.yml"
|
||||||
|
log_note "Generating ${resource_name} PackageRepository yaml..."
|
||||||
|
log_note "generating ${PACKAGE_REPO_PACKGE_FILE}"
|
||||||
|
ytt \
|
||||||
|
--file "${resource_name}/package-template.yml" \
|
||||||
|
--data-value-file openapi="$(pwd)/${resource_name}/schema-openapi.yml" \
|
||||||
|
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||||
|
--data-value package_image_repo="${package_push_repo_location}" > "${PACKAGE_REPO_PACKGE_FILE}"
|
||||||
|
|
||||||
|
PACKAGE_METADATA_FILE="${RSOURCE_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/metadata.yml"
|
||||||
|
log_note "generating ${PACKAGE_METADATA_FILE}"
|
||||||
|
ytt \
|
||||||
|
--file "${resource_name}/metadata.yml" \
|
||||||
|
--data-value-file openapi="$(pwd)/${resource_name}/schema-openapi.yml" \
|
||||||
|
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||||
|
--data-value package_image_repo="${package_push_repo_location}" > "${PACKAGE_METADATA_FILE}"
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
log_note "Generating Pinniped PackageRepository..."
|
||||||
|
log_note "Generating ${RESOURCE_DIR}/${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||||
|
kbld --file "${RESOURCE_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/" --imgpkg-lock-output "${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||||
|
package_repository_push_repo_location="${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
log_note "Pushing Pinniped package repository image: ${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}..."
|
||||||
|
imgpkg push --bundle "${package_repository_push_repo_location}" --file "./${PACKAGE_REPOSITORY_DIR}"
|
||||||
|
docker pull "${package_repository_push_repo_location}"
|
||||||
|
|
||||||
|
# handy for a quick debug
|
||||||
|
# log_note "Validating imgpkg package bundle contents..."
|
||||||
|
# imgpkg pull --bundle "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}" --output "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
# ls -la "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
|
||||||
|
|
||||||
|
log_note "Generating PackageRepository yaml file..."
|
||||||
|
PINNIPED_PACKGE_REPOSITORY_NAME="pinniped-package-repository"
|
||||||
|
PINNIPED_PACKGE_REPOSITORY_FILE="packagerepository.${PINNIPED_PACKAGE_VERSION}.yml"
|
||||||
|
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# - match prepare-for-integration-tests.sh
|
||||||
|
# - do we want this in this script, or do we want to split things apart into several scripts?
|
||||||
|
log_note "Loading PackageRepository PINNIPED_PACKGE_REPOSITORY_NAME into kind from repo ${package_repository_push_repo_location}..."
|
||||||
|
kind load docker-image "${package_repository_push_repo_location}" --name "${PINNIPED_PACKGE_REPOSITORY_NAME}"
|
||||||
|
|
||||||
|
|
||||||
|
echo -n "" > "${PINNIPED_PACKGE_REPOSITORY_FILE}"
|
||||||
|
|
||||||
|
cat <<EOT >> "${PINNIPED_PACKGE_REPOSITORY_FILE}"
|
||||||
|
---
|
||||||
|
apiVersion: packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageRepository
|
||||||
|
metadata:
|
||||||
|
name: "${PINNIPED_PACKGE_REPOSITORY_NAME}"
|
||||||
|
spec:
|
||||||
|
fetch:
|
||||||
|
imgpkgBundle:
|
||||||
|
image: "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
EOT
|
||||||
|
|
||||||
|
log_note "To deploy the PackageRepository, run 'kapp deploy --app pinniped-repo --file ${PINNIPED_PACKGE_REPOSITORY_FILE}'"
|
||||||
|
log_note "Or use the sibling deploy.sh script"
|
3
deploy_carvel/concierge/.imgpkg/images.yml
Normal file
3
deploy_carvel/concierge/.imgpkg/images.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
apiVersion: imgpkg.carvel.dev/v1alpha1
|
||||||
|
kind: ImagesLock
|
23
deploy_carvel/concierge/build.yaml
Normal file
23
deploy_carvel/concierge/build.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
---
|
||||||
|
apiVersion: kbld.k14s.io/v1alpha1
|
||||||
|
kind: Config
|
||||||
|
minimumRequiredVersion: 0.31.0 #! minimum version of kbld. We probably don't need to specify.
|
||||||
|
overrides:
|
||||||
|
#! TODO: in the pinniped yamls, this is provided by values.yaml, not declared in the deployment.
|
||||||
|
#! we should assess if we want to leave it there or move it to this form of configuration.
|
||||||
|
- image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
newImage: #@ data.values.image_repo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#! I don't think we need any of these (until we need them 😊). IE, don't use prematurely.
|
||||||
|
#! searchRules: ... # for searching input files to find container images
|
||||||
|
#! overrides: ... # overrides to apply to container images before resolving or building
|
||||||
|
#! sources: ... # source/content of a container image
|
||||||
|
#! destinations: ... # where to push built images
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#! source: TODO: we may need this at least to specify that we want kbld to build
|
||||||
|
#! a set of container images that are found in our package config yaml files.
|
3
deploy_carvel/concierge/config/README.md
Normal file
3
deploy_carvel/concierge/config/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Pinniped Concierge Deployment
|
||||||
|
|
||||||
|
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-concierge/).
|
@ -0,0 +1,176 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: authentication.concierge.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
- pinniped-authenticator
|
||||||
|
- pinniped-authenticators
|
||||||
|
kind: JWTAuthenticator
|
||||||
|
listKind: JWTAuthenticatorList
|
||||||
|
plural: jwtauthenticators
|
||||||
|
singular: jwtauthenticator
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.issuer
|
||||||
|
name: Issuer
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.audience
|
||||||
|
name: Audience
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: "JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||||
|
\n Upon receiving a signed JWT, a JWTAuthenticator will performs some validation
|
||||||
|
on it (e.g., valid signature, existence of claims, etc.) and extract the
|
||||||
|
username and groups from the token."
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec for configuring the authenticator.
|
||||||
|
properties:
|
||||||
|
audience:
|
||||||
|
description: Audience is the required value of the "aud" JWT claim.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
claims:
|
||||||
|
description: Claims allows customization of the claims that will be
|
||||||
|
mapped to user identity for Kubernetes access.
|
||||||
|
properties:
|
||||||
|
groups:
|
||||||
|
description: Groups is the name of the claim which should be read
|
||||||
|
to extract the user's group membership from the JWT token. When
|
||||||
|
not specified, it will default to "groups".
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
description: Username is the name of the claim which should be
|
||||||
|
read to extract the username from the JWT token. When not specified,
|
||||||
|
it will default to "username".
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
issuer:
|
||||||
|
description: Issuer is the OIDC issuer URL that will be used to discover
|
||||||
|
public signing keys. Issuer is also used to validate the "iss" JWT
|
||||||
|
claim.
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^https://
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS configuration for communicating with the OIDC provider.
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||||
|
If omitted, a default set of system roots will be trusted.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- audience
|
||||||
|
- issuer
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the authenticator.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Represents the observations of the authenticator's current
|
||||||
|
state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -0,0 +1,149 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: authentication.concierge.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
- pinniped-authenticator
|
||||||
|
- pinniped-authenticators
|
||||||
|
kind: WebhookAuthenticator
|
||||||
|
listKind: WebhookAuthenticatorList
|
||||||
|
plural: webhookauthenticators
|
||||||
|
singular: webhookauthenticator
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.endpoint
|
||||||
|
name: Endpoint
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: WebhookAuthenticator describes the configuration of a webhook
|
||||||
|
authenticator.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec for configuring the authenticator.
|
||||||
|
properties:
|
||||||
|
endpoint:
|
||||||
|
description: Webhook server endpoint URL.
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^https://
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS configuration.
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||||
|
If omitted, a default set of system roots will be trusted.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- endpoint
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the authenticator.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Represents the observations of the authenticator's current
|
||||||
|
state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -0,0 +1,264 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: credentialissuers.config.concierge.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: config.concierge.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
kind: CredentialIssuer
|
||||||
|
listKind: CredentialIssuerList
|
||||||
|
plural: credentialissuers
|
||||||
|
singular: credentialissuer
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.impersonationProxy.mode
|
||||||
|
name: ProxyMode
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.strategies[?(@.status == "Success")].type
|
||||||
|
name: DefaultStrategy
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: CredentialIssuer describes the configuration and status of the
|
||||||
|
Pinniped Concierge credential issuer.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec describes the intended configuration of the Concierge.
|
||||||
|
properties:
|
||||||
|
impersonationProxy:
|
||||||
|
description: ImpersonationProxy describes the intended configuration
|
||||||
|
of the Concierge impersonation proxy.
|
||||||
|
properties:
|
||||||
|
externalEndpoint:
|
||||||
|
description: "ExternalEndpoint describes the HTTPS endpoint where
|
||||||
|
the proxy will be exposed. If not set, the proxy will be served
|
||||||
|
using the external name of the LoadBalancer service or the cluster
|
||||||
|
service DNS name. \n This field must be non-empty when spec.impersonationProxy.service.type
|
||||||
|
is \"None\"."
|
||||||
|
type: string
|
||||||
|
mode:
|
||||||
|
description: 'Mode configures whether the impersonation proxy
|
||||||
|
should be started: - "disabled" explicitly disables the impersonation
|
||||||
|
proxy. This is the default. - "enabled" explicitly enables the
|
||||||
|
impersonation proxy. - "auto" enables or disables the impersonation
|
||||||
|
proxy based upon the cluster in which it is running.'
|
||||||
|
enum:
|
||||||
|
- auto
|
||||||
|
- enabled
|
||||||
|
- disabled
|
||||||
|
type: string
|
||||||
|
service:
|
||||||
|
default:
|
||||||
|
type: LoadBalancer
|
||||||
|
description: Service describes the configuration of the Service
|
||||||
|
provisioned to expose the impersonation proxy to clients.
|
||||||
|
properties:
|
||||||
|
annotations:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Annotations specifies zero or more key/value
|
||||||
|
pairs to set as annotations on the provisioned Service.
|
||||||
|
type: object
|
||||||
|
loadBalancerIP:
|
||||||
|
description: LoadBalancerIP specifies the IP address to set
|
||||||
|
in the spec.loadBalancerIP field of the provisioned Service.
|
||||||
|
This is not supported on all cloud providers.
|
||||||
|
maxLength: 255
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
default: LoadBalancer
|
||||||
|
description: "Type specifies the type of Service to provision
|
||||||
|
for the impersonation proxy. \n If the type is \"None\",
|
||||||
|
then the \"spec.impersonationProxy.externalEndpoint\" field
|
||||||
|
must be set to a non-empty value so that the Concierge can
|
||||||
|
properly advertise the endpoint in the CredentialIssuer's
|
||||||
|
status."
|
||||||
|
enum:
|
||||||
|
- LoadBalancer
|
||||||
|
- ClusterIP
|
||||||
|
- None
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
tls:
|
||||||
|
description: "TLS contains information about how the Concierge
|
||||||
|
impersonation proxy should serve TLS. \n If this field is empty,
|
||||||
|
the impersonation proxy will generate its own TLS certificate."
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM
|
||||||
|
bundle). Used to advertise the CA bundle for the impersonation
|
||||||
|
proxy endpoint.
|
||||||
|
type: string
|
||||||
|
secretName:
|
||||||
|
description: SecretName is the name of a Secret in the same
|
||||||
|
namespace, of type `kubernetes.io/tls`, which contains the
|
||||||
|
TLS serving certificate for the Concierge impersonation
|
||||||
|
proxy endpoint.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- mode
|
||||||
|
- service
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- impersonationProxy
|
||||||
|
type: object
|
||||||
|
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.
|
||||||
|
items:
|
||||||
|
description: CredentialIssuerStrategy describes the status of an
|
||||||
|
integration strategy that was attempted by Pinniped.
|
||||||
|
properties:
|
||||||
|
frontend:
|
||||||
|
description: Frontend describes how clients can connect using
|
||||||
|
this strategy.
|
||||||
|
properties:
|
||||||
|
impersonationProxyInfo:
|
||||||
|
description: ImpersonationProxyInfo describes the parameters
|
||||||
|
for the impersonation proxy on this Concierge. This field
|
||||||
|
is only set when Type is "ImpersonationProxy".
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: CertificateAuthorityData is the base64-encoded
|
||||||
|
PEM CA bundle of the impersonation proxy.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
endpoint:
|
||||||
|
description: Endpoint is the HTTPS endpoint of the impersonation
|
||||||
|
proxy.
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^https://
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- certificateAuthorityData
|
||||||
|
- endpoint
|
||||||
|
type: object
|
||||||
|
tokenCredentialRequestInfo:
|
||||||
|
description: TokenCredentialRequestAPIInfo describes the
|
||||||
|
parameters for the TokenCredentialRequest API on this
|
||||||
|
Concierge. This field is only set when Type is "TokenCredentialRequestAPI".
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: CertificateAuthorityData is the base64-encoded
|
||||||
|
Kubernetes API server CA bundle.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
server:
|
||||||
|
description: Server is the Kubernetes API server URL.
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^https://|^http://
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- certificateAuthorityData
|
||||||
|
- server
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
description: Type describes which frontend mechanism clients
|
||||||
|
can use with a strategy.
|
||||||
|
enum:
|
||||||
|
- TokenCredentialRequestAPI
|
||||||
|
- ImpersonationProxy
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
lastUpdateTime:
|
||||||
|
description: When the status was last checked.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: Human-readable description of the current status.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
reason:
|
||||||
|
description: Reason for the current status.
|
||||||
|
enum:
|
||||||
|
- Listening
|
||||||
|
- Pending
|
||||||
|
- Disabled
|
||||||
|
- ErrorDuringSetup
|
||||||
|
- CouldNotFetchKey
|
||||||
|
- CouldNotGetClusterInfo
|
||||||
|
- FetchedKey
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: Status of the attempted integration strategy.
|
||||||
|
enum:
|
||||||
|
- Success
|
||||||
|
- Error
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: Type of integration attempted.
|
||||||
|
enum:
|
||||||
|
- KubeClusterSigningCertificate
|
||||||
|
- ImpersonationProxy
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastUpdateTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- strategies
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
360
deploy_carvel/concierge/config/deployment.yaml
Normal file
360
deploy_carvel/concierge/config/deployment.yaml
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:json", "json")
|
||||||
|
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel", "pinnipedDevAPIGroupWithPrefix")
|
||||||
|
#@ load("@ytt:template", "template")
|
||||||
|
|
||||||
|
#@ if not data.values.into_namespace:
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: #@ data.values.namespace
|
||||||
|
labels:
|
||||||
|
_: #@ template.replace(labels())
|
||||||
|
#! When deploying onto a cluster which has PSAs enabled by default for namespaces,
|
||||||
|
#! effectively disable them for this namespace. The kube-cert-agent Deployment's pod
|
||||||
|
#! created by the Concierge in this namespace needs to be able to perform privileged
|
||||||
|
#! actions. The regular Concierge pod containers created by the Deployment below do
|
||||||
|
#! not need special privileges and are marked as such in their securityContext settings.
|
||||||
|
pod-security.kubernetes.io/enforce: privileged
|
||||||
|
#@ end
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
annotations:
|
||||||
|
#! we need to create this service account before we create the secret
|
||||||
|
kapp.k14s.io/change-group: "impersonation-proxy.concierge.pinniped.dev/serviceaccount"
|
||||||
|
secrets: #! make sure the token controller does not create any other secrets
|
||||||
|
- name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("config")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
data:
|
||||||
|
#! If names.apiService is changed in this ConfigMap, must also change name of the ClusterIP Service resource below.
|
||||||
|
#@yaml/text-templated-strings
|
||||||
|
pinniped.yaml: |
|
||||||
|
discovery:
|
||||||
|
url: (@= data.values.discovery_url or "null" @)
|
||||||
|
api:
|
||||||
|
servingCertificate:
|
||||||
|
durationSeconds: (@= str(data.values.api_serving_certificate_duration_seconds) @)
|
||||||
|
renewBeforeSeconds: (@= str(data.values.api_serving_certificate_renew_before_seconds) @)
|
||||||
|
apiGroupSuffix: (@= data.values.api_group_suffix @)
|
||||||
|
# aggregatedAPIServerPort may be set here, although other YAML references to the default port (10250) may also need to be updated
|
||||||
|
# impersonationProxyServerPort may be set here, although other YAML references to the default port (8444) may also need to be updated
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: (@= defaultResourceNameWithSuffix("api-tls-serving-certificate") @)
|
||||||
|
credentialIssuer: (@= defaultResourceNameWithSuffix("config") @)
|
||||||
|
apiService: (@= defaultResourceNameWithSuffix("api") @)
|
||||||
|
impersonationLoadBalancerService: (@= defaultResourceNameWithSuffix("impersonation-proxy-load-balancer") @)
|
||||||
|
impersonationClusterIPService: (@= defaultResourceNameWithSuffix("impersonation-proxy-cluster-ip") @)
|
||||||
|
impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @)
|
||||||
|
impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @)
|
||||||
|
impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @)
|
||||||
|
agentServiceAccount: (@= defaultResourceNameWithSuffix("kube-cert-agent") @)
|
||||||
|
labels: (@= json.encode(labels()).rstrip() @)
|
||||||
|
kubeCertAgent:
|
||||||
|
namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @)
|
||||||
|
(@ if data.values.kube_cert_agent_image: @)
|
||||||
|
image: (@= data.values.kube_cert_agent_image @)
|
||||||
|
(@ else: @)
|
||||||
|
(@ if data.values.image_digest: @)
|
||||||
|
image: (@= data.values.image_repo + "@" + data.values.image_digest @)
|
||||||
|
(@ else: @)
|
||||||
|
image: (@= data.values.image_repo + ":" + data.values.image_tag @)
|
||||||
|
(@ end @)
|
||||||
|
(@ end @)
|
||||||
|
(@ if data.values.image_pull_dockerconfigjson: @)
|
||||||
|
imagePullSecrets:
|
||||||
|
- image-pull-secret
|
||||||
|
(@ end @)
|
||||||
|
(@ if data.values.log_level or data.values.deprecated_log_format: @)
|
||||||
|
log:
|
||||||
|
(@ if data.values.log_level: @)
|
||||||
|
level: (@= getAndValidateLogLevel() @)
|
||||||
|
(@ end @)
|
||||||
|
(@ if data.values.deprecated_log_format: @)
|
||||||
|
format: (@= data.values.deprecated_log_format @)
|
||||||
|
(@ end @)
|
||||||
|
(@ end @)
|
||||||
|
---
|
||||||
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: image-pull-secret
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
.dockerconfigjson: #@ data.values.image_pull_dockerconfigjson
|
||||||
|
#@ end
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
replicas: #@ data.values.replicas
|
||||||
|
selector:
|
||||||
|
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
|
||||||
|
matchLabels: #@ defaultLabel()
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
#! This has always included defaultLabel(), which is used by this Deployment's selector.
|
||||||
|
_: #@ template.replace(defaultLabel())
|
||||||
|
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||||
|
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
||||||
|
_: #@ template.replace(deploymentPodLabel())
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: #@ data.values.run_as_user
|
||||||
|
runAsGroup: #@ data.values.run_as_group
|
||||||
|
serviceAccountName: #@ defaultResourceName()
|
||||||
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: image-pull-secret
|
||||||
|
#@ end
|
||||||
|
containers:
|
||||||
|
- name: #@ defaultResourceName()
|
||||||
|
#@ if data.values.image_digest:
|
||||||
|
image: #@ data.values.image_repo + "@" + data.values.image_digest
|
||||||
|
#@ else:
|
||||||
|
image: #@ data.values.image_repo + ":" + data.values.image_tag
|
||||||
|
#@ end
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ "ALL" ]
|
||||||
|
#! seccompProfile was introduced in Kube v1.19. Using it on an older Kube version will result in a
|
||||||
|
#! kubectl validation error when installing via `kubectl apply`, which can be ignored using kubectl's
|
||||||
|
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||||
|
seccompProfile:
|
||||||
|
type: "RuntimeDefault"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "128Mi"
|
||||||
|
limits:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "128Mi"
|
||||||
|
command:
|
||||||
|
- pinniped-concierge
|
||||||
|
- --config=/etc/config/pinniped.yaml
|
||||||
|
- --downward-api-path=/etc/podinfo
|
||||||
|
volumeMounts:
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /etc/config
|
||||||
|
readOnly: true
|
||||||
|
- name: podinfo
|
||||||
|
mountPath: /etc/podinfo
|
||||||
|
readOnly: true
|
||||||
|
- name: impersonation-proxy
|
||||||
|
mountPath: /var/run/secrets/impersonation-proxy.concierge.pinniped.dev/serviceaccount
|
||||||
|
readOnly: true
|
||||||
|
env:
|
||||||
|
#@ if data.values.https_proxy:
|
||||||
|
- name: HTTPS_PROXY
|
||||||
|
value: #@ data.values.https_proxy
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.https_proxy and data.values.no_proxy:
|
||||||
|
- name: NO_PROXY
|
||||||
|
value: #@ data.values.no_proxy
|
||||||
|
#@ end
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10250
|
||||||
|
scheme: HTTPS
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
timeoutSeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10250
|
||||||
|
scheme: HTTPS
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
timeoutSeconds: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
volumes:
|
||||||
|
- name: tmp
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
sizeLimit: 100Mi
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("config")
|
||||||
|
- name: impersonation-proxy
|
||||||
|
secret:
|
||||||
|
secretName: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
items: #! make sure our pod does not start until the token controller has a chance to populate the secret
|
||||||
|
- key: token
|
||||||
|
path: token
|
||||||
|
- name: podinfo
|
||||||
|
downwardAPI:
|
||||||
|
items:
|
||||||
|
- path: "labels"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.labels
|
||||||
|
- path: "name"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- path: "namespace"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
tolerations:
|
||||||
|
- key: CriticalAddonsOnly
|
||||||
|
operator: Exists
|
||||||
|
- key: node-role.kubernetes.io/master #! Allow running on master nodes too (name deprecated by kubernetes 1.20).
|
||||||
|
effect: NoSchedule
|
||||||
|
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||||
|
effect: NoSchedule
|
||||||
|
#! "system-cluster-critical" cannot be used outside the kube-system namespace until Kubernetes >= 1.17,
|
||||||
|
#! so we skip setting this for now (see https://github.com/kubernetes/kubernetes/issues/60596).
|
||||||
|
#!priorityClassName: system-cluster-critical
|
||||||
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
|
#! our deployment "more" "HA".
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- weight: 50
|
||||||
|
podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels: #@ deploymentPodLabel()
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
#! If name is changed, must also change names.apiService in the ConfigMap above and spec.service.name in the APIService below.
|
||||||
|
name: #@ defaultResourceNameWithSuffix("api")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 10250
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("proxy")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 8444
|
||||||
|
---
|
||||||
|
apiVersion: apiregistration.k8s.io/v1
|
||||||
|
kind: APIService
|
||||||
|
metadata:
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.login.concierge")
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
version: v1alpha1
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("login.concierge")
|
||||||
|
groupPriorityMinimum: 9900
|
||||||
|
versionPriority: 15
|
||||||
|
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||||
|
service:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("api")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
port: 443
|
||||||
|
---
|
||||||
|
apiVersion: apiregistration.k8s.io/v1
|
||||||
|
kind: APIService
|
||||||
|
metadata:
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.identity.concierge")
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
version: v1alpha1
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("identity.concierge")
|
||||||
|
groupPriorityMinimum: 9900
|
||||||
|
versionPriority: 15
|
||||||
|
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||||
|
service:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("api")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
port: 443
|
||||||
|
---
|
||||||
|
apiVersion: #@ pinnipedDevAPIGroupWithPrefix("config.concierge") + "/v1alpha1"
|
||||||
|
kind: CredentialIssuer
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("config")
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
impersonationProxy:
|
||||||
|
mode: #@ data.values.impersonation_proxy_spec.mode
|
||||||
|
#@ if data.values.impersonation_proxy_spec.external_endpoint:
|
||||||
|
externalEndpoint: #@ data.values.impersonation_proxy_spec.external_endpoint
|
||||||
|
#@ end
|
||||||
|
service:
|
||||||
|
type: #@ data.values.impersonation_proxy_spec.service.type
|
||||||
|
#@ if data.values.impersonation_proxy_spec.service.load_balancer_ip:
|
||||||
|
loadBalancerIP: #@ data.values.impersonation_proxy_spec.service.load_balancer_ip
|
||||||
|
#@ end
|
||||||
|
annotations: #@ data.values.impersonation_proxy_spec.service.annotations
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
annotations:
|
||||||
|
#! wait until the SA exists to create this secret so that the token controller does not delete it
|
||||||
|
#! we have this secret at the end so that kubectl will create the service account first
|
||||||
|
kapp.k14s.io/change-rule: "upsert after upserting impersonation-proxy.concierge.pinniped.dev/serviceaccount"
|
||||||
|
kubernetes.io/service-account.name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
type: kubernetes.io/service-account-token
|
47
deploy_carvel/concierge/config/helpers.lib.yaml
Normal file
47
deploy_carvel/concierge/config/helpers.lib.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:template", "template")
|
||||||
|
|
||||||
|
#@ def defaultResourceName():
|
||||||
|
#@ return data.values.app_name
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def defaultResourceNameWithSuffix(suffix):
|
||||||
|
#@ return data.values.app_name + "-" + suffix
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def pinnipedDevAPIGroupWithPrefix(prefix):
|
||||||
|
#@ return prefix + "." + data.values.api_group_suffix
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def namespace():
|
||||||
|
#@ if data.values.into_namespace:
|
||||||
|
#@ return data.values.into_namespace
|
||||||
|
#@ else:
|
||||||
|
#@ return data.values.namespace
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def defaultLabel():
|
||||||
|
#! Note that the name of this label's key is also assumed by kubecertagent.go and impersonator_config.go
|
||||||
|
app: #@ data.values.app_name
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def deploymentPodLabel():
|
||||||
|
deployment.pinniped.dev: concierge
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def labels():
|
||||||
|
_: #@ template.replace(defaultLabel())
|
||||||
|
_: #@ template.replace(data.values.custom_labels)
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def getAndValidateLogLevel():
|
||||||
|
#@ log_level = data.values.log_level
|
||||||
|
#@ if log_level != "info" and log_level != "debug" and log_level != "trace" and log_level != "all":
|
||||||
|
#@ fail("log_level '" + log_level + "' is invalid")
|
||||||
|
#@ end
|
||||||
|
#@ return log_level
|
||||||
|
#@ end
|
296
deploy_carvel/concierge/config/rbac.yaml
Normal file
296
deploy_carvel/concierge/config/rbac.yaml
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("helpers.lib.yaml", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "pinnipedDevAPIGroupWithPrefix")
|
||||||
|
|
||||||
|
#! Give permission to various cluster-scoped objects
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ namespaces ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
- apiGroups: [ apiregistration.k8s.io ]
|
||||||
|
resources: [ apiservices ]
|
||||||
|
verbs: [ get, list, patch, update, watch ]
|
||||||
|
- apiGroups: [ admissionregistration.k8s.io ]
|
||||||
|
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||||
|
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
- apiGroups: [ security.openshift.io ]
|
||||||
|
resources: [ securitycontextconstraints ]
|
||||||
|
verbs: [ use ]
|
||||||
|
resourceNames: [ nonroot ]
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ nodes ]
|
||||||
|
verbs: [ list ]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||||
|
resources: [ credentialissuers ]
|
||||||
|
verbs: [ get, list, watch, create ]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||||
|
resources: [ credentialissuers/status ]
|
||||||
|
verbs: [ get, patch, update ]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||||
|
resources: [ jwtauthenticators, webhookauthenticators ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give minimal permissions to impersonation proxy service account
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ "users", "groups", "serviceaccounts" ]
|
||||||
|
verbs: [ "impersonate" ]
|
||||||
|
- apiGroups: [ "authentication.k8s.io" ]
|
||||||
|
resources: [ "*" ] #! What we really want is userextras/* but the RBAC authorizer only supports */subresource, not resource/*
|
||||||
|
verbs: [ "impersonate" ]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permission to the kube-cert-agent Pod to run privileged.
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ policy ]
|
||||||
|
resources: [ podsecuritypolicies ]
|
||||||
|
verbs: [ use ]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permission to various objects within the app's own namespace
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ services ]
|
||||||
|
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ secrets ]
|
||||||
|
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||||
|
#! We need to be able to watch pods in our namespace so we can find the kube-cert-agent pods.
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ pods ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
#! We need to be able to exec into pods in our namespace so we can grab the API server's private key
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ pods/exec ]
|
||||||
|
verbs: [ create ]
|
||||||
|
#! We need to be able to delete pods in our namespace so we can clean up legacy kube-cert-agent pods.
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ pods ]
|
||||||
|
verbs: [ delete ]
|
||||||
|
#! We need to be able to create and update deployments in our namespace so we can manage the kube-cert-agent Deployment.
|
||||||
|
- apiGroups: [ apps ]
|
||||||
|
resources: [ deployments ]
|
||||||
|
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||||
|
#! We need to be able to get replicasets so we can form the correct owner references on our generated objects.
|
||||||
|
- apiGroups: [ apps ]
|
||||||
|
resources: [ replicasets ]
|
||||||
|
verbs: [ get ]
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ configmaps ]
|
||||||
|
verbs: [ list, get, watch ]
|
||||||
|
- apiGroups: [ coordination.k8s.io ]
|
||||||
|
resources: [ leases ]
|
||||||
|
verbs: [ create, get, update ]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permission to read pods in the kube-system namespace so we can find the API server's private key
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||||
|
namespace: kube-system
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ pods ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||||
|
namespace: kube-system
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Allow both authenticated and unauthenticated TokenCredentialRequests (i.e. allow all requests)
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("login.concierge")
|
||||||
|
resources: [ tokencredentialrequests ]
|
||||||
|
verbs: [ create, list ]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("identity.concierge")
|
||||||
|
resources: [ whoamirequests ]
|
||||||
|
verbs: [ create, list ]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: system:authenticated
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
- kind: Group
|
||||||
|
name: system:unauthenticated
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:auth-delegator
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permissions for a special configmap of CA bundles that is needed by aggregated api servers
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("extension-apiserver-authentication-reader")
|
||||||
|
namespace: kube-system
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: extension-apiserver-authentication-reader
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permission to list and watch ConfigMaps in kube-public
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||||
|
namespace: kube-public
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ configmaps ]
|
||||||
|
verbs: [ list, watch ]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||||
|
namespace: kube-public
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
123
deploy_carvel/concierge/config/values.yaml
Normal file
123
deploy_carvel/concierge/config/values.yaml
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@data/values-schema
|
||||||
|
---
|
||||||
|
#@schema/desc "Namespace of pinniped-concierge"
|
||||||
|
app_name: pinniped-concierge
|
||||||
|
|
||||||
|
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||||
|
namespace: pinniped-concierge
|
||||||
|
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||||
|
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||||
|
#@schema/desc "Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???"
|
||||||
|
#@schema/nullable
|
||||||
|
into_namespace: my-preexisting-namespace
|
||||||
|
|
||||||
|
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||||
|
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||||
|
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||||
|
#! The app can be uninstalled either by:
|
||||||
|
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||||
|
#! resources that were dynamically created by controllers at runtime
|
||||||
|
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||||
|
#@schema/desc "All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here."
|
||||||
|
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||||
|
|
||||||
|
#! Specify how many replicas of the Pinniped server to run.
|
||||||
|
replicas: 2
|
||||||
|
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
#@schema/nullable
|
||||||
|
image_digest: sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
image_tag: latest
|
||||||
|
|
||||||
|
#! TODO: preserve even if this file is revised!
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_repo: docker.io/benjaminapetersen/some-pinniped-concierge-package
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_digest: sha256:123456
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_tag: latest
|
||||||
|
#! prob should not be nullable
|
||||||
|
#@schema/nullable
|
||||||
|
package_version: 1.2.3
|
||||||
|
|
||||||
|
#@schema/desc 'Optionally specify a different image for the "kube-cert-agent" pod which is scheduled on the control plane. This image needs only to include `sleep` and `cat` binaries. By default, the same image specified for image_repo/image_digest/image_tag will be re-used.'
|
||||||
|
kube_cert_agent_image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
|
||||||
|
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||||
|
#! Can be used when the above image_repo is a private registry.
|
||||||
|
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry."
|
||||||
|
#@schema/nullable
|
||||||
|
image_pull_dockerconfigjson: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||||
|
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden."
|
||||||
|
#@schema/nullable
|
||||||
|
discovery_url: https://example.com
|
||||||
|
|
||||||
|
#@schema/desc "Specify the duration and renewal interval for the API serving certificate. The defaults are set to expire the cert about every 30 days, and to rotate it about every 25 days."
|
||||||
|
api_serving_certificate_duration_seconds: 2592000
|
||||||
|
api_serving_certificate_renew_before_seconds: 2160000
|
||||||
|
|
||||||
|
#@schema/desc 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||||
|
#@schema/nullable
|
||||||
|
log_level: info #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||||
|
#@schema/desc "Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json."
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_log_format: json
|
||||||
|
|
||||||
|
#@schema/desc "run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||||
|
run_as_user: 65532
|
||||||
|
#@schema/desc "run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||||
|
run_as_group: 65532
|
||||||
|
|
||||||
|
#@schema/desc "Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc."
|
||||||
|
api_group_suffix: pinniped.dev
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#@schema/desc "Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation."
|
||||||
|
impersonation_proxy_spec:
|
||||||
|
#! options are "auto", "disabled" or "enabled".
|
||||||
|
#! If auto, the impersonation proxy will run only if the cluster signing key is not available
|
||||||
|
#! and the other strategy does not work.
|
||||||
|
#! If disabled, the impersonation proxy will never run, which could mean that the concierge
|
||||||
|
#! doesn't work at all.
|
||||||
|
#! If enabled, the impersonation proxy will always run regardless of other strategies available.
|
||||||
|
#@schema/desc 'options are "auto", "disabled" or "enabled".'
|
||||||
|
mode: auto
|
||||||
|
#! The endpoint which the client should use to connect to the impersonation proxy.
|
||||||
|
#! If left unset, the client will default to connecting based on the ClusterIP or LoadBalancer
|
||||||
|
#! endpoint.
|
||||||
|
#@schema/desc "The endpoint which the client should use to connect to the impersonation proxy."
|
||||||
|
external_endpoint: http://example.com
|
||||||
|
service:
|
||||||
|
#! Options are "LoadBalancer", "ClusterIP" and "None".
|
||||||
|
#! LoadBalancer automatically provisions a Service of type LoadBalancer pointing at
|
||||||
|
#! the impersonation proxy. Some cloud providers will allocate
|
||||||
|
#! a public IP address by default even on private clusters.
|
||||||
|
#! ClusterIP automatically provisions a Service of type ClusterIP pointing at the
|
||||||
|
#! impersonation proxy.
|
||||||
|
#! None does not provision either and assumes that you have set the external_endpoint
|
||||||
|
#! and set up your own ingress to connect to the impersonation proxy.
|
||||||
|
#@schema/desc 'Options are "LoadBalancer", "ClusterIP" and "None".'
|
||||||
|
type: LoadBalancer
|
||||||
|
#@schema/desc "The annotations that should be set on the ClusterIP or LoadBalancer Service."
|
||||||
|
annotations:
|
||||||
|
{service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "4000"}
|
||||||
|
#@schema/desc "When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP."
|
||||||
|
load_balancer_ip: 1.2.3.4
|
||||||
|
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks. The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||||
|
#@schema/nullable
|
||||||
|
https_proxy: http://proxy.example.com
|
||||||
|
#@schema/desc "NO_PROXY environment variable. do not proxy Kubernetes endpoints"
|
||||||
|
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
33
deploy_carvel/concierge/config/z0_crd_overlay.yaml
Normal file
33
deploy_carvel/concierge/config/z0_crd_overlay.yaml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:overlay", "overlay")
|
||||||
|
#@ load("helpers.lib.yaml", "labels", "pinnipedDevAPIGroupWithPrefix")
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"credentialissuers.config.concierge.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("credentialissuers.config.concierge")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"webhookauthenticators.authentication.concierge.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("webhookauthenticators.authentication.concierge")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"jwtauthenticators.authentication.concierge.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("jwtauthenticators.authentication.concierge")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
13
deploy_carvel/concierge/metadata.yml
Normal file
13
deploy_carvel/concierge/metadata.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||||
|
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||||
|
---
|
||||||
|
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageMetadata
|
||||||
|
metadata:
|
||||||
|
name: concierge.pinniped.dev
|
||||||
|
spec:
|
||||||
|
displayName: "Pinniped Concierge"
|
||||||
|
longDescription: "Pinniped concierge enables consistent login across Kubernetes clusters on public cloud providers such as AKS, EKS and GKE"
|
||||||
|
shortDescription: "Pinniped concierge enables consistent login across public clouds"
|
||||||
|
categories:
|
||||||
|
- auth
|
30
deploy_carvel/concierge/package-template.yml
Normal file
30
deploy_carvel/concierge/package-template.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||||
|
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||||
|
---
|
||||||
|
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||||
|
kind: Package
|
||||||
|
metadata:
|
||||||
|
name: #@ "concierge.pinniped.dev." + data.values.package_version
|
||||||
|
spec:
|
||||||
|
refName: concierge.pinniped.dev
|
||||||
|
version: #@ data.values.package_version
|
||||||
|
releaseNotes: |
|
||||||
|
Initial release of the pinniped concierge package, TODO: AUTOMATE THIS??
|
||||||
|
valuesSchema:
|
||||||
|
openAPIv3: #@ yaml.decode(data.values.openapi)["components"]["schemas"]["dataValues"]
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
fetch:
|
||||||
|
- imgpkgBundle:
|
||||||
|
#! image: #@ data.values.package_image_repo + "/packages/:" + data.values.package_version
|
||||||
|
image: #@ data.values.package_image_repo
|
||||||
|
template:
|
||||||
|
- ytt:
|
||||||
|
paths:
|
||||||
|
- "config/"
|
||||||
|
- kbld:
|
||||||
|
paths:
|
||||||
|
- ".imgpkg/images.yml"
|
||||||
|
- "-"
|
||||||
|
deploy:
|
||||||
|
- kapp: {}
|
164
deploy_carvel/concierge/schema-openapi.yml
Normal file
164
deploy_carvel/concierge/schema-openapi.yml
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
version: 0.1.0
|
||||||
|
title: Schema for data values, generated by ytt
|
||||||
|
paths: {}
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
dataValues:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
app_name:
|
||||||
|
type: string
|
||||||
|
description: Namespace of pinniped-concierge
|
||||||
|
default: pinniped-concierge
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||||
|
default: pinniped-concierge
|
||||||
|
into_namespace:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||||
|
default: null
|
||||||
|
custom_labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||||
|
properties: {}
|
||||||
|
replicas:
|
||||||
|
type: integer
|
||||||
|
default: 2
|
||||||
|
image_repo:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: null
|
||||||
|
image_tag:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: latest
|
||||||
|
package_image_repo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_tag:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_version:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
kube_cert_agent_image:
|
||||||
|
type: string
|
||||||
|
description: Optionally specify a different image for the "kube-cert-agent" pod which is scheduled on the control plane. This image needs only to include `sleep` and `cat` binaries. By default, the same image specified for image_repo/image_digest/image_tag will be re-used.
|
||||||
|
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
image_pull_dockerconfigjson:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
nullable: true
|
||||||
|
description: Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry.
|
||||||
|
properties:
|
||||||
|
auths:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
https://registry.example.com:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
default: USERNAME
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
default: PASSWORD
|
||||||
|
auth:
|
||||||
|
type: string
|
||||||
|
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||||
|
discovery_url:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden.
|
||||||
|
default: null
|
||||||
|
api_serving_certificate_duration_seconds:
|
||||||
|
type: integer
|
||||||
|
description: Specify the duration and renewal interval for the API serving certificate. The defaults are set to expire the cert about every 30 days, and to rotate it about every 25 days.
|
||||||
|
default: 2592000
|
||||||
|
api_serving_certificate_renew_before_seconds:
|
||||||
|
type: integer
|
||||||
|
default: 2160000
|
||||||
|
log_level:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||||
|
default: null
|
||||||
|
deprecated_log_format:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||||
|
default: null
|
||||||
|
run_as_user:
|
||||||
|
type: integer
|
||||||
|
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
run_as_group:
|
||||||
|
type: integer
|
||||||
|
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
api_group_suffix:
|
||||||
|
type: string
|
||||||
|
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||||
|
default: pinniped.dev
|
||||||
|
impersonation_proxy_spec:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation.
|
||||||
|
properties:
|
||||||
|
mode:
|
||||||
|
type: string
|
||||||
|
description: options are "auto", "disabled" or "enabled".
|
||||||
|
default: auto
|
||||||
|
external_endpoint:
|
||||||
|
type: string
|
||||||
|
description: The endpoint which the client should use to connect to the impersonation proxy.
|
||||||
|
default: http://example.com
|
||||||
|
service:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: Options are "LoadBalancer", "ClusterIP" and "None".
|
||||||
|
default: LoadBalancer
|
||||||
|
annotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: The annotations that should be set on the ClusterIP or LoadBalancer Service.
|
||||||
|
properties:
|
||||||
|
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout:
|
||||||
|
type: string
|
||||||
|
default: "4000"
|
||||||
|
load_balancer_ip:
|
||||||
|
type: string
|
||||||
|
description: When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP.
|
||||||
|
default: 1.2.3.4
|
||||||
|
https_proxy:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks. The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||||
|
default: null
|
||||||
|
no_proxy:
|
||||||
|
type: string
|
||||||
|
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||||
|
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
62
deploy_carvel/delete.sh
Executable file
62
deploy_carvel/delete.sh
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||||
|
set -e # immediately exit
|
||||||
|
set -u # error if variables undefined
|
||||||
|
set -o pipefail # prevent masking errors in a pipeline
|
||||||
|
# set -x # print all executed commands to terminal
|
||||||
|
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
DEFAULT='\033[0m'
|
||||||
|
|
||||||
|
echo_yellow() {
|
||||||
|
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${GREEN}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_green() {
|
||||||
|
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
echo_red() {
|
||||||
|
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
echo_blue() {
|
||||||
|
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_yellow "creating fresh kind cluster - my-pinniped-package-repo-cluster"
|
||||||
|
kind delete cluster --name my-pinniped-package-repo-cluster
|
||||||
|
kind create cluster --name my-pinniped-package-repo-cluster
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#echo_yellow "check before install..."
|
||||||
|
#echo_yellow "kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A"
|
||||||
|
#kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A
|
||||||
|
## NAMESPACE NAME AGE DESCRIPTION
|
||||||
|
## default pinniped-package-repository 18h Reconcile succeeded
|
||||||
|
## NAMESPACE NAME PACKAGEMETADATA NAME VERSION AGE
|
||||||
|
## default concierge.pinniped.dev.0.25.0 concierge.pinniped.dev 0.25.0 18h16m28s
|
||||||
|
## default supervisor.pinniped.dev.0.25.0 supervisor.pinniped.dev 0.25.0 18h16m28s
|
||||||
|
## NAMESPACE NAME PACKAGE NAME PACKAGE VERSION DESCRIPTION AGE
|
||||||
|
## default supervisor-package-install supervisor.pinniped.dev 0.25.0 Delete failed: Error (see .status.usefulErrorMessage for details) 92m
|
||||||
|
## supervisor-ns supervisor-package-install supervisor.pinniped.dev Reconcile failed: Package supervisor.pinniped.dev not found 18h
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#kubectl delete pkgr pinniped-package-repository
|
||||||
|
## should be automatic
|
||||||
|
## kubectl delete pkg concierge.pinniped.dev.0.25.0
|
||||||
|
## kubectl delete pkg supervisor.pinniped.dev.0.25.0
|
||||||
|
#kubectl delete pkgi supervisor-package-install
|
||||||
|
#kubectl delete pkgi concierge-package-install
|
||||||
|
#
|
||||||
|
#echo_yellow "check after install..."
|
||||||
|
#echo_yellow "kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A"
|
||||||
|
#kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A
|
402
deploy_carvel/deploy-packages.sh
Executable file
402
deploy_carvel/deploy-packages.sh
Executable file
@ -0,0 +1,402 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script can be used to prepare a kind cluster and deploy the app.
|
||||||
|
# You can call this script again to redeploy the app.
|
||||||
|
# It will also output instructions on how to run the integration.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e # immediately exit
|
||||||
|
set -u # error if variables undefined
|
||||||
|
set -o pipefail # prevent masking errors in a pipeline
|
||||||
|
# set -x # print all executed commands to terminal
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
# TODO: add support for
|
||||||
|
# Read the env vars output by hack/prepare-for-integration-tests.sh
|
||||||
|
# source /tmp/integration-test-env
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Deploy the PackageRepository and Package resources
|
||||||
|
# Requires a running kind cluster
|
||||||
|
# Does not configure Pinniped
|
||||||
|
#
|
||||||
|
app="${1:-undefined}"
|
||||||
|
tag="${2:-$(uuidgen)}" # always a new tag to force K8s to reload the image on redeploy
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
log_note "log-args.sh >>> script dir: ${SCRIPT_DIR} 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄"
|
||||||
|
log_note "log-args.sh >>> app: ${app} tag: ${tag} 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# from prepare-for-integration-tests.sh
|
||||||
|
api_group_suffix="pinniped.dev" # same default as in the values.yaml ytt file
|
||||||
|
registry="pinniped.local"
|
||||||
|
repo="test/build"
|
||||||
|
registry_repo="$registry/$repo"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
log_note "Deploying kapp-controller on kind cluster..."
|
||||||
|
kapp deploy --app kapp-controller --file https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml -y
|
||||||
|
kubectl get customresourcedefinitions
|
||||||
|
# Global kapp-controller-namespace:
|
||||||
|
# -packaging-global-namespace=kapp-controller-packaging-global
|
||||||
|
# kapp-controller resources like PackageRepository and Package are namepaced.
|
||||||
|
# However, this namespace, provided via flag to kapp-controller in the yaml above,
|
||||||
|
# defines a "global" namespace. That is, resources installed in this namespace
|
||||||
|
# can be installed in every namespace as kapp will always pay attention to its
|
||||||
|
# pseudo-global namespace.
|
||||||
|
KAPP_CONTROLLER_GLOBAL_NAMESPACE="kapp-controller-packaging-global"
|
||||||
|
|
||||||
|
|
||||||
|
# deploy the Carvel packages for Pinniped & Supervisor.
|
||||||
|
# - Deploy the PackageRepository
|
||||||
|
# - Create PackageInstalls for Supervisor, Concierge
|
||||||
|
# - deploy these
|
||||||
|
# - then after, run hack/prepare-supervisor-on-kind.sh
|
||||||
|
# - ideally this configures the Supervisor
|
||||||
|
|
||||||
|
|
||||||
|
# need a directory for our yamls for deployment
|
||||||
|
log_note "Clean previous PackageInstalls in order to create new ones..."
|
||||||
|
PACKAGE_INSTALL_DIR="temp_actual_deploy_resources"
|
||||||
|
rm -rf "${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}"
|
||||||
|
mkdir "${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}"
|
||||||
|
|
||||||
|
|
||||||
|
# this is built via the build.sh script
|
||||||
|
# build.sh must be run first.
|
||||||
|
# TODO: since the ytt values.yaml takes in a version="x.y.z"
|
||||||
|
# for Pinniped, our packages are currently not meaningfully versioned.
|
||||||
|
# this is one of the questions we must answer, do we deviate in the
|
||||||
|
# "./deploy_carvel" directory by hard-coding this version in the packages?
|
||||||
|
log_note "Deploying Pinniped PackageRepository on kind cluster..."
|
||||||
|
PINNIPED_PACKAGE_VERSION="0.25.0"
|
||||||
|
PINNIPED_PACKGE_REPOSITORY_NAME="pinniped-package-repository"
|
||||||
|
PINNIPED_PACKGE_REPOSITORY_FILE_NAME="packagerepository.${PINNIPED_PACKAGE_VERSION}.yml"
|
||||||
|
PINNIPED_PACKGE_REPOSITORY_FILE_PATH="${SCRIPT_DIR}/${PINNIPED_PACKGE_REPOSITORY_FILE_NAME}"
|
||||||
|
# Now, gotta make this work. It'll be interesting if we can...
|
||||||
|
kapp deploy \
|
||||||
|
--namespace "${KAPP_CONTROLLER_GLOBAL_NAMESPACE}" \
|
||||||
|
--app "${PINNIPED_PACKGE_REPOSITORY_NAME}" \
|
||||||
|
--file "${PINNIPED_PACKGE_REPOSITORY_FILE_PATH}" -y
|
||||||
|
kapp inspect \
|
||||||
|
--namespace "${KAPP_CONTROLLER_GLOBAL_NAMESPACE}" \
|
||||||
|
--app "${PINNIPED_PACKGE_REPOSITORY_NAME}" \
|
||||||
|
--tree
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: obviously a mega-role that can do everything is not good. we need to scope this down to appropriate things.
|
||||||
|
declare -a arr=("supervisor" "concierge")
|
||||||
|
for resource_name in "${arr[@]}"
|
||||||
|
do
|
||||||
|
log_note "Generating RBAC for use with ${resource_name} PackageInstall..."
|
||||||
|
# we want the install-ns to not be "default"
|
||||||
|
# it should be a unique namespace
|
||||||
|
# but it should also not be in kapp-controllers global namespace
|
||||||
|
# nor should it be in any Pinniped resource namespace
|
||||||
|
# - PackageRepository,Package = global kapp-controller namespace
|
||||||
|
# - PackageInstall,RBAC = *-install namespace
|
||||||
|
# - App = (supervisor, concierge) generated via ytt namespace
|
||||||
|
INSTALL_NAMESPACE="${resource_name}-install-ns"
|
||||||
|
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||||
|
PINNIPED_PACKAGE_RBAC_FILE_NAME="${PINNIPED_PACKAGE_RBAC_PREFIX}-${resource_name}-rbac.yml"
|
||||||
|
PINNIPED_PACKAGE_RBAC_FILE_PATH="${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}/${PINNIPED_PACKAGE_RBAC_FILE_NAME}"
|
||||||
|
|
||||||
|
# empty and regenerate
|
||||||
|
echo -n "" > "${PINNIPED_PACKAGE_RBAC_FILE_PATH}"
|
||||||
|
cat <<EOF >> "${PINNIPED_PACKAGE_RBAC_FILE_PATH}"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: "${INSTALL_NAMESPACE}"
|
||||||
|
---
|
||||||
|
# ServiceAccount details from the file linked above
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||||
|
namespace: "${INSTALL_NAMESPACE}"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["*"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["*"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-binding-superadmin-dangerous"
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||||
|
namespace: "${INSTALL_NAMESPACE}"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
kapp deploy --app "${PINNIPED_PACKAGE_RBAC_PREFIX}" --file "${PINNIPED_PACKAGE_RBAC_FILE_PATH}" -y
|
||||||
|
done
|
||||||
|
|
||||||
|
# IF SUPERVISOR ........
|
||||||
|
if [ "${app}" = "pinniped-supervisor" ]; then
|
||||||
|
resource_name="supervisor"
|
||||||
|
|
||||||
|
# matching the hack/prepare-for-integration-tests.sh variables
|
||||||
|
supervisor_app_name="pinniped-supervisor"
|
||||||
|
supervisor_namespace="supervisor"
|
||||||
|
supervisor_custom_labels="{mySupervisorCustomLabelName: mySupervisorCustomLabelValue}"
|
||||||
|
log_level="debug"
|
||||||
|
service_https_nodeport_port="443"
|
||||||
|
service_https_nodeport_nodeport="31243"
|
||||||
|
service_https_clusterip_port="443"
|
||||||
|
|
||||||
|
# package install variables
|
||||||
|
INSTALL_NAME="${resource_name}-install"
|
||||||
|
INSTALL_NAMESPACE="${INSTALL_NAME}-ns"
|
||||||
|
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||||
|
RESOURCE_PACKGE_VERSION="${resource_name}.pinniped.dev"
|
||||||
|
PACKAGE_INSTALL_FILE_NAME="./${PACKAGE_INSTALL_DIR}/${resource_name}-pkginstall.yml"
|
||||||
|
PACKAGE_INSTALL_FILE_PATH="${SCRIPT_DIR}/${PACKAGE_INSTALL_FILE_NAME}"
|
||||||
|
SECRET_NAME="${resource_name}-package-install-secret"
|
||||||
|
log_note "🦄${resource_name}🦄: Creating PackageInstall resources for ${resource_name}..."
|
||||||
|
# generate an install file to use
|
||||||
|
cat > "${PACKAGE_INSTALL_FILE_PATH}" << EOF
|
||||||
|
---
|
||||||
|
apiVersion: packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageInstall
|
||||||
|
metadata:
|
||||||
|
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||||
|
name: ${INSTALL_NAME}
|
||||||
|
namespace: ${INSTALL_NAMESPACE}
|
||||||
|
spec:
|
||||||
|
serviceAccountName: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||||
|
packageRef:
|
||||||
|
refName: "${RESOURCE_PACKGE_VERSION}"
|
||||||
|
versionSelection:
|
||||||
|
constraints: "${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
values:
|
||||||
|
- secretRef:
|
||||||
|
name: "${SECRET_NAME}"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "${SECRET_NAME}"
|
||||||
|
namespace: ${INSTALL_NAMESPACE}
|
||||||
|
stringData:
|
||||||
|
values.yml: |
|
||||||
|
---
|
||||||
|
app_name: $supervisor_app_name
|
||||||
|
namespace: $supervisor_namespace
|
||||||
|
api_group_suffix: $api_group_suffix
|
||||||
|
image_repo: $registry_repo
|
||||||
|
image_tag: $tag
|
||||||
|
log_level: $log_level
|
||||||
|
|
||||||
|
service_https_nodeport_port: $service_https_nodeport_port
|
||||||
|
service_https_nodeport_nodeport: $service_https_nodeport_nodeport
|
||||||
|
service_https_clusterip_port: $service_https_clusterip_port
|
||||||
|
EOF
|
||||||
|
# removed from above:
|
||||||
|
# custom_labels: $supervisor_custom_labels
|
||||||
|
|
||||||
|
KAPP_CONTROLLER_APP_NAME="${resource_name}-pkginstall"
|
||||||
|
log_note "🦄${resource_name}🦄: Deploying ${KAPP_CONTROLLER_APP_NAME}..."
|
||||||
|
kapp deploy --yes --app "$supervisor_app_name" --diff-changes --file "${PACKAGE_INSTALL_FILE_PATH}"
|
||||||
|
kubectl apply --dry-run=client -f "${PACKAGE_INSTALL_FILE_PATH}" # Validate manifest schema.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# IF CONCIERGE ........
|
||||||
|
if [ "${app}" = "pinniped-concierge" ]; then
|
||||||
|
resource_name="concierge"
|
||||||
|
|
||||||
|
# matching the hack/prepare-for-integration-tests.sh variables
|
||||||
|
concierge_app_name="pinniped-concierge"
|
||||||
|
concierge_namespace="concierge"
|
||||||
|
webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate"
|
||||||
|
webhook_ca_bundle="$(kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')"
|
||||||
|
discovery_url="$(TERM=dumb kubectl cluster-info | awk '/master|control plane/ {print $NF}')"
|
||||||
|
concierge_custom_labels="{myConciergeCustomLabelName: myConciergeCustomLabelValue}"
|
||||||
|
log_level="debug"
|
||||||
|
|
||||||
|
# package install variables
|
||||||
|
RESOURCE_NAMESPACE="${resource_name}" # to match the hack/prepare-for-integration-tests.sh file
|
||||||
|
INSTALL_NAME="${resource_name}-install"
|
||||||
|
INSTALL_NAMESPACE="${INSTALL_NAME}-ns"
|
||||||
|
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||||
|
RESOURCE_PACKGE_VERSION="${resource_name}.pinniped.dev"
|
||||||
|
PACKAGE_INSTALL_FILE_NAME="./${PACKAGE_INSTALL_DIR}/${resource_name}-pkginstall.yml"
|
||||||
|
PACKAGE_INSTALL_FILE_PATH="${SCRIPT_DIR}/${PACKAGE_INSTALL_FILE_NAME}"
|
||||||
|
SECRET_NAME="${resource_name}-package-install-secret"
|
||||||
|
log_note "🦄${resource_name}🦄: Creating PackageInstall resources for ${resource_name}..." # concierge version
|
||||||
|
|
||||||
|
cat > "${PACKAGE_INSTALL_FILE_PATH}" << EOF
|
||||||
|
---
|
||||||
|
apiVersion: packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageInstall
|
||||||
|
metadata:
|
||||||
|
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||||
|
name: ${INSTALL_NAME}
|
||||||
|
namespace: ${INSTALL_NAMESPACE}
|
||||||
|
spec:
|
||||||
|
serviceAccountName: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||||
|
packageRef:
|
||||||
|
refName: "${RESOURCE_PACKGE_VERSION}"
|
||||||
|
versionSelection:
|
||||||
|
constraints: "${PINNIPED_PACKAGE_VERSION}"
|
||||||
|
values:
|
||||||
|
- secretRef:
|
||||||
|
name: "${SECRET_NAME}"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "${SECRET_NAME}"
|
||||||
|
namespace: ${INSTALL_NAMESPACE}
|
||||||
|
stringData:
|
||||||
|
values.yml: |
|
||||||
|
---
|
||||||
|
app_name: $concierge_app_name
|
||||||
|
namespace: $concierge_namespace
|
||||||
|
api_group_suffix: $api_group_suffix
|
||||||
|
log_level: $log_level
|
||||||
|
custom_labels: $concierge_custom_labels
|
||||||
|
image_repo: $registry_repo
|
||||||
|
image_tag: $tag
|
||||||
|
discovery_url: $discovery_url
|
||||||
|
EOF
|
||||||
|
KAPP_CONTROLLER_APP_NAME="${resource_name}-pkginstall"
|
||||||
|
log_note "🦄${resource_name}🦄: Deploying ${KAPP_CONTROLLER_APP_NAME}..."
|
||||||
|
# kapp deploy --app "${KAPP_CONTROLLER_APP_NAME}" --file "${PACKAGE_INSTALL_FILE_PATH}" -y
|
||||||
|
kapp deploy --yes --app "$concierge_app_name" --diff-changes --file "${PACKAGE_INSTALL_FILE_PATH}"
|
||||||
|
kubectl apply --dry-run=client -f "${PACKAGE_INSTALL_FILE_PATH}" # Validate manifest schema.
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
log_note "Available Packages:"
|
||||||
|
kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A
|
||||||
|
|
||||||
|
log_note "Pinniped Supervisor Package Deployed"
|
||||||
|
log_note "Pinniped Concierge Package Deployed"
|
||||||
|
kubectl get namespace -A | grep pinniped
|
||||||
|
kubectl get deploy -n supervisor
|
||||||
|
kubectl get deploy -n concierge
|
||||||
|
|
||||||
|
|
||||||
|
# FLOW:
|
||||||
|
# kind delete cluster --name pinniped
|
||||||
|
# ./hack/prepare-for-integration-tests.sh --alternate-deploy-supervisor $(pwd)/deploy_carvel/deploy-packges.sh --alternate-deploy-concierge $(pwd)/deploy_carvel/deploy-packges.sh
|
||||||
|
# ./hack/prepare-supervisor-on-kind.sh --oidc
|
||||||
|
#
|
||||||
|
# TODO:
|
||||||
|
# - change the namespace to whatever it is in ./hack/prepare-for-integration-tests.sh
|
||||||
|
# - make a script that can work for $alternate-deploy
|
||||||
|
# - then run ./hack/prepare-supervisor-on-kind.sh and make sure it works
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# openssl x509 -text -noout -in ./root_ca.crt
|
||||||
|
#curl --insecure https://127.0.0.1:61759/live
|
||||||
|
#{
|
||||||
|
# "kind": "Status",
|
||||||
|
# "apiVersion": "v1",
|
||||||
|
# "metadata": {},
|
||||||
|
# "status": "Failure",
|
||||||
|
# "message": "forbidden: User \"system:anonymous\" cannot get path \"/live\"",
|
||||||
|
# "reason": "Forbidden",
|
||||||
|
# "details": {},
|
||||||
|
# "code": 403
|
||||||
|
#}%
|
||||||
|
#curl --insecure https://127.0.0.1:61759/readyz
|
||||||
|
#ok%
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#log_note "verifying PackageInstall resources..."
|
||||||
|
#kubectl get PackageInstall -A | grep pinniped
|
||||||
|
#kubectl get secret -A | grep pinniped
|
||||||
|
#
|
||||||
|
#log_note "listing all package resources (PackageRepository, Package, PackageInstall)..."
|
||||||
|
#kubectl get pkgi && kubectl get pkgr && kubectl get pkg
|
||||||
|
#
|
||||||
|
#log_note "listing all kapp cli apps..."
|
||||||
|
## list again what is installed so we can ensure we have everything
|
||||||
|
#kapp ls --all-namespaces
|
||||||
|
#
|
||||||
|
## these are fundamentally different than what kapp cli understands, unfortunately.
|
||||||
|
## the term "app" is overloaded in Carvel and can mean two different things, based on
|
||||||
|
## the use of kapp cli and kapp-controller on cluster
|
||||||
|
#log_note "listing all kapp-controller apps..."
|
||||||
|
#kubectl get app --all-namespaces
|
||||||
|
#
|
||||||
|
## TODO:
|
||||||
|
## update the deployment.yaml and remove the deployment-HACKED.yaml files
|
||||||
|
## both are probably hacked a bit, so delete them and just get fresh from the ./deploy directory
|
||||||
|
## then make sure REAL PINNIPED actually deploys.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
## In the end we should have:
|
||||||
|
## docker pull benjaminapetersen/pinniped-package-repo:latest
|
||||||
|
## docker pull benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||||
|
## docker pull benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||||
|
#
|
||||||
|
## log_note "verifying RBAC resources created (namespace, serviceaccount, clusterrole, clusterrolebinding)..."
|
||||||
|
## kubectl get ns -A | grep pinniped
|
||||||
|
## kubectl get sa -A | grep pinniped
|
||||||
|
## kubectl get ClusterRole -A | grep pinniped
|
||||||
|
## kubectl get clusterrolebinding -A | grep pinniped
|
||||||
|
#
|
||||||
|
#
|
||||||
|
## stuff
|
||||||
|
#kubectl get PackageRepository -A
|
||||||
|
#kubectl get Package -A
|
||||||
|
#kubectl get PackageInstall -A
|
32
deploy_carvel/deploy_supervisor.sh
Executable file
32
deploy_carvel/deploy_supervisor.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||||
|
set -e # immediately exit
|
||||||
|
set -u # error if variables undefined
|
||||||
|
set -o pipefail # prevent masking errors in a pipeline
|
||||||
|
# set -x # print all executed commands to terminal
|
||||||
|
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
DEFAULT='\033[0m'
|
||||||
|
|
||||||
|
echo_yellow() {
|
||||||
|
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${GREEN}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_green() {
|
||||||
|
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
echo_red() {
|
||||||
|
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
||||||
|
echo_blue() {
|
||||||
|
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||||
|
# printf "${BLUE}$@${DEFAULT}"
|
||||||
|
}
|
85
deploy_carvel/hack/deploy-packages.sh
Executable file
85
deploy_carvel/hack/deploy-packages.sh
Executable file
@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script is intended to be used with:
|
||||||
|
# - $repo_root/hack/prepare-for-integration-test.sh --alternate-deploy $(pwd)/deploy_carvel/hack/log-args.sh
|
||||||
|
# and originated with the following:
|
||||||
|
# - https://github.com/jvanzyl/pinniped-charts/blob/main/alternate-deploy-helm
|
||||||
|
# along with this PR to pinniped:
|
||||||
|
# - https://github.com/vmware-tanzu/pinniped/pull/1028
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log_note "log-args.sh 🐳 🐳 🐳"
|
||||||
|
|
||||||
|
# two vars will be received by this script:
|
||||||
|
# Received: local-user-authenticator
|
||||||
|
# Received: D00A4537-80F1-4AF2-A3B3-5F20BDBB9AEB
|
||||||
|
log_note "passed this invocation:"
|
||||||
|
app=${1}
|
||||||
|
# tag is fed in from the prepare-for-integration-tests.sh script, just uuidgen to identify a
|
||||||
|
# specific docker build of the pinniped-server image.
|
||||||
|
tag=${2}
|
||||||
|
|
||||||
|
registry="pinniped.local"
|
||||||
|
repo="test/build"
|
||||||
|
registry_repo="$registry/$repo"
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${app}" = "local-user-authenticator" ]; then
|
||||||
|
log_note "deploy-pachage.sh: local-user-authenticator 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠"
|
||||||
|
log_note "deploy-pachage.sh: local-user-authenticator 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠"
|
||||||
|
log_note "deploy-pachage.sh: local-user-authenticator 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠 🐠"
|
||||||
|
pushd deploy/local-user-authenticator >/dev/null
|
||||||
|
manifest=/tmp/pinniped-local-user-authenticator.yaml
|
||||||
|
|
||||||
|
ytt --file . \
|
||||||
|
--data-value "image_repo=$registry_repo" \
|
||||||
|
--data-value "image_tag=$tag" >"$manifest"
|
||||||
|
|
||||||
|
kapp deploy --yes --app local-user-authenticator --diff-changes --file "$manifest"
|
||||||
|
kubectl apply --dry-run=client -f "$manifest" # Validate manifest schema.
|
||||||
|
popd >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${app}" = "pinniped-supervisor" ]; then
|
||||||
|
log_note "deploy-pachage.sh: supervisor 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡"
|
||||||
|
log_note "deploy-pachage.sh: supervisor 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡"
|
||||||
|
log_note "deploy-pachage.sh: supervisor 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡 🐡"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${app}" = "pinniped-concierge" ]; then
|
||||||
|
log_note "deploy-pachage.sh: concierge 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼"
|
||||||
|
log_note "deploy-pachage.sh: concierge 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼"
|
||||||
|
log_note "deploy-pachage.sh: concierge 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼 🪼"
|
||||||
|
fi
|
69
deploy_carvel/hack/kind-with-registry.sh
Executable file
69
deploy_carvel/hack/kind-with-registry.sh
Executable file
@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
# default name if not provided
|
||||||
|
# KIND_CLUSTER_NAME=my-kind-of-cluster ./kind-with-registry.sh
|
||||||
|
KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:=my-kind-cluster}"
|
||||||
|
|
||||||
|
# 1. Create registry container unless it already exists
|
||||||
|
reg_name='kind-registry'
|
||||||
|
reg_port='5001'
|
||||||
|
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
|
||||||
|
docker run \
|
||||||
|
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \
|
||||||
|
registry:2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Create kind cluster with containerd registry config dir enabled
|
||||||
|
# TODO: kind will eventually enable this by default and this patch will
|
||||||
|
# be unnecessary.
|
||||||
|
#
|
||||||
|
# See:
|
||||||
|
# https://github.com/kubernetes-sigs/kind/issues/2875
|
||||||
|
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
|
||||||
|
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
|
||||||
|
cat <<EOF | kind create cluster --config=-
|
||||||
|
kind: Cluster
|
||||||
|
apiVersion: kind.x-k8s.io/v1alpha4
|
||||||
|
name: ${KIND_CLUSTER_NAME}
|
||||||
|
containerdConfigPatches:
|
||||||
|
- |-
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||||
|
config_path = "/etc/containerd/certs.d"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 3. Add the registry config to the nodes
|
||||||
|
#
|
||||||
|
# This is necessary because localhost resolves to loopback addresses that are
|
||||||
|
# network-namespace local.
|
||||||
|
# In other words: localhost in the container is not localhost on the host.
|
||||||
|
#
|
||||||
|
# We want a consistent name that works from both ends, so we tell containerd to
|
||||||
|
# alias localhost:${reg_port} to the registry container when pulling images
|
||||||
|
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
|
||||||
|
for node in $(kind get nodes); do
|
||||||
|
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
|
||||||
|
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
|
||||||
|
[host."http://${reg_name}:5000"]
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
# 4. Connect the registry to the cluster network if not already connected
|
||||||
|
# This allows kind to bootstrap the network but ensures they're on the same network
|
||||||
|
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
|
||||||
|
docker network connect "kind" "${reg_name}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Document the local registry
|
||||||
|
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
|
||||||
|
cat <<EOF | kubectl apply -f -
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: local-registry-hosting
|
||||||
|
namespace: kube-public
|
||||||
|
data:
|
||||||
|
localRegistryHosting.v1: |
|
||||||
|
host: "localhost:${reg_port}"
|
||||||
|
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
|
||||||
|
EOF
|
55
deploy_carvel/hack/log-args.sh
Executable file
55
deploy_carvel/hack/log-args.sh
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script is intended to be used with:
|
||||||
|
# - $repo_root/hack/prepare-for-integration-test.sh --alternate-deploy $(pwd)/deploy_carvel/hack/log-args.sh
|
||||||
|
# and originated with the following:
|
||||||
|
# - https://github.com/jvanzyl/pinniped-charts/blob/main/alternate-deploy-helm
|
||||||
|
# along with this PR to pinniped:
|
||||||
|
# - https://github.com/vmware-tanzu/pinniped/pull/1028
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# two vars will be received by this script:
|
||||||
|
# Received: local-user-authenticator
|
||||||
|
# Received: D00A4537-80F1-4AF2-A3B3-5F20BDBB9AEB
|
||||||
|
app=${1}
|
||||||
|
# tag is fed in from the prepare-for-integration-tests.sh script, just uuidgen to identify a
|
||||||
|
# specific docker build of the pinniped-server image.
|
||||||
|
tag=${2}
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
log_note "log-args.sh >>> script dir: ${SCRIPT_DIR}"
|
||||||
|
log_note "log-args.sh >>> app: ${app} tag: ${tag}"
|
||||||
|
|
||||||
|
|
||||||
|
# nothing else, this is a test.
|
53
deploy_carvel/hack/log-args2.sh
Executable file
53
deploy_carvel/hack/log-args2.sh
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script is intended to be used with:
|
||||||
|
# - $repo_root/hack/prepare-for-integration-test.sh --alternate-deploy $(pwd)/deploy_carvel/hack/log-args.sh
|
||||||
|
# and originated with the following:
|
||||||
|
# - https://github.com/jvanzyl/pinniped-charts/blob/main/alternate-deploy-helm
|
||||||
|
# along with this PR to pinniped:
|
||||||
|
# - https://github.com/vmware-tanzu/pinniped/pull/1028
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# two vars will be received by this script:
|
||||||
|
# Received: local-user-authenticator
|
||||||
|
# Received: D00A4537-80F1-4AF2-A3B3-5F20BDBB9AEB
|
||||||
|
app=${1}
|
||||||
|
# tag is fed in from the prepare-for-integration-tests.sh script, just uuidgen to identify a
|
||||||
|
# specific docker build of the pinniped-server image.
|
||||||
|
tag=${2}
|
||||||
|
|
||||||
|
log_note "🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄"
|
||||||
|
log_note "log-args2.sh >>> app: ${app} tag: ${tag} 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄"
|
||||||
|
log_note "🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄 🦄"
|
99
deploy_carvel/hack/prepare-alt-deploy-with-package.sh
Executable file
99
deploy_carvel/hack/prepare-alt-deploy-with-package.sh
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script is intended to be used with:
|
||||||
|
# - $repo_root/hack/prepare-for-integration-test.sh --alternate-deploy deploy_carvel/prepare-alt-deploy-with-package.sh
|
||||||
|
# and originated with the following:
|
||||||
|
# - https://github.com/jvanzyl/pinniped-charts/blob/main/alternate-deploy-helm
|
||||||
|
# along with this PR to pinniped:
|
||||||
|
# - https://github.com/vmware-tanzu/pinniped/pull/1028
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper functions
|
||||||
|
#
|
||||||
|
function log_note() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "${GREEN}$*${NC}"
|
||||||
|
else
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||||
|
echo -e "🙁${RED} Error: $* ${NC}"
|
||||||
|
else
|
||||||
|
echo ":( Error: $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! command -v "$1" >/dev/null; then
|
||||||
|
log_error "Missing dependency..."
|
||||||
|
log_error "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# two vars will be received by this script:
|
||||||
|
# Received: local-user-authenticator
|
||||||
|
# Received: D00A4537-80F1-4AF2-A3B3-5F20BDBB9AEB
|
||||||
|
log_note "passed this invocation:"
|
||||||
|
app=${1}
|
||||||
|
# tag is fed in from the prepare-for-integration-tests.sh script, just uuidgen to identify a
|
||||||
|
# specific docker build of the pinniped-server image.
|
||||||
|
tag=${2}
|
||||||
|
|
||||||
|
if [ "${app}" = "local-user-authenticator" ]; then
|
||||||
|
#
|
||||||
|
# TODO: continue on from here.
|
||||||
|
# get this to install correctly, exaclty as it did before
|
||||||
|
# and then do the rest?
|
||||||
|
# OR TODO: correct the $alternate_deploy issue by creating 3 new flags:
|
||||||
|
# $alternate_deploy-supervisor
|
||||||
|
# $alternate_deploy-concierge
|
||||||
|
# $alternate_deploy-local-user-authenticator
|
||||||
|
#
|
||||||
|
# TODO step 1: test to ensure current change did not break the script!
|
||||||
|
#
|
||||||
|
log_note "🦄 🦄 🦄 where are we?!?!?"
|
||||||
|
pwd
|
||||||
|
log_note "Deploying the local-user-authenticator app to the cluster using kapp..."
|
||||||
|
ytt --file . \
|
||||||
|
--data-value "image_repo=$registry_repo" \
|
||||||
|
--data-value "image_tag=$tag" >"$manifest"
|
||||||
|
|
||||||
|
kapp deploy --yes --app local-user-authenticator --diff-changes --file "$manifest"
|
||||||
|
kubectl apply --dry-run=client -f "$manifest" # Validate manifest schema.
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${app}" = "pinniped-supervisor" ]; then
|
||||||
|
# helm upgrade pinniped-supervisor charts/pinniped-supervisor \
|
||||||
|
# --install \
|
||||||
|
# --values source/pinniped-supervisor/values-lit.yaml \
|
||||||
|
# --set image.version=${tag} \
|
||||||
|
# --namespace supervisor \
|
||||||
|
# --create-namespace \
|
||||||
|
# --atomic
|
||||||
|
# --atomic
|
||||||
|
log_note "ignoring supervisor, so sad........."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${app}" = "pinniped-concierge" ]; then
|
||||||
|
# discovery_url="$(TERM=dumb kubectl cluster-info | awk '/master|control plane/ {print $NF}')"
|
||||||
|
# helm upgrade pinniped-concierge charts/pinniped-concierge \
|
||||||
|
# --install \
|
||||||
|
# --values source/pinniped-concierge/values-lit.yaml \
|
||||||
|
# --set image.version=${tag} \
|
||||||
|
# --set config.discovery.url=${discovery_url} \
|
||||||
|
# --set config.logLevel="debug" \
|
||||||
|
# --namespace concierge \
|
||||||
|
# --create-namespace \
|
||||||
|
# --atomic
|
||||||
|
log_note "ignoring concierge, so sad........."
|
||||||
|
fi
|
9
deploy_carvel/packagerepository.0.25.0.yml
Normal file
9
deploy_carvel/packagerepository.0.25.0.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
apiVersion: packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageRepository
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-repository"
|
||||||
|
spec:
|
||||||
|
fetch:
|
||||||
|
imgpkgBundle:
|
||||||
|
image: "benjaminapetersen/pinniped-package-repo:0.25.0"
|
3
deploy_carvel/supervisor/.imgpkg/images.yml
Normal file
3
deploy_carvel/supervisor/.imgpkg/images.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
apiVersion: imgpkg.carvel.dev/v1alpha1
|
||||||
|
kind: ImagesLock
|
23
deploy_carvel/supervisor/build.yaml
Normal file
23
deploy_carvel/supervisor/build.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
---
|
||||||
|
apiVersion: kbld.k14s.io/v1alpha1
|
||||||
|
kind: Config
|
||||||
|
minimumRequiredVersion: 0.31.0 #! minimum version of kbld. We probably don't need to specify.
|
||||||
|
overrides:
|
||||||
|
#! TODO: in the pinniped yamls, this is provided by values.yaml, not declared in the deployment.
|
||||||
|
#! we should assess if we want to leave it there or move it to this form of configuration.
|
||||||
|
- image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
newImage: #@ data.values.image_repo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#! I don't think we need any of these (until we need them 😊). IE, don't use prematurely.
|
||||||
|
#! searchRules: ... # for searching input files to find container images
|
||||||
|
#! overrides: ... # overrides to apply to container images before resolving or building
|
||||||
|
#! sources: ... # source/content of a container image
|
||||||
|
#! destinations: ... # where to push built images
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#! source: TODO: we may need this at least to specify that we want kbld to build
|
||||||
|
#! a set of container images that are found in our package config yaml files.
|
3
deploy_carvel/supervisor/config/README.md
Normal file
3
deploy_carvel/supervisor/config/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Pinniped Supervisor Deployment
|
||||||
|
|
||||||
|
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-supervisor/).
|
@ -0,0 +1,170 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: federationdomains.config.supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: config.supervisor.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
kind: FederationDomain
|
||||||
|
listKind: FederationDomainList
|
||||||
|
plural: federationdomains
|
||||||
|
singular: federationdomain
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.issuer
|
||||||
|
name: Issuer
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.status
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: FederationDomain describes the configuration of an OIDC provider.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec of the OIDC provider.
|
||||||
|
properties:
|
||||||
|
issuer:
|
||||||
|
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||||
|
Metadata document, as well as the identifier that it will use for
|
||||||
|
the iss claim in issued JWTs. This field will also be used as the
|
||||||
|
base URL for any endpoints used by the OIDC Provider (e.g., if your
|
||||||
|
issuer is https://example.com/foo, then your authorization endpoint
|
||||||
|
will look like https://example.com/foo/some/path/to/auth/endpoint).
|
||||||
|
\n See https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3
|
||||||
|
for more information."
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS configures how this FederationDomain is served over
|
||||||
|
Transport Layer Security (TLS).
|
||||||
|
properties:
|
||||||
|
secretName:
|
||||||
|
description: "SecretName is an optional name of a Secret in the
|
||||||
|
same namespace, of type `kubernetes.io/tls`, which contains
|
||||||
|
the TLS serving certificate for the HTTPS endpoints served by
|
||||||
|
this FederationDomain. When provided, the TLS Secret named here
|
||||||
|
must contain keys named `tls.crt` and `tls.key` that contain
|
||||||
|
the certificate and private key to use for TLS. \n Server Name
|
||||||
|
Indication (SNI) is an extension to the Transport Layer Security
|
||||||
|
(TLS) supported by all major browsers. \n SecretName is required
|
||||||
|
if you would like to use different TLS certificates for issuers
|
||||||
|
of different hostnames. SNI requests do not include port numbers,
|
||||||
|
so all issuers with the same DNS hostname must use the same
|
||||||
|
SecretName value even if they have different port numbers. \n
|
||||||
|
SecretName is not required when you would like to use only the
|
||||||
|
HTTP endpoints (e.g. when the HTTP listener is configured to
|
||||||
|
listen on loopback interfaces or UNIX domain sockets for traffic
|
||||||
|
from a service mesh sidecar). It is also not required when you
|
||||||
|
would like all requests to this OIDC Provider's HTTPS endpoints
|
||||||
|
to use the default TLS certificate, which is configured elsewhere.
|
||||||
|
\n When your Issuer URL's host is an IP address, then this field
|
||||||
|
is ignored. SNI does not work for IP addresses."
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- issuer
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the OIDC provider.
|
||||||
|
properties:
|
||||||
|
lastUpdateTime:
|
||||||
|
description: LastUpdateTime holds the time at which the Status was
|
||||||
|
last updated. It is a pointer to get around some undesirable behavior
|
||||||
|
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: Message provides human-readable details about the Status.
|
||||||
|
type: string
|
||||||
|
secrets:
|
||||||
|
description: Secrets contains information about this OIDC Provider's
|
||||||
|
secrets.
|
||||||
|
properties:
|
||||||
|
jwks:
|
||||||
|
description: JWKS holds the name of the corev1.Secret in which
|
||||||
|
this OIDC Provider's signing/verification keys are stored. If
|
||||||
|
it is empty, then the signing/verification keys are either unknown
|
||||||
|
or they don't exist.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
stateEncryptionKey:
|
||||||
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
|
in which this OIDC Provider's key for encrypting state parameters
|
||||||
|
is stored.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
stateSigningKey:
|
||||||
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
|
in which this OIDC Provider's key for signing state parameters
|
||||||
|
is stored.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
tokenSigningKey:
|
||||||
|
description: TokenSigningKey holds the name of the corev1.Secret
|
||||||
|
in which this OIDC Provider's key for signing tokens is stored.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status holds an enum that describes the state of this
|
||||||
|
OIDC Provider. Note that this Status can represent success or failure.
|
||||||
|
enum:
|
||||||
|
- Success
|
||||||
|
- Duplicate
|
||||||
|
- Invalid
|
||||||
|
- SameIssuerHostMustUseSameSecret
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -0,0 +1,221 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: oidcclients.config.supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: config.supervisor.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
kind: OIDCClient
|
||||||
|
listKind: OIDCClientList
|
||||||
|
plural: oidcclients
|
||||||
|
singular: oidcclient
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.allowedScopes[?(@ == "pinniped:request-audience")]
|
||||||
|
name: Privileged Scopes
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.totalClientSecrets
|
||||||
|
name: Client Secrets
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.phase
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: OIDCClient describes the configuration of an OIDC client.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec of the OIDC client.
|
||||||
|
properties:
|
||||||
|
allowedGrantTypes:
|
||||||
|
description: "allowedGrantTypes is a list of the allowed grant_type
|
||||||
|
param values that should be accepted during OIDC flows with this
|
||||||
|
client. \n Must only contain the following values: - authorization_code:
|
||||||
|
allows the client to perform the authorization code grant flow,
|
||||||
|
i.e. allows the webapp to authenticate users. This grant must always
|
||||||
|
be listed. - refresh_token: allows the client to perform refresh
|
||||||
|
grants for the user to extend the user's session. This grant must
|
||||||
|
be listed if allowedScopes lists offline_access. - urn:ietf:params:oauth:grant-type:token-exchange:
|
||||||
|
allows the client to perform RFC8693 token exchange, which is a
|
||||||
|
step in the process to be able to get a cluster credential for the
|
||||||
|
user. This grant must be listed if allowedScopes lists pinniped:request-audience."
|
||||||
|
items:
|
||||||
|
enum:
|
||||||
|
- authorization_code
|
||||||
|
- refresh_token
|
||||||
|
- urn:ietf:params:oauth:grant-type:token-exchange
|
||||||
|
type: string
|
||||||
|
minItems: 1
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: set
|
||||||
|
allowedRedirectURIs:
|
||||||
|
description: allowedRedirectURIs is a list of the allowed redirect_uri
|
||||||
|
param values that should be accepted during OIDC flows with this
|
||||||
|
client. Any other uris will be rejected. Must be a URI with the
|
||||||
|
https scheme, unless the hostname is 127.0.0.1 or ::1 which may
|
||||||
|
use the http scheme. Port numbers are not required for 127.0.0.1
|
||||||
|
or ::1 and are ignored when checking for a matching redirect_uri.
|
||||||
|
items:
|
||||||
|
pattern: ^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/
|
||||||
|
type: string
|
||||||
|
minItems: 1
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: set
|
||||||
|
allowedScopes:
|
||||||
|
description: "allowedScopes is a list of the allowed scopes param
|
||||||
|
values that should be accepted during OIDC flows with this client.
|
||||||
|
\n Must only contain the following values: - openid: The client
|
||||||
|
is allowed to request ID tokens. ID tokens only include the required
|
||||||
|
claims by default (iss, sub, aud, exp, iat). This scope must always
|
||||||
|
be listed. - offline_access: The client is allowed to request an
|
||||||
|
initial refresh token during the authorization code grant flow.
|
||||||
|
This scope must be listed if allowedGrantTypes lists refresh_token.
|
||||||
|
- pinniped:request-audience: The client is allowed to request a
|
||||||
|
new audience value during a RFC8693 token exchange, which is a step
|
||||||
|
in the process to be able to get a cluster credential for the user.
|
||||||
|
openid, username and groups scopes must be listed when this scope
|
||||||
|
is present. This scope must be listed if allowedGrantTypes lists
|
||||||
|
urn:ietf:params:oauth:grant-type:token-exchange. - username: The
|
||||||
|
client is allowed to request that ID tokens contain the user's username.
|
||||||
|
Without the username scope being requested and allowed, the ID token
|
||||||
|
will not contain the user's username. - groups: The client is allowed
|
||||||
|
to request that ID tokens contain the user's group membership, if
|
||||||
|
their group membership is discoverable by the Supervisor. Without
|
||||||
|
the groups scope being requested and allowed, the ID token will
|
||||||
|
not contain groups."
|
||||||
|
items:
|
||||||
|
enum:
|
||||||
|
- openid
|
||||||
|
- offline_access
|
||||||
|
- username
|
||||||
|
- groups
|
||||||
|
- pinniped:request-audience
|
||||||
|
type: string
|
||||||
|
minItems: 1
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: set
|
||||||
|
required:
|
||||||
|
- allowedGrantTypes
|
||||||
|
- allowedRedirectURIs
|
||||||
|
- allowedScopes
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the OIDC client.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: conditions represent the observations of an OIDCClient's
|
||||||
|
current state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
phase:
|
||||||
|
default: Pending
|
||||||
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
|
enum:
|
||||||
|
- Pending
|
||||||
|
- Ready
|
||||||
|
- Error
|
||||||
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
format: int32
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
236
deploy_carvel/supervisor/config/deployment.yaml
Normal file
236
deploy_carvel/supervisor/config/deployment.yaml
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:yaml", "yaml")
|
||||||
|
#@ load("helpers.lib.yaml",
|
||||||
|
#@ "defaultLabel",
|
||||||
|
#@ "labels",
|
||||||
|
#@ "deploymentPodLabel",
|
||||||
|
#@ "namespace",
|
||||||
|
#@ "defaultResourceName",
|
||||||
|
#@ "defaultResourceNameWithSuffix",
|
||||||
|
#@ "pinnipedDevAPIGroupWithPrefix",
|
||||||
|
#@ "getPinnipedConfigMapData",
|
||||||
|
#@ "hasUnixNetworkEndpoint",
|
||||||
|
#@ )
|
||||||
|
#@ load("@ytt:template", "template")
|
||||||
|
|
||||||
|
#@ if not data.values.into_namespace:
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: #@ data.values.namespace
|
||||||
|
labels: #@ labels()
|
||||||
|
#@ end
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("static-config")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
data:
|
||||||
|
#@yaml/text-templated-strings
|
||||||
|
pinniped.yaml: #@ yaml.encode(getPinnipedConfigMapData())
|
||||||
|
---
|
||||||
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: image-pull-secret
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
.dockerconfigjson: #@ data.values.image_pull_dockerconfigjson
|
||||||
|
#@ end
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
replicas: #@ data.values.replicas
|
||||||
|
selector:
|
||||||
|
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
|
||||||
|
matchLabels: #@ defaultLabel()
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
#! This has always included defaultLabel(), which is used by this Deployment's selector.
|
||||||
|
_: #@ template.replace(defaultLabel())
|
||||||
|
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||||
|
#! without accidentally selecting pods from any future Deployments which might also want to use the defaultLabel().
|
||||||
|
_: #@ template.replace(deploymentPodLabel())
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: #@ data.values.run_as_user
|
||||||
|
runAsGroup: #@ data.values.run_as_group
|
||||||
|
serviceAccountName: #@ defaultResourceName()
|
||||||
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: image-pull-secret
|
||||||
|
#@ end
|
||||||
|
containers:
|
||||||
|
- name: #@ defaultResourceName()
|
||||||
|
#@ if data.values.image_digest:
|
||||||
|
image: #@ data.values.image_repo + "@" + data.values.image_digest
|
||||||
|
#@ else:
|
||||||
|
image: #@ data.values.image_repo + ":" + data.values.image_tag
|
||||||
|
#@ end
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command:
|
||||||
|
- pinniped-supervisor
|
||||||
|
- /etc/podinfo
|
||||||
|
- /etc/config/pinniped.yaml
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ "ALL" ]
|
||||||
|
#! seccompProfile was introduced in Kube v1.19. Using it on an older Kube version will result in a
|
||||||
|
#! kubectl validation error when installing via `kubectl apply`, which can be ignored using kubectl's
|
||||||
|
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||||
|
seccompProfile:
|
||||||
|
type: "RuntimeDefault"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
#! If OIDCClient CRs are being used, then the Supervisor needs enough CPU to run expensive bcrypt
|
||||||
|
#! operations inside the implementation of the token endpoint for any authcode flows performed by those
|
||||||
|
#! clients, so for that use case administrators may wish to increase the requests.cpu value to more
|
||||||
|
#! closely align with their anticipated needs. Increasing this value will cause Kubernetes to give more
|
||||||
|
#! available CPU to this process during times of high CPU contention. By default, don't ask for too much
|
||||||
|
#! because that would make it impossible to install the Pinniped Supervisor on small clusters.
|
||||||
|
#! Aside from performing bcrypts at the token endpoint for those clients, the Supervisor is not a
|
||||||
|
#! particularly CPU-intensive process.
|
||||||
|
cpu: "100m" #! by default, request one-tenth of a CPU
|
||||||
|
memory: "128Mi"
|
||||||
|
limits:
|
||||||
|
#! By declaring a CPU limit that is not equal to the CPU request value, the Supervisor will be classified
|
||||||
|
#! by Kubernetes to have "burstable" quality of service.
|
||||||
|
#! See https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-burstable
|
||||||
|
#! If OIDCClient CRs are being used, and lots of simultaneous users have active sessions, then it is hard
|
||||||
|
#! pre-determine what the CPU limit should be for that use case. Guessing too low would cause the
|
||||||
|
#! pod's CPU usage to be throttled, resulting in poor performance. Guessing too high would allow clients
|
||||||
|
#! to cause the usage of lots of CPU resources. Administrators who have a good sense of anticipated usage
|
||||||
|
#! patterns may choose to set the requests.cpu and limits.cpu differently from these defaults.
|
||||||
|
cpu: "1000m" #! by default, throttle each pod's usage at 1 CPU
|
||||||
|
memory: "128Mi"
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /etc/config
|
||||||
|
readOnly: true
|
||||||
|
- name: podinfo
|
||||||
|
mountPath: /etc/podinfo
|
||||||
|
readOnly: true
|
||||||
|
#@ if hasUnixNetworkEndpoint():
|
||||||
|
- name: socket
|
||||||
|
mountPath: /pinniped_socket
|
||||||
|
readOnly: false #! writable to allow for socket use
|
||||||
|
#@ end
|
||||||
|
ports:
|
||||||
|
- containerPort: 8443
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
#@ if data.values.https_proxy:
|
||||||
|
- name: HTTPS_PROXY
|
||||||
|
value: #@ data.values.https_proxy
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.https_proxy and data.values.no_proxy:
|
||||||
|
- name: NO_PROXY
|
||||||
|
value: #@ data.values.no_proxy
|
||||||
|
#@ end
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8443
|
||||||
|
scheme: HTTPS
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
timeoutSeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8443
|
||||||
|
scheme: HTTPS
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
timeoutSeconds: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("static-config")
|
||||||
|
- name: podinfo
|
||||||
|
downwardAPI:
|
||||||
|
items:
|
||||||
|
- path: "labels"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.labels
|
||||||
|
- path: "namespace"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- path: "name"
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
#@ if hasUnixNetworkEndpoint():
|
||||||
|
- name: socket
|
||||||
|
emptyDir: {}
|
||||||
|
#@ end
|
||||||
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
|
#! our deployment "more" "HA".
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- weight: 50
|
||||||
|
podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels: #@ deploymentPodLabel()
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
#! If name is changed, must also change names.apiService in the ConfigMap above and spec.service.name in the APIService below.
|
||||||
|
name: #@ defaultResourceNameWithSuffix("api")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 10250
|
||||||
|
---
|
||||||
|
apiVersion: apiregistration.k8s.io/v1
|
||||||
|
kind: APIService
|
||||||
|
metadata:
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.clientsecret.supervisor")
|
||||||
|
labels: #@ labels()
|
||||||
|
spec:
|
||||||
|
version: v1alpha1
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("clientsecret.supervisor")
|
||||||
|
groupPriorityMinimum: 9900
|
||||||
|
versionPriority: 15
|
||||||
|
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||||
|
service:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("api")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
port: 443
|
88
deploy_carvel/supervisor/config/helpers.lib.yaml
Normal file
88
deploy_carvel/supervisor/config/helpers.lib.yaml
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:template", "template")
|
||||||
|
|
||||||
|
#@ def defaultResourceName():
|
||||||
|
#@ return data.values.app_name
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def defaultResourceNameWithSuffix(suffix):
|
||||||
|
#@ return data.values.app_name + "-" + suffix
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def pinnipedDevAPIGroupWithPrefix(prefix):
|
||||||
|
#@ return prefix + "." + data.values.api_group_suffix
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def namespace():
|
||||||
|
#@ if data.values.into_namespace:
|
||||||
|
#@ return data.values.into_namespace
|
||||||
|
#@ else:
|
||||||
|
#@ return data.values.namespace
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def defaultLabel():
|
||||||
|
app: #@ data.values.app_name
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def deploymentPodLabel():
|
||||||
|
deployment.pinniped.dev: supervisor
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def labels():
|
||||||
|
_: #@ template.replace(defaultLabel())
|
||||||
|
_: #@ template.replace(data.values.custom_labels)
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def getAndValidateLogLevel():
|
||||||
|
#@ log_level = data.values.log_level
|
||||||
|
#@ if log_level != "info" and log_level != "debug" and log_level != "trace" and log_level != "all":
|
||||||
|
#@ fail("log_level '" + log_level + "' is invalid")
|
||||||
|
#@ end
|
||||||
|
#@ return log_level
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def getPinnipedConfigMapData():
|
||||||
|
#@ config = {
|
||||||
|
#@ "apiGroupSuffix": data.values.api_group_suffix,
|
||||||
|
#@ "names": {
|
||||||
|
#@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"),
|
||||||
|
#@ "apiService": defaultResourceNameWithSuffix("api"),
|
||||||
|
#@ },
|
||||||
|
#@ "labels": labels(),
|
||||||
|
#@ "insecureAcceptExternalUnencryptedHttpRequests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests
|
||||||
|
#@ }
|
||||||
|
#@ if data.values.log_level or data.values.deprecated_log_format:
|
||||||
|
#@ config["log"] = {}
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.log_level:
|
||||||
|
#@ config["log"]["level"] = getAndValidateLogLevel()
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.deprecated_log_format:
|
||||||
|
#@ config["log"]["format"] = data.values.deprecated_log_format
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.endpoints:
|
||||||
|
#@ config["endpoints"] = data.values.endpoints
|
||||||
|
#@ end
|
||||||
|
#@ return config
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def getattr_safe(val, *args):
|
||||||
|
#@ out = None
|
||||||
|
#@ for arg in args:
|
||||||
|
#@ if not hasattr(val, arg):
|
||||||
|
#@ return None
|
||||||
|
#@ end
|
||||||
|
#@ out = getattr(val, arg)
|
||||||
|
#@ val = out
|
||||||
|
#@ end
|
||||||
|
#@ return out
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ def hasUnixNetworkEndpoint():
|
||||||
|
#@ return getattr_safe(data.values.endpoints, "http", "network") == "unix" or \
|
||||||
|
#@ getattr_safe(data.values.endpoints, "https", "network") == "unix"
|
||||||
|
#@ end
|
@ -0,0 +1,319 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: idp.supervisor.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
- pinniped-idp
|
||||||
|
- pinniped-idps
|
||||||
|
kind: ActiveDirectoryIdentityProvider
|
||||||
|
listKind: ActiveDirectoryIdentityProviderList
|
||||||
|
plural: activedirectoryidentityproviders
|
||||||
|
singular: activedirectoryidentityprovider
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.host
|
||||||
|
name: Host
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.phase
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ActiveDirectoryIdentityProvider describes the configuration of
|
||||||
|
an upstream Microsoft Active Directory identity provider.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec for configuring the identity provider.
|
||||||
|
properties:
|
||||||
|
bind:
|
||||||
|
description: Bind contains the configuration for how to provide access
|
||||||
|
credentials during an initial bind to the ActiveDirectory server
|
||||||
|
to be allowed to perform searches and binds to validate a user's
|
||||||
|
credentials during a user's authentication attempt.
|
||||||
|
properties:
|
||||||
|
secretName:
|
||||||
|
description: SecretName contains the name of a namespace-local
|
||||||
|
Secret object that provides the username and password for an
|
||||||
|
Active Directory bind user. This account will be used to perform
|
||||||
|
LDAP searches. The Secret should be of type "kubernetes.io/basic-auth"
|
||||||
|
which includes "username" and "password" keys. The username
|
||||||
|
value should be the full dn (distinguished name) of your bind
|
||||||
|
account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
|
||||||
|
The password must be non-empty.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- secretName
|
||||||
|
type: object
|
||||||
|
groupSearch:
|
||||||
|
description: GroupSearch contains the configuration for searching
|
||||||
|
for a user's group membership in ActiveDirectory.
|
||||||
|
properties:
|
||||||
|
attributes:
|
||||||
|
description: Attributes specifies how the group's information
|
||||||
|
should be read from each ActiveDirectory entry which was found
|
||||||
|
as the result of the group search.
|
||||||
|
properties:
|
||||||
|
groupName:
|
||||||
|
description: GroupName specifies the name of the attribute
|
||||||
|
in the Active Directory entries whose value shall become
|
||||||
|
a group name in the user's list of groups after a successful
|
||||||
|
authentication. The value of this field is case-sensitive
|
||||||
|
and must match the case of the attribute name returned by
|
||||||
|
the ActiveDirectory server in the user's entry. E.g. "cn"
|
||||||
|
for common name. Distinguished names can be used by specifying
|
||||||
|
lower-case "dn". Optional. When not specified, this defaults
|
||||||
|
to a custom field that looks like "sAMAccountName@domain",
|
||||||
|
where domain is constructed from the domain components of
|
||||||
|
the group DN.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
base:
|
||||||
|
description: Base is the dn (distinguished name) that should be
|
||||||
|
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
|
||||||
|
Optional, when not specified it will be based on the result
|
||||||
|
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
|
||||||
|
The default behavior searches your entire domain for groups.
|
||||||
|
It may make sense to specify a subtree as a search base if you
|
||||||
|
wish to exclude some groups for security reasons or to make
|
||||||
|
searches faster.
|
||||||
|
type: string
|
||||||
|
filter:
|
||||||
|
description: Filter is the ActiveDirectory search filter which
|
||||||
|
should be applied when searching for groups for a user. The
|
||||||
|
pattern "{}" must occur in the filter at least once and will
|
||||||
|
be dynamically replaced by the value of an attribute of the
|
||||||
|
user entry found as a result of the user search. Which attribute's
|
||||||
|
value is used to replace the placeholder(s) depends on the value
|
||||||
|
of UserAttributeForFilter. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||||
|
For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
||||||
|
Note that the dn (distinguished name) is not an attribute of
|
||||||
|
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
||||||
|
the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
|
||||||
|
This searches nested groups by default. Note that nested group
|
||||||
|
search can be slow for some Active Directory servers. To disable
|
||||||
|
it, you can set the filter to "(&(objectClass=group)(member={})"
|
||||||
|
type: string
|
||||||
|
skipGroupRefresh:
|
||||||
|
description: "The user's group membership is refreshed as they
|
||||||
|
interact with the supervisor to obtain new credentials (as their
|
||||||
|
old credentials expire). This allows group membership changes
|
||||||
|
to be quickly reflected into Kubernetes clusters. Since group
|
||||||
|
membership is often used to bind authorization policies, it
|
||||||
|
is important to keep the groups observed in Kubernetes clusters
|
||||||
|
in-sync with the identity provider. \n In some environments,
|
||||||
|
frequent group membership queries may result in a significant
|
||||||
|
performance impact on the identity provider and/or the supervisor.
|
||||||
|
The best approach to handle performance impacts is to tweak
|
||||||
|
the group query to be more performant, for example by disabling
|
||||||
|
nested group search or by using a more targeted group search
|
||||||
|
base. \n If the group search query cannot be made performant
|
||||||
|
and you are willing to have group memberships remain static
|
||||||
|
for approximately a day, then set skipGroupRefresh to true.
|
||||||
|
\ This is an insecure configuration as authorization policies
|
||||||
|
that are bound to group membership will not notice if a user
|
||||||
|
has been removed from a particular group until their next login.
|
||||||
|
\n This is an experimental feature that may be removed or significantly
|
||||||
|
altered in the future. Consumers of this configuration should
|
||||||
|
carefully read all release notes before upgrading to ensure
|
||||||
|
that the meaning of this field has not changed."
|
||||||
|
type: boolean
|
||||||
|
userAttributeForFilter:
|
||||||
|
description: UserAttributeForFilter specifies which attribute's
|
||||||
|
value from the user entry found as a result of the user search
|
||||||
|
will be used to replace the "{}" placeholder(s) in the group
|
||||||
|
search Filter. For example, specifying "uid" as the UserAttributeForFilter
|
||||||
|
while specifying "&(objectClass=posixGroup)(memberUid={})" as
|
||||||
|
the Filter would search for groups by replacing the "{}" placeholder
|
||||||
|
in the Filter with the value of the user's "uid" attribute.
|
||||||
|
Optional. When not specified, the default will act as if "dn"
|
||||||
|
were specified. For example, leaving UserAttributeForFilter
|
||||||
|
unspecified while specifying "&(objectClass=groupOfNames)(member={})"
|
||||||
|
as the Filter would search for groups by replacing the "{}"
|
||||||
|
placeholder(s) with the dn (distinguished name) of the user.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
host:
|
||||||
|
description: 'Host is the hostname of this Active Directory identity
|
||||||
|
provider, i.e., where to connect. For example: ldap.example.com:636.'
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS contains the connection settings for how to establish
|
||||||
|
the connection to the Host.
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||||
|
If omitted, a default set of system roots will be trusted.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
userSearch:
|
||||||
|
description: UserSearch contains the configuration for searching for
|
||||||
|
a user by name in Active Directory.
|
||||||
|
properties:
|
||||||
|
attributes:
|
||||||
|
description: Attributes specifies how the user's information should
|
||||||
|
be read from the ActiveDirectory entry which was found as the
|
||||||
|
result of the user search.
|
||||||
|
properties:
|
||||||
|
uid:
|
||||||
|
description: UID specifies the name of the attribute in the
|
||||||
|
ActiveDirectory entry which whose value shall be used to
|
||||||
|
uniquely identify the user within this ActiveDirectory provider
|
||||||
|
after a successful authentication. Optional, when empty
|
||||||
|
this defaults to "objectGUID".
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
description: Username specifies the name of the attribute
|
||||||
|
in Active Directory entry whose value shall become the username
|
||||||
|
of the user after a successful authentication. Optional,
|
||||||
|
when empty this defaults to "userPrincipalName".
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
base:
|
||||||
|
description: Base is the dn (distinguished name) that should be
|
||||||
|
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
|
||||||
|
Optional, when not specified it will be based on the result
|
||||||
|
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
|
||||||
|
The default behavior searches your entire domain for users.
|
||||||
|
It may make sense to specify a subtree as a search base if you
|
||||||
|
wish to exclude some users or to make searches faster.
|
||||||
|
type: string
|
||||||
|
filter:
|
||||||
|
description: Filter is the search filter which should be applied
|
||||||
|
when searching for users. The pattern "{}" must occur in the
|
||||||
|
filter at least once and will be dynamically replaced by the
|
||||||
|
username for which the search is being run. E.g. "mail={}" or
|
||||||
|
"&(objectClass=person)(uid={})". For more information about
|
||||||
|
LDAP filters, see https://ldap.com/ldap-filters. Note that the
|
||||||
|
dn (distinguished name) is not an attribute of an entry, so
|
||||||
|
"dn={}" cannot be used. Optional. When not specified, the default
|
||||||
|
will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
|
||||||
|
This means that the user is a person, is not a computer, the
|
||||||
|
sAMAccountType is for a normal user account, and is not shown
|
||||||
|
in advanced view only (which would likely mean its a system
|
||||||
|
created service account with advanced permissions). Also, either
|
||||||
|
the sAMAccountName, the userPrincipalName, or the mail attribute
|
||||||
|
matches the input username.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- host
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the identity provider.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Represents the observations of an identity provider's
|
||||||
|
current state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
phase:
|
||||||
|
default: Pending
|
||||||
|
description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
|
||||||
|
enum:
|
||||||
|
- Pending
|
||||||
|
- Ready
|
||||||
|
- Error
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -0,0 +1,316 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: idp.supervisor.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
- pinniped-idp
|
||||||
|
- pinniped-idps
|
||||||
|
kind: LDAPIdentityProvider
|
||||||
|
listKind: LDAPIdentityProviderList
|
||||||
|
plural: ldapidentityproviders
|
||||||
|
singular: ldapidentityprovider
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.host
|
||||||
|
name: Host
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.phase
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: LDAPIdentityProvider describes the configuration of an upstream
|
||||||
|
Lightweight Directory Access Protocol (LDAP) identity provider.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec for configuring the identity provider.
|
||||||
|
properties:
|
||||||
|
bind:
|
||||||
|
description: Bind contains the configuration for how to provide access
|
||||||
|
credentials during an initial bind to the LDAP server to be allowed
|
||||||
|
to perform searches and binds to validate a user's credentials during
|
||||||
|
a user's authentication attempt.
|
||||||
|
properties:
|
||||||
|
secretName:
|
||||||
|
description: SecretName contains the name of a namespace-local
|
||||||
|
Secret object that provides the username and password for an
|
||||||
|
LDAP bind user. This account will be used to perform LDAP searches.
|
||||||
|
The Secret should be of type "kubernetes.io/basic-auth" which
|
||||||
|
includes "username" and "password" keys. The username value
|
||||||
|
should be the full dn (distinguished name) of your bind account,
|
||||||
|
e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password
|
||||||
|
must be non-empty.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- secretName
|
||||||
|
type: object
|
||||||
|
groupSearch:
|
||||||
|
description: GroupSearch contains the configuration for searching
|
||||||
|
for a user's group membership in the LDAP provider.
|
||||||
|
properties:
|
||||||
|
attributes:
|
||||||
|
description: Attributes specifies how the group's information
|
||||||
|
should be read from each LDAP entry which was found as the result
|
||||||
|
of the group search.
|
||||||
|
properties:
|
||||||
|
groupName:
|
||||||
|
description: GroupName specifies the name of the attribute
|
||||||
|
in the LDAP entries whose value shall become a group name
|
||||||
|
in the user's list of groups after a successful authentication.
|
||||||
|
The value of this field is case-sensitive and must match
|
||||||
|
the case of the attribute name returned by the LDAP server
|
||||||
|
in the user's entry. E.g. "cn" for common name. Distinguished
|
||||||
|
names can be used by specifying lower-case "dn". Optional.
|
||||||
|
When not specified, the default will act as if the GroupName
|
||||||
|
were specified as "dn" (distinguished name).
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
base:
|
||||||
|
description: Base is the dn (distinguished name) that should be
|
||||||
|
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
|
||||||
|
When not specified, no group search will be performed and authenticated
|
||||||
|
users will not belong to any groups from the LDAP provider.
|
||||||
|
Also, when not specified, the values of Filter, UserAttributeForFilter,
|
||||||
|
Attributes, and SkipGroupRefresh are ignored.
|
||||||
|
type: string
|
||||||
|
filter:
|
||||||
|
description: Filter is the LDAP search filter which should be
|
||||||
|
applied when searching for groups for a user. The pattern "{}"
|
||||||
|
must occur in the filter at least once and will be dynamically
|
||||||
|
replaced by the value of an attribute of the user entry found
|
||||||
|
as a result of the user search. Which attribute's value is used
|
||||||
|
to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||||
|
For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
||||||
|
Note that the dn (distinguished name) is not an attribute of
|
||||||
|
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
||||||
|
the default will act as if the Filter were specified as "member={}".
|
||||||
|
type: string
|
||||||
|
skipGroupRefresh:
|
||||||
|
description: "The user's group membership is refreshed as they
|
||||||
|
interact with the supervisor to obtain new credentials (as their
|
||||||
|
old credentials expire). This allows group membership changes
|
||||||
|
to be quickly reflected into Kubernetes clusters. Since group
|
||||||
|
membership is often used to bind authorization policies, it
|
||||||
|
is important to keep the groups observed in Kubernetes clusters
|
||||||
|
in-sync with the identity provider. \n In some environments,
|
||||||
|
frequent group membership queries may result in a significant
|
||||||
|
performance impact on the identity provider and/or the supervisor.
|
||||||
|
The best approach to handle performance impacts is to tweak
|
||||||
|
the group query to be more performant, for example by disabling
|
||||||
|
nested group search or by using a more targeted group search
|
||||||
|
base. \n If the group search query cannot be made performant
|
||||||
|
and you are willing to have group memberships remain static
|
||||||
|
for approximately a day, then set skipGroupRefresh to true.
|
||||||
|
\ This is an insecure configuration as authorization policies
|
||||||
|
that are bound to group membership will not notice if a user
|
||||||
|
has been removed from a particular group until their next login.
|
||||||
|
\n This is an experimental feature that may be removed or significantly
|
||||||
|
altered in the future. Consumers of this configuration should
|
||||||
|
carefully read all release notes before upgrading to ensure
|
||||||
|
that the meaning of this field has not changed."
|
||||||
|
type: boolean
|
||||||
|
userAttributeForFilter:
|
||||||
|
description: UserAttributeForFilter specifies which attribute's
|
||||||
|
value from the user entry found as a result of the user search
|
||||||
|
will be used to replace the "{}" placeholder(s) in the group
|
||||||
|
search Filter. For example, specifying "uid" as the UserAttributeForFilter
|
||||||
|
while specifying "&(objectClass=posixGroup)(memberUid={})" as
|
||||||
|
the Filter would search for groups by replacing the "{}" placeholder
|
||||||
|
in the Filter with the value of the user's "uid" attribute.
|
||||||
|
Optional. When not specified, the default will act as if "dn"
|
||||||
|
were specified. For example, leaving UserAttributeForFilter
|
||||||
|
unspecified while specifying "&(objectClass=groupOfNames)(member={})"
|
||||||
|
as the Filter would search for groups by replacing the "{}"
|
||||||
|
placeholder(s) with the dn (distinguished name) of the user.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
host:
|
||||||
|
description: 'Host is the hostname of this LDAP identity provider,
|
||||||
|
i.e., where to connect. For example: ldap.example.com:636.'
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS contains the connection settings for how to establish
|
||||||
|
the connection to the Host.
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||||
|
If omitted, a default set of system roots will be trusted.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
userSearch:
|
||||||
|
description: UserSearch contains the configuration for searching for
|
||||||
|
a user by name in the LDAP provider.
|
||||||
|
properties:
|
||||||
|
attributes:
|
||||||
|
description: Attributes specifies how the user's information should
|
||||||
|
be read from the LDAP entry which was found as the result of
|
||||||
|
the user search.
|
||||||
|
properties:
|
||||||
|
uid:
|
||||||
|
description: UID specifies the name of the attribute in the
|
||||||
|
LDAP entry which whose value shall be used to uniquely identify
|
||||||
|
the user within this LDAP provider after a successful authentication.
|
||||||
|
E.g. "uidNumber" or "objectGUID". The value of this field
|
||||||
|
is case-sensitive and must match the case of the attribute
|
||||||
|
name returned by the LDAP server in the user's entry. Distinguished
|
||||||
|
names can be used by specifying lower-case "dn".
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
description: Username specifies the name of the attribute
|
||||||
|
in the LDAP entry whose value shall become the username
|
||||||
|
of the user after a successful authentication. This would
|
||||||
|
typically be the same attribute name used in the user search
|
||||||
|
filter, although it can be different. E.g. "mail" or "uid"
|
||||||
|
or "userPrincipalName". The value of this field is case-sensitive
|
||||||
|
and must match the case of the attribute name returned by
|
||||||
|
the LDAP server in the user's entry. Distinguished names
|
||||||
|
can be used by specifying lower-case "dn". When this field
|
||||||
|
is set to "dn" then the LDAPIdentityProviderUserSearch's
|
||||||
|
Filter field cannot be blank, since the default value of
|
||||||
|
"dn={}" would not work.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
base:
|
||||||
|
description: Base is the dn (distinguished name) that should be
|
||||||
|
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
filter:
|
||||||
|
description: Filter is the LDAP search filter which should be
|
||||||
|
applied when searching for users. The pattern "{}" must occur
|
||||||
|
in the filter at least once and will be dynamically replaced
|
||||||
|
by the username for which the search is being run. E.g. "mail={}"
|
||||||
|
or "&(objectClass=person)(uid={})". For more information about
|
||||||
|
LDAP filters, see https://ldap.com/ldap-filters. Note that the
|
||||||
|
dn (distinguished name) is not an attribute of an entry, so
|
||||||
|
"dn={}" cannot be used. Optional. When not specified, the default
|
||||||
|
will act as if the Filter were specified as the value from Attributes.Username
|
||||||
|
appended by "={}". When the Attributes.Username is set to "dn"
|
||||||
|
then the Filter must be explicitly specified, since the default
|
||||||
|
value of "dn={}" would not work.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- host
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the identity provider.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Represents the observations of an identity provider's
|
||||||
|
current state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
phase:
|
||||||
|
default: Pending
|
||||||
|
description: Phase summarizes the overall status of the LDAPIdentityProvider.
|
||||||
|
enum:
|
||||||
|
- Pending
|
||||||
|
- Ready
|
||||||
|
- Error
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -0,0 +1,346 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
group: idp.supervisor.pinniped.dev
|
||||||
|
names:
|
||||||
|
categories:
|
||||||
|
- pinniped
|
||||||
|
- pinniped-idp
|
||||||
|
- pinniped-idps
|
||||||
|
kind: OIDCIdentityProvider
|
||||||
|
listKind: OIDCIdentityProviderList
|
||||||
|
plural: oidcidentityproviders
|
||||||
|
singular: oidcidentityprovider
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.issuer
|
||||||
|
name: Issuer
|
||||||
|
type: string
|
||||||
|
- jsonPath: .status.phase
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: OIDCIdentityProvider describes the configuration of an upstream
|
||||||
|
OpenID Connect identity provider.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: Spec for configuring the identity provider.
|
||||||
|
properties:
|
||||||
|
authorizationConfig:
|
||||||
|
description: AuthorizationConfig holds information about how to form
|
||||||
|
the OAuth2 authorization request parameters to be used with this
|
||||||
|
OIDC identity provider.
|
||||||
|
properties:
|
||||||
|
additionalAuthorizeParameters:
|
||||||
|
description: additionalAuthorizeParameters are extra query parameters
|
||||||
|
that should be included in the authorize request to your OIDC
|
||||||
|
provider in the authorization request during an OIDC Authorization
|
||||||
|
Code Flow. By default, no extra parameters are sent. The standard
|
||||||
|
parameters that will be sent are "response_type", "scope", "client_id",
|
||||||
|
"state", "nonce", "code_challenge", "code_challenge_method",
|
||||||
|
and "redirect_uri". These parameters cannot be included in this
|
||||||
|
setting. Additionally, the "hd" parameter cannot be included
|
||||||
|
in this setting at this time. The "hd" parameter is used by
|
||||||
|
Google's OIDC provider to provide a hint as to which "hosted
|
||||||
|
domain" the user should use during login. However, Pinniped
|
||||||
|
does not yet support validating the hosted domain in the resulting
|
||||||
|
ID token, so it is not yet safe to use this feature of Google's
|
||||||
|
OIDC provider with Pinniped. This setting does not influence
|
||||||
|
the parameters sent to the token endpoint in the Resource Owner
|
||||||
|
Password Credentials Grant. The Pinniped Supervisor requires
|
||||||
|
that your OIDC provider returns refresh tokens to the Supervisor
|
||||||
|
from the authorization flows. Some OIDC providers may require
|
||||||
|
a certain value for the "prompt" parameter in order to properly
|
||||||
|
request refresh tokens. See the documentation of your OIDC provider's
|
||||||
|
authorization endpoint for its requirements for what to include
|
||||||
|
in the request in order to receive a refresh token in the response,
|
||||||
|
if anything. If your provider requires the prompt parameter
|
||||||
|
to request a refresh token, then include it here. Also note
|
||||||
|
that most providers also require a certain scope to be requested
|
||||||
|
in order to receive refresh tokens. See the additionalScopes
|
||||||
|
setting for more information about using scopes to request refresh
|
||||||
|
tokens.
|
||||||
|
items:
|
||||||
|
description: Parameter is a key/value pair which represents
|
||||||
|
a parameter in an HTTP request.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: The name of the parameter. Required.
|
||||||
|
minLength: 1
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
description: The value of the parameter.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- name
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
additionalScopes:
|
||||||
|
description: 'additionalScopes are the additional scopes that
|
||||||
|
will be requested from your OIDC provider in the authorization
|
||||||
|
request during an OIDC Authorization Code Flow and in the token
|
||||||
|
request during a Resource Owner Password Credentials Grant.
|
||||||
|
Note that the "openid" scope will always be requested regardless
|
||||||
|
of the value in this setting, since it is always required according
|
||||||
|
to the OIDC spec. By default, when this field is not set, the
|
||||||
|
Supervisor will request the following scopes: "openid", "offline_access",
|
||||||
|
"email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
|
||||||
|
for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
||||||
|
for a description of the "offline_access" scope. This default
|
||||||
|
value may change in future versions of Pinniped as the standard
|
||||||
|
evolves, or as common patterns used by providers who implement
|
||||||
|
the standard in the ecosystem evolve. By setting this list to
|
||||||
|
anything other than an empty list, you are overriding the default
|
||||||
|
value, so you may wish to include some of "offline_access",
|
||||||
|
"email", and "profile" in your override list. If you do not
|
||||||
|
want any of these scopes to be requested, you may set this list
|
||||||
|
to contain only "openid". Some OIDC providers may also require
|
||||||
|
a scope to get access to the user''s group membership, in which
|
||||||
|
case you may wish to include it in this list. Sometimes the
|
||||||
|
scope to request the user''s group membership is called "groups",
|
||||||
|
but unfortunately this is not specified in the OIDC standard.
|
||||||
|
Generally speaking, you should include any scopes required to
|
||||||
|
cause the appropriate claims to be the returned by your OIDC
|
||||||
|
provider in the ID token or userinfo endpoint results for those
|
||||||
|
claims which you would like to use in the oidcClaims settings
|
||||||
|
to determine the usernames and group memberships of your Kubernetes
|
||||||
|
users. See your OIDC provider''s documentation for more information
|
||||||
|
about what scopes are available to request claims. Additionally,
|
||||||
|
the Pinniped Supervisor requires that your OIDC provider returns
|
||||||
|
refresh tokens to the Supervisor from these authorization flows.
|
||||||
|
For most OIDC providers, the scope required to receive refresh
|
||||||
|
tokens will be "offline_access". See the documentation of your
|
||||||
|
OIDC provider''s authorization and token endpoints for its requirements
|
||||||
|
for what to include in the request in order to receive a refresh
|
||||||
|
token in the response, if anything. Note that it may be safe
|
||||||
|
to send "offline_access" even to providers which do not require
|
||||||
|
it, since the provider may ignore scopes that it does not understand
|
||||||
|
or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3).
|
||||||
|
In the unusual case that you must avoid sending the "offline_access"
|
||||||
|
scope, then you must override the default value of this setting.
|
||||||
|
This is required if your OIDC provider will reject the request
|
||||||
|
when it includes "offline_access" (e.g. GitLab''s OIDC provider).'
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
allowPasswordGrant:
|
||||||
|
description: allowPasswordGrant, when true, will allow the use
|
||||||
|
of OAuth 2.0's Resource Owner Password Credentials Grant (see
|
||||||
|
https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to
|
||||||
|
authenticate to the OIDC provider using a username and password
|
||||||
|
without a web browser, in addition to the usual browser-based
|
||||||
|
OIDC Authorization Code Flow. The Resource Owner Password Credentials
|
||||||
|
Grant is not officially part of the OIDC specification, so it
|
||||||
|
may not be supported by your OIDC provider. If your OIDC provider
|
||||||
|
supports returning ID tokens from a Resource Owner Password
|
||||||
|
Credentials Grant token request, then you can choose to set
|
||||||
|
this field to true. This will allow end users to choose to present
|
||||||
|
their username and password to the kubectl CLI (using the Pinniped
|
||||||
|
plugin) to authenticate to the cluster, without using a web
|
||||||
|
browser to log in as is customary in OIDC Authorization Code
|
||||||
|
Flow. This may be convenient for users, especially for identities
|
||||||
|
from your OIDC provider which are not intended to represent
|
||||||
|
a human actor, such as service accounts performing actions in
|
||||||
|
a CI/CD environment. Even if your OIDC provider supports it,
|
||||||
|
you may wish to disable this behavior by setting this field
|
||||||
|
to false when you prefer to only allow users of this OIDCIdentityProvider
|
||||||
|
to log in via the browser-based OIDC Authorization Code Flow.
|
||||||
|
Using the Resource Owner Password Credentials Grant means that
|
||||||
|
the Pinniped CLI and Pinniped Supervisor will directly handle
|
||||||
|
your end users' passwords (similar to LDAPIdentityProvider),
|
||||||
|
and you will not be able to require multi-factor authentication
|
||||||
|
or use the other web-based login features of your OIDC provider
|
||||||
|
during Resource Owner Password Credentials Grant logins. allowPasswordGrant
|
||||||
|
defaults to false.
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
claims:
|
||||||
|
description: Claims provides the names of token claims that will be
|
||||||
|
used when inspecting an identity from this OIDC identity provider.
|
||||||
|
properties:
|
||||||
|
additionalClaimMappings:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: AdditionalClaimMappings allows for additional arbitrary
|
||||||
|
upstream claim values to be mapped into the "additionalClaims"
|
||||||
|
claim of the ID tokens generated by the Supervisor. This should
|
||||||
|
be specified as a map of new claim names as the keys, and upstream
|
||||||
|
claim names as the values. These new claim names will be nested
|
||||||
|
under the top-level "additionalClaims" claim in ID tokens generated
|
||||||
|
by the Supervisor when this OIDCIdentityProvider was used for
|
||||||
|
user authentication. These claims will be made available to
|
||||||
|
all clients. This feature is not required to use the Supervisor
|
||||||
|
to provide authentication for Kubernetes clusters, but can be
|
||||||
|
used when using the Supervisor for other authentication purposes.
|
||||||
|
When this map is empty or the upstream claims are not available,
|
||||||
|
the "additionalClaims" claim will be excluded from the ID tokens
|
||||||
|
generated by the Supervisor.
|
||||||
|
type: object
|
||||||
|
groups:
|
||||||
|
description: Groups provides the name of the ID token claim or
|
||||||
|
userinfo endpoint response claim that will be used to ascertain
|
||||||
|
the groups to which an identity belongs. By default, the identities
|
||||||
|
will not include any group memberships when this setting is
|
||||||
|
not configured.
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
description: Username provides the name of the ID token claim
|
||||||
|
or userinfo endpoint response claim that will be used to ascertain
|
||||||
|
an identity's username. When not set, the username will be an
|
||||||
|
automatically constructed unique string which will include the
|
||||||
|
issuer URL of your OIDC provider along with the value of the
|
||||||
|
"sub" (subject) claim from the ID token.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
client:
|
||||||
|
description: OIDCClient contains OIDC client information to be used
|
||||||
|
used with this OIDC identity provider.
|
||||||
|
properties:
|
||||||
|
secretName:
|
||||||
|
description: SecretName contains the name of a namespace-local
|
||||||
|
Secret object that provides the clientID and clientSecret for
|
||||||
|
an OIDC client. If only the SecretName is specified in an OIDCClient
|
||||||
|
struct, then it is expected that the Secret is of type "secrets.pinniped.dev/oidc-client"
|
||||||
|
with keys "clientID" and "clientSecret".
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- secretName
|
||||||
|
type: object
|
||||||
|
issuer:
|
||||||
|
description: Issuer is the issuer URL of this OIDC identity provider,
|
||||||
|
i.e., where to fetch /.well-known/openid-configuration.
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^https://
|
||||||
|
type: string
|
||||||
|
tls:
|
||||||
|
description: TLS configuration for discovery/JWKS requests to the
|
||||||
|
issuer.
|
||||||
|
properties:
|
||||||
|
certificateAuthorityData:
|
||||||
|
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||||
|
If omitted, a default set of system roots will be trusted.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- client
|
||||||
|
- issuer
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status of the identity provider.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Represents the observations of an identity provider's
|
||||||
|
current state.
|
||||||
|
items:
|
||||||
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: lastTransitionTime is the last time the condition
|
||||||
|
transitioned from one status to another. This should be when
|
||||||
|
the underlying condition changed. If that is not known, then
|
||||||
|
using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: message is a human readable message indicating
|
||||||
|
details about the transition. This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: observedGeneration represents the .metadata.generation
|
||||||
|
that the condition was set based upon. For instance, if .metadata.generation
|
||||||
|
is currently 12, but the .status.conditions[x].observedGeneration
|
||||||
|
is 9, the condition is out of date with respect to the current
|
||||||
|
state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: reason contains a programmatic identifier indicating
|
||||||
|
the reason for the condition's last transition. Producers
|
||||||
|
of specific condition types may define expected values and
|
||||||
|
meanings for this field, and whether the values are considered
|
||||||
|
a guaranteed API. The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
--- Many .condition.type values are consistent across resources
|
||||||
|
like Available, but because arbitrary conditions can be useful
|
||||||
|
(see .node.status.conditions), the ability to deconflict is
|
||||||
|
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
phase:
|
||||||
|
default: Pending
|
||||||
|
description: Phase summarizes the overall status of the OIDCIdentityProvider.
|
||||||
|
enum:
|
||||||
|
- Pending
|
||||||
|
- Ready
|
||||||
|
- Error
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
152
deploy_carvel/supervisor/config/rbac.yaml
Normal file
152
deploy_carvel/supervisor/config/rbac.yaml
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("helpers.lib.yaml", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "pinnipedDevAPIGroupWithPrefix")
|
||||||
|
|
||||||
|
#! Give permission to various objects within the app's own namespace
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [secrets]
|
||||||
|
verbs: [create, get, list, patch, update, watch, delete]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
resources: [federationdomains]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
resources: [federationdomains/status]
|
||||||
|
verbs: [get, patch, update]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
resources: [oidcclients]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
resources: [oidcclients/status]
|
||||||
|
verbs: [get, patch, update]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [oidcidentityproviders]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [oidcidentityproviders/status]
|
||||||
|
verbs: [get, patch, update]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [ldapidentityproviders]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [ldapidentityproviders/status]
|
||||||
|
verbs: [get, patch, update]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [activedirectoryidentityproviders]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups:
|
||||||
|
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
resources: [activedirectoryidentityproviders/status]
|
||||||
|
verbs: [get, patch, update]
|
||||||
|
#! We want to be able to read pods/replicasets/deployment so we can learn who our deployment is to set
|
||||||
|
#! as an owner reference.
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [pods]
|
||||||
|
verbs: [get]
|
||||||
|
- apiGroups: [apps]
|
||||||
|
resources: [replicasets,deployments]
|
||||||
|
verbs: [get]
|
||||||
|
- apiGroups: [ coordination.k8s.io ]
|
||||||
|
resources: [ leases ]
|
||||||
|
verbs: [ create, get, update ]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permissions for a special configmap of CA bundles that is needed by aggregated api servers
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("extension-apiserver-authentication-reader")
|
||||||
|
namespace: kube-system
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: extension-apiserver-authentication-reader
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:auth-delegator
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
#! Give permission to various cluster-scoped objects
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
labels: #@ labels()
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ namespaces ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
- apiGroups: [ apiregistration.k8s.io ]
|
||||||
|
resources: [ apiservices ]
|
||||||
|
verbs: [ get, list, patch, update, watch ]
|
||||||
|
- apiGroups: [ admissionregistration.k8s.io ]
|
||||||
|
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||||
|
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||||
|
verbs: [ get, list, watch ]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
labels: #@ labels()
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: #@ defaultResourceName()
|
||||||
|
namespace: #@ namespace()
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
115
deploy_carvel/supervisor/config/service.yaml
Normal file
115
deploy_carvel/supervisor/config/service.yaml
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:assert", "assert")
|
||||||
|
#@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix")
|
||||||
|
|
||||||
|
#@ if hasattr(data.values, "service_http_nodeport_port"):
|
||||||
|
#@ assert.fail('value "service_http_nodeport_port" has been renamed to "deprecated_service_http_nodeport_port" and will be removed in a future release')
|
||||||
|
#@ end
|
||||||
|
#@ if hasattr(data.values, "service_http_nodeport_nodeport"):
|
||||||
|
#@ assert.fail('value "service_http_nodeport_nodeport" has been renamed to "deprecated_service_http_nodeport_nodeport" and will be removed in a future release')
|
||||||
|
#@ end
|
||||||
|
#@ if hasattr(data.values, "service_http_loadbalancer_port"):
|
||||||
|
#@ assert.fail('value "service_http_loadbalancer_port" has been renamed to "deprecated_service_http_loadbalancer_port" and will be removed in a future release')
|
||||||
|
#@ end
|
||||||
|
#@ if hasattr(data.values, "service_http_clusterip_port"):
|
||||||
|
#@ assert.fail('value "service_http_clusterip_port" has been renamed to "deprecated_service_http_clusterip_port" and will be removed in a future release')
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ if data.values.deprecated_service_http_nodeport_port or data.values.service_https_nodeport_port:
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("nodeport")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
ports:
|
||||||
|
#@ if data.values.deprecated_service_http_nodeport_port:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.deprecated_service_http_nodeport_port
|
||||||
|
targetPort: 8080
|
||||||
|
#@ if data.values.deprecated_service_http_nodeport_nodeport:
|
||||||
|
nodePort: #@ data.values.deprecated_service_http_nodeport_nodeport
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.service_https_nodeport_port:
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.service_https_nodeport_port
|
||||||
|
targetPort: 8443
|
||||||
|
#@ if data.values.service_https_nodeport_nodeport:
|
||||||
|
nodePort: #@ data.values.service_https_nodeport_nodeport
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ if data.values.deprecated_service_http_clusterip_port or data.values.service_https_clusterip_port:
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("clusterip")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
ports:
|
||||||
|
#@ if data.values.deprecated_service_http_clusterip_port:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.deprecated_service_http_clusterip_port
|
||||||
|
targetPort: 8080
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.service_https_clusterip_port:
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.service_https_clusterip_port
|
||||||
|
targetPort: 8443
|
||||||
|
#@ end
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
#@ if data.values.deprecated_service_http_loadbalancer_port or data.values.service_https_loadbalancer_port:
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: #@ defaultResourceNameWithSuffix("loadbalancer")
|
||||||
|
namespace: #@ namespace()
|
||||||
|
labels: #@ labels()
|
||||||
|
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||||
|
annotations:
|
||||||
|
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector: #@ deploymentPodLabel()
|
||||||
|
#@ if data.values.service_loadbalancer_ip:
|
||||||
|
loadBalancerIP: #@ data.values.service_loadbalancer_ip
|
||||||
|
#@ end
|
||||||
|
ports:
|
||||||
|
#@ if data.values.deprecated_service_http_loadbalancer_port:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.deprecated_service_http_loadbalancer_port
|
||||||
|
targetPort: 8080
|
||||||
|
#@ end
|
||||||
|
#@ if data.values.service_https_loadbalancer_port:
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: #@ data.values.service_https_loadbalancer_port
|
||||||
|
targetPort: 8443
|
||||||
|
#@ end
|
||||||
|
#@ end
|
170
deploy_carvel/supervisor/config/values.yaml
Normal file
170
deploy_carvel/supervisor/config/values.yaml
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@data/values-schema
|
||||||
|
---
|
||||||
|
#@schema/desc "Namespace of pinniped-supervisor"
|
||||||
|
app_name: pinniped-supervisor
|
||||||
|
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||||
|
namespace: pinniped-supervisor
|
||||||
|
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||||
|
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||||
|
#@schema/desc "Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???"
|
||||||
|
#@schema/nullable
|
||||||
|
into_namespace: my-preexisting-namespace
|
||||||
|
|
||||||
|
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||||
|
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||||
|
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||||
|
#! The app can be uninstalled either by:
|
||||||
|
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||||
|
#! resources that were dynamically created by controllers at runtime
|
||||||
|
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||||
|
#@schema/desc "All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here."
|
||||||
|
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||||
|
|
||||||
|
#@schema/desc "Specify how many replicas of the Pinniped server to run."
|
||||||
|
replicas: 2
|
||||||
|
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
#@schema/nullable
|
||||||
|
image_digest: sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||||
|
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||||
|
image_tag: latest
|
||||||
|
|
||||||
|
#! TODO: preserve even if this file is revised!
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_repo: docker.io/benjaminapetersen/some-pinniped-supervisor-package
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_digest: sha256:123456
|
||||||
|
#@schema/nullable
|
||||||
|
package_image_tag: latest #! TODO; so since we allow the deployment to pass in the image tag, not sure the value in versions of packages?
|
||||||
|
#! prob should not be nullable
|
||||||
|
#@schema/nullable
|
||||||
|
package_version: 1.2.3
|
||||||
|
|
||||||
|
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||||
|
#! Can be used when the above image_repo is a private registry.
|
||||||
|
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||||
|
#! Optional.
|
||||||
|
#@schema/description "Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry."
|
||||||
|
#@schema/nullable
|
||||||
|
image_pull_dockerconfigjson: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||||
|
|
||||||
|
#! Specify how to expose the Supervisor app's HTTPS port as a Service.
|
||||||
|
#! Typically, you would set a value for only one of the following service types.
|
||||||
|
#! Setting any of these values means that a Service of that type will be created. They are all optional.
|
||||||
|
#! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`.
|
||||||
|
#! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to
|
||||||
|
#! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated.
|
||||||
|
#@schema/desc "will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234"
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_service_http_nodeport_port: 31234
|
||||||
|
#@schema/desc "will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234"
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_service_http_nodeport_nodeport: 31234
|
||||||
|
#@schema/desc "will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443"
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_service_http_loadbalancer_port: 8443
|
||||||
|
#@schema/desc "will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443"
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_service_http_clusterip_port: 8443
|
||||||
|
#@schema/desc "when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243"
|
||||||
|
#@schema/nullable
|
||||||
|
service_https_nodeport_port: 31243
|
||||||
|
#@schema/desc "the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243"
|
||||||
|
#@schema/nullable
|
||||||
|
service_https_nodeport_nodeport: 31243
|
||||||
|
#@schema/desc "when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443"
|
||||||
|
#@schema/nullable
|
||||||
|
service_https_loadbalancer_port: 8443
|
||||||
|
#@schema/desc "when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443"
|
||||||
|
#@schema/nullable
|
||||||
|
service_https_clusterip_port: 8443
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4"
|
||||||
|
#@schema/nullable
|
||||||
|
service_loadbalancer_ip: 1.2.3.4
|
||||||
|
|
||||||
|
#@schema/desc 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||||
|
#@schema/nullable
|
||||||
|
log_level: info #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||||
|
#@schema/desc "Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json."
|
||||||
|
#@schema/nullable
|
||||||
|
deprecated_log_format: json
|
||||||
|
|
||||||
|
#@schema/desc "run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||||
|
run_as_user: 65532
|
||||||
|
#@schema/desc "run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||||
|
run_as_group: 65532
|
||||||
|
|
||||||
|
#@schema/desc "Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc."
|
||||||
|
api_group_suffix: pinniped.dev
|
||||||
|
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||||
|
#@schema/nullable
|
||||||
|
https_proxy: http://proxy.example.com
|
||||||
|
#@schema/desc "NO_PROXY environment variable. do not proxy Kubernetes endpoints"
|
||||||
|
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
||||||
|
|
||||||
|
#! Control the HTTP and HTTPS listeners of the Supervisor.
|
||||||
|
#!
|
||||||
|
#! The schema of this config is as follows:
|
||||||
|
#!
|
||||||
|
#! endpoints:
|
||||||
|
#! https:
|
||||||
|
#! network: tcp | unix | disabled
|
||||||
|
#! address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||||
|
#! http:
|
||||||
|
#! network: same as above
|
||||||
|
#! address: same as above, except that when network=tcp then the address is only allowed to bind to loopback interfaces
|
||||||
|
#!
|
||||||
|
#! Setting network to disabled turns off that particular listener.
|
||||||
|
#! See https://pkg.go.dev/net#Listen and https://pkg.go.dev/net#Dial for a description of what can be
|
||||||
|
#! specified in the address parameter based on the given network parameter. To aid in the use of unix
|
||||||
|
#! domain sockets, a writable empty dir volume is mounted at /pinniped_socket when network is set to "unix."
|
||||||
|
#!
|
||||||
|
#! The current defaults are:
|
||||||
|
#!
|
||||||
|
#! endpoints:
|
||||||
|
#! https:
|
||||||
|
#! network: tcp
|
||||||
|
#! address: :8443
|
||||||
|
#! http:
|
||||||
|
#! network: disabled
|
||||||
|
#!
|
||||||
|
#! These defaults mean: For HTTPS listening, bind to all interfaces using TCP on port 8443.
|
||||||
|
#! Disable HTTP listening by default.
|
||||||
|
#!
|
||||||
|
#! The HTTP listener can only be bound to loopback interfaces. This allows the listener to accept
|
||||||
|
#! traffic from within the pod, e.g. from a service mesh sidecar. The HTTP listener should not be
|
||||||
|
#! used to accept traffic from outside the pod, since that would mean that the network traffic could be
|
||||||
|
#! transmitted unencrypted. The HTTPS listener should be used instead to accept traffic from outside the pod.
|
||||||
|
#! Ingresses and load balancers that terminate TLS connections should re-encrypt the data and route traffic
|
||||||
|
#! to the HTTPS listener. Unix domain sockets may also be used for integrations with service meshes.
|
||||||
|
#!
|
||||||
|
#! Changing the HTTPS port number must be accompanied by matching changes to the service and deployment
|
||||||
|
#! manifests. Changes to the HTTPS listener must be coordinated with the deployment health checks.
|
||||||
|
#!
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Control the HTTP and HTTPS listeners of the Supervisor."
|
||||||
|
#@schema/nullable
|
||||||
|
endpoints:
|
||||||
|
https:
|
||||||
|
network: tcp | unix | disabled
|
||||||
|
address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||||
|
|
||||||
|
#! Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||||
|
#! When deprecated_insecure_accept_external_unencrypted_http_requests is true, the HTTP listener is allowed to bind to any
|
||||||
|
#! interface, including interfaces that are listening for traffic from outside the pod. This value is being introduced
|
||||||
|
#! to ease the transition to the new loopback interface validation for the HTTP port for any users who need more time
|
||||||
|
#! to change their ingress strategy to avoid using plain HTTP into the Supervisor pods.
|
||||||
|
#! This value is immediately deprecated upon its introduction. It will be removed in some future release, at which time
|
||||||
|
#! traffic from outside the pod will need to be sent to the HTTPS listener instead, with no simple workaround available.
|
||||||
|
#! Allowed values are true (boolean), "true" (string), false (boolean), and "false" (string). The default is false.
|
||||||
|
#! Optional.
|
||||||
|
#@schema/desc "Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used."
|
||||||
|
deprecated_insecure_accept_external_unencrypted_http_requests: false
|
63
deploy_carvel/supervisor/config/z0_crd_overlay.yaml
Normal file
63
deploy_carvel/supervisor/config/z0_crd_overlay.yaml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:overlay", "overlay")
|
||||||
|
#@ load("helpers.lib.yaml", "labels", "pinnipedDevAPIGroupWithPrefix")
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"federationdomains.config.supervisor.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("federationdomains.config.supervisor")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"oidcidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("oidcidentityproviders.idp.supervisor")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"ldapidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("ldapidentityproviders.idp.supervisor")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"activedirectoryidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("activedirectoryidentityproviders.idp.supervisor")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||||
|
|
||||||
|
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"oidcclients.config.supervisor.pinniped.dev"}}), expects=1
|
||||||
|
---
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
labels: #@ labels()
|
||||||
|
name: #@ pinnipedDevAPIGroupWithPrefix("oidcclients.config.supervisor")
|
||||||
|
spec:
|
||||||
|
group: #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||||
|
versions:
|
||||||
|
#@overlay/match by=overlay.all, expects="1+"
|
||||||
|
- schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
#@overlay/match by=overlay.subset({"metadata":{"type":"object"}}), expects=1
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
#@overlay/match missing_ok=True
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
pattern: ^client\.oauth\.pinniped\.dev-
|
||||||
|
type: string
|
13
deploy_carvel/supervisor/metadata.yml
Normal file
13
deploy_carvel/supervisor/metadata.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||||
|
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||||
|
---
|
||||||
|
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageMetadata
|
||||||
|
metadata:
|
||||||
|
name: supervisor.pinniped.dev
|
||||||
|
spec:
|
||||||
|
displayName: "Pinniped Supervisor"
|
||||||
|
longDescription: "Pinniped supervisor allows seamless login across one or many Kubernetes clusters including AKS, EKS and GKE"
|
||||||
|
shortDescription: "Pinniped supervisor provides login capabilities"
|
||||||
|
categories:
|
||||||
|
- auth
|
32
deploy_carvel/supervisor/package-template.yml
Normal file
32
deploy_carvel/supervisor/package-template.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||||
|
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||||
|
---
|
||||||
|
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||||
|
kind: Package
|
||||||
|
metadata:
|
||||||
|
name: #@ "supervisor.pinniped.dev." + data.values.package_version
|
||||||
|
spec:
|
||||||
|
refName: supervisor.pinniped.dev
|
||||||
|
version: #@ data.values.package_version
|
||||||
|
releaseNotes: |
|
||||||
|
Initial release of the pinniped supervisor package
|
||||||
|
licenses:
|
||||||
|
- "Apache-2.0"
|
||||||
|
valuesSchema:
|
||||||
|
openAPIv3: #@ yaml.decode(data.values.openapi)["components"]["schemas"]["dataValues"]
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
fetch:
|
||||||
|
- imgpkgBundle:
|
||||||
|
#! image: #@ data.values.package_image_repo + "/packages/:" + data.values.package_version
|
||||||
|
image: #@ data.values.package_image_repo
|
||||||
|
template:
|
||||||
|
- ytt:
|
||||||
|
paths:
|
||||||
|
- "config/"
|
||||||
|
- kbld:
|
||||||
|
paths:
|
||||||
|
- ".imgpkg/images.yml"
|
||||||
|
- "-"
|
||||||
|
deploy:
|
||||||
|
- kapp: {}
|
180
deploy_carvel/supervisor/schema-openapi.yaml
Normal file
180
deploy_carvel/supervisor/schema-openapi.yaml
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
version: 0.1.0
|
||||||
|
title: Schema for data values, generated by ytt
|
||||||
|
paths: {}
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
dataValues:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
app_name:
|
||||||
|
type: string
|
||||||
|
description: Namespace of pinniped-supervisor
|
||||||
|
default: pinniped-supervisor
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||||
|
default: pinniped-supervisor
|
||||||
|
into_namespace:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||||
|
default: null
|
||||||
|
custom_labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||||
|
properties: {}
|
||||||
|
replicas:
|
||||||
|
type: integer
|
||||||
|
description: Specify how many replicas of the Pinniped server to run.
|
||||||
|
default: 2
|
||||||
|
image_repo:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: null
|
||||||
|
image_tag:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: latest
|
||||||
|
package_image_repo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_tag:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_version:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
image_pull_dockerconfigjson:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
nullable: true
|
||||||
|
properties:
|
||||||
|
auths:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
https://registry.example.com:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
default: USERNAME
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
default: PASSWORD
|
||||||
|
auth:
|
||||||
|
type: string
|
||||||
|
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||||
|
deprecated_service_http_nodeport_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_nodeport_nodeport:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_loadbalancer_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_clusterip_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_https_nodeport_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243
|
||||||
|
default: null
|
||||||
|
service_https_nodeport_nodeport:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243
|
||||||
|
default: null
|
||||||
|
service_https_loadbalancer_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_https_clusterip_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_loadbalancer_ip:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4
|
||||||
|
default: null
|
||||||
|
log_level:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||||
|
default: null
|
||||||
|
deprecated_log_format:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||||
|
default: null
|
||||||
|
run_as_user:
|
||||||
|
type: integer
|
||||||
|
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
run_as_group:
|
||||||
|
type: integer
|
||||||
|
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
api_group_suffix:
|
||||||
|
type: string
|
||||||
|
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||||
|
default: pinniped.dev
|
||||||
|
https_proxy:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||||
|
default: null
|
||||||
|
no_proxy:
|
||||||
|
type: string
|
||||||
|
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||||
|
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
||||||
|
endpoints:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
nullable: true
|
||||||
|
description: Control the HTTP and HTTPS listeners of the Supervisor.
|
||||||
|
properties:
|
||||||
|
https:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
network:
|
||||||
|
type: string
|
||||||
|
default: tcp | unix | disabled
|
||||||
|
address:
|
||||||
|
type: string
|
||||||
|
default: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||||
|
deprecated_insecure_accept_external_unencrypted_http_requests:
|
||||||
|
type: boolean
|
||||||
|
description: Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||||
|
default: false
|
180
deploy_carvel/supervisor/schema-openapi.yml
Normal file
180
deploy_carvel/supervisor/schema-openapi.yml
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
version: 0.1.0
|
||||||
|
title: Schema for data values, generated by ytt
|
||||||
|
paths: {}
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
dataValues:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
app_name:
|
||||||
|
type: string
|
||||||
|
description: Namespace of pinniped-supervisor
|
||||||
|
default: pinniped-supervisor
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||||
|
default: pinniped-supervisor
|
||||||
|
into_namespace:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||||
|
default: null
|
||||||
|
custom_labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||||
|
properties: {}
|
||||||
|
replicas:
|
||||||
|
type: integer
|
||||||
|
description: Specify how many replicas of the Pinniped server to run.
|
||||||
|
default: 2
|
||||||
|
image_repo:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||||
|
image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: null
|
||||||
|
image_tag:
|
||||||
|
type: string
|
||||||
|
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||||
|
default: latest
|
||||||
|
package_image_repo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_digest:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_image_tag:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
package_version:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
default: null
|
||||||
|
image_pull_dockerconfigjson:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
nullable: true
|
||||||
|
properties:
|
||||||
|
auths:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
https://registry.example.com:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
default: USERNAME
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
default: PASSWORD
|
||||||
|
auth:
|
||||||
|
type: string
|
||||||
|
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||||
|
deprecated_service_http_nodeport_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_nodeport_nodeport:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_loadbalancer_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
deprecated_service_http_clusterip_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_https_nodeport_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243
|
||||||
|
default: null
|
||||||
|
service_https_nodeport_nodeport:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243
|
||||||
|
default: null
|
||||||
|
service_https_loadbalancer_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_https_clusterip_port:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
description: when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||||
|
default: null
|
||||||
|
service_loadbalancer_ip:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4
|
||||||
|
default: null
|
||||||
|
log_level:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||||
|
default: null
|
||||||
|
deprecated_log_format:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||||
|
default: null
|
||||||
|
run_as_user:
|
||||||
|
type: integer
|
||||||
|
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
run_as_group:
|
||||||
|
type: integer
|
||||||
|
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||||
|
default: 65532
|
||||||
|
api_group_suffix:
|
||||||
|
type: string
|
||||||
|
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||||
|
default: pinniped.dev
|
||||||
|
https_proxy:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||||
|
default: null
|
||||||
|
no_proxy:
|
||||||
|
type: string
|
||||||
|
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||||
|
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
||||||
|
endpoints:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
nullable: true
|
||||||
|
description: Control the HTTP and HTTPS listeners of the Supervisor.
|
||||||
|
properties:
|
||||||
|
https:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
network:
|
||||||
|
type: string
|
||||||
|
default: tcp | unix | disabled
|
||||||
|
address:
|
||||||
|
type: string
|
||||||
|
default: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||||
|
deprecated_insecure_accept_external_unencrypted_http_requests:
|
||||||
|
type: boolean
|
||||||
|
description: Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||||
|
default: false
|
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: "concierge-install-ns"
|
||||||
|
---
|
||||||
|
# ServiceAccount details from the file linked above
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-concierge-sa-superadmin-dangerous"
|
||||||
|
namespace: "concierge-install-ns"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-concierge-role-superadmin-dangerous"
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["*"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["*"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-concierge-role-binding-superadmin-dangerous"
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "pinniped-package-rbac-concierge-sa-superadmin-dangerous"
|
||||||
|
namespace: "concierge-install-ns"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: "pinniped-package-rbac-concierge-role-superadmin-dangerous"
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: "supervisor-install-ns"
|
||||||
|
---
|
||||||
|
# ServiceAccount details from the file linked above
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-supervisor-sa-superadmin-dangerous"
|
||||||
|
namespace: "supervisor-install-ns"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-supervisor-role-superadmin-dangerous"
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["*"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["*"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "pinniped-package-rbac-supervisor-role-binding-superadmin-dangerous"
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "pinniped-package-rbac-supervisor-sa-superadmin-dangerous"
|
||||||
|
namespace: "supervisor-install-ns"
|
||||||
|
# namespace: default # --> sticking to default for everything for now.
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: "pinniped-package-rbac-supervisor-role-superadmin-dangerous"
|
||||||
|
|
@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
apiVersion: packaging.carvel.dev/v1alpha1
|
||||||
|
kind: PackageInstall
|
||||||
|
metadata:
|
||||||
|
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||||
|
name: supervisor-install
|
||||||
|
namespace: supervisor-install-ns
|
||||||
|
spec:
|
||||||
|
serviceAccountName: "pinniped-package-rbac-supervisor-sa-superadmin-dangerous"
|
||||||
|
packageRef:
|
||||||
|
refName: "supervisor.pinniped.dev"
|
||||||
|
versionSelection:
|
||||||
|
constraints: "0.25.0"
|
||||||
|
values:
|
||||||
|
- secretRef:
|
||||||
|
name: "supervisor-package-install-secret"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "supervisor-package-install-secret"
|
||||||
|
namespace: supervisor-install-ns
|
||||||
|
stringData:
|
||||||
|
values.yml: |
|
||||||
|
---
|
||||||
|
app_name: pinniped-supervisor
|
||||||
|
namespace: supervisor
|
||||||
|
api_group_suffix: pinniped.dev
|
||||||
|
image_repo: pinniped.local/test/build
|
||||||
|
image_tag: 9EA78F67-5129-45B4-96E1-597073E864F9
|
||||||
|
log_level: debug
|
||||||
|
|
||||||
|
service_https_nodeport_port: 443
|
||||||
|
service_https_nodeport_nodeport: 31243
|
||||||
|
service_https_clusterip_port: 443
|
3
deploy_carvel/temp_pinniped_config_resources/README.md
Normal file
3
deploy_carvel/temp_pinniped_config_resources/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# README
|
||||||
|
|
||||||
|
These are hand crafted files, not generated.
|
@ -0,0 +1,60 @@
|
|||||||
|
apiVersion: idp.supervisor.pinniped.dev/v1alpha1
|
||||||
|
kind: OIDCIdentityProvider
|
||||||
|
metadata:
|
||||||
|
# namespace: pinniped-supervisor
|
||||||
|
namespace: supervisor-ns # for this install this is the namespace that I've ben using.
|
||||||
|
name: gitlab
|
||||||
|
spec:
|
||||||
|
|
||||||
|
# Specify the upstream issuer URL.
|
||||||
|
issuer: https://gitlab.eng.vmware.com
|
||||||
|
|
||||||
|
# Specify how to form authorization requests to GitLab.
|
||||||
|
authorizationConfig:
|
||||||
|
|
||||||
|
# GitLab is unusual among OIDC providers in that it returns an
|
||||||
|
# error if you request the "offline_access" scope during an
|
||||||
|
# authorization flow, so ask Pinniped to avoid requesting that
|
||||||
|
# scope when using GitLab by excluding it from this list.
|
||||||
|
# By specifying only "openid" here then Pinniped will only
|
||||||
|
# request "openid".
|
||||||
|
additionalScopes: [openid,email]
|
||||||
|
|
||||||
|
# If you would also like to allow your end users to authenticate using
|
||||||
|
# a password grant, then change this to true. See
|
||||||
|
# https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow
|
||||||
|
# for more information about using the password grant with GitLab.
|
||||||
|
allowPasswordGrant: false
|
||||||
|
|
||||||
|
# Specify how GitLab claims are mapped to Kubernetes identities.
|
||||||
|
claims:
|
||||||
|
|
||||||
|
# Specify the name of the claim in your GitLab token that will be mapped
|
||||||
|
# to the "username" claim in downstream tokens minted by the Supervisor.
|
||||||
|
username: email
|
||||||
|
|
||||||
|
# Specify the name of the claim in GitLab that represents the groups
|
||||||
|
# that the user belongs to. Note that GitLab's "groups" claim comes from
|
||||||
|
# their "/userinfo" endpoint, not the token.
|
||||||
|
groups: groups
|
||||||
|
|
||||||
|
# Specify the name of the Kubernetes Secret that contains your GitLab
|
||||||
|
# application's client credentials (created below).
|
||||||
|
client:
|
||||||
|
secretName: gitlab-client-credentials
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
# namespace: pinniped-supervisor
|
||||||
|
namespace: supervisor-ns # for this install this is the namespace that I've ben using.
|
||||||
|
name: gitlab-client-credentials
|
||||||
|
type: secrets.pinniped.dev/oidc-client
|
||||||
|
stringData:
|
||||||
|
|
||||||
|
# The "Application ID" that you got from GitLab.
|
||||||
|
clientID: "bbf1c9e13b38642adec54d47a112159549c2de10ae3506086c5af2ff4beb32d6"
|
||||||
|
|
||||||
|
# The "Secret" that you got from GitLab.
|
||||||
|
clientSecret: "16a92c0fdbba5f87a7ea61d6c64a526b5fb838bf436825c98af95459c7c5eeb8"
|
431
generated/1.21/README.adoc
generated
431
generated/1.21/README.adoc
generated
@ -23,6 +23,41 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped concierge authenticatio
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-condition"]
|
||||||
|
==== Condition
|
||||||
|
|
||||||
|
Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API version we can switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-jwtauthenticatorstatus[$$JWTAuthenticatorStatus$$]
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-webhookauthenticatorstatus[$$WebhookAuthenticatorStatus$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
[cols="25a,75a", options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Description
|
||||||
|
| *`type`* __string__ | type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-conditionstatus[$$ConditionStatus$$]__ | status of the condition, one of True, False, Unknown.
|
||||||
|
| *`observedGeneration`* __integer__ | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
|
||||||
|
| *`lastTransitionTime`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
| *`reason`* __string__ | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
|
||||||
|
| *`message`* __string__ | message is a human readable message indicating details about the transition. This may be an empty string.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-conditionstatus"]
|
||||||
|
==== ConditionStatus (string)
|
||||||
|
|
||||||
|
ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-condition[$$Condition$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-jwtauthenticator"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-jwtauthenticator"]
|
||||||
==== JWTAuthenticator
|
==== JWTAuthenticator
|
||||||
|
|
||||||
@ -79,7 +114,7 @@ Status of a JWT authenticator.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Represents the observations of the authenticator's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of the authenticator's current state.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -172,7 +207,7 @@ Status of a webhook authenticator.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Represents the observations of the authenticator's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-authentication-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of the authenticator's current state.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -197,7 +232,30 @@ OIDCClientSecretRequest can be used to update the client secrets associated with
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`ObjectMeta`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#objectmeta-v1-meta[$$ObjectMeta$$]__ |
|
| *`name`* __string__ | Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names
|
||||||
|
| *`generateName`* __string__ | GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.
|
||||||
|
If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).
|
||||||
|
Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency
|
||||||
|
| *`namespace`* __string__ | Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.
|
||||||
|
Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces
|
||||||
|
| *`selfLink`* __string__ | SelfLink is a URL representing this object. Populated by the system. Read-only.
|
||||||
|
DEPRECATED Kubernetes will stop propagating this field in 1.20 release and the field is planned to be removed in 1.21 release.
|
||||||
|
| *`uid`* __UID__ | UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.
|
||||||
|
Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids
|
||||||
|
| *`resourceVersion`* __string__ | An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.
|
||||||
|
Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
|
||||||
|
| *`generation`* __integer__ | A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.
|
||||||
|
| *`creationTimestamp`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
||||||
|
Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||||
|
| *`deletionTimestamp`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.
|
||||||
|
Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||||
|
| *`deletionGracePeriodSeconds`* __integer__ | Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.
|
||||||
|
| *`labels`* __object (keys:string, values:string)__ | Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels
|
||||||
|
| *`annotations`* __object (keys:string, values:string)__ | Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations
|
||||||
|
| *`ownerReferences`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#ownerreference-v1-meta[$$OwnerReference$$] array__ | List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.
|
||||||
|
| *`finalizers`* __string array__ | Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list.
|
||||||
|
| *`clusterName`* __string__ | The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
|
||||||
|
| *`managedFields`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#managedfieldsentry-v1-meta[$$ManagedFieldsEntry$$] array__ | ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like "ci-cd". The set of fields is always in the version that the workflow used when modifying the object.
|
||||||
| *`Spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-clientsecret-oidcclientsecretrequestspec[$$OIDCClientSecretRequestSpec$$]__ |
|
| *`Spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-clientsecret-oidcclientsecretrequestspec[$$OIDCClientSecretRequestSpec$$]__ |
|
||||||
| *`Status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-clientsecret-oidcclientsecretrequeststatus[$$OIDCClientSecretRequestStatus$$]__ |
|
| *`Status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-clientsecret-oidcclientsecretrequeststatus[$$OIDCClientSecretRequestStatus$$]__ |
|
||||||
|===
|
|===
|
||||||
@ -444,7 +502,7 @@ FrontendType enumerates a type of "frontend" used to provide access to users of
|
|||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyinfo"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyinfo"]
|
||||||
==== ImpersonationProxyInfo (xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-struct-endpoint string -json-endpoint- certificateauthoritydata string -json-certificateauthoritydata-[$$struct{Endpoint string "json:\"endpoint\""; CertificateAuthorityData string "json:\"certificateAuthorityData\""}$$])
|
==== ImpersonationProxyInfo
|
||||||
|
|
||||||
ImpersonationProxyInfo describes the parameters for the impersonation proxy on this Concierge.
|
ImpersonationProxyInfo describes the parameters for the impersonation proxy on this Concierge.
|
||||||
|
|
||||||
@ -453,6 +511,12 @@ ImpersonationProxyInfo describes the parameters for the impersonation proxy on t
|
|||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-credentialissuerfrontend[$$CredentialIssuerFrontend$$]
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-credentialissuerfrontend[$$CredentialIssuerFrontend$$]
|
||||||
****
|
****
|
||||||
|
|
||||||
|
[cols="25a,75a", options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Description
|
||||||
|
| *`endpoint`* __string__ | Endpoint is the HTTPS endpoint of the impersonation proxy.
|
||||||
|
| *`certificateAuthorityData`* __string__ | CertificateAuthorityData is the base64-encoded PEM CA bundle of the impersonation proxy.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxymode"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxymode"]
|
||||||
@ -480,9 +544,8 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy.
|
||||||
|
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status.
|
||||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status.
|
|
||||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. This is not supported on all cloud providers.
|
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. This is not supported on all cloud providers.
|
||||||
| *`annotations`* __object (keys:string, values:string)__ | Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
|
| *`annotations`* __object (keys:string, values:string)__ | Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
|
||||||
|===
|
|===
|
||||||
@ -515,12 +578,10 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
|||||||
| Field | Description
|
| Field | Description
|
||||||
| *`mode`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxymode[$$ImpersonationProxyMode$$]__ | Mode configures whether the impersonation proxy should be started: - "disabled" explicitly disables the impersonation proxy. This is the default. - "enabled" explicitly enables the impersonation proxy. - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
|
| *`mode`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxymode[$$ImpersonationProxyMode$$]__ | Mode configures whether the impersonation proxy should be started: - "disabled" explicitly disables the impersonation proxy. This is the default. - "enabled" explicitly enables the impersonation proxy. - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
|
||||||
| *`service`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]__ | Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
|
| *`service`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]__ | Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
|
||||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will be served using the external name of the LoadBalancer service or the cluster service DNS name.
|
||||||
|
This field must be non-empty when spec.impersonationProxy.service.type is "None".
|
||||||
This field must be non-empty when spec.impersonationProxy.service.type is "None".
|
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS.
|
||||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
If this field is empty, the impersonation proxy will generate its own TLS certificate.
|
||||||
|
|
||||||
If this field is empty, the impersonation proxy will generate its own TLS certificate.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -581,7 +642,7 @@ StrategyType enumerates a type of "strategy" used to implement credential access
|
|||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-tokencredentialrequestapiinfo"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-tokencredentialrequestapiinfo"]
|
||||||
==== TokenCredentialRequestAPIInfo (xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-struct-server string -json-server- certificateauthoritydata string -json-certificateauthoritydata-[$$struct{Server string "json:\"server\""; CertificateAuthorityData string "json:\"certificateAuthorityData\""}$$])
|
==== TokenCredentialRequestAPIInfo
|
||||||
|
|
||||||
TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRequest API on this Concierge.
|
TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRequest API on this Concierge.
|
||||||
|
|
||||||
@ -590,6 +651,12 @@ TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRe
|
|||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-credentialissuerfrontend[$$CredentialIssuerFrontend$$]
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-config-v1alpha1-credentialissuerfrontend[$$CredentialIssuerFrontend$$]
|
||||||
****
|
****
|
||||||
|
|
||||||
|
[cols="25a,75a", options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Description
|
||||||
|
| *`server`* __string__ | Server is the Kubernetes API server URL.
|
||||||
|
| *`certificateAuthorityData`* __string__ | CertificateAuthorityData is the base64-encoded Kubernetes API server CA bundle.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -600,6 +667,40 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor configuratio
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-condition"]
|
||||||
|
==== Condition
|
||||||
|
|
||||||
|
Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API version we can switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-oidcclientstatus[$$OIDCClientStatus$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
[cols="25a,75a", options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Description
|
||||||
|
| *`type`* __string__ | type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-conditionstatus[$$ConditionStatus$$]__ | status of the condition, one of True, False, Unknown.
|
||||||
|
| *`observedGeneration`* __integer__ | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
|
||||||
|
| *`lastTransitionTime`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
| *`reason`* __string__ | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
|
||||||
|
| *`message`* __string__ | message is a human readable message indicating details about the transition. This may be an empty string.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-conditionstatus"]
|
||||||
|
==== ConditionStatus (string)
|
||||||
|
|
||||||
|
ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-condition[$$Condition$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomain"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomain"]
|
||||||
==== FederationDomain
|
==== FederationDomain
|
||||||
|
|
||||||
@ -620,37 +721,6 @@ FederationDomain describes the configuration of an OIDC provider.
|
|||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainidentityprovider"]
|
|
||||||
==== FederationDomainIdentityProvider
|
|
||||||
|
|
||||||
FederationDomainIdentityProvider describes how an identity provider is made available in this FederationDomain.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainspec[$$FederationDomainSpec$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`displayName`* __string__ | DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a disruptive change for those users.
|
|
||||||
| *`objectRef`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#typedlocalobjectreference-v1-core[$$TypedLocalObjectReference$$]__ | ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required. If the reference cannot be resolved then the identity provider will not be made available. Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider, LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
|
||||||
| *`transforms`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransforms[$$FederationDomainTransforms$$]__ | Transforms is an optional way to specify transformations to be applied during user authentication and session refresh.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainphase"]
|
|
||||||
==== FederationDomainPhase (string)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainstatus[$$FederationDomainStatus$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainsecrets"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainsecrets"]
|
||||||
@ -686,15 +756,9 @@ FederationDomainSpec is a struct that describes an OIDC Provider.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`issuer`* __string__ | Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the identifier that it will use for the iss claim in issued JWTs. This field will also be used as the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer is https://example.com/foo, then your authorization endpoint will look like https://example.com/foo/some/path/to/auth/endpoint). +
|
| *`issuer`* __string__ | Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the identifier that it will use for the iss claim in issued JWTs. This field will also be used as the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer is https://example.com/foo, then your authorization endpoint will look like https://example.com/foo/some/path/to/auth/endpoint).
|
||||||
|
See https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||||
See https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
|
||||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
|
||||||
|
|
||||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to extract a normalized user identity. Normalized user identities include a username and a list of group names. In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid accidental conflicts when multiple identity providers have different users with the same username (e.g. "idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could disallow the authentication unless the user belongs to a specific group in the identity provider. +
|
|
||||||
|
|
||||||
For backwards compatibility with versions of Pinniped which predate support for multiple identity providers, an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which exist in the same namespace, but also to reject all authentication requests when there is more than one identity provider currently defined. In this backwards compatibility mode, the name of the identity provider resource (e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead explicitly list the identity provider using this IdentityProviders field.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -711,12 +775,25 @@ FederationDomainStatus is a struct that describes the actual state of an OIDC Pr
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainphase[$$FederationDomainPhase$$]__ | Phase summarizes the overall status of the FederationDomain.
|
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainstatuscondition[$$FederationDomainStatusCondition$$]__ | Status holds an enum that describes the state of this OIDC Provider. Note that this Status can represent success or failure.
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Conditions represent the observations of an FederationDomain's current state.
|
| *`message`* __string__ | Message provides human-readable details about the Status.
|
||||||
|
| *`lastUpdateTime`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get around some undesirable behavior with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
| *`secrets`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainsecrets[$$FederationDomainSecrets$$]__ | Secrets contains information about this OIDC Provider's secrets.
|
| *`secrets`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainsecrets[$$FederationDomainSecrets$$]__ | Secrets contains information about this OIDC Provider's secrets.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainstatuscondition"]
|
||||||
|
==== FederationDomainStatusCondition (string)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainstatus[$$FederationDomainStatus$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintlsspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintlsspec"]
|
||||||
==== FederationDomainTLSSpec
|
==== FederationDomainTLSSpec
|
||||||
|
|
||||||
@ -730,118 +807,11 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. +
|
| *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS.
|
||||||
|
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers.
|
||||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers.
|
||||||
|
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere.
|
||||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. +
|
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses.
|
||||||
|
|
||||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. +
|
|
||||||
|
|
||||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransforms"]
|
|
||||||
==== FederationDomainTransforms
|
|
||||||
|
|
||||||
FederationDomainTransforms defines identity transformations for an identity provider's usage on a FederationDomain.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`constants`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsconstant[$$FederationDomainTransformsConstant$$] array__ | Constants defines constant variables and their values which will be made available to the transform expressions.
|
|
||||||
| *`expressions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexpression[$$FederationDomainTransformsExpression$$] array__ | Expressions are an optional list of transforms and policies to be executed in the order given during every authentication attempt, including during every session refresh. Each is a CEL expression. It may use the basic CEL language as defined in https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in https://github.com/google/cel-go/tree/master/ext#strings. +
|
|
||||||
|
|
||||||
The username and groups extracted from the identity provider, and the constants defined in this CR, are available as variables in all expressions. The username is provided via a variable called `username` and the list of group names is provided via a variable called `groups` (which may be an empty list). Each user-provided constants is provided via a variable named `strConst.varName` for string constants and `strListConst.varName` for string list constants. +
|
|
||||||
|
|
||||||
The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1. Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated and the authentication attempt is rejected. Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the username or group names. Each username/v1 transform must return the new username (a string), which can be the same as the old username. Transformations of type username/v1 do not return group names, and therefore cannot change the group names. Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old groups list. Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames. After each expression, the new (potentially changed) username or groups get passed to the following expression. +
|
|
||||||
|
|
||||||
Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain. During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username and group names have been decided for that authentication attempt.
|
|
||||||
| *`examples`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexample[$$FederationDomainTransformsExample$$] array__ | Examples can optionally be used to ensure that the sequence of transformation expressions are working as expected. Examples define sample input identities which are then run through the expression list, and the results are compared to the expected results. If any example in this list fails, then this identity provider will not be available for use within this FederationDomain, and the error(s) will be added to the FederationDomain status. This can be used to help guard against programming mistakes in the expressions, and also act as living documentation for other administrators to better understand the expressions.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsconstant"]
|
|
||||||
==== FederationDomainTransformsConstant
|
|
||||||
|
|
||||||
FederationDomainTransformsConstant defines a constant variable and its value which will be made available to the transform expressions. This is a union type, and Type is the discriminator field.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransforms[$$FederationDomainTransforms$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`name`* __string__ | Name determines the name of the constant. It must be a valid identifier name.
|
|
||||||
| *`type`* __string__ | Type determines the type of the constant, and indicates which other field should be non-empty.
|
|
||||||
| *`stringValue`* __string__ | StringValue should hold the value when Type is "string", and is otherwise ignored.
|
|
||||||
| *`stringListValue`* __string array__ | StringListValue should hold the value when Type is "stringList", and is otherwise ignored.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexample"]
|
|
||||||
==== FederationDomainTransformsExample
|
|
||||||
|
|
||||||
FederationDomainTransformsExample defines a transform example.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransforms[$$FederationDomainTransforms$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`username`* __string__ | Username is the input username.
|
|
||||||
| *`groups`* __string array__ | Groups is the input list of group names.
|
|
||||||
| *`expects`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexampleexpects[$$FederationDomainTransformsExampleExpects$$]__ | Expects is the expected output of the entire sequence of transforms when they are run against the input Username and Groups.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexampleexpects"]
|
|
||||||
==== FederationDomainTransformsExampleExpects
|
|
||||||
|
|
||||||
FederationDomainTransformsExampleExpects defines the expected result for a transforms example.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexample[$$FederationDomainTransformsExample$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`username`* __string__ | Username is the expected username after the transformations have been applied.
|
|
||||||
| *`groups`* __string array__ | Groups is the expected list of group names after the transformations have been applied.
|
|
||||||
| *`rejected`* __boolean__ | Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression after the transformations have been applied. True means that it is expected that the authentication would be rejected. The default value of false means that it is expected that the authentication would not be rejected by any policy expression.
|
|
||||||
| *`message`* __string__ | Message is the expected error message of the transforms. When Rejected is true, then Message is the expected message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank, then Message will be treated as the default error message for authentication attempts which are rejected by a policy. When Rejected is false, then Message is the expected error message for some other non-policy transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransformsexpression"]
|
|
||||||
==== FederationDomainTransformsExpression
|
|
||||||
|
|
||||||
FederationDomainTransformsExpression defines a transform expression.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-federationdomaintransforms[$$FederationDomainTransforms$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
[cols="25a,75a", options="header"]
|
|
||||||
|===
|
|
||||||
| Field | Description
|
|
||||||
| *`type`* __string__ | Type determines the type of the expression. It must be one of the supported types.
|
|
||||||
| *`expression`* __string__ | Expression is a CEL expression that will be evaluated based on the Type during an authentication.
|
|
||||||
| *`message`* __string__ | Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects an authentication attempt. When empty, a default message will be used.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -905,12 +875,10 @@ OIDCClientSpec is a struct that describes an OIDCClient.
|
|||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`allowedRedirectURIs`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-redirecturi[$$RedirectURI$$] array__ | allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this client. Any other uris will be rejected. Must be a URI with the https scheme, unless the hostname is 127.0.0.1 or ::1 which may use the http scheme. Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking for a matching redirect_uri.
|
| *`allowedRedirectURIs`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-redirecturi[$$RedirectURI$$] array__ | allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this client. Any other uris will be rejected. Must be a URI with the https scheme, unless the hostname is 127.0.0.1 or ::1 which may use the http scheme. Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking for a matching redirect_uri.
|
||||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this client. +
|
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this client.
|
||||||
|
Must only contain the following values: - authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to authenticate users. This grant must always be listed. - refresh_token: allows the client to perform refresh grants for the user to extend the user's session. This grant must be listed if allowedScopes lists offline_access. - urn:ietf:params:oauth:grant-type:token-exchange: allows the client to perform RFC8693 token exchange, which is a step in the process to be able to get a cluster credential for the user. This grant must be listed if allowedScopes lists pinniped:request-audience.
|
||||||
Must only contain the following values: - authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to authenticate users. This grant must always be listed. - refresh_token: allows the client to perform refresh grants for the user to extend the user's session. This grant must be listed if allowedScopes lists offline_access. - urn:ietf:params:oauth:grant-type:token-exchange: allows the client to perform RFC8693 token exchange, which is a step in the process to be able to get a cluster credential for the user. This grant must be listed if allowedScopes lists pinniped:request-audience.
|
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client.
|
||||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
Must only contain the following values: - openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). This scope must always be listed. - offline_access: The client is allowed to request an initial refresh token during the authorization code grant flow. This scope must be listed if allowedGrantTypes lists refresh_token. - pinniped:request-audience: The client is allowed to request a new audience value during a RFC8693 token exchange, which is a step in the process to be able to get a cluster credential for the user. openid, username and groups scopes must be listed when this scope is present. This scope must be listed if allowedGrantTypes lists urn:ietf:params:oauth:grant-type:token-exchange. - username: The client is allowed to request that ID tokens contain the user's username. Without the username scope being requested and allowed, the ID token will not contain the user's username. - groups: The client is allowed to request that ID tokens contain the user's group membership, if their group membership is discoverable by the Supervisor. Without the groups scope being requested and allowed, the ID token will not contain groups.
|
||||||
|
|
||||||
Must only contain the following values: - openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). This scope must always be listed. - offline_access: The client is allowed to request an initial refresh token during the authorization code grant flow. This scope must be listed if allowedGrantTypes lists refresh_token. - pinniped:request-audience: The client is allowed to request a new audience value during a RFC8693 token exchange, which is a step in the process to be able to get a cluster credential for the user. openid, username and groups scopes must be listed when this scope is present. This scope must be listed if allowedGrantTypes lists urn:ietf:params:oauth:grant-type:token-exchange. - username: The client is allowed to request that ID tokens contain the user's username. Without the username scope being requested and allowed, the ID token will not contain the user's username. - groups: The client is allowed to request that ID tokens contain the user's group membership, if their group membership is discoverable by the Supervisor. Without the groups scope being requested and allowed, the ID token will not contain groups.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -928,7 +896,7 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-oidcclientphase[$$OIDCClientPhase$$]__ | phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-oidcclientphase[$$OIDCClientPhase$$]__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
@ -966,7 +934,7 @@ Package identity is the internal version of the Pinniped identity API.
|
|||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-extravalue"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-extravalue"]
|
||||||
==== ExtraValue (string array)
|
==== ExtraValue
|
||||||
|
|
||||||
ExtraValue masks the value so protobuf can generate
|
ExtraValue masks the value so protobuf can generate
|
||||||
|
|
||||||
@ -1028,7 +996,30 @@ WhoAmIRequest submits a request to echo back the current authenticated user.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`ObjectMeta`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#objectmeta-v1-meta[$$ObjectMeta$$]__ |
|
| *`name`* __string__ | Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names
|
||||||
|
| *`generateName`* __string__ | GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.
|
||||||
|
If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).
|
||||||
|
Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency
|
||||||
|
| *`namespace`* __string__ | Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.
|
||||||
|
Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces
|
||||||
|
| *`selfLink`* __string__ | SelfLink is a URL representing this object. Populated by the system. Read-only.
|
||||||
|
DEPRECATED Kubernetes will stop propagating this field in 1.20 release and the field is planned to be removed in 1.21 release.
|
||||||
|
| *`uid`* __UID__ | UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.
|
||||||
|
Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids
|
||||||
|
| *`resourceVersion`* __string__ | An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.
|
||||||
|
Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
|
||||||
|
| *`generation`* __integer__ | A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.
|
||||||
|
| *`creationTimestamp`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
||||||
|
Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||||
|
| *`deletionTimestamp`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.
|
||||||
|
Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||||
|
| *`deletionGracePeriodSeconds`* __integer__ | Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.
|
||||||
|
| *`labels`* __object (keys:string, values:string)__ | Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels
|
||||||
|
| *`annotations`* __object (keys:string, values:string)__ | Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations
|
||||||
|
| *`ownerReferences`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#ownerreference-v1-meta[$$OwnerReference$$] array__ | List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.
|
||||||
|
| *`finalizers`* __string array__ | Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list.
|
||||||
|
| *`clusterName`* __string__ | The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
|
||||||
|
| *`managedFields`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#managedfieldsentry-v1-meta[$$ManagedFieldsEntry$$] array__ | ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like "ci-cd". The set of fields is always in the version that the workflow used when modifying the object.
|
||||||
| *`Spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequestspec[$$WhoAmIRequestSpec$$]__ |
|
| *`Spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequestspec[$$WhoAmIRequestSpec$$]__ |
|
||||||
| *`Status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequeststatus[$$WhoAmIRequestStatus$$]__ |
|
| *`Status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequeststatus[$$WhoAmIRequestStatus$$]__ |
|
||||||
|===
|
|===
|
||||||
@ -1036,16 +1027,6 @@ WhoAmIRequest submits a request to echo back the current authenticated user.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequestspec"]
|
|
||||||
==== WhoAmIRequestSpec
|
|
||||||
|
|
||||||
Spec is always empty for a WhoAmIRequest.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequest[$$WhoAmIRequest$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequeststatus"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-whoamirequeststatus"]
|
||||||
@ -1074,7 +1055,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped identity API.
|
|||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-extravalue"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-extravalue"]
|
||||||
==== ExtraValue (string array)
|
==== ExtraValue
|
||||||
|
|
||||||
ExtraValue masks the value so protobuf can generate
|
ExtraValue masks the value so protobuf can generate
|
||||||
|
|
||||||
@ -1145,16 +1126,6 @@ WhoAmIRequest submits a request to echo back the current authenticated user.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-whoamirequestspec"]
|
|
||||||
==== WhoAmIRequestSpec
|
|
||||||
|
|
||||||
Spec is always empty for a WhoAmIRequest.
|
|
||||||
|
|
||||||
.Appears In:
|
|
||||||
****
|
|
||||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-whoamirequest[$$WhoAmIRequest$$]
|
|
||||||
****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-whoamirequeststatus"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-concierge-identity-v1alpha1-whoamirequeststatus"]
|
||||||
@ -1236,13 +1207,10 @@ ActiveDirectoryIdentityProvider describes the configuration of an upstream Micro
|
|||||||
| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the value of an attribute of the user entry found as a result of the user search. Which attribute's value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})". This searches nested groups by default. Note that nested group search can be slow for some Active Directory servers. To disable it, you can set the filter to "(&(objectClass=group)(member={})"
|
| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the value of an attribute of the user entry found as a result of the user search. Which attribute's value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})". This searches nested groups by default. Note that nested group search can be slow for some Active Directory servers. To disable it, you can set the filter to "(&(objectClass=group)(member={})"
|
||||||
| *`userAttributeForFilter`* __string__ | UserAttributeForFilter specifies which attribute's value from the user entry found as a result of the user search will be used to replace the "{}" placeholder(s) in the group search Filter. For example, specifying "uid" as the UserAttributeForFilter while specifying "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing the "{}" placeholder in the Filter with the value of the user's "uid" attribute. Optional. When not specified, the default will act as if "dn" were specified. For example, leaving UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
| *`userAttributeForFilter`* __string__ | UserAttributeForFilter specifies which attribute's value from the user entry found as a result of the user search will be used to replace the "{}" placeholder(s) in the group search Filter. For example, specifying "uid" as the UserAttributeForFilter while specifying "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing the "{}" placeholder in the Filter with the value of the user's "uid" attribute. Optional. When not specified, the default will act as if "dn" were specified. For example, leaving UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||||
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search.
|
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search.
|
||||||
| *`skipGroupRefresh`* __boolean__ | The user's group membership is refreshed as they interact with the supervisor to obtain new credentials (as their old credentials expire). This allows group membership changes to be quickly reflected into Kubernetes clusters. Since group membership is often used to bind authorization policies, it is important to keep the groups observed in Kubernetes clusters in-sync with the identity provider. +
|
| *`skipGroupRefresh`* __boolean__ | The user's group membership is refreshed as they interact with the supervisor to obtain new credentials (as their old credentials expire). This allows group membership changes to be quickly reflected into Kubernetes clusters. Since group membership is often used to bind authorization policies, it is important to keep the groups observed in Kubernetes clusters in-sync with the identity provider.
|
||||||
|
In some environments, frequent group membership queries may result in a significant performance impact on the identity provider and/or the supervisor. The best approach to handle performance impacts is to tweak the group query to be more performant, for example by disabling nested group search or by using a more targeted group search base.
|
||||||
In some environments, frequent group membership queries may result in a significant performance impact on the identity provider and/or the supervisor. The best approach to handle performance impacts is to tweak the group query to be more performant, for example by disabling nested group search or by using a more targeted group search base. +
|
If the group search query cannot be made performant and you are willing to have group memberships remain static for approximately a day, then set skipGroupRefresh to true. This is an insecure configuration as authorization policies that are bound to group membership will not notice if a user has been removed from a particular group until their next login.
|
||||||
|
This is an experimental feature that may be removed or significantly altered in the future. Consumers of this configuration should carefully read all release notes before upgrading to ensure that the meaning of this field has not changed.
|
||||||
If the group search query cannot be made performant and you are willing to have group memberships remain static for approximately a day, then set skipGroupRefresh to true. This is an insecure configuration as authorization policies that are bound to group membership will not notice if a user has been removed from a particular group until their next login. +
|
|
||||||
|
|
||||||
This is an experimental feature that may be removed or significantly altered in the future. Consumers of this configuration should carefully read all release notes before upgrading to ensure that the meaning of this field has not changed.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -1312,7 +1280,7 @@ Status of an Active Directory identity provider.
|
|||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderphase[$$ActiveDirectoryIdentityProviderPhase$$]__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
|
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderphase[$$ActiveDirectoryIdentityProviderPhase$$]__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -1353,6 +1321,42 @@ Status of an Active Directory identity provider.
|
|||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-condition"]
|
||||||
|
==== Condition
|
||||||
|
|
||||||
|
Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API version we can switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$]
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
[cols="25a,75a", options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Description
|
||||||
|
| *`type`* __string__ | type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-conditionstatus[$$ConditionStatus$$]__ | status of the condition, one of True, False, Unknown.
|
||||||
|
| *`observedGeneration`* __integer__ | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
|
||||||
|
| *`lastTransitionTime`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#time-v1-meta[$$Time$$]__ | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
| *`reason`* __string__ | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
|
||||||
|
| *`message`* __string__ | message is a human readable message indicating details about the transition. This may be an empty string.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-conditionstatus"]
|
||||||
|
==== ConditionStatus (string)
|
||||||
|
|
||||||
|
ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
|
||||||
|
.Appears In:
|
||||||
|
****
|
||||||
|
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-condition[$$Condition$$]
|
||||||
|
****
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityprovider"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityprovider"]
|
||||||
==== LDAPIdentityProvider
|
==== LDAPIdentityProvider
|
||||||
|
|
||||||
@ -1407,13 +1411,10 @@ LDAPIdentityProvider describes the configuration of an upstream Lightweight Dire
|
|||||||
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the value of an attribute of the user entry found as a result of the user search. Which attribute's value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter. For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}".
|
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the value of an attribute of the user entry found as a result of the user search. Which attribute's value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter. For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}".
|
||||||
| *`userAttributeForFilter`* __string__ | UserAttributeForFilter specifies which attribute's value from the user entry found as a result of the user search will be used to replace the "{}" placeholder(s) in the group search Filter. For example, specifying "uid" as the UserAttributeForFilter while specifying "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing the "{}" placeholder in the Filter with the value of the user's "uid" attribute. Optional. When not specified, the default will act as if "dn" were specified. For example, leaving UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
| *`userAttributeForFilter`* __string__ | UserAttributeForFilter specifies which attribute's value from the user entry found as a result of the user search will be used to replace the "{}" placeholder(s) in the group search Filter. For example, specifying "uid" as the UserAttributeForFilter while specifying "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing the "{}" placeholder in the Filter with the value of the user's "uid" attribute. Optional. When not specified, the default will act as if "dn" were specified. For example, leaving UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||||
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes[$$LDAPIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each LDAP entry which was found as the result of the group search.
|
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes[$$LDAPIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each LDAP entry which was found as the result of the group search.
|
||||||
| *`skipGroupRefresh`* __boolean__ | The user's group membership is refreshed as they interact with the supervisor to obtain new credentials (as their old credentials expire). This allows group membership changes to be quickly reflected into Kubernetes clusters. Since group membership is often used to bind authorization policies, it is important to keep the groups observed in Kubernetes clusters in-sync with the identity provider. +
|
| *`skipGroupRefresh`* __boolean__ | The user's group membership is refreshed as they interact with the supervisor to obtain new credentials (as their old credentials expire). This allows group membership changes to be quickly reflected into Kubernetes clusters. Since group membership is often used to bind authorization policies, it is important to keep the groups observed in Kubernetes clusters in-sync with the identity provider.
|
||||||
|
In some environments, frequent group membership queries may result in a significant performance impact on the identity provider and/or the supervisor. The best approach to handle performance impacts is to tweak the group query to be more performant, for example by disabling nested group search or by using a more targeted group search base.
|
||||||
In some environments, frequent group membership queries may result in a significant performance impact on the identity provider and/or the supervisor. The best approach to handle performance impacts is to tweak the group query to be more performant, for example by disabling nested group search or by using a more targeted group search base. +
|
If the group search query cannot be made performant and you are willing to have group memberships remain static for approximately a day, then set skipGroupRefresh to true. This is an insecure configuration as authorization policies that are bound to group membership will not notice if a user has been removed from a particular group until their next login.
|
||||||
|
This is an experimental feature that may be removed or significantly altered in the future. Consumers of this configuration should carefully read all release notes before upgrading to ensure that the meaning of this field has not changed.
|
||||||
If the group search query cannot be made performant and you are willing to have group memberships remain static for approximately a day, then set skipGroupRefresh to true. This is an insecure configuration as authorization policies that are bound to group membership will not notice if a user has been removed from a particular group until their next login. +
|
|
||||||
|
|
||||||
This is an experimental feature that may be removed or significantly altered in the future. Consumers of this configuration should carefully read all release notes before upgrading to ensure that the meaning of this field has not changed.
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -1483,7 +1484,7 @@ Status of an LDAP identity provider.
|
|||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityproviderphase[$$LDAPIdentityProviderPhase$$]__ | Phase summarizes the overall status of the LDAPIdentityProvider.
|
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-ldapidentityproviderphase[$$LDAPIdentityProviderPhase$$]__ | Phase summarizes the overall status of the LDAPIdentityProvider.
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
@ -1648,7 +1649,7 @@ OIDCIdentityProviderStatus is the status of an OIDC identity provider.
|
|||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-oidcidentityproviderphase[$$OIDCIdentityProviderPhase$$]__ | Phase summarizes the overall status of the OIDCIdentityProvider.
|
| *`phase`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-oidcidentityproviderphase[$$OIDCIdentityProviderPhase$$]__ | Phase summarizes the overall status of the OIDCIdentityProvider.
|
||||||
| *`conditions`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#condition-v1-meta[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a JWT authenticator.
|
// Spec for configuring a JWT authenticator.
|
||||||
|
75
generated/1.21/apis/concierge/authentication/v1alpha1/types_meta.go
generated
Normal file
75
generated/1.21/apis/concierge/authentication/v1alpha1/types_meta.go
generated
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a webhook authenticator.
|
// Spec for configuring a webhook authenticator.
|
||||||
|
@ -9,10 +9,26 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Condition) DeepCopyInto(out *Condition) {
|
||||||
|
*out = *in
|
||||||
|
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||||
|
func (in *Condition) DeepCopy() *Condition {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Condition)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -101,7 +117,7 @@ func (in *JWTAuthenticatorStatus) DeepCopyInto(out *JWTAuthenticatorStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@ -238,7 +254,7 @@ func (in *WebhookAuthenticatorStatus) DeepCopyInto(out *WebhookAuthenticatorStat
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,17 +8,14 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FederationDomainPhase string
|
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||||
|
type FederationDomainStatusCondition string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FederationDomainPhasePending is the default phase for newly-created FederationDomain resources.
|
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||||
FederationDomainPhasePending FederationDomainPhase = "Pending"
|
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||||
|
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||||
// FederationDomainPhaseReady is the phase for an FederationDomain resource in a healthy state.
|
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||||
FederationDomainPhaseReady FederationDomainPhase = "Ready"
|
|
||||||
|
|
||||||
// FederationDomainPhaseError is the phase for an FederationDomain in an unhealthy state.
|
|
||||||
FederationDomainPhaseError FederationDomainPhase = "Error"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||||
@ -45,157 +42,6 @@ type FederationDomainTLSSpec struct {
|
|||||||
SecretName string `json:"secretName,omitempty"`
|
SecretName string `json:"secretName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainTransformsConstant defines a constant variable and its value which will be made available to
|
|
||||||
// the transform expressions. This is a union type, and Type is the discriminator field.
|
|
||||||
type FederationDomainTransformsConstant struct {
|
|
||||||
// Name determines the name of the constant. It must be a valid identifier name.
|
|
||||||
// +kubebuilder:validation:Pattern=`^[a-zA-Z][_a-zA-Z0-9]*$`
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
// +kubebuilder:validation:MaxLength=64
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Type determines the type of the constant, and indicates which other field should be non-empty.
|
|
||||||
// +kubebuilder:validation:Enum=string;stringList
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// StringValue should hold the value when Type is "string", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringValue string `json:"stringValue,omitempty"`
|
|
||||||
|
|
||||||
// StringListValue should hold the value when Type is "stringList", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringListValue []string `json:"stringListValue,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExpression defines a transform expression.
|
|
||||||
type FederationDomainTransformsExpression struct {
|
|
||||||
// Type determines the type of the expression. It must be one of the supported types.
|
|
||||||
// +kubebuilder:validation:Enum=policy/v1;username/v1;groups/v1
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// Expression is a CEL expression that will be evaluated based on the Type during an authentication.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Expression string `json:"expression"`
|
|
||||||
|
|
||||||
// Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects
|
|
||||||
// an authentication attempt. When empty, a default message will be used.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExample defines a transform example.
|
|
||||||
type FederationDomainTransformsExample struct {
|
|
||||||
// Username is the input username.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Username string `json:"username"`
|
|
||||||
|
|
||||||
// Groups is the input list of group names.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Expects is the expected output of the entire sequence of transforms when they are run against the
|
|
||||||
// input Username and Groups.
|
|
||||||
Expects FederationDomainTransformsExampleExpects `json:"expects"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExampleExpects defines the expected result for a transforms example.
|
|
||||||
type FederationDomainTransformsExampleExpects struct {
|
|
||||||
// Username is the expected username after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
|
|
||||||
// Groups is the expected list of group names after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression
|
|
||||||
// after the transformations have been applied. True means that it is expected that the authentication would be
|
|
||||||
// rejected. The default value of false means that it is expected that the authentication would not be rejected
|
|
||||||
// by any policy expression.
|
|
||||||
// +optional
|
|
||||||
Rejected bool `json:"rejected,omitempty"`
|
|
||||||
|
|
||||||
// Message is the expected error message of the transforms. When Rejected is true, then Message is the expected
|
|
||||||
// message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank,
|
|
||||||
// then Message will be treated as the default error message for authentication attempts which are rejected by a
|
|
||||||
// policy. When Rejected is false, then Message is the expected error message for some other non-policy
|
|
||||||
// transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransforms defines identity transformations for an identity provider's usage on a FederationDomain.
|
|
||||||
type FederationDomainTransforms struct {
|
|
||||||
// Constants defines constant variables and their values which will be made available to the transform expressions.
|
|
||||||
// +patchMergeKey=name
|
|
||||||
// +patchStrategy=merge
|
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=name
|
|
||||||
// +optional
|
|
||||||
Constants []FederationDomainTransformsConstant `json:"constants,omitempty"`
|
|
||||||
|
|
||||||
// Expressions are an optional list of transforms and policies to be executed in the order given during every
|
|
||||||
// authentication attempt, including during every session refresh.
|
|
||||||
// Each is a CEL expression. It may use the basic CEL language as defined in
|
|
||||||
// https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in
|
|
||||||
// https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
//
|
|
||||||
// The username and groups extracted from the identity provider, and the constants defined in this CR, are
|
|
||||||
// available as variables in all expressions. The username is provided via a variable called `username` and
|
|
||||||
// the list of group names is provided via a variable called `groups` (which may be an empty list).
|
|
||||||
// Each user-provided constants is provided via a variable named `strConst.varName` for string constants
|
|
||||||
// and `strListConst.varName` for string list constants.
|
|
||||||
//
|
|
||||||
// The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1.
|
|
||||||
// Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated
|
|
||||||
// and the authentication attempt is rejected.
|
|
||||||
// Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the
|
|
||||||
// username or group names.
|
|
||||||
// Each username/v1 transform must return the new username (a string), which can be the same as the old username.
|
|
||||||
// Transformations of type username/v1 do not return group names, and therefore cannot change the group names.
|
|
||||||
// Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old
|
|
||||||
// groups list.
|
|
||||||
// Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames.
|
|
||||||
// After each expression, the new (potentially changed) username or groups get passed to the following expression.
|
|
||||||
//
|
|
||||||
// Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain.
|
|
||||||
// During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the
|
|
||||||
// authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username
|
|
||||||
// and group names have been decided for that authentication attempt.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
Expressions []FederationDomainTransformsExpression `json:"expressions,omitempty"`
|
|
||||||
|
|
||||||
// Examples can optionally be used to ensure that the sequence of transformation expressions are working as
|
|
||||||
// expected. Examples define sample input identities which are then run through the expression list, and the
|
|
||||||
// results are compared to the expected results. If any example in this list fails, then this
|
|
||||||
// identity provider will not be available for use within this FederationDomain, and the error(s) will be
|
|
||||||
// added to the FederationDomain status. This can be used to help guard against programming mistakes in the
|
|
||||||
// expressions, and also act as living documentation for other administrators to better understand the expressions.
|
|
||||||
// +optional
|
|
||||||
Examples []FederationDomainTransformsExample `json:"examples,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainIdentityProvider describes how an identity provider is made available in this FederationDomain.
|
|
||||||
type FederationDomainIdentityProvider struct {
|
|
||||||
// DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the
|
|
||||||
// kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a
|
|
||||||
// disruptive change for those users.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
|
|
||||||
// ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required.
|
|
||||||
// If the reference cannot be resolved then the identity provider will not be made available.
|
|
||||||
// Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider,
|
|
||||||
// LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
|
||||||
ObjectRef corev1.TypedLocalObjectReference `json:"objectRef"`
|
|
||||||
|
|
||||||
// Transforms is an optional way to specify transformations to be applied during user authentication and
|
|
||||||
// session refresh.
|
|
||||||
// +optional
|
|
||||||
Transforms FederationDomainTransforms `json:"transforms,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||||
type FederationDomainSpec struct {
|
type FederationDomainSpec struct {
|
||||||
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||||
@ -209,35 +55,9 @@ type FederationDomainSpec struct {
|
|||||||
// +kubebuilder:validation:MinLength=1
|
// +kubebuilder:validation:MinLength=1
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
|
|
||||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||||
// +optional
|
// +optional
|
||||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||||
|
|
||||||
// IdentityProviders is the list of identity providers available for use by this FederationDomain.
|
|
||||||
//
|
|
||||||
// An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server,
|
|
||||||
// how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to
|
|
||||||
// extract a normalized user identity. Normalized user identities include a username and a list of group names.
|
|
||||||
// In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which
|
|
||||||
// belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations
|
|
||||||
// on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid
|
|
||||||
// accidental conflicts when multiple identity providers have different users with the same username (e.g.
|
|
||||||
// "idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication
|
|
||||||
// rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow
|
|
||||||
// the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could
|
|
||||||
// disallow the authentication unless the user belongs to a specific group in the identity provider.
|
|
||||||
//
|
|
||||||
// For backwards compatibility with versions of Pinniped which predate support for multiple identity providers,
|
|
||||||
// an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which
|
|
||||||
// exist in the same namespace, but also to reject all authentication requests when there is more than one identity
|
|
||||||
// provider currently defined. In this backwards compatibility mode, the name of the identity provider resource
|
|
||||||
// (e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this
|
|
||||||
// FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of
|
|
||||||
// relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead
|
|
||||||
// explicitly list the identity provider using this IdentityProviders field.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
IdentityProviders []FederationDomainIdentityProvider `json:"identityProviders,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||||
@ -266,17 +86,20 @@ type FederationDomainSecrets struct {
|
|||||||
|
|
||||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||||
type FederationDomainStatus struct {
|
type FederationDomainStatus struct {
|
||||||
// Phase summarizes the overall status of the FederationDomain.
|
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||||
// +kubebuilder:default=Pending
|
// represent success or failure.
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +optional
|
||||||
Phase FederationDomainPhase `json:"phase,omitempty"`
|
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||||
|
|
||||||
// Conditions represent the observations of an FederationDomain's current state.
|
// Message provides human-readable details about the Status.
|
||||||
// +patchMergeKey=type
|
// +optional
|
||||||
// +patchStrategy=merge
|
Message string `json:"message,omitempty"`
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=type
|
// LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
// around some undesirable behavior with respect to the empty metav1.Time value (see
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
|
// +optional
|
||||||
|
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||||
|
|
||||||
// Secrets contains information about this OIDC Provider's secrets.
|
// Secrets contains information about this OIDC Provider's secrets.
|
||||||
// +optional
|
// +optional
|
||||||
@ -288,7 +111,7 @@ type FederationDomainStatus struct {
|
|||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
// +kubebuilder:resource:categories=pinniped
|
// +kubebuilder:resource:categories=pinniped
|
||||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
type FederationDomain struct {
|
type FederationDomain struct {
|
||||||
|
75
generated/1.21/apis/supervisor/config/v1alpha1/types_meta.go
generated
Normal file
75
generated/1.21/apis/supervisor/config/v1alpha1/types_meta.go
generated
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|||||||
type OIDCClientPhase string
|
type OIDCClientPhase string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
PhasePending OIDCClientPhase = "Pending"
|
||||||
|
|
||||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
PhaseReady OIDCClientPhase = "Ready"
|
||||||
|
|
||||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
PhaseError OIDCClientPhase = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||||
@ -85,7 +85,7 @@ type OIDCClientStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -9,10 +9,26 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Condition) DeepCopyInto(out *Condition) {
|
||||||
|
*out = *in
|
||||||
|
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||||
|
func (in *Condition) DeepCopy() *Condition {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Condition)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *FederationDomain) DeepCopyInto(out *FederationDomain) {
|
func (in *FederationDomain) DeepCopyInto(out *FederationDomain) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -41,24 +57,6 @@ func (in *FederationDomain) DeepCopyObject() runtime.Object {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainIdentityProvider) DeepCopyInto(out *FederationDomainIdentityProvider) {
|
|
||||||
*out = *in
|
|
||||||
in.ObjectRef.DeepCopyInto(&out.ObjectRef)
|
|
||||||
in.Transforms.DeepCopyInto(&out.Transforms)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainIdentityProvider.
|
|
||||||
func (in *FederationDomainIdentityProvider) DeepCopy() *FederationDomainIdentityProvider {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainIdentityProvider)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *FederationDomainList) DeepCopyInto(out *FederationDomainList) {
|
func (in *FederationDomainList) DeepCopyInto(out *FederationDomainList) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -120,13 +118,6 @@ func (in *FederationDomainSpec) DeepCopyInto(out *FederationDomainSpec) {
|
|||||||
*out = new(FederationDomainTLSSpec)
|
*out = new(FederationDomainTLSSpec)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
if in.IdentityProviders != nil {
|
|
||||||
in, out := &in.IdentityProviders, &out.IdentityProviders
|
|
||||||
*out = make([]FederationDomainIdentityProvider, len(*in))
|
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +134,9 @@ func (in *FederationDomainSpec) DeepCopy() *FederationDomainSpec {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *FederationDomainStatus) DeepCopyInto(out *FederationDomainStatus) {
|
func (in *FederationDomainStatus) DeepCopyInto(out *FederationDomainStatus) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.LastUpdateTime != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.LastUpdateTime, &out.LastUpdateTime
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = (*in).DeepCopy()
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out.Secrets = in.Secrets
|
out.Secrets = in.Secrets
|
||||||
return
|
return
|
||||||
@ -180,121 +168,6 @@ func (in *FederationDomainTLSSpec) DeepCopy() *FederationDomainTLSSpec {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainTransforms) DeepCopyInto(out *FederationDomainTransforms) {
|
|
||||||
*out = *in
|
|
||||||
if in.Constants != nil {
|
|
||||||
in, out := &in.Constants, &out.Constants
|
|
||||||
*out = make([]FederationDomainTransformsConstant, len(*in))
|
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if in.Expressions != nil {
|
|
||||||
in, out := &in.Expressions, &out.Expressions
|
|
||||||
*out = make([]FederationDomainTransformsExpression, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
if in.Examples != nil {
|
|
||||||
in, out := &in.Examples, &out.Examples
|
|
||||||
*out = make([]FederationDomainTransformsExample, len(*in))
|
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTransforms.
|
|
||||||
func (in *FederationDomainTransforms) DeepCopy() *FederationDomainTransforms {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainTransforms)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainTransformsConstant) DeepCopyInto(out *FederationDomainTransformsConstant) {
|
|
||||||
*out = *in
|
|
||||||
if in.StringListValue != nil {
|
|
||||||
in, out := &in.StringListValue, &out.StringListValue
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTransformsConstant.
|
|
||||||
func (in *FederationDomainTransformsConstant) DeepCopy() *FederationDomainTransformsConstant {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainTransformsConstant)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainTransformsExample) DeepCopyInto(out *FederationDomainTransformsExample) {
|
|
||||||
*out = *in
|
|
||||||
if in.Groups != nil {
|
|
||||||
in, out := &in.Groups, &out.Groups
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
in.Expects.DeepCopyInto(&out.Expects)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTransformsExample.
|
|
||||||
func (in *FederationDomainTransformsExample) DeepCopy() *FederationDomainTransformsExample {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainTransformsExample)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainTransformsExampleExpects) DeepCopyInto(out *FederationDomainTransformsExampleExpects) {
|
|
||||||
*out = *in
|
|
||||||
if in.Groups != nil {
|
|
||||||
in, out := &in.Groups, &out.Groups
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTransformsExampleExpects.
|
|
||||||
func (in *FederationDomainTransformsExampleExpects) DeepCopy() *FederationDomainTransformsExampleExpects {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainTransformsExampleExpects)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *FederationDomainTransformsExpression) DeepCopyInto(out *FederationDomainTransformsExpression) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTransformsExpression.
|
|
||||||
func (in *FederationDomainTransformsExpression) DeepCopy() *FederationDomainTransformsExpression {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(FederationDomainTransformsExpression)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *OIDCClient) DeepCopyInto(out *OIDCClient) {
|
func (in *OIDCClient) DeepCopyInto(out *OIDCClient) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -392,7 +265,7 @@ func (in *OIDCClientStatus) DeepCopyInto(out *OIDCClientStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ type ActiveDirectoryIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActiveDirectoryIdentityProviderBind struct {
|
type ActiveDirectoryIdentityProviderBind struct {
|
||||||
|
@ -32,7 +32,7 @@ type LDAPIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LDAPIdentityProviderBind struct {
|
type LDAPIdentityProviderBind struct {
|
||||||
|
75
generated/1.21/apis/supervisor/idp/v1alpha1/types_meta.go
generated
Normal file
75
generated/1.21/apis/supervisor/idp/v1alpha1/types_meta.go
generated
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -32,7 +32,7 @@ type OIDCIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -152,7 +151,7 @@ func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirecto
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@ -203,6 +202,23 @@ func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *Activ
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Condition) DeepCopyInto(out *Condition) {
|
||||||
|
*out = *in
|
||||||
|
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||||
|
func (in *Condition) DeepCopy() *Condition {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Condition)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *LDAPIdentityProvider) DeepCopyInto(out *LDAPIdentityProvider) {
|
func (in *LDAPIdentityProvider) DeepCopyInto(out *LDAPIdentityProvider) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -342,7 +358,7 @@ func (in *LDAPIdentityProviderStatus) DeepCopyInto(out *LDAPIdentityProviderStat
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@ -548,7 +564,7 @@ func (in *OIDCIdentityProviderStatus) DeepCopyInto(out *OIDCIdentityProviderStat
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -96,15 +97,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -173,3 +168,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -69,15 +70,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -146,3 +141,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: credentialissuers.config.concierge.pinniped.dev
|
name: credentialissuers.config.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.concierge.pinniped.dev
|
group: config.concierge.pinniped.dev
|
||||||
@ -255,3 +256,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: federationdomains.config.supervisor.pinniped.dev
|
name: federationdomains.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -20,7 +21,7 @@ spec:
|
|||||||
- jsonPath: .spec.issuer
|
- jsonPath: .spec.issuer
|
||||||
name: Issuer
|
name: Issuer
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .status.phase
|
- jsonPath: .status.status
|
||||||
name: Status
|
name: Status
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .metadata.creationTimestamp
|
- jsonPath: .metadata.creationTimestamp
|
||||||
@ -46,263 +47,6 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
description: Spec of the OIDC provider.
|
description: Spec of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
identityProviders:
|
|
||||||
description: "IdentityProviders is the list of identity providers
|
|
||||||
available for use by this FederationDomain. \n An identity provider
|
|
||||||
CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes
|
|
||||||
how to connect to a server, how to talk in a specific protocol for
|
|
||||||
authentication, and how to use the schema of that server/protocol
|
|
||||||
to extract a normalized user identity. Normalized user identities
|
|
||||||
include a username and a list of group names. In contrast, IdentityProviders
|
|
||||||
describes how to use that normalized identity in those Kubernetes
|
|
||||||
clusters which belong to this FederationDomain. Each entry in IdentityProviders
|
|
||||||
can be configured with arbitrary transformations on that normalized
|
|
||||||
identity. For example, a transformation can add a prefix to all
|
|
||||||
usernames to help avoid accidental conflicts when multiple identity
|
|
||||||
providers have different users with the same username (e.g. \"idp1:ryan\"
|
|
||||||
versus \"idp2:ryan\"). Each entry in IdentityProviders can also
|
|
||||||
implement arbitrary authentication rejection policies. Even though
|
|
||||||
a user was able to authenticate with the identity provider, a policy
|
|
||||||
can disallow the authentication to the Kubernetes clusters that
|
|
||||||
belong to this FederationDomain. For example, a policy could disallow
|
|
||||||
the authentication unless the user belongs to a specific group in
|
|
||||||
the identity provider. \n For backwards compatibility with versions
|
|
||||||
of Pinniped which predate support for multiple identity providers,
|
|
||||||
an empty IdentityProviders list will cause the FederationDomain
|
|
||||||
to use all available identity providers which exist in the same
|
|
||||||
namespace, but also to reject all authentication requests when there
|
|
||||||
is more than one identity provider currently defined. In this backwards
|
|
||||||
compatibility mode, the name of the identity provider resource (e.g.
|
|
||||||
the Name of an OIDCIdentityProvider resource) will be used as the
|
|
||||||
name of the identity provider in this FederationDomain. This mode
|
|
||||||
is provided to make upgrading from older versions easier. However,
|
|
||||||
instead of relying on this backwards compatibility mode, please
|
|
||||||
consider this mode to be deprecated and please instead explicitly
|
|
||||||
list the identity provider using this IdentityProviders field."
|
|
||||||
items:
|
|
||||||
description: FederationDomainIdentityProvider describes how an identity
|
|
||||||
provider is made available in this FederationDomain.
|
|
||||||
properties:
|
|
||||||
displayName:
|
|
||||||
description: DisplayName is the name of this identity provider
|
|
||||||
as it will appear to clients. This name ends up in the kubeconfig
|
|
||||||
of end users, so changing the name of an identity provider
|
|
||||||
that is in use by end users will be a disruptive change for
|
|
||||||
those users.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
objectRef:
|
|
||||||
description: ObjectRef is a reference to a Pinniped identity
|
|
||||||
provider resource. A valid reference is required. If the reference
|
|
||||||
cannot be resolved then the identity provider will not be
|
|
||||||
made available. Must refer to a resource of one of the Pinniped
|
|
||||||
identity provider types, e.g. OIDCIdentityProvider, LDAPIdentityProvider,
|
|
||||||
ActiveDirectoryIdentityProvider.
|
|
||||||
properties:
|
|
||||||
apiGroup:
|
|
||||||
description: APIGroup is the group for the resource being
|
|
||||||
referenced. If APIGroup is not specified, the specified
|
|
||||||
Kind must be in the core API group. For any other third-party
|
|
||||||
types, APIGroup is required.
|
|
||||||
type: string
|
|
||||||
kind:
|
|
||||||
description: Kind is the type of resource being referenced
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
description: Name is the name of resource being referenced
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
transforms:
|
|
||||||
description: Transforms is an optional way to specify transformations
|
|
||||||
to be applied during user authentication and session refresh.
|
|
||||||
properties:
|
|
||||||
constants:
|
|
||||||
description: Constants defines constant variables and their
|
|
||||||
values which will be made available to the transform expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsConstant defines
|
|
||||||
a constant variable and its value which will be made
|
|
||||||
available to the transform expressions. This is a union
|
|
||||||
type, and Type is the discriminator field.
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name determines the name of the constant.
|
|
||||||
It must be a valid identifier name.
|
|
||||||
maxLength: 64
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[a-zA-Z][_a-zA-Z0-9]*$
|
|
||||||
type: string
|
|
||||||
stringListValue:
|
|
||||||
description: StringListValue should hold the value
|
|
||||||
when Type is "stringList", and is otherwise ignored.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
stringValue:
|
|
||||||
description: StringValue should hold the value when
|
|
||||||
Type is "string", and is otherwise ignored.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the constant,
|
|
||||||
and indicates which other field should be non-empty.
|
|
||||||
enum:
|
|
||||||
- string
|
|
||||||
- stringList
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- name
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
examples:
|
|
||||||
description: Examples can optionally be used to ensure that
|
|
||||||
the sequence of transformation expressions are working
|
|
||||||
as expected. Examples define sample input identities which
|
|
||||||
are then run through the expression list, and the results
|
|
||||||
are compared to the expected results. If any example in
|
|
||||||
this list fails, then this identity provider will not
|
|
||||||
be available for use within this FederationDomain, and
|
|
||||||
the error(s) will be added to the FederationDomain status.
|
|
||||||
This can be used to help guard against programming mistakes
|
|
||||||
in the expressions, and also act as living documentation
|
|
||||||
for other administrators to better understand the expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExample defines
|
|
||||||
a transform example.
|
|
||||||
properties:
|
|
||||||
expects:
|
|
||||||
description: Expects is the expected output of the
|
|
||||||
entire sequence of transforms when they are run
|
|
||||||
against the input Username and Groups.
|
|
||||||
properties:
|
|
||||||
groups:
|
|
||||||
description: Groups is the expected list of group
|
|
||||||
names after the transformations have been applied.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
message:
|
|
||||||
description: Message is the expected error message
|
|
||||||
of the transforms. When Rejected is true, then
|
|
||||||
Message is the expected message for the policy
|
|
||||||
which rejected the authentication attempt. When
|
|
||||||
Rejected is true and Message is blank, then
|
|
||||||
Message will be treated as the default error
|
|
||||||
message for authentication attempts which are
|
|
||||||
rejected by a policy. When Rejected is false,
|
|
||||||
then Message is the expected error message for
|
|
||||||
some other non-policy transformation error,
|
|
||||||
such as a runtime error. When Rejected is false,
|
|
||||||
there is no default expected Message.
|
|
||||||
type: string
|
|
||||||
rejected:
|
|
||||||
description: Rejected is a boolean that indicates
|
|
||||||
whether authentication is expected to be rejected
|
|
||||||
by a policy expression after the transformations
|
|
||||||
have been applied. True means that it is expected
|
|
||||||
that the authentication would be rejected. The
|
|
||||||
default value of false means that it is expected
|
|
||||||
that the authentication would not be rejected
|
|
||||||
by any policy expression.
|
|
||||||
type: boolean
|
|
||||||
username:
|
|
||||||
description: Username is the expected username
|
|
||||||
after the transformations have been applied.
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
groups:
|
|
||||||
description: Groups is the input list of group names.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
username:
|
|
||||||
description: Username is the input username.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expects
|
|
||||||
- username
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
expressions:
|
|
||||||
description: "Expressions are an optional list of transforms
|
|
||||||
and policies to be executed in the order given during
|
|
||||||
every authentication attempt, including during every session
|
|
||||||
refresh. Each is a CEL expression. It may use the basic
|
|
||||||
CEL language as defined in https://github.com/google/cel-spec/blob/master/doc/langdef.md
|
|
||||||
plus the CEL string extensions defined in https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
\n The username and groups extracted from the identity
|
|
||||||
provider, and the constants defined in this CR, are available
|
|
||||||
as variables in all expressions. The username is provided
|
|
||||||
via a variable called `username` and the list of group
|
|
||||||
names is provided via a variable called `groups` (which
|
|
||||||
may be an empty list). Each user-provided constants is
|
|
||||||
provided via a variable named `strConst.varName` for string
|
|
||||||
constants and `strListConst.varName` for string list constants.
|
|
||||||
\n The only allowed types for expressions are currently
|
|
||||||
policy/v1, username/v1, and groups/v1. Each policy/v1
|
|
||||||
must return a boolean, and when it returns false, no more
|
|
||||||
expressions from the list are evaluated and the authentication
|
|
||||||
attempt is rejected. Transformations of type policy/v1
|
|
||||||
do not return usernames or group names, and therefore
|
|
||||||
cannot change the username or group names. Each username/v1
|
|
||||||
transform must return the new username (a string), which
|
|
||||||
can be the same as the old username. Transformations of
|
|
||||||
type username/v1 do not return group names, and therefore
|
|
||||||
cannot change the group names. Each groups/v1 transform
|
|
||||||
must return the new groups list (list of strings), which
|
|
||||||
can be the same as the old groups list. Transformations
|
|
||||||
of type groups/v1 do not return usernames, and therefore
|
|
||||||
cannot change the usernames. After each expression, the
|
|
||||||
new (potentially changed) username or groups get passed
|
|
||||||
to the following expression. \n Any compilation or static
|
|
||||||
type-checking failure of any expression will cause an
|
|
||||||
error status on the FederationDomain. During an authentication
|
|
||||||
attempt, any unexpected runtime evaluation errors (e.g.
|
|
||||||
division by zero) cause the authentication attempt to
|
|
||||||
fail. When all expressions evaluate successfully, then
|
|
||||||
the (potentially changed) username and group names have
|
|
||||||
been decided for that authentication attempt."
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExpression defines
|
|
||||||
a transform expression.
|
|
||||||
properties:
|
|
||||||
expression:
|
|
||||||
description: Expression is a CEL expression that will
|
|
||||||
be evaluated based on the Type during an authentication.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: Message is only used when Type is policy/v1.
|
|
||||||
It defines an error message to be used when the
|
|
||||||
policy rejects an authentication attempt. When empty,
|
|
||||||
a default message will be used.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the expression.
|
|
||||||
It must be one of the supported types.
|
|
||||||
enum:
|
|
||||||
- policy/v1
|
|
||||||
- username/v1
|
|
||||||
- groups/v1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expression
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- displayName
|
|
||||||
- objectRef
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
issuer:
|
issuer:
|
||||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||||
Metadata document, as well as the identifier that it will use for
|
Metadata document, as well as the identifier that it will use for
|
||||||
@ -315,8 +59,8 @@ spec:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
type: string
|
type: string
|
||||||
tls:
|
tls:
|
||||||
description: TLS specifies a secret which will contain Transport Layer
|
description: TLS configures how this FederationDomain is served over
|
||||||
Security (TLS) configuration for the FederationDomain.
|
Transport Layer Security (TLS).
|
||||||
properties:
|
properties:
|
||||||
secretName:
|
secretName:
|
||||||
description: "SecretName is an optional name of a Secret in the
|
description: "SecretName is an optional name of a Secret in the
|
||||||
@ -347,86 +91,14 @@ spec:
|
|||||||
status:
|
status:
|
||||||
description: Status of the OIDC provider.
|
description: Status of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
lastUpdateTime:
|
||||||
description: Conditions represent the observations of an FederationDomain's
|
description: LastUpdateTime holds the time at which the Status was
|
||||||
current state.
|
last updated. It is a pointer to get around some undesirable behavior
|
||||||
items:
|
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
description: "Condition contains details for one aspect of the current
|
format: date-time
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type: string
|
||||||
use as an array at the field path .status.conditions. For example,
|
message:
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
description: Message provides human-readable details about the Status.
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
|
||||||
lastTransitionTime:
|
|
||||||
description: lastTransitionTime is the last time the condition
|
|
||||||
transitioned from one status to another. This should be when
|
|
||||||
the underlying condition changed. If that is not known, then
|
|
||||||
using the time when the API field changed is acceptable.
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: message is a human readable message indicating
|
|
||||||
details about the transition. This may be an empty string.
|
|
||||||
maxLength: 32768
|
|
||||||
type: string
|
|
||||||
observedGeneration:
|
|
||||||
description: observedGeneration represents the .metadata.generation
|
|
||||||
that the condition was set based upon. For instance, if .metadata.generation
|
|
||||||
is currently 12, but the .status.conditions[x].observedGeneration
|
|
||||||
is 9, the condition is out of date with respect to the current
|
|
||||||
state of the instance.
|
|
||||||
format: int64
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
reason:
|
|
||||||
description: reason contains a programmatic identifier indicating
|
|
||||||
the reason for the condition's last transition. Producers
|
|
||||||
of specific condition types may define expected values and
|
|
||||||
meanings for this field, and whether the values are considered
|
|
||||||
a guaranteed API. The value should be a CamelCase string.
|
|
||||||
This field may not be empty.
|
|
||||||
maxLength: 1024
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: status of the condition, one of True, False, Unknown.
|
|
||||||
enum:
|
|
||||||
- "True"
|
|
||||||
- "False"
|
|
||||||
- Unknown
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
|
||||||
--- Many .condition.type values are consistent across resources
|
|
||||||
like Available, but because arbitrary conditions can be useful
|
|
||||||
(see .node.status.conditions), the ability to deconflict is
|
|
||||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
|
||||||
maxLength: 316
|
|
||||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- lastTransitionTime
|
|
||||||
- message
|
|
||||||
- reason
|
|
||||||
- status
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- type
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
phase:
|
|
||||||
default: Pending
|
|
||||||
description: Phase summarizes the overall status of the FederationDomain.
|
|
||||||
enum:
|
|
||||||
- Pending
|
|
||||||
- Ready
|
|
||||||
- Error
|
|
||||||
type: string
|
type: string
|
||||||
secrets:
|
secrets:
|
||||||
description: Secrets contains information about this OIDC Provider's
|
description: Secrets contains information about this OIDC Provider's
|
||||||
@ -473,6 +145,15 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status holds an enum that describes the state of this
|
||||||
|
OIDC Provider. Note that this Status can represent success or failure.
|
||||||
|
enum:
|
||||||
|
- Success
|
||||||
|
- Duplicate
|
||||||
|
- Invalid
|
||||||
|
- SameIssuerHostMustUseSameSecret
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
@ -481,3 +162,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcclients.config.supervisor.pinniped.dev
|
name: oidcclients.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -128,15 +129,9 @@ spec:
|
|||||||
description: conditions represent the observations of an OIDCClient's
|
description: conditions represent the observations of an OIDCClient's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -218,3 +213,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -231,15 +232,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -316,3 +311,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -228,15 +229,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -313,3 +308,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -258,15 +259,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
type FooStatus struct{ // Represents the observations of a foo's
|
|
||||||
current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -343,3 +338,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user