Compare commits
1 Commits
main
...
jtc/add-bl
Author | SHA1 | Date | |
---|---|---|---|
|
e5f6165385 |
@ -21,6 +21,3 @@
|
||||
|
||||
# MacOS Desktop Services 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
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -8,12 +8,6 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
open-pull-requests-limit: 2
|
||||
directory: "/hack/update-go-mod"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
|
39
.github/workflows/codeql-analysis.yml
vendored
39
.github/workflows/codeql-analysis.yml
vendored
@ -1,23 +1,18 @@
|
||||
# See https://codeql.github.com and https://github.com/github/codeql-action
|
||||
# This action runs GitHub's industry-leading semantic code analysis engine, CodeQL, against a
|
||||
# repository's source code to find security vulnerabilities. It then automatically uploads the
|
||||
# results to GitHub so they can be displayed in the repository's security tab.
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", release* ]
|
||||
branches: [ main, release*, dynamic_clients ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main" ]
|
||||
branches: [ main, release*, dynamic_clients ]
|
||||
schedule:
|
||||
- cron: '24 3 * * 3'
|
||||
- cron: '39 13 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@ -30,35 +25,33 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
55
.github/workflows/scorecards.yml
vendored
Normal file
55
.github/workflows/scorecards.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '29 11 * * 3'
|
||||
push:
|
||||
branches: [ main, release* ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@c1aec4ac820532bab364f02a81873c555a0ba3a1 # v1.0.4
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# Read-only PAT token. To create it,
|
||||
# follow the steps in https://github.com/ossf/scorecard-action#pat-token-creation.
|
||||
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||
# Publish the results to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`,
|
||||
# regardless of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional).
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -19,6 +19,3 @@
|
||||
|
||||
# MacOS Desktop Services Store
|
||||
.DS_Store
|
||||
|
||||
# Hugo temp file
|
||||
.hugo_build.lock
|
||||
|
@ -114,6 +114,7 @@ go build -o pinniped ./cmd/pinniped
|
||||
|
||||
1. Install dependencies:
|
||||
|
||||
- [`chromedriver`](https://chromedriver.chromium.org/) (and [Chrome](https://www.google.com/chrome/))
|
||||
- [`docker`](https://www.docker.com/)
|
||||
- `htpasswd` (installed by default on MacOS, usually found in `apache2-utils` package for linux)
|
||||
- [`kapp`](https://carvel.dev/#getting-started)
|
||||
@ -121,13 +122,11 @@ go build -o pinniped ./cmd/pinniped
|
||||
- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||
- [`ytt`](https://carvel.dev/#getting-started)
|
||||
- [`nmap`](https://nmap.org/download.html)
|
||||
- [`openssl`](https://www.openssl.org) (installed by default on MacOS)
|
||||
- [Chrome](https://www.google.com/chrome/)
|
||||
|
||||
On macOS, these tools can be installed with [Homebrew](https://brew.sh/) (assuming you have Chrome installed already):
|
||||
|
||||
```bash
|
||||
brew install kind vmware-tanzu/carvel/ytt vmware-tanzu/carvel/kapp kubectl nmap && brew cask install docker
|
||||
brew install kind vmware-tanzu/carvel/ytt vmware-tanzu/carvel/kapp kubectl chromedriver nmap && brew cask install docker
|
||||
```
|
||||
|
||||
1. Create a kind cluster, compile, create container images, and install Pinniped and supporting test dependencies using:
|
||||
|
28
Dockerfile
28
Dockerfile
@ -1,31 +1,22 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
# Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
# 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 --platform=linux/amd64 golang:1.21.3 as build-env
|
||||
FROM golang:1.19.5 as build-env
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
COPY . .
|
||||
ARG GOPROXY
|
||||
|
||||
ARG 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".
|
||||
# Useful for building multi-arch container images.
|
||||
ARG TARGETOS
|
||||
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/
|
||||
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
||||
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
||||
# can be re-used between image builds.
|
||||
RUN \
|
||||
--mount=target=. \
|
||||
--mount=type=cache,target=/cache/gocache \
|
||||
--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-server ./cmd/pinniped-server/... && \
|
||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
||||
@ -33,9 +24,6 @@ RUN \
|
||||
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.
|
||||
# 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
|
||||
|
||||
# Copy the server binary from the build-env stage.
|
||||
|
@ -16,3 +16,9 @@
|
||||
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) |
|
||||
| Mo Khan | [enj](https://github.com/enj) |
|
||||
| Pablo Schuhmacher | [pabloschuhmacher](https://github.com/pabloschuhmacher) |
|
||||
|
||||
## Pinniped Community Management
|
||||
|
||||
| Community Manager | GitHub ID |
|
||||
|-------------------|---------------------------------------|
|
||||
| Nigel Brown | [pnbrown](https://github.com/pnbrown) |
|
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
||||
|
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
|
||||
|
||||
package v1alpha1
|
||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
||||
|
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -80,28 +80,6 @@ const (
|
||||
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
|
||||
)
|
||||
|
||||
// ImpersonationProxyTLSSpec contains information about how the Concierge impersonation proxy should
|
||||
// serve TLS.
|
||||
//
|
||||
// If CertificateAuthorityData is not provided, the Concierge impersonation proxy will check the secret
|
||||
// for a field called "ca.crt", which will be used as the CertificateAuthorityData.
|
||||
//
|
||||
// If neither CertificateAuthorityData nor ca.crt is provided, no CA bundle will be advertised for
|
||||
// the impersonation proxy endpoint.
|
||||
type ImpersonationProxyTLSSpec struct {
|
||||
// X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
// Used to advertise the CA bundle for the impersonation proxy endpoint.
|
||||
//
|
||||
// +optional
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData,omitempty"`
|
||||
|
||||
// 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.
|
||||
//
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
|
||||
type ImpersonationProxySpec struct {
|
||||
// Mode configures whether the impersonation proxy should be started:
|
||||
@ -122,13 +100,6 @@ type ImpersonationProxySpec struct {
|
||||
//
|
||||
// +optional
|
||||
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
|
||||
|
||||
// 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.
|
||||
//
|
||||
// +optional
|
||||
TLS *ImpersonationProxyTLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
|
||||
|
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -8,17 +8,14 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type FederationDomainPhase string
|
||||
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||
type FederationDomainStatusCondition string
|
||||
|
||||
const (
|
||||
// FederationDomainPhasePending is the default phase for newly-created FederationDomain resources.
|
||||
FederationDomainPhasePending FederationDomainPhase = "Pending"
|
||||
|
||||
// FederationDomainPhaseReady is the phase for an FederationDomain resource in a healthy state.
|
||||
FederationDomainPhaseReady FederationDomainPhase = "Ready"
|
||||
|
||||
// FederationDomainPhaseError is the phase for an FederationDomain in an unhealthy state.
|
||||
FederationDomainPhaseError FederationDomainPhase = "Error"
|
||||
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||
)
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// 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.
|
||||
type FederationDomainSpec struct {
|
||||
// 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
|
||||
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
|
||||
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.
|
||||
@ -266,17 +86,20 @@ type FederationDomainSecrets struct {
|
||||
|
||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||
type FederationDomainStatus struct {
|
||||
// Phase summarizes the overall status of the FederationDomain.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase FederationDomainPhase `json:"phase,omitempty"`
|
||||
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||
// represent success or failure.
|
||||
// +optional
|
||||
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||
|
||||
// Conditions represent the observations of an FederationDomain's current state.
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
// Message provides human-readable details about the Status.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// 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).
|
||||
// +optional
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
|
||||
// Secrets contains information about this OIDC Provider's secrets.
|
||||
// +optional
|
||||
@ -288,7 +111,7 @@ type FederationDomainStatus struct {
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped
|
||||
// +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:subresource:status
|
||||
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
|
||||
|
||||
package v1alpha1
|
||||
@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
type OIDCClientPhase string
|
||||
|
||||
const (
|
||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
||||
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||
PhasePending OIDCClientPhase = "Pending"
|
||||
|
||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
||||
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
PhaseReady OIDCClientPhase = "Ready"
|
||||
|
||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
||||
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
PhaseError OIDCClientPhase = "Error"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||
@ -85,7 +85,7 @@ type OIDCClientStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
||||
// +optional
|
||||
|
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -32,7 +32,7 @@ type ActiveDirectoryIdentityProviderStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
type ActiveDirectoryIdentityProviderBind struct {
|
||||
@ -114,10 +114,9 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
||||
|
||||
// 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.
|
||||
// dn (distinguished name) of the user entry found as a result of the user search. 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:={})".
|
||||
@ -128,17 +127,6 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
||||
// +optional
|
||||
Filter string `json:"filter,omitempty"`
|
||||
|
||||
// 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.
|
||||
// +optional
|
||||
UserAttributeForFilter string `json:"userAttributeForFilter,omitempty"`
|
||||
|
||||
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
|
||||
// the result of the group search.
|
||||
// +optional
|
||||
|
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -32,7 +32,7 @@ type LDAPIdentityProviderStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
type LDAPIdentityProviderBind struct {
|
||||
@ -101,31 +101,20 @@ type LDAPIdentityProviderGroupSearch struct {
|
||||
// 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.
|
||||
// the values of Filter and Attributes are ignored.
|
||||
// +optional
|
||||
Base string `json:"base,omitempty"`
|
||||
|
||||
// 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.
|
||||
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
|
||||
// "&(objectClass=groupOfNames)(member={})". 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={}".
|
||||
// +optional
|
||||
Filter string `json:"filter,omitempty"`
|
||||
|
||||
// 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.
|
||||
// +optional
|
||||
UserAttributeForFilter string `json:"userAttributeForFilter,omitempty"`
|
||||
|
||||
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
|
||||
// the result of the group search.
|
||||
// +optional
|
||||
|
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
|
||||
// +listType=map
|
||||
// +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
|
||||
|
@ -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
|
||||
|
||||
package cmd
|
||||
@ -15,6 +15,7 @@ import (
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
||||
func TestConciergeModeFlag(t *testing.T) {
|
||||
@ -51,7 +52,7 @@ func TestConciergeModeFlag(t *testing.T) {
|
||||
func TestCABundleFlag(t *testing.T) {
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := t.TempDir()
|
||||
tmpdir := testutil.TempDir(t)
|
||||
emptyFilePath := filepath.Join(tmpdir, "empty")
|
||||
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
||||
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
@ -96,12 +95,6 @@ type getKubeconfigParams struct {
|
||||
credentialCachePath string
|
||||
credentialCachePathSet bool
|
||||
installHint string
|
||||
pinnipedCliPath string
|
||||
}
|
||||
|
||||
type discoveryResponseScopesSupported struct {
|
||||
// Same as ScopesSupported in the Supervisor's discovery handler's struct.
|
||||
ScopesSupported []string `json:"scopes_supported"`
|
||||
}
|
||||
|
||||
func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||
@ -152,16 +145,14 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||
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.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.")
|
||||
mustMarkHidden(cmd, "oidc-debug-session-cache")
|
||||
|
||||
mustMarkHidden(cmd,
|
||||
"oidc-debug-session-cache",
|
||||
"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",
|
||||
)
|
||||
// --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
||||
mustMarkHidden(cmd, "oidc-skip-listen")
|
||||
|
||||
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
||||
mustMarkHidden(cmd, "concierge-namespace")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
if flags.outputPath != "" {
|
||||
@ -241,9 +232,11 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
cluster.CertificateAuthorityData = flags.concierge.caBundle
|
||||
}
|
||||
|
||||
if len(flags.oidc.issuer) > 0 {
|
||||
err = pinnipedSupervisorDiscovery(ctx, &flags, deps.log)
|
||||
if err != nil {
|
||||
// If there is an issuer, and if any upstream IDP flags are not already set, then try to discover Supervisor upstream IDP details.
|
||||
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input. Maybe they know something
|
||||
// that we can't know, like the name of an IDP that they are going to define in the future.
|
||||
if len(flags.oidc.issuer) > 0 && (flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "") {
|
||||
if err := discoverSupervisorUpstreamIDP(ctx, &flags, deps.log); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -271,12 +264,7 @@ func newExecConfig(deps kubeconfigDeps, flags getKubeconfigParams) (*clientcmdap
|
||||
|
||||
execConfig.InstallHint = flags.installHint
|
||||
var err error
|
||||
execConfig.Command, err = func() (string, error) {
|
||||
if flags.pinnipedCliPath != "" {
|
||||
return flags.pinnipedCliPath, nil
|
||||
}
|
||||
return deps.getPathToSelf()
|
||||
}()
|
||||
execConfig.Command, err = deps.getPathToSelf()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
||||
}
|
||||
@ -745,75 +733,21 @@ func hasPendingStrategy(credentialIssuer *configv1alpha1.CredentialIssuer) bool
|
||||
return false
|
||||
}
|
||||
|
||||
func pinnipedSupervisorDiscovery(ctx context.Context, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
// Make a client suitable for calling the provider, which may or may not be a Pinniped Supervisor.
|
||||
oidcProviderHTTPClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||
func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Call the provider's discovery endpoint, but don't parse the results yet.
|
||||
discoveredProvider, err := discoverOIDCProvider(ctx, flags.oidc.issuer, oidcProviderHTTPClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse the discovery response to find the Supervisor IDP discovery endpoint.
|
||||
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(discoveredProvider)
|
||||
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(ctx, flags.oidc.issuer, httpClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pinnipedIDPsEndpoint == "" {
|
||||
// The issuer is not advertising itself as a Pinniped Supervisor which supports upstream IDP discovery.
|
||||
// Since this field is not present, then assume that the provider is not a Pinniped Supervisor. This field
|
||||
// was added to the discovery response in v0.9.0, which is so long ago that we can assume there are no such
|
||||
// old Supervisors in the wild which need to work with this CLI command anymore. Since the issuer is not a
|
||||
// Supervisor, then there is no need to do the rest of the Supervisor-specific business logic below related
|
||||
// to username/groups scopes or IDP types/names/flows.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now that we know that the provider is a Supervisor, perform an additional check based on its response.
|
||||
// The username and groups scopes were added to the Supervisor in v0.20.0, and were also added to the
|
||||
// "scopes_supported" field in the discovery response in that same version. If this CLI command is talking
|
||||
// to an older Supervisor, then remove the username and groups scopes from the list of requested scopes
|
||||
// since they will certainly cause an error from the old Supervisor during authentication.
|
||||
supervisorSupportsBothUsernameAndGroupsScopes, err := discoverScopesSupportedIncludesBothUsernameAndGroups(discoveredProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !supervisorSupportsBothUsernameAndGroupsScopes {
|
||||
flags.oidc.scopes = slices.Filter(nil, flags.oidc.scopes, func(scope string) bool {
|
||||
if scope == oidcapi.ScopeUsername || scope == oidcapi.ScopeGroups {
|
||||
log.Info("removed scope from --oidc-scopes list because it is not supported by this Supervisor", "scope", scope)
|
||||
return false // Remove username and groups scopes if there were present in the flags.
|
||||
}
|
||||
return true // Keep any other scopes in the flag list.
|
||||
})
|
||||
}
|
||||
|
||||
// If any upstream IDP flags are not already set, then try to discover Supervisor upstream IDP details.
|
||||
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input.
|
||||
// Maybe they know something that we can't know, like the name of an IDP that they are going to define in the
|
||||
// future.
|
||||
if flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "" {
|
||||
if err := discoverSupervisorUpstreamIDP(ctx, pinnipedIDPsEndpoint, oidcProviderHTTPClient, flags, log); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func discoverOIDCProvider(ctx context.Context, issuer string, httpClient *http.Client) (*coreosoidc.Provider, error) {
|
||||
discoveredProvider, err := coreosoidc.NewProvider(coreosoidc.ClientContext(ctx, httpClient), issuer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
return discoveredProvider, nil
|
||||
}
|
||||
|
||||
func discoverSupervisorUpstreamIDP(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
discoveredUpstreamIDPs, err := discoverAllAvailableSupervisorUpstreamIDPs(ctx, pinnipedIDPsEndpoint, httpClient)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -853,22 +787,19 @@ func newDiscoveryHTTPClient(caBundleFlag caBundleFlag) (*http.Client, error) {
|
||||
return phttp.Default(rootCAs), nil
|
||||
}
|
||||
|
||||
func discoverIDPsDiscoveryEndpointURL(discoveredProvider *coreosoidc.Provider) (string, error) {
|
||||
var body idpdiscoveryv1alpha1.OIDCDiscoveryResponse
|
||||
err := discoveredProvider.Claims(&body)
|
||||
func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpClient *http.Client) (string, error) {
|
||||
discoveredProvider, err := coreosoidc.NewProvider(coreosoidc.ClientContext(ctx, httpClient), issuer)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
return body.SupervisorDiscovery.PinnipedIDPsEndpoint, nil
|
||||
}
|
||||
|
||||
func discoverScopesSupportedIncludesBothUsernameAndGroups(discoveredProvider *coreosoidc.Provider) (bool, error) {
|
||||
var body discoveryResponseScopesSupported
|
||||
err := discoveredProvider.Claims(&body)
|
||||
var body idpdiscoveryv1alpha1.OIDCDiscoveryResponse
|
||||
err = discoveredProvider.Claims(&body)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
return slices.Contains(body.ScopesSupported, oidcapi.ScopeUsername) && slices.Contains(body.ScopesSupported, oidcapi.ScopeGroups), nil
|
||||
|
||||
return body.SupervisorDiscovery.PinnipedIDPsEndpoint, nil
|
||||
}
|
||||
|
||||
func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]idpdiscoveryv1alpha1.PinnipedIDP, error) {
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
func TestGetKubeconfig(t *testing.T) {
|
||||
testOIDCCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := t.TempDir()
|
||||
tmpdir := testutil.TempDir(t)
|
||||
testOIDCCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||
require.NoError(t, os.WriteFile(testOIDCCABundlePath, testOIDCCA.Bundle(), 0600))
|
||||
|
||||
@ -81,7 +81,6 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
"discovery.supervisor.pinniped.dev/v1alpha1": {
|
||||
"pinniped_identity_providers_endpoint": "%s/v1alpha1/pinniped_identity_providers"
|
||||
},
|
||||
"scopes_supported": ["openid", "offline_access", "pinniped:request-audience", "username", "groups"],
|
||||
"another-key": "another-value"
|
||||
}`, issuerURL, issuerURL)
|
||||
}
|
||||
@ -147,7 +146,6 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
--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)
|
||||
-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)
|
||||
--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
|
||||
@ -1088,8 +1086,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
"issuer": "%s",
|
||||
"discovery.supervisor.pinniped.dev/v1alpha1": {
|
||||
"pinniped_identity_providers_endpoint": "https%%://illegal_url"
|
||||
},
|
||||
"scopes_supported": ["openid", "offline_access", "pinniped:request-audience", "username", "groups"]
|
||||
}
|
||||
}`, issuerURL)
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
@ -1372,7 +1369,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -1409,41 +1406,41 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Doc(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --token=test-token
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --token=test-token
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -1473,42 +1470,42 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Doc(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --credential-cache=
|
||||
- --token-env=TEST_TOKEN
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --credential-cache=
|
||||
- --token-env=TEST_TOKEN
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -1576,7 +1573,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -1584,6 +1581,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
name: "autodetect nothing, set a bunch of options",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
f := testutil.WriteStringToTempFile(t, "testca-*.pem", issuerCABundle)
|
||||
@ -1607,7 +1605,6 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
"--skip-validation",
|
||||
"--generated-name-suffix", "-sso",
|
||||
"--credential-cache", "/path/to/cache/dir/credentials.yaml",
|
||||
"--pinniped-cli-path", "/some/path/to/command-exe",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
@ -1659,10 +1656,10 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
- --session-cache=/path/to/cache/dir/sessions.yaml
|
||||
- --debug-session-cache
|
||||
- --request-audience=test-audience
|
||||
command: /some/path/to/command-exe
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||
@ -1775,7 +1772,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||
@ -1884,7 +1881,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -1963,7 +1960,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2042,7 +2039,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2117,7 +2114,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2190,7 +2187,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2270,272 +2267,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IDP discovery endpoint is listed in OIDC discovery document but scopes_supported does not include username or groups, so do not request username or groups in kubeconfig's --scopes",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--skip-validation",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticator(issuerCABundle, issuerURL),
|
||||
}
|
||||
},
|
||||
oidcDiscoveryResponse: func(issuerURL string) string {
|
||||
return here.Docf(`{
|
||||
"issuer": "%s",
|
||||
"discovery.supervisor.pinniped.dev/v1alpha1": {
|
||||
"pinniped_identity_providers_endpoint": "%s/v1alpha1/pinniped_identity_providers"
|
||||
},
|
||||
"scopes_supported": ["openid", "offline_access", "pinniped:request-audience"]
|
||||
}`, issuerURL, issuerURL)
|
||||
},
|
||||
idpsDiscoveryResponse: here.Docf(`{
|
||||
"pinniped_identity_providers": [
|
||||
{"name": "some-oidc-idp", "type": "oidc"}
|
||||
]
|
||||
}`),
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||
fmt.Sprintf(`"level"=0 "msg"="discovered OIDC issuer" "issuer"="%s"`, issuerURL),
|
||||
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||
`"level"=0 "msg"="removed scope from --oidc-scopes list because it is not supported by this Supervisor" "scope"="username"`,
|
||||
`"level"=0 "msg"="removed scope from --oidc-scopes list because it is not supported by this Supervisor" "scope"="groups"`,
|
||||
}
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=offline_access,openid,pinniped:request-audience
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
- --upstream-identity-provider-name=some-oidc-idp
|
||||
- --upstream-identity-provider-type=oidc
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IDP discovery endpoint is listed in OIDC discovery document but scopes_supported is not listed (which shouldn't really happen), so do not request username or groups in kubeconfig's --scopes",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--skip-validation",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticator(issuerCABundle, issuerURL),
|
||||
}
|
||||
},
|
||||
oidcDiscoveryResponse: func(issuerURL string) string {
|
||||
return here.Docf(`{
|
||||
"issuer": "%s",
|
||||
"discovery.supervisor.pinniped.dev/v1alpha1": {
|
||||
"pinniped_identity_providers_endpoint": "%s/v1alpha1/pinniped_identity_providers"
|
||||
}
|
||||
}`, issuerURL, issuerURL)
|
||||
},
|
||||
idpsDiscoveryResponse: here.Docf(`{
|
||||
"pinniped_identity_providers": [
|
||||
{"name": "some-oidc-idp", "type": "oidc"}
|
||||
]
|
||||
}`),
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||
fmt.Sprintf(`"level"=0 "msg"="discovered OIDC issuer" "issuer"="%s"`, issuerURL),
|
||||
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||
`"level"=0 "msg"="removed scope from --oidc-scopes list because it is not supported by this Supervisor" "scope"="username"`,
|
||||
`"level"=0 "msg"="removed scope from --oidc-scopes list because it is not supported by this Supervisor" "scope"="groups"`,
|
||||
}
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=offline_access,openid,pinniped:request-audience
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
- --upstream-identity-provider-name=some-oidc-idp
|
||||
- --upstream-identity-provider-type=oidc
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IDP discovery endpoint is listed in OIDC discovery document but scopes_supported does not include username or groups, and scopes username and groups were also not requested by flags",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--skip-validation",
|
||||
"--oidc-scopes", "foo,bar,baz",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticator(issuerCABundle, issuerURL),
|
||||
}
|
||||
},
|
||||
oidcDiscoveryResponse: func(issuerURL string) string {
|
||||
return here.Docf(`{
|
||||
"issuer": "%s",
|
||||
"discovery.supervisor.pinniped.dev/v1alpha1": {
|
||||
"pinniped_identity_providers_endpoint": "%s/v1alpha1/pinniped_identity_providers"
|
||||
},
|
||||
"scopes_supported": ["openid", "offline_access", "pinniped:request-audience"]
|
||||
}`, issuerURL, issuerURL)
|
||||
},
|
||||
idpsDiscoveryResponse: here.Docf(`{
|
||||
"pinniped_identity_providers": [
|
||||
{"name": "some-oidc-idp", "type": "oidc"}
|
||||
]
|
||||
}`),
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||
fmt.Sprintf(`"level"=0 "msg"="discovered OIDC issuer" "issuer"="%s"`, issuerURL),
|
||||
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||
}
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=foo,bar,baz
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
- --upstream-identity-provider-name=some-oidc-idp
|
||||
- --upstream-identity-provider-type=oidc
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2559,8 +2291,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
jwtAuthenticator(issuerCABundle, issuerURL),
|
||||
}
|
||||
},
|
||||
oidcDiscoveryResponse: happyOIDCDiscoveryResponse, // still called to check for support of username and groups scopes
|
||||
idpsDiscoveryStatusCode: http.StatusNotFound, // should not get called by the client in this case
|
||||
oidcDiscoveryStatusCode: http.StatusNotFound, // should not get called by the client in this case
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||
@ -2614,7 +2345,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2697,7 +2428,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2755,7 +2486,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2816,7 +2547,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2877,7 +2608,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -2939,7 +2670,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -3002,7 +2733,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -3063,7 +2794,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -3123,7 +2854,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
@ -3157,40 +2888,40 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Doc(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --token=test-token
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: Test installHint message
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- static
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=webhook
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --token=test-token
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: Test installHint message
|
||||
provideClusterInfo: true
|
||||
`)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
||||
// Initialize the login handler.
|
||||
opts := []oidcclient.Option{
|
||||
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.WithSessionCache(sessionCache),
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/conciergeclient"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
@ -33,7 +34,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := t.TempDir()
|
||||
tmpdir := testutil.TempDir(t)
|
||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||
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-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
|
||||
"--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-type", "ldap",
|
||||
},
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/conciergeclient"
|
||||
)
|
||||
|
||||
@ -29,7 +30,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := t.TempDir()
|
||||
tmpdir := testutil.TempDir(t)
|
||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||
|
||||
|
@ -1,16 +1,13 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"go.pinniped.dev/internal/pversion"
|
||||
"k8s.io/component-base/version"
|
||||
)
|
||||
|
||||
//nolint:gochecknoinits
|
||||
@ -18,44 +15,14 @@ func init() {
|
||||
rootCmd.AddCommand(newVersionCommand())
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var (
|
||||
output = new(string)
|
||||
// getBuildInfo can be overwritten by tests.
|
||||
getBuildInfo = pversion.Get
|
||||
)
|
||||
|
||||
func newVersionCommand() *cobra.Command {
|
||||
c := &cobra.Command{
|
||||
RunE: runner,
|
||||
return &cobra.Command{
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%#v\n", version.Get())
|
||||
return nil
|
||||
},
|
||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||
Use: "version",
|
||||
Short: "Print the version of this Pinniped CLI",
|
||||
}
|
||||
c.Flags().StringVarP(output, "output", "o", "", "one of 'yaml' or 'json'")
|
||||
return c
|
||||
}
|
||||
|
||||
func runner(cmd *cobra.Command, _ []string) error {
|
||||
buildVersion := getBuildInfo()
|
||||
|
||||
switch {
|
||||
case output == nil || *output == "":
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", buildVersion.GitVersion)
|
||||
case *output == "json":
|
||||
bytes, err := json.MarshalIndent(buildVersion, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", bytes)
|
||||
case *output == "yaml":
|
||||
bytes, err := yaml.Marshal(buildVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprint(cmd.OutOrStdout(), string(bytes))
|
||||
default:
|
||||
return fmt.Errorf("'%s' is not a valid option for output", *output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@ -9,10 +9,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/pversion"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -21,8 +19,8 @@ var (
|
||||
version \[flags\]
|
||||
|
||||
Flags:
|
||||
-h, --help help for version
|
||||
-o, --output string one of 'yaml' or 'json'
|
||||
-h, --help help for version
|
||||
|
||||
`)
|
||||
|
||||
knownGoodHelpRegexpForVersion = here.Doc(`
|
||||
@ -32,55 +30,24 @@ var (
|
||||
version \[flags\]
|
||||
|
||||
Flags:
|
||||
-h, --help help for version
|
||||
-o, --output string one of 'yaml' or 'json'
|
||||
-h, --help help for version
|
||||
`)
|
||||
|
||||
jsonRegexp = here.Doc(`{
|
||||
"major": "\d*",
|
||||
"minor": "\d*",
|
||||
"gitVersion": "i am a version for json output",
|
||||
"gitCommit": ".*",
|
||||
"gitTreeState": ".*",
|
||||
"buildDate": ".*",
|
||||
"goVersion": ".*",
|
||||
"compiler": ".*",
|
||||
"platform": ".*/.*"
|
||||
}`)
|
||||
|
||||
yamlRegexp = here.Doc(`buildDate: ".*"
|
||||
compiler: .*
|
||||
gitCommit: .*
|
||||
gitTreeState: .*
|
||||
gitVersion: i am a version for yaml output
|
||||
goVersion: .*
|
||||
major: "\d*"
|
||||
minor: "\d*"
|
||||
platform: .*/.*
|
||||
`)
|
||||
emptyVersionRegexp = `version.Info{Major:"", Minor:"", GitVersion:".*", GitCommit:".*", GitTreeState:"", BuildDate:".*", GoVersion:".*", Compiler:".*", Platform:".*/.*"}`
|
||||
)
|
||||
|
||||
func TestNewVersionCmd(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
getBuildInfo = pversion.Get
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
vars string
|
||||
getBuildInfo func() apimachineryversion.Info
|
||||
wantError bool
|
||||
wantStdoutRegexp string
|
||||
wantStderrRegexp string
|
||||
}{
|
||||
{
|
||||
name: "no flags",
|
||||
args: []string{},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{GitVersion: "v55.66.44"}
|
||||
},
|
||||
wantStdoutRegexp: "v55.66.44\n",
|
||||
name: "no flags",
|
||||
args: []string{},
|
||||
wantStdoutRegexp: emptyVersionRegexp + "\n",
|
||||
},
|
||||
{
|
||||
name: "help flag passed",
|
||||
@ -94,44 +61,10 @@ func TestNewVersionCmd(t *testing.T) {
|
||||
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||
},
|
||||
{
|
||||
name: "json output",
|
||||
args: []string{"--output", "json"},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{
|
||||
GitVersion: "i am a version for json output",
|
||||
Platform: "a/b",
|
||||
}
|
||||
},
|
||||
wantStdoutRegexp: jsonRegexp,
|
||||
},
|
||||
{
|
||||
name: "yaml output",
|
||||
args: []string{"--output", "yaml"},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{
|
||||
GitVersion: "i am a version for yaml output",
|
||||
Platform: "c/d",
|
||||
}
|
||||
},
|
||||
wantStdoutRegexp: yamlRegexp,
|
||||
},
|
||||
{
|
||||
name: "incorrect output",
|
||||
args: []string{"--output", "foo"},
|
||||
wantError: true,
|
||||
wantStderrRegexp: `Error: 'foo' is not a valid option for output`,
|
||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.getBuildInfo != nil {
|
||||
getBuildInfo = tt.getBuildInfo
|
||||
}
|
||||
|
||||
cmd := newVersionCommand()
|
||||
require.NotNil(t, cmd)
|
||||
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
@ -96,15 +97,9 @@ spec:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -173,3 +168,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
@ -69,15 +70,9 @@ spec:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -146,3 +141,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@ -102,24 +103,6 @@ spec:
|
||||
- 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
|
||||
@ -255,3 +238,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
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
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@ -134,6 +134,8 @@ spec:
|
||||
#! 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
|
||||
@ -245,14 +247,9 @@ spec:
|
||||
effect: NoSchedule
|
||||
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||
effect: NoSchedule
|
||||
- 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.
|
||||
#! "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:
|
||||
|
@ -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
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@ -76,15 +76,6 @@ spec:
|
||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||
seccompProfile:
|
||||
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
|
||||
kind: Service
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@ -20,7 +21,7 @@ spec:
|
||||
- jsonPath: .spec.issuer
|
||||
name: Issuer
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
- jsonPath: .status.status
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
@ -46,264 +47,6 @@ spec:
|
||||
spec:
|
||||
description: Spec of the OIDC provider.
|
||||
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:
|
||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||
Metadata document, as well as the identifier that it will use for
|
||||
@ -316,8 +59,8 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
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
|
||||
@ -348,86 +91,14 @@ spec:
|
||||
status:
|
||||
description: Status of the OIDC provider.
|
||||
properties:
|
||||
conditions:
|
||||
description: Conditions represent the observations of an FederationDomain's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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:
|
||||
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
|
||||
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
|
||||
@ -444,7 +115,6 @@ spec:
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
stateEncryptionKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for encrypting state parameters
|
||||
@ -455,7 +125,6 @@ spec:
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
stateSigningKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for signing state parameters
|
||||
@ -466,7 +135,6 @@ spec:
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
tokenSigningKey:
|
||||
description: TokenSigningKey holds the name of the corev1.Secret
|
||||
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?'
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
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
|
||||
@ -486,3 +162,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@ -128,15 +129,9 @@ spec:
|
||||
description: conditions represent the observations of an OIDCClient's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -218,3 +213,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
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
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@ -190,15 +190,6 @@ spec:
|
||||
- name: socket
|
||||
emptyDir: {}
|
||||
#@ 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
|
||||
#! our deployment "more" "HA".
|
||||
affinity:
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@ -106,11 +107,10 @@ spec:
|
||||
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.
|
||||
be dynamically replaced by the dn (distinguished name) of the
|
||||
user entry found as a result of the user search. 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:={})".
|
||||
@ -142,20 +142,6 @@ spec:
|
||||
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
|
||||
@ -231,15 +217,9 @@ spec:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -316,3 +296,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@ -95,16 +96,15 @@ spec:
|
||||
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.
|
||||
Also, when not specified, the values of Filter and Attributes
|
||||
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.
|
||||
replaced by the dn (distinguished name) of the user entry found
|
||||
as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||
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,
|
||||
@ -134,20 +134,6 @@ spec:
|
||||
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,
|
||||
@ -228,15 +214,9 @@ spec:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -313,3 +293,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
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
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@ -258,15 +259,9 @@ spec:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\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 }"
|
||||
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
|
||||
@ -343,3 +338,9 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
1037
generated/1.28/README.adoc → generated/1.17/README.adoc
generated
1037
generated/1.28/README.adoc → generated/1.17/README.adoc
generated
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
package v1alpha1
|
||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
75
generated/1.17/apis/concierge/authentication/v1alpha1/types_meta.go
generated
Normal file
75
generated/1.17/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
|
||||
|
||||
package v1alpha1
|
||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
@ -9,10 +9,26 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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.
|
||||
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
||||
*out = *in
|
||||
@ -101,7 +117,7 @@ func (in *JWTAuthenticatorStatus) DeepCopyInto(out *JWTAuthenticatorStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
*out = make([]Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
@ -238,7 +254,7 @@ func (in *WebhookAuthenticatorStatus) DeepCopyInto(out *WebhookAuthenticatorStat
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
*out = make([]Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*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
|
||||
|
||||
package v1alpha1
|
||||
@ -80,28 +80,6 @@ const (
|
||||
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
|
||||
)
|
||||
|
||||
// ImpersonationProxyTLSSpec contains information about how the Concierge impersonation proxy should
|
||||
// serve TLS.
|
||||
//
|
||||
// If CertificateAuthorityData is not provided, the Concierge impersonation proxy will check the secret
|
||||
// for a field called "ca.crt", which will be used as the CertificateAuthorityData.
|
||||
//
|
||||
// If neither CertificateAuthorityData nor ca.crt is provided, no CA bundle will be advertised for
|
||||
// the impersonation proxy endpoint.
|
||||
type ImpersonationProxyTLSSpec struct {
|
||||
// X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
// Used to advertise the CA bundle for the impersonation proxy endpoint.
|
||||
//
|
||||
// +optional
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData,omitempty"`
|
||||
|
||||
// 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.
|
||||
//
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
|
||||
type ImpersonationProxySpec struct {
|
||||
// Mode configures whether the impersonation proxy should be started:
|
||||
@ -122,13 +100,6 @@ type ImpersonationProxySpec struct {
|
||||
//
|
||||
// +optional
|
||||
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
|
||||
|
||||
// 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.
|
||||
//
|
||||
// +optional
|
||||
TLS *ImpersonationProxyTLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
|
@ -229,11 +229,6 @@ func (in *ImpersonationProxyServiceSpec) DeepCopy() *ImpersonationProxyServiceSp
|
||||
func (in *ImpersonationProxySpec) DeepCopyInto(out *ImpersonationProxySpec) {
|
||||
*out = *in
|
||||
in.Service.DeepCopyInto(&out.Service)
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(ImpersonationProxyTLSSpec)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -247,22 +242,6 @@ func (in *ImpersonationProxySpec) DeepCopy() *ImpersonationProxySpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImpersonationProxyTLSSpec) DeepCopyInto(out *ImpersonationProxyTLSSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxyTLSSpec.
|
||||
func (in *ImpersonationProxyTLSSpec) DeepCopy() *ImpersonationProxyTLSSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImpersonationProxyTLSSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TokenCredentialRequestAPIInfo) DeepCopyInto(out *TokenCredentialRequestAPIInfo) {
|
||||
*out = *in
|
@ -3,7 +3,7 @@
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.28/apis/concierge/identity
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/concierge/identity
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=identity.concierge.pinniped.dev
|
||||
|
@ -11,7 +11,7 @@ package v1alpha1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
identity "go.pinniped.dev/generated/1.28/apis/concierge/identity"
|
||||
identity "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
@ -6,7 +6,7 @@ package validation
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
identityapi "go.pinniped.dev/generated/1.27/apis/concierge/identity"
|
||||
identityapi "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||
)
|
||||
|
||||
func ValidateWhoAmIRequest(whoAmIRequest *identityapi.WhoAmIRequest) field.ErrorList {
|
@ -3,7 +3,7 @@
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.28/apis/concierge/login
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/concierge/login
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=login.concierge.pinniped.dev
|
||||
|
@ -11,7 +11,7 @@ package v1alpha1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
login "go.pinniped.dev/generated/1.27/apis/concierge/login"
|
||||
login "go.pinniped.dev/generated/1.17/apis/concierge/login"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
9
generated/1.17/apis/go.mod
generated
Normal file
9
generated/1.17/apis/go.mod
generated
Normal file
@ -0,0 +1,9 @@
|
||||
// This go.mod file is generated by ./hack/codegen.sh.
|
||||
module go.pinniped.dev/generated/1.17/apis
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
k8s.io/api v0.17.17
|
||||
k8s.io/apimachinery v0.17.17
|
||||
)
|
105
generated/1.17/apis/go.sum
generated
Normal file
105
generated/1.17/apis/go.sum
generated
Normal file
@ -0,0 +1,105 @@
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
k8s.io/api v0.17.17 h1:S+Yv5pdfvy9OG1t148zMFk3/l/VYpF1N4j5Y/q8IMdg=
|
||||
k8s.io/api v0.17.17/go.mod h1:kk4nQM0EVx+BEY7o8CN5YL99CWmWEQ2a4NCak58yB6E=
|
||||
k8s.io/apimachinery v0.17.17 h1:HMpFl9yqNI5G2+2WllKOe2XYLkCyaWzfXvk7SosyVko=
|
||||
k8s.io/apimachinery v0.17.17/go.mod h1:T54ZSpncArE25c5r2PbUPsLeTpkPWY/ivafigSX6+xk=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU=
|
||||
sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
@ -3,7 +3,7 @@
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.27/apis/supervisor/clientsecret
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/supervisor/clientsecret
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=clientsecret.supervisor.pinniped.dev
|
||||
|
@ -11,7 +11,7 @@ package v1alpha1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
clientsecret "go.pinniped.dev/generated/1.28/apis/supervisor/clientsecret"
|
||||
clientsecret "go.pinniped.dev/generated/1.17/apis/supervisor/clientsecret"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
@ -3,7 +3,7 @@
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.28/apis/supervisor/config
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/supervisor/config
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=config.supervisor.pinniped.dev
|
||||
|
135
generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go
generated
Normal file
135
generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go
generated
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||
type FederationDomainStatusCondition string
|
||||
|
||||
const (
|
||||
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||
)
|
||||
|
||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||
type FederationDomainTLSSpec struct {
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses.
|
||||
//
|
||||
// +optional
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||
type FederationDomainSpec struct {
|
||||
// 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.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||
// +optional
|
||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||
type FederationDomainSecrets struct {
|
||||
// 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.
|
||||
// +optional
|
||||
JWKS corev1.LocalObjectReference `json:"jwks,omitempty"`
|
||||
|
||||
// TokenSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// signing tokens is stored.
|
||||
// +optional
|
||||
TokenSigningKey corev1.LocalObjectReference `json:"tokenSigningKey,omitempty"`
|
||||
|
||||
// StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// signing state parameters is stored.
|
||||
// +optional
|
||||
StateSigningKey corev1.LocalObjectReference `json:"stateSigningKey,omitempty"`
|
||||
|
||||
// StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// encrypting state parameters is stored.
|
||||
// +optional
|
||||
StateEncryptionKey corev1.LocalObjectReference `json:"stateEncryptionKey,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||
type FederationDomainStatus struct {
|
||||
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||
// represent success or failure.
|
||||
// +optional
|
||||
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||
|
||||
// Message provides human-readable details about the Status.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// 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).
|
||||
// +optional
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
|
||||
// Secrets contains information about this OIDC Provider's secrets.
|
||||
// +optional
|
||||
Secrets FederationDomainSecrets `json:"secrets,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomain describes the configuration of an OIDC provider.
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped
|
||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type FederationDomain struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec of the OIDC provider.
|
||||
Spec FederationDomainSpec `json:"spec"`
|
||||
|
||||
// Status of the OIDC provider.
|
||||
Status FederationDomainStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// List of FederationDomain objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type FederationDomainList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []FederationDomain `json:"items"`
|
||||
}
|
75
generated/1.17/apis/supervisor/config/v1alpha1/types_meta.go
generated
Normal file
75
generated/1.17/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
|
||||
|
||||
package v1alpha1
|
||||
@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
type OIDCClientPhase string
|
||||
|
||||
const (
|
||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
||||
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||
PhasePending OIDCClientPhase = "Pending"
|
||||
|
||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
||||
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
PhaseReady OIDCClientPhase = "Ready"
|
||||
|
||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
||||
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
PhaseError OIDCClientPhase = "Error"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||
@ -85,7 +85,7 @@ type OIDCClientStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +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.
|
||||
// +optional
|
@ -9,10 +9,26 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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.
|
||||
func (in *FederationDomain) DeepCopyInto(out *FederationDomain) {
|
||||
*out = *in
|
||||
@ -41,24 +57,6 @@ func (in *FederationDomain) DeepCopyObject() runtime.Object {
|
||||
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.
|
||||
func (in *FederationDomainList) DeepCopyInto(out *FederationDomainList) {
|
||||
*out = *in
|
||||
@ -120,13 +118,6 @@ func (in *FederationDomainSpec) DeepCopyInto(out *FederationDomainSpec) {
|
||||
*out = new(FederationDomainTLSSpec)
|
||||
**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
|
||||
}
|
||||
|
||||
@ -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.
|
||||
func (in *FederationDomainStatus) DeepCopyInto(out *FederationDomainStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
if in.LastUpdateTime != nil {
|
||||
in, out := &in.LastUpdateTime, &out.LastUpdateTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
out.Secrets = in.Secrets
|
||||
return
|
||||
@ -180,121 +168,6 @@ func (in *FederationDomainTLSSpec) DeepCopy() *FederationDomainTLSSpec {
|
||||
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.
|
||||
func (in *OIDCClient) DeepCopyInto(out *OIDCClient) {
|
||||
*out = *in
|
||||
@ -392,7 +265,7 @@ func (in *OIDCClientStatus) DeepCopyInto(out *OIDCClientStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
*out = make([]Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user