Compare commits
7 Commits
main
...
jtc/test-c
Author | SHA1 | Date | |
---|---|---|---|
|
c6112ad3a9 | ||
|
bfe8dc11ce | ||
|
d7b5f4d4ea | ||
|
7b01c3ce18 | ||
|
87fe42e18d | ||
|
02ed2d9c95 | ||
|
cd17bdb5f7 |
@ -21,6 +21,3 @@
|
|||||||
|
|
||||||
# MacOS Desktop Services Store
|
# MacOS Desktop Services Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Hugo temp file
|
|
||||||
.hugo_build.lock
|
|
||||||
|
19
.drone.yml
19
.drone.yml
@ -1,19 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: kubernetes
|
|
||||||
name: Container
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build & publish
|
|
||||||
image: spritsail/docker-build
|
|
||||||
context: .
|
|
||||||
settings:
|
|
||||||
repo: bv11-cr01.bessems.eu/library/pinniped-server
|
|
||||||
registry: bv11-cr01.bessems.eu
|
|
||||||
tags: latest
|
|
||||||
build_args:
|
|
||||||
- BUILDPLATFORM=linux/amd64
|
|
||||||
mtu: 1450
|
|
||||||
username:
|
|
||||||
from_secret: harbor_username
|
|
||||||
password:
|
|
||||||
from_secret: harbor_password
|
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -8,12 +8,6 @@ updates:
|
|||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
|
||||||
- package-ecosystem: "gomod"
|
|
||||||
open-pull-requests-limit: 2
|
|
||||||
directory: "/hack/update-go-mod"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
|
|
||||||
- package-ecosystem: "docker"
|
- package-ecosystem: "docker"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
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"
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main", release* ]
|
branches: [ main, release*, dynamic_clients ]
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
# The branches below must be a subset of the branches above
|
||||||
branches: [ "main" ]
|
branches: [ main, release*, dynamic_clients ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '24 3 * * 3'
|
- cron: '39 13 * * 2'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
@ -30,35 +25,33 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v1
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# 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.
|
# 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.
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
# 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
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
# ✏️ 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.
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
# - run: |
|
#- run: |
|
||||||
# echo "Run, Build Application using script"
|
# make bootstrap
|
||||||
# ./location_of_script_within_repo/buildscript.sh
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v1
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
|
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
|
# MacOS Desktop Services Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Hugo temp file
|
|
||||||
.hugo_build.lock
|
|
||||||
|
@ -114,6 +114,7 @@ go build -o pinniped ./cmd/pinniped
|
|||||||
|
|
||||||
1. Install dependencies:
|
1. Install dependencies:
|
||||||
|
|
||||||
|
- [`chromedriver`](https://chromedriver.chromium.org/) (and [Chrome](https://www.google.com/chrome/))
|
||||||
- [`docker`](https://www.docker.com/)
|
- [`docker`](https://www.docker.com/)
|
||||||
- `htpasswd` (installed by default on MacOS, usually found in `apache2-utils` package for linux)
|
- `htpasswd` (installed by default on MacOS, usually found in `apache2-utils` package for linux)
|
||||||
- [`kapp`](https://carvel.dev/#getting-started)
|
- [`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/)
|
- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||||
- [`ytt`](https://carvel.dev/#getting-started)
|
- [`ytt`](https://carvel.dev/#getting-started)
|
||||||
- [`nmap`](https://nmap.org/download.html)
|
- [`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):
|
On macOS, these tools can be installed with [Homebrew](https://brew.sh/) (assuming you have Chrome installed already):
|
||||||
|
|
||||||
```bash
|
```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:
|
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
|
# 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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Prepare to cross-compile by always running the build stage in the build platform, not the target platform.
|
FROM golang:1.19.4 as build-env
|
||||||
FROM --platform=linux/amd64 golang:1.21.3 as build-env
|
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
COPY . .
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
|
|
||||||
ARG KUBE_GIT_VERSION
|
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
||||||
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
||||||
|
# can be re-used between image builds.
|
||||||
# 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/
|
|
||||||
RUN \
|
RUN \
|
||||||
--mount=target=. \
|
|
||||||
--mount=type=cache,target=/cache/gocache \
|
--mount=type=cache,target=/cache/gocache \
|
||||||
--mount=type=cache,target=/cache/gomodcache \
|
--mount=type=cache,target=/cache/gomodcache \
|
||||||
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH && \
|
mkdir out && \
|
||||||
|
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=linux GOARCH=amd64 && \
|
||||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/... && \
|
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/... && \
|
||||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/... && \
|
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/... && \
|
||||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
||||||
@ -33,9 +24,6 @@ RUN \
|
|||||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
||||||
|
|
||||||
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
|
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
|
||||||
# Note that we are not using --platform here, so it will choose the base image for the target platform, not the build platform.
|
|
||||||
# By using "distroless/static" instead of "distroless/static-debianXX" we can float on the latest stable version of debian.
|
|
||||||
# See https://github.com/GoogleContainerTools/distroless#base-operating-system
|
|
||||||
FROM gcr.io/distroless/static:nonroot@sha256:2a9e2b4fa771d31fe3346a873be845bfc2159695b9f90ca08e950497006ccc2e
|
FROM gcr.io/distroless/static:nonroot@sha256:2a9e2b4fa771d31fe3346a873be845bfc2159695b9f90ca08e950497006ccc2e
|
||||||
|
|
||||||
# Copy the server binary from the build-env stage.
|
# Copy the server binary from the build-env stage.
|
||||||
|
@ -16,3 +16,9 @@
|
|||||||
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) |
|
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) |
|
||||||
| Mo Khan | [enj](https://github.com/enj) |
|
| Mo Khan | [enj](https://github.com/enj) |
|
||||||
| Pablo Schuhmacher | [pabloschuhmacher](https://github.com/pabloschuhmacher) |
|
| 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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a JWT authenticator.
|
// Spec for configuring a JWT authenticator.
|
||||||
|
75
apis/concierge/authentication/v1alpha1/types_meta.go.tmpl
Normal file
75
apis/concierge/authentication/v1alpha1/types_meta.go.tmpl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a webhook authenticator.
|
// Spec for configuring a webhook authenticator.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -80,28 +80,6 @@ const (
|
|||||||
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
|
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.
|
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
|
||||||
type ImpersonationProxySpec struct {
|
type ImpersonationProxySpec struct {
|
||||||
// Mode configures whether the impersonation proxy should be started:
|
// Mode configures whether the impersonation proxy should be started:
|
||||||
@ -122,13 +100,6 @@ type ImpersonationProxySpec struct {
|
|||||||
//
|
//
|
||||||
// +optional
|
// +optional
|
||||||
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
|
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.
|
// 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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,17 +8,14 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FederationDomainPhase string
|
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||||
|
type FederationDomainStatusCondition string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FederationDomainPhasePending is the default phase for newly-created FederationDomain resources.
|
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||||
FederationDomainPhasePending FederationDomainPhase = "Pending"
|
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||||
|
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||||
// FederationDomainPhaseReady is the phase for an FederationDomain resource in a healthy state.
|
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||||
FederationDomainPhaseReady FederationDomainPhase = "Ready"
|
|
||||||
|
|
||||||
// FederationDomainPhaseError is the phase for an FederationDomain in an unhealthy state.
|
|
||||||
FederationDomainPhaseError FederationDomainPhase = "Error"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||||
@ -45,157 +42,6 @@ type FederationDomainTLSSpec struct {
|
|||||||
SecretName string `json:"secretName,omitempty"`
|
SecretName string `json:"secretName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainTransformsConstant defines a constant variable and its value which will be made available to
|
|
||||||
// the transform expressions. This is a union type, and Type is the discriminator field.
|
|
||||||
type FederationDomainTransformsConstant struct {
|
|
||||||
// Name determines the name of the constant. It must be a valid identifier name.
|
|
||||||
// +kubebuilder:validation:Pattern=`^[a-zA-Z][_a-zA-Z0-9]*$`
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
// +kubebuilder:validation:MaxLength=64
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Type determines the type of the constant, and indicates which other field should be non-empty.
|
|
||||||
// +kubebuilder:validation:Enum=string;stringList
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// StringValue should hold the value when Type is "string", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringValue string `json:"stringValue,omitempty"`
|
|
||||||
|
|
||||||
// StringListValue should hold the value when Type is "stringList", and is otherwise ignored.
|
|
||||||
// +optional
|
|
||||||
StringListValue []string `json:"stringListValue,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExpression defines a transform expression.
|
|
||||||
type FederationDomainTransformsExpression struct {
|
|
||||||
// Type determines the type of the expression. It must be one of the supported types.
|
|
||||||
// +kubebuilder:validation:Enum=policy/v1;username/v1;groups/v1
|
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// Expression is a CEL expression that will be evaluated based on the Type during an authentication.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Expression string `json:"expression"`
|
|
||||||
|
|
||||||
// Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects
|
|
||||||
// an authentication attempt. When empty, a default message will be used.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExample defines a transform example.
|
|
||||||
type FederationDomainTransformsExample struct {
|
|
||||||
// Username is the input username.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
Username string `json:"username"`
|
|
||||||
|
|
||||||
// Groups is the input list of group names.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Expects is the expected output of the entire sequence of transforms when they are run against the
|
|
||||||
// input Username and Groups.
|
|
||||||
Expects FederationDomainTransformsExampleExpects `json:"expects"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransformsExampleExpects defines the expected result for a transforms example.
|
|
||||||
type FederationDomainTransformsExampleExpects struct {
|
|
||||||
// Username is the expected username after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
|
|
||||||
// Groups is the expected list of group names after the transformations have been applied.
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
|
|
||||||
// Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression
|
|
||||||
// after the transformations have been applied. True means that it is expected that the authentication would be
|
|
||||||
// rejected. The default value of false means that it is expected that the authentication would not be rejected
|
|
||||||
// by any policy expression.
|
|
||||||
// +optional
|
|
||||||
Rejected bool `json:"rejected,omitempty"`
|
|
||||||
|
|
||||||
// Message is the expected error message of the transforms. When Rejected is true, then Message is the expected
|
|
||||||
// message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank,
|
|
||||||
// then Message will be treated as the default error message for authentication attempts which are rejected by a
|
|
||||||
// policy. When Rejected is false, then Message is the expected error message for some other non-policy
|
|
||||||
// transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
|
||||||
// +optional
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainTransforms defines identity transformations for an identity provider's usage on a FederationDomain.
|
|
||||||
type FederationDomainTransforms struct {
|
|
||||||
// Constants defines constant variables and their values which will be made available to the transform expressions.
|
|
||||||
// +patchMergeKey=name
|
|
||||||
// +patchStrategy=merge
|
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=name
|
|
||||||
// +optional
|
|
||||||
Constants []FederationDomainTransformsConstant `json:"constants,omitempty"`
|
|
||||||
|
|
||||||
// Expressions are an optional list of transforms and policies to be executed in the order given during every
|
|
||||||
// authentication attempt, including during every session refresh.
|
|
||||||
// Each is a CEL expression. It may use the basic CEL language as defined in
|
|
||||||
// https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in
|
|
||||||
// https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
//
|
|
||||||
// The username and groups extracted from the identity provider, and the constants defined in this CR, are
|
|
||||||
// available as variables in all expressions. The username is provided via a variable called `username` and
|
|
||||||
// the list of group names is provided via a variable called `groups` (which may be an empty list).
|
|
||||||
// Each user-provided constants is provided via a variable named `strConst.varName` for string constants
|
|
||||||
// and `strListConst.varName` for string list constants.
|
|
||||||
//
|
|
||||||
// The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1.
|
|
||||||
// Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated
|
|
||||||
// and the authentication attempt is rejected.
|
|
||||||
// Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the
|
|
||||||
// username or group names.
|
|
||||||
// Each username/v1 transform must return the new username (a string), which can be the same as the old username.
|
|
||||||
// Transformations of type username/v1 do not return group names, and therefore cannot change the group names.
|
|
||||||
// Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old
|
|
||||||
// groups list.
|
|
||||||
// Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames.
|
|
||||||
// After each expression, the new (potentially changed) username or groups get passed to the following expression.
|
|
||||||
//
|
|
||||||
// Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain.
|
|
||||||
// During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the
|
|
||||||
// authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username
|
|
||||||
// and group names have been decided for that authentication attempt.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
Expressions []FederationDomainTransformsExpression `json:"expressions,omitempty"`
|
|
||||||
|
|
||||||
// Examples can optionally be used to ensure that the sequence of transformation expressions are working as
|
|
||||||
// expected. Examples define sample input identities which are then run through the expression list, and the
|
|
||||||
// results are compared to the expected results. If any example in this list fails, then this
|
|
||||||
// identity provider will not be available for use within this FederationDomain, and the error(s) will be
|
|
||||||
// added to the FederationDomain status. This can be used to help guard against programming mistakes in the
|
|
||||||
// expressions, and also act as living documentation for other administrators to better understand the expressions.
|
|
||||||
// +optional
|
|
||||||
Examples []FederationDomainTransformsExample `json:"examples,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainIdentityProvider describes how an identity provider is made available in this FederationDomain.
|
|
||||||
type FederationDomainIdentityProvider struct {
|
|
||||||
// DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the
|
|
||||||
// kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a
|
|
||||||
// disruptive change for those users.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
|
|
||||||
// ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required.
|
|
||||||
// If the reference cannot be resolved then the identity provider will not be made available.
|
|
||||||
// Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider,
|
|
||||||
// LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
|
||||||
ObjectRef corev1.TypedLocalObjectReference `json:"objectRef"`
|
|
||||||
|
|
||||||
// Transforms is an optional way to specify transformations to be applied during user authentication and
|
|
||||||
// session refresh.
|
|
||||||
// +optional
|
|
||||||
Transforms FederationDomainTransforms `json:"transforms,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||||
type FederationDomainSpec struct {
|
type FederationDomainSpec struct {
|
||||||
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||||
@ -209,35 +55,9 @@ type FederationDomainSpec struct {
|
|||||||
// +kubebuilder:validation:MinLength=1
|
// +kubebuilder:validation:MinLength=1
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
|
|
||||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||||
// +optional
|
// +optional
|
||||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||||
|
|
||||||
// IdentityProviders is the list of identity providers available for use by this FederationDomain.
|
|
||||||
//
|
|
||||||
// An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server,
|
|
||||||
// how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to
|
|
||||||
// extract a normalized user identity. Normalized user identities include a username and a list of group names.
|
|
||||||
// In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which
|
|
||||||
// belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations
|
|
||||||
// on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid
|
|
||||||
// accidental conflicts when multiple identity providers have different users with the same username (e.g.
|
|
||||||
// "idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication
|
|
||||||
// rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow
|
|
||||||
// the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could
|
|
||||||
// disallow the authentication unless the user belongs to a specific group in the identity provider.
|
|
||||||
//
|
|
||||||
// For backwards compatibility with versions of Pinniped which predate support for multiple identity providers,
|
|
||||||
// an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which
|
|
||||||
// exist in the same namespace, but also to reject all authentication requests when there is more than one identity
|
|
||||||
// provider currently defined. In this backwards compatibility mode, the name of the identity provider resource
|
|
||||||
// (e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this
|
|
||||||
// FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of
|
|
||||||
// relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead
|
|
||||||
// explicitly list the identity provider using this IdentityProviders field.
|
|
||||||
//
|
|
||||||
// +optional
|
|
||||||
IdentityProviders []FederationDomainIdentityProvider `json:"identityProviders,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||||
@ -266,17 +86,20 @@ type FederationDomainSecrets struct {
|
|||||||
|
|
||||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||||
type FederationDomainStatus struct {
|
type FederationDomainStatus struct {
|
||||||
// Phase summarizes the overall status of the FederationDomain.
|
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||||
// +kubebuilder:default=Pending
|
// represent success or failure.
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +optional
|
||||||
Phase FederationDomainPhase `json:"phase,omitempty"`
|
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||||
|
|
||||||
// Conditions represent the observations of an FederationDomain's current state.
|
// Message provides human-readable details about the Status.
|
||||||
// +patchMergeKey=type
|
// +optional
|
||||||
// +patchStrategy=merge
|
Message string `json:"message,omitempty"`
|
||||||
// +listType=map
|
|
||||||
// +listMapKey=type
|
// LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
// around some undesirable behavior with respect to the empty metav1.Time value (see
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
|
// +optional
|
||||||
|
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||||
|
|
||||||
// Secrets contains information about this OIDC Provider's secrets.
|
// Secrets contains information about this OIDC Provider's secrets.
|
||||||
// +optional
|
// +optional
|
||||||
@ -288,7 +111,7 @@ type FederationDomainStatus struct {
|
|||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
// +kubebuilder:resource:categories=pinniped
|
// +kubebuilder:resource:categories=pinniped
|
||||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
type FederationDomain struct {
|
type FederationDomain struct {
|
||||||
|
75
apis/supervisor/config/v1alpha1/types_meta.go.tmpl
Normal file
75
apis/supervisor/config/v1alpha1/types_meta.go.tmpl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||||
|
type ConditionStatus string
|
||||||
|
|
||||||
|
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||||
|
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||||
|
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||||
|
// intermediate conditions, e.g. ConditionDegraded.
|
||||||
|
const (
|
||||||
|
ConditionTrue ConditionStatus = "True"
|
||||||
|
ConditionFalse ConditionStatus = "False"
|
||||||
|
ConditionUnknown ConditionStatus = "Unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||||
|
// version we can switch to using the upstream type.
|
||||||
|
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
|
type Condition struct {
|
||||||
|
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
// ---
|
||||||
|
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||||
|
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||||
|
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||||
|
// +kubebuilder:validation:MaxLength=316
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// status of the condition, one of True, False, Unknown.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||||
|
Status ConditionStatus `json:"status"`
|
||||||
|
|
||||||
|
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
// with respect to the current state of the instance.
|
||||||
|
// +optional
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:Type=string
|
||||||
|
// +kubebuilder:validation:Format=date-time
|
||||||
|
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||||
|
|
||||||
|
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
// Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
// and whether the values are considered a guaranteed API.
|
||||||
|
// The value should be a CamelCase string.
|
||||||
|
// This field may not be empty.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=1024
|
||||||
|
// +kubebuilder:validation:MinLength=1
|
||||||
|
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
|
||||||
|
// message is a human readable message indicating details about the transition.
|
||||||
|
// This may be an empty string.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// +kubebuilder:validation:MaxLength=32768
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|||||||
type OIDCClientPhase string
|
type OIDCClientPhase string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
PhasePending OIDCClientPhase = "Pending"
|
||||||
|
|
||||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
PhaseReady OIDCClientPhase = "Ready"
|
||||||
|
|
||||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
PhaseError OIDCClientPhase = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||||
@ -85,7 +85,7 @@ type OIDCClientStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -32,7 +32,7 @@ type ActiveDirectoryIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActiveDirectoryIdentityProviderBind struct {
|
type ActiveDirectoryIdentityProviderBind struct {
|
||||||
@ -114,10 +114,9 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
|||||||
|
|
||||||
// Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
|
// 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
|
// 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
|
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
|
||||||
// value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
// "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see
|
||||||
// E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
// https://ldap.com/ldap-filters.
|
||||||
// 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.
|
// 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
|
// 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:={})".
|
// "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
|
||||||
@ -128,17 +127,6 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Filter string `json:"filter,omitempty"`
|
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
|
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
|
||||||
// the result of the group search.
|
// the result of the group search.
|
||||||
// +optional
|
// +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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -32,7 +32,7 @@ type LDAPIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LDAPIdentityProviderBind struct {
|
type LDAPIdentityProviderBind struct {
|
||||||
@ -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.
|
// 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
|
// "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,
|
// 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
|
// +optional
|
||||||
Base string `json:"base,omitempty"`
|
Base string `json:"base,omitempty"`
|
||||||
|
|
||||||
// Filter is the LDAP search filter which should be applied when searching for groups for a user.
|
// 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
|
// 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
|
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
|
||||||
// value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
// "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see
|
||||||
// For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
// https://ldap.com/ldap-filters.
|
||||||
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
|
// 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. When not specified, the default will act as if the Filter were specified as "member={}".
|
||||||
// +optional
|
// +optional
|
||||||
Filter string `json:"filter,omitempty"`
|
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
|
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
|
||||||
// the result of the group search.
|
// the result of the group search.
|
||||||
// +optional
|
// +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"`
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -32,7 +32,7 @@ type OIDCIdentityProviderStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
||||||
@ -143,12 +143,12 @@ type OIDCClaims struct {
|
|||||||
// "additionalClaims" claim of the ID tokens generated by the Supervisor. This should be specified as a map of
|
// "additionalClaims" claim of the ID tokens generated by the Supervisor. This should be specified as a map of
|
||||||
// new claim names as the keys, and upstream claim names as the values. These new claim names will be nested
|
// new claim names as the keys, and upstream claim names as the values. These new claim names will be nested
|
||||||
// under the top-level "additionalClaims" claim in ID tokens generated by the Supervisor when this
|
// under the top-level "additionalClaims" claim in ID tokens generated by the Supervisor when this
|
||||||
// OIDCIdentityProvider was used for user authentication. These claims will be made available to all clients.
|
// OIDCIdentityProvider was used for user authentication. This feature is not required for using the Supervisor to
|
||||||
// This feature is not required to use the Supervisor to provide authentication for Kubernetes clusters, but can be
|
// provide authentication for Kubernetes clusters, but can be used when using the Supervisor for other
|
||||||
// used when using the Supervisor for other authentication purposes. When this map is empty or the upstream claims
|
// authentication purposes. When this map is empty, the "additionalClaims" claim will be excluded from the ID
|
||||||
// are not available, the "additionalClaims" claim will be excluded from the ID tokens generated by the Supervisor.
|
// tokens generated by the Supervisor.
|
||||||
// +optional
|
// +optional
|
||||||
AdditionalClaimMappings map[string]string `json:"additionalClaimMappings,omitempty"`
|
AdditionalClaimMappings map[string]string `json:"additionalClaimMappings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient contains information about an OIDC client (e.g., client ID and client
|
// OIDCClient contains information about an OIDC client (e.g., client ID and client
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package oidc
|
package oidc
|
||||||
@ -40,10 +40,6 @@ const (
|
|||||||
// group names which were mapped from the upstream identity provider.
|
// group names which were mapped from the upstream identity provider.
|
||||||
IDTokenClaimGroups = "groups"
|
IDTokenClaimGroups = "groups"
|
||||||
|
|
||||||
// IDTokenClaimAdditionalClaims is the top level claim used to hold additional claims in the downstream ID
|
|
||||||
// token, if any claims are present.
|
|
||||||
IDTokenClaimAdditionalClaims = "additionalClaims"
|
|
||||||
|
|
||||||
// GrantTypeAuthorizationCode is the name of the grant type for authorization code flows defined by the OIDC spec.
|
// GrantTypeAuthorizationCode is the name of the grant type for authorization code flows defined by the OIDC spec.
|
||||||
GrantTypeAuthorizationCode = "authorization_code"
|
GrantTypeAuthorizationCode = "authorization_code"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package main is the combined entrypoint for the Pinniped "kube-cert-agent" component.
|
// Package main is the combined entrypoint for the Pinniped "kube-cert-agent" component.
|
||||||
@ -13,23 +13,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
// This side effect import ensures that we use fipsonly crypto during TLS in fips_strict mode.
|
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
||||||
//
|
_ "go.pinniped.dev/internal/crypto/ptls"
|
||||||
// Commenting this out because it causes the runtime memory consumption of this binary to increase
|
|
||||||
// from ~1 MB to ~8 MB (as measured when running the sleep subcommand). This binary does not use TLS,
|
|
||||||
// so it should not be needed. If this binary is ever changed to make use of TLS client and/or server
|
|
||||||
// code, then we should bring this import back to support the use of the ptls library for client and
|
|
||||||
// server code, and we should also increase the memory limits on the kube cert agent deployment (as
|
|
||||||
// decided by the kube cert agent controller in the Concierge).
|
|
||||||
//
|
|
||||||
//nolint:godot // This is not sentence, it is a commented out line of import code.
|
|
||||||
// _ "go.pinniped.dev/internal/crypto/ptls"
|
|
||||||
|
|
||||||
// This side effect imports cgo so that runtime/cgo gets linked, when in fips_strict mode.
|
|
||||||
// Without this line, the binary will exit 133 upon startup in fips_strict mode.
|
|
||||||
// It also enables fipsonly tls mode, just to be absolutely sure that the fips code is enabled,
|
|
||||||
// even though it shouldn't be used currently by this binary.
|
|
||||||
_ "go.pinniped.dev/internal/crypto/fips"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals // these are swapped during unit tests.
|
//nolint:gochecknoglobals // these are swapped during unit tests.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package main is the combined entrypoint for all Pinniped server components.
|
// Package main is the combined entrypoint for all Pinniped server components.
|
||||||
@ -14,8 +14,8 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
|
||||||
concierge "go.pinniped.dev/internal/concierge/server"
|
|
||||||
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
||||||
|
concierge "go.pinniped.dev/internal/concierge/server"
|
||||||
_ "go.pinniped.dev/internal/crypto/ptls"
|
_ "go.pinniped.dev/internal/crypto/ptls"
|
||||||
lua "go.pinniped.dev/internal/localuserauthenticator"
|
lua "go.pinniped.dev/internal/localuserauthenticator"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
22
cmd/pinniped/cmd/alpha.go
Normal file
22
cmd/pinniped/cmd/alpha.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:gochecknoglobals
|
||||||
|
var alphaCmd = &cobra.Command{
|
||||||
|
Use: "alpha",
|
||||||
|
Short: "alpha",
|
||||||
|
Long: "alpha subcommands (syntax or flags are still subject to change)",
|
||||||
|
SilenceUsage: true, // do not print usage message when commands fail
|
||||||
|
Hidden: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gochecknoinits
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(alphaCmd)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConciergeModeFlag(t *testing.T) {
|
func TestConciergeModeFlag(t *testing.T) {
|
||||||
@ -51,7 +52,7 @@ func TestConciergeModeFlag(t *testing.T) {
|
|||||||
func TestCABundleFlag(t *testing.T) {
|
func TestCABundleFlag(t *testing.T) {
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
emptyFilePath := filepath.Join(tmpdir, "empty")
|
emptyFilePath := filepath.Join(tmpdir, "empty")
|
||||||
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -24,7 +24,7 @@ func generateMarkdownHelpCommand() *cobra.Command {
|
|||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Use: "generate-markdown-help",
|
Use: "generate-markdown-help",
|
||||||
Short: "Generate markdown help for the current set of non-hidden CLI commands",
|
Short: "Generate markdown help for the current set of non-hidden CLI commands",
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
SilenceUsage: true,
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
RunE: runGenerateMarkdownHelp,
|
RunE: runGenerateMarkdownHelp,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -8,11 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
var getCmd = &cobra.Command{
|
var getCmd = &cobra.Command{Use: "get", Short: "get"}
|
||||||
Use: "get",
|
|
||||||
Short: "Gets one of [kubeconfig]",
|
|
||||||
SilenceUsage: true, // Do not print usage message when commands fail.
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -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/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
"k8s.io/utils/strings/slices"
|
|
||||||
|
|
||||||
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
@ -96,12 +95,6 @@ type getKubeconfigParams struct {
|
|||||||
credentialCachePath string
|
credentialCachePath string
|
||||||
credentialCachePathSet bool
|
credentialCachePathSet bool
|
||||||
installHint string
|
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 {
|
func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||||
@ -110,7 +103,7 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
|||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Use: "kubeconfig",
|
Use: "kubeconfig",
|
||||||
Short: "Generate a Pinniped-based kubeconfig for a cluster",
|
Short: "Generate a Pinniped-based kubeconfig for a cluster",
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
SilenceUsage: true,
|
||||||
}
|
}
|
||||||
flags getKubeconfigParams
|
flags getKubeconfigParams
|
||||||
namespace string // unused now
|
namespace string // unused now
|
||||||
@ -152,16 +145,14 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
|||||||
f.StringVarP(&flags.outputPath, "output", "o", "", "Output file path (default: stdout)")
|
f.StringVarP(&flags.outputPath, "output", "o", "", "Output file path (default: stdout)")
|
||||||
f.StringVar(&flags.generatedNameSuffix, "generated-name-suffix", "-pinniped", "Suffix to append to generated cluster, context, user kubeconfig entries")
|
f.StringVar(&flags.generatedNameSuffix, "generated-name-suffix", "-pinniped", "Suffix to append to generated cluster, context, user kubeconfig entries")
|
||||||
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
|
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
|
||||||
f.StringVar(&flags.pinnipedCliPath, "pinniped-cli-path", "", "Full path or executable name for the Pinniped CLI binary to be embedded in the resulting kubeconfig output (e.g. 'pinniped') (default: full path of the binary used to execute this command)")
|
|
||||||
f.StringVar(&flags.installHint, "install-hint", "The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli for more details", "This text is shown to the user when the pinniped CLI is not installed.")
|
f.StringVar(&flags.installHint, "install-hint", "The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli for more details", "This text is shown to the user when the pinniped CLI is not installed.")
|
||||||
|
mustMarkHidden(cmd, "oidc-debug-session-cache")
|
||||||
|
|
||||||
mustMarkHidden(cmd,
|
// --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
||||||
"oidc-debug-session-cache",
|
mustMarkHidden(cmd, "oidc-skip-listen")
|
||||||
"oidc-skip-listen", // --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
|
||||||
"concierge-namespace",
|
|
||||||
)
|
|
||||||
|
|
||||||
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
||||||
|
mustMarkHidden(cmd, "concierge-namespace")
|
||||||
|
|
||||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
if flags.outputPath != "" {
|
if flags.outputPath != "" {
|
||||||
@ -241,9 +232,11 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
|||||||
cluster.CertificateAuthorityData = flags.concierge.caBundle
|
cluster.CertificateAuthorityData = flags.concierge.caBundle
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(flags.oidc.issuer) > 0 {
|
// If there is an issuer, and if any upstream IDP flags are not already set, then try to discover Supervisor upstream IDP details.
|
||||||
err = pinnipedSupervisorDiscovery(ctx, &flags, deps.log)
|
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input. Maybe they know something
|
||||||
if err != nil {
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,12 +264,7 @@ func newExecConfig(deps kubeconfigDeps, flags getKubeconfigParams) (*clientcmdap
|
|||||||
|
|
||||||
execConfig.InstallHint = flags.installHint
|
execConfig.InstallHint = flags.installHint
|
||||||
var err error
|
var err error
|
||||||
execConfig.Command, err = func() (string, error) {
|
execConfig.Command, err = deps.getPathToSelf()
|
||||||
if flags.pinnipedCliPath != "" {
|
|
||||||
return flags.pinnipedCliPath, nil
|
|
||||||
}
|
|
||||||
return deps.getPathToSelf()
|
|
||||||
}()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
||||||
}
|
}
|
||||||
@ -732,7 +720,6 @@ func validateKubeconfig(ctx context.Context, flags getKubeconfigParams, kubeconf
|
|||||||
func countCACerts(pemData []byte) int {
|
func countCACerts(pemData []byte) int {
|
||||||
pool := x509.NewCertPool()
|
pool := x509.NewCertPool()
|
||||||
pool.AppendCertsFromPEM(pemData)
|
pool.AppendCertsFromPEM(pemData)
|
||||||
//nolint:staticcheck // since we're not using .Subjects() to access the system pool
|
|
||||||
return len(pool.Subjects())
|
return len(pool.Subjects())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,75 +732,21 @@ func hasPendingStrategy(credentialIssuer *configv1alpha1.CredentialIssuer) bool
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func pinnipedSupervisorDiscovery(ctx context.Context, flags *getKubeconfigParams, log plog.MinLogger) error {
|
func discoverSupervisorUpstreamIDP(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.
|
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||||
oidcProviderHTTPClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the provider's discovery endpoint, but don't parse the results yet.
|
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(ctx, flags.oidc.issuer, httpClient)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if pinnipedIDPsEndpoint == "" {
|
if pinnipedIDPsEndpoint == "" {
|
||||||
// The issuer is not advertising itself as a Pinniped Supervisor which supports upstream IDP discovery.
|
// 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
|
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)
|
discoveredUpstreamIDPs, err := discoverAllAvailableSupervisorUpstreamIDPs(ctx, pinnipedIDPsEndpoint, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -853,22 +786,19 @@ func newDiscoveryHTTPClient(caBundleFlag caBundleFlag) (*http.Client, error) {
|
|||||||
return phttp.Default(rootCAs), nil
|
return phttp.Default(rootCAs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverIDPsDiscoveryEndpointURL(discoveredProvider *coreosoidc.Provider) (string, error) {
|
func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpClient *http.Client) (string, error) {
|
||||||
var body idpdiscoveryv1alpha1.OIDCDiscoveryResponse
|
discoveredProvider, err := coreosoidc.NewProvider(coreosoidc.ClientContext(ctx, httpClient), issuer)
|
||||||
err := discoveredProvider.Claims(&body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
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 idpdiscoveryv1alpha1.OIDCDiscoveryResponse
|
||||||
var body discoveryResponseScopesSupported
|
err = discoveredProvider.Claims(&body)
|
||||||
err := discoveredProvider.Claims(&body)
|
|
||||||
if err != nil {
|
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) {
|
func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]idpdiscoveryv1alpha1.PinnipedIDP, error) {
|
||||||
|
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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -7,27 +7,15 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||||
"k8s.io/client-go/tools/auth/exec"
|
"k8s.io/client-go/tools/auth/exec"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/here"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
var loginCmd = &cobra.Command{
|
var loginCmd = &cobra.Command{
|
||||||
Use: "login",
|
Use: "login",
|
||||||
Short: "Authenticates with one of [oidc, static]",
|
Short: "login",
|
||||||
Long: here.Doc(
|
Long: "Login to a Pinniped server",
|
||||||
`Authenticates with one of [oidc, static]
|
|
||||||
|
|
||||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which will include
|
|
||||||
one of these login subcommands in its configuration. The oidc and static
|
|
||||||
subcommands are not meant to be invoked directly by a user.
|
|
||||||
|
|
||||||
The oidc and static subcommands are Kubernetes client-go credential plugins
|
|
||||||
which are meant to be configured inside a kubeconfig file. (See the Kubernetes
|
|
||||||
authentication documentation for more information about client-go credential
|
|
||||||
plugins.)`,
|
|
||||||
),
|
|
||||||
SilenceUsage: true, // Do not print usage message when commands fail.
|
SilenceUsage: true, // Do not print usage message when commands fail.
|
||||||
|
Hidden: true, // These commands are not really meant to be used directly by users, so it's confusing to have them discoverable.
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -23,7 +23,6 @@ import (
|
|||||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||||
"go.pinniped.dev/internal/execcredcache"
|
"go.pinniped.dev/internal/execcredcache"
|
||||||
"go.pinniped.dev/internal/groupsuffix"
|
"go.pinniped.dev/internal/groupsuffix"
|
||||||
"go.pinniped.dev/internal/here"
|
|
||||||
"go.pinniped.dev/internal/net/phttp"
|
"go.pinniped.dev/internal/net/phttp"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
@ -89,21 +88,10 @@ type oidcLoginFlags struct {
|
|||||||
func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
|
func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
|
||||||
var (
|
var (
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Use: "oidc --issuer ISSUER",
|
Use: "oidc --issuer ISSUER",
|
||||||
Short: "Login using an OpenID Connect provider",
|
Short: "Login using an OpenID Connect provider",
|
||||||
Long: here.Doc(
|
SilenceUsage: true,
|
||||||
`Login using an OpenID Connect provider
|
|
||||||
|
|
||||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
|
||||||
login command in its configuration. This login command is not meant to be
|
|
||||||
invoked directly by a user.
|
|
||||||
|
|
||||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
|
||||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
|
||||||
documentation for more information about client-go credential plugins.)`,
|
|
||||||
),
|
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
|
||||||
}
|
}
|
||||||
flags oidcLoginFlags
|
flags oidcLoginFlags
|
||||||
conciergeNamespace string // unused now
|
conciergeNamespace string // unused now
|
||||||
@ -164,7 +152,7 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
|||||||
// Initialize the login handler.
|
// Initialize the login handler.
|
||||||
opts := []oidcclient.Option{
|
opts := []oidcclient.Option{
|
||||||
oidcclient.WithContext(cmd.Context()),
|
oidcclient.WithContext(cmd.Context()),
|
||||||
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
||||||
oidcclient.WithScopes(flags.scopes),
|
oidcclient.WithScopes(flags.scopes),
|
||||||
oidcclient.WithSessionCache(sessionCache),
|
oidcclient.WithSessionCache(sessionCache),
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -23,6 +23,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient"
|
"go.pinniped.dev/pkg/oidcclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||||
@ -33,7 +34,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
|
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||||
|
|
||||||
@ -61,14 +62,6 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
wantStdout: here.Doc(`
|
wantStdout: here.Doc(`
|
||||||
Login using an OpenID Connect provider
|
Login using an OpenID Connect provider
|
||||||
|
|
||||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
|
||||||
login command in its configuration. This login command is not meant to be
|
|
||||||
invoked directly by a user.
|
|
||||||
|
|
||||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
|
||||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
|
||||||
documentation for more information about client-go credential plugins.)
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
oidc --issuer ISSUER [flags]
|
oidc --issuer ISSUER [flags]
|
||||||
|
|
||||||
@ -490,8 +483,8 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
wantOptionsCount: 4,
|
wantOptionsCount: 4,
|
||||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:243 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:231 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:263 No concierge configured, skipping token credential exchange`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:251 No concierge configured, skipping token credential exchange`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -512,7 +505,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
"--concierge-endpoint", "https://127.0.0.1:1234/",
|
"--concierge-endpoint", "https://127.0.0.1:1234/",
|
||||||
"--concierge-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
|
"--concierge-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
|
||||||
"--concierge-api-group-suffix", "some.suffix.com",
|
"--concierge-api-group-suffix", "some.suffix.com",
|
||||||
"--credential-cache", t.TempDir() + "/credentials.yaml", // must specify --credential-cache or else the cache file on disk causes test pollution
|
"--credential-cache", testutil.TempDir(t) + "/credentials.yaml", // must specify --credential-cache or else the cache file on disk causes test pollution
|
||||||
"--upstream-identity-provider-name", "some-upstream-name",
|
"--upstream-identity-provider-name", "some-upstream-name",
|
||||||
"--upstream-identity-provider-type", "ldap",
|
"--upstream-identity-provider-type", "ldap",
|
||||||
},
|
},
|
||||||
@ -520,10 +513,10 @@ func TestLoginOIDCCommand(t *testing.T) {
|
|||||||
wantOptionsCount: 11,
|
wantOptionsCount: 11,
|
||||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
|
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:243 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:231 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:253 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:241 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:261 Successfully exchanged token for cluster credential.`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:249 Successfully exchanged token for cluster credential.`,
|
||||||
nowStr + ` pinniped-login cmd/login_oidc.go:268 caching cluster credential for future use.`,
|
nowStr + ` pinniped-login cmd/login_oidc.go:256 caching cluster credential for future use.`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -16,7 +16,6 @@ import (
|
|||||||
|
|
||||||
"go.pinniped.dev/internal/execcredcache"
|
"go.pinniped.dev/internal/execcredcache"
|
||||||
"go.pinniped.dev/internal/groupsuffix"
|
"go.pinniped.dev/internal/groupsuffix"
|
||||||
"go.pinniped.dev/internal/here"
|
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||||
@ -56,21 +55,10 @@ type staticLoginParams struct {
|
|||||||
func staticLoginCommand(deps staticLoginDeps) *cobra.Command {
|
func staticLoginCommand(deps staticLoginDeps) *cobra.Command {
|
||||||
var (
|
var (
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Use: "static [--token TOKEN] [--token-env TOKEN_NAME]",
|
Use: "static [--token TOKEN] [--token-env TOKEN_NAME]",
|
||||||
Short: "Login using a static token",
|
Short: "Login using a static token",
|
||||||
Long: here.Doc(
|
SilenceUsage: true,
|
||||||
`Login using a static token
|
|
||||||
|
|
||||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
|
||||||
login command in its configuration. This login command is not meant to be
|
|
||||||
invoked directly by a user.
|
|
||||||
|
|
||||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
|
||||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
|
||||||
documentation for more information about client-go credential plugins.)`,
|
|
||||||
),
|
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
|
||||||
}
|
}
|
||||||
flags staticLoginParams
|
flags staticLoginParams
|
||||||
conciergeNamespace string // unused now
|
conciergeNamespace string // unused now
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
|||||||
|
|
||||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tmpdir := t.TempDir()
|
tmpdir := testutil.TempDir(t)
|
||||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||||
|
|
||||||
@ -55,14 +56,6 @@ func TestLoginStaticCommand(t *testing.T) {
|
|||||||
wantStdout: here.Doc(`
|
wantStdout: here.Doc(`
|
||||||
Login using a static token
|
Login using a static token
|
||||||
|
|
||||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
|
||||||
login command in its configuration. This login command is not meant to be
|
|
||||||
invoked directly by a user.
|
|
||||||
|
|
||||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
|
||||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
|
||||||
documentation for more information about client-go credential plugins.)
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
static [--token TOKEN] [--token-env TOKEN_NAME] [flags]
|
static [--token TOKEN] [--token-env TOKEN_NAME] [flags]
|
||||||
|
|
||||||
@ -147,7 +140,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
|||||||
Error: could not complete Concierge credential exchange: some concierge error
|
Error: could not complete Concierge credential exchange: some concierge error
|
||||||
`),
|
`),
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
nowStr + ` pinniped-login cmd/login_static.go:159 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
nowStr + ` pinniped-login cmd/login_static.go:147 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -8,18 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/here"
|
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "pinniped",
|
Use: "pinniped",
|
||||||
Long: here.Doc(
|
Short: "pinniped",
|
||||||
`The Pinniped CLI is the client-side binary for use with Pinniped-enabled Kubernetes clusters
|
Long: "pinniped is the client-side binary for use with Pinniped-enabled Kubernetes clusters.",
|
||||||
|
|
||||||
Find more information at: https://pinniped.dev`,
|
|
||||||
),
|
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
SilenceUsage: true, // do not print usage message when commands fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/yaml"
|
"k8s.io/component-base/version"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/pversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
@ -18,44 +15,14 @@ func init() {
|
|||||||
rootCmd.AddCommand(newVersionCommand())
|
rootCmd.AddCommand(newVersionCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
|
||||||
var (
|
|
||||||
output = new(string)
|
|
||||||
// getBuildInfo can be overwritten by tests.
|
|
||||||
getBuildInfo = pversion.Get
|
|
||||||
)
|
|
||||||
|
|
||||||
func newVersionCommand() *cobra.Command {
|
func newVersionCommand() *cobra.Command {
|
||||||
c := &cobra.Command{
|
return &cobra.Command{
|
||||||
RunE: runner,
|
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
|
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print the version of this Pinniped CLI",
|
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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -9,10 +9,8 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
|
||||||
|
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/pversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -21,8 +19,8 @@ var (
|
|||||||
version \[flags\]
|
version \[flags\]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for version
|
-h, --help help for version
|
||||||
-o, --output string one of 'yaml' or 'json'
|
|
||||||
`)
|
`)
|
||||||
|
|
||||||
knownGoodHelpRegexpForVersion = here.Doc(`
|
knownGoodHelpRegexpForVersion = here.Doc(`
|
||||||
@ -32,55 +30,24 @@ var (
|
|||||||
version \[flags\]
|
version \[flags\]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for version
|
-h, --help help for version
|
||||||
-o, --output string one of 'yaml' or 'json'
|
|
||||||
`)
|
`)
|
||||||
|
|
||||||
jsonRegexp = here.Doc(`{
|
emptyVersionRegexp = `version.Info{Major:"", Minor:"", GitVersion:".*", GitCommit:".*", GitTreeState:"", BuildDate:".*", GoVersion:".*", Compiler:".*", Platform:".*/.*"}`
|
||||||
"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: .*/.*
|
|
||||||
`)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewVersionCmd(t *testing.T) {
|
func TestNewVersionCmd(t *testing.T) {
|
||||||
t.Cleanup(func() {
|
|
||||||
getBuildInfo = pversion.Get
|
|
||||||
})
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
vars string
|
|
||||||
getBuildInfo func() apimachineryversion.Info
|
|
||||||
wantError bool
|
wantError bool
|
||||||
wantStdoutRegexp string
|
wantStdoutRegexp string
|
||||||
wantStderrRegexp string
|
wantStderrRegexp string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no flags",
|
name: "no flags",
|
||||||
args: []string{},
|
args: []string{},
|
||||||
getBuildInfo: func() apimachineryversion.Info {
|
wantStdoutRegexp: emptyVersionRegexp + "\n",
|
||||||
return apimachineryversion.Info{GitVersion: "v55.66.44"}
|
|
||||||
},
|
|
||||||
wantStdoutRegexp: "v55.66.44\n",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "help flag passed",
|
name: "help flag passed",
|
||||||
@ -94,44 +61,10 @@ func TestNewVersionCmd(t *testing.T) {
|
|||||||
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
||||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
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 {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if tt.getBuildInfo != nil {
|
|
||||||
getBuildInfo = tt.getBuildInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := newVersionCommand()
|
cmd := newVersionCommand()
|
||||||
require.NotNil(t, cmd)
|
require.NotNil(t, cmd)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -48,7 +48,7 @@ func newWhoamiCommand(getClientset getConciergeClientsetFunc) *cobra.Command {
|
|||||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||||
Use: "whoami",
|
Use: "whoami",
|
||||||
Short: "Print information about the current user",
|
Short: "Print information about the current user",
|
||||||
SilenceUsage: true, // do not print usage message when commands fail
|
SilenceUsage: true,
|
||||||
}
|
}
|
||||||
flags := &whoamiFlags{}
|
flags := &whoamiFlags{}
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -96,15 +97,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -173,3 +168,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: authentication.concierge.pinniped.dev
|
group: authentication.concierge.pinniped.dev
|
||||||
@ -69,15 +70,9 @@ spec:
|
|||||||
description: Represents the observations of the authenticator's current
|
description: Represents the observations of the authenticator's current
|
||||||
state.
|
state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -146,3 +141,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: credentialissuers.config.concierge.pinniped.dev
|
name: credentialissuers.config.concierge.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.concierge.pinniped.dev
|
group: config.concierge.pinniped.dev
|
||||||
@ -102,24 +103,6 @@ spec:
|
|||||||
- None
|
- None
|
||||||
type: string
|
type: string
|
||||||
type: object
|
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:
|
required:
|
||||||
- mode
|
- mode
|
||||||
- service
|
- service
|
||||||
@ -255,3 +238,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -134,6 +134,8 @@ spec:
|
|||||||
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||||
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
||||||
_: #@ template.replace(deploymentPodLabel())
|
_: #@ template.replace(deploymentPodLabel())
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: #@ data.values.run_as_user
|
runAsUser: #@ data.values.run_as_user
|
||||||
@ -245,14 +247,9 @@ spec:
|
|||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
- key: kubernetes.io/arch
|
#! "system-cluster-critical" cannot be used outside the kube-system namespace until Kubernetes >= 1.17,
|
||||||
effect: NoSchedule
|
#! so we skip setting this for now (see https://github.com/kubernetes/kubernetes/issues/60596).
|
||||||
operator: Equal
|
#!priorityClassName: system-cluster-critical
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
#! This will help make sure our multiple pods run on different nodes, making
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
#! our deployment "more" "HA".
|
#! our deployment "more" "HA".
|
||||||
affinity:
|
affinity:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -76,15 +76,6 @@ spec:
|
|||||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: "RuntimeDefault"
|
type: "RuntimeDefault"
|
||||||
tolerations:
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: federationdomains.config.supervisor.pinniped.dev
|
name: federationdomains.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -20,7 +21,7 @@ spec:
|
|||||||
- jsonPath: .spec.issuer
|
- jsonPath: .spec.issuer
|
||||||
name: Issuer
|
name: Issuer
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .status.phase
|
- jsonPath: .status.status
|
||||||
name: Status
|
name: Status
|
||||||
type: string
|
type: string
|
||||||
- jsonPath: .metadata.creationTimestamp
|
- jsonPath: .metadata.creationTimestamp
|
||||||
@ -46,264 +47,6 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
description: Spec of the OIDC provider.
|
description: Spec of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
identityProviders:
|
|
||||||
description: "IdentityProviders is the list of identity providers
|
|
||||||
available for use by this FederationDomain. \n An identity provider
|
|
||||||
CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes
|
|
||||||
how to connect to a server, how to talk in a specific protocol for
|
|
||||||
authentication, and how to use the schema of that server/protocol
|
|
||||||
to extract a normalized user identity. Normalized user identities
|
|
||||||
include a username and a list of group names. In contrast, IdentityProviders
|
|
||||||
describes how to use that normalized identity in those Kubernetes
|
|
||||||
clusters which belong to this FederationDomain. Each entry in IdentityProviders
|
|
||||||
can be configured with arbitrary transformations on that normalized
|
|
||||||
identity. For example, a transformation can add a prefix to all
|
|
||||||
usernames to help avoid accidental conflicts when multiple identity
|
|
||||||
providers have different users with the same username (e.g. \"idp1:ryan\"
|
|
||||||
versus \"idp2:ryan\"). Each entry in IdentityProviders can also
|
|
||||||
implement arbitrary authentication rejection policies. Even though
|
|
||||||
a user was able to authenticate with the identity provider, a policy
|
|
||||||
can disallow the authentication to the Kubernetes clusters that
|
|
||||||
belong to this FederationDomain. For example, a policy could disallow
|
|
||||||
the authentication unless the user belongs to a specific group in
|
|
||||||
the identity provider. \n For backwards compatibility with versions
|
|
||||||
of Pinniped which predate support for multiple identity providers,
|
|
||||||
an empty IdentityProviders list will cause the FederationDomain
|
|
||||||
to use all available identity providers which exist in the same
|
|
||||||
namespace, but also to reject all authentication requests when there
|
|
||||||
is more than one identity provider currently defined. In this backwards
|
|
||||||
compatibility mode, the name of the identity provider resource (e.g.
|
|
||||||
the Name of an OIDCIdentityProvider resource) will be used as the
|
|
||||||
name of the identity provider in this FederationDomain. This mode
|
|
||||||
is provided to make upgrading from older versions easier. However,
|
|
||||||
instead of relying on this backwards compatibility mode, please
|
|
||||||
consider this mode to be deprecated and please instead explicitly
|
|
||||||
list the identity provider using this IdentityProviders field."
|
|
||||||
items:
|
|
||||||
description: FederationDomainIdentityProvider describes how an identity
|
|
||||||
provider is made available in this FederationDomain.
|
|
||||||
properties:
|
|
||||||
displayName:
|
|
||||||
description: DisplayName is the name of this identity provider
|
|
||||||
as it will appear to clients. This name ends up in the kubeconfig
|
|
||||||
of end users, so changing the name of an identity provider
|
|
||||||
that is in use by end users will be a disruptive change for
|
|
||||||
those users.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
objectRef:
|
|
||||||
description: ObjectRef is a reference to a Pinniped identity
|
|
||||||
provider resource. A valid reference is required. If the reference
|
|
||||||
cannot be resolved then the identity provider will not be
|
|
||||||
made available. Must refer to a resource of one of the Pinniped
|
|
||||||
identity provider types, e.g. OIDCIdentityProvider, LDAPIdentityProvider,
|
|
||||||
ActiveDirectoryIdentityProvider.
|
|
||||||
properties:
|
|
||||||
apiGroup:
|
|
||||||
description: APIGroup is the group for the resource being
|
|
||||||
referenced. If APIGroup is not specified, the specified
|
|
||||||
Kind must be in the core API group. For any other third-party
|
|
||||||
types, APIGroup is required.
|
|
||||||
type: string
|
|
||||||
kind:
|
|
||||||
description: Kind is the type of resource being referenced
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
description: Name is the name of resource being referenced
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
transforms:
|
|
||||||
description: Transforms is an optional way to specify transformations
|
|
||||||
to be applied during user authentication and session refresh.
|
|
||||||
properties:
|
|
||||||
constants:
|
|
||||||
description: Constants defines constant variables and their
|
|
||||||
values which will be made available to the transform expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsConstant defines
|
|
||||||
a constant variable and its value which will be made
|
|
||||||
available to the transform expressions. This is a union
|
|
||||||
type, and Type is the discriminator field.
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name determines the name of the constant.
|
|
||||||
It must be a valid identifier name.
|
|
||||||
maxLength: 64
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[a-zA-Z][_a-zA-Z0-9]*$
|
|
||||||
type: string
|
|
||||||
stringListValue:
|
|
||||||
description: StringListValue should hold the value
|
|
||||||
when Type is "stringList", and is otherwise ignored.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
stringValue:
|
|
||||||
description: StringValue should hold the value when
|
|
||||||
Type is "string", and is otherwise ignored.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the constant,
|
|
||||||
and indicates which other field should be non-empty.
|
|
||||||
enum:
|
|
||||||
- string
|
|
||||||
- stringList
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- name
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
examples:
|
|
||||||
description: Examples can optionally be used to ensure that
|
|
||||||
the sequence of transformation expressions are working
|
|
||||||
as expected. Examples define sample input identities which
|
|
||||||
are then run through the expression list, and the results
|
|
||||||
are compared to the expected results. If any example in
|
|
||||||
this list fails, then this identity provider will not
|
|
||||||
be available for use within this FederationDomain, and
|
|
||||||
the error(s) will be added to the FederationDomain status.
|
|
||||||
This can be used to help guard against programming mistakes
|
|
||||||
in the expressions, and also act as living documentation
|
|
||||||
for other administrators to better understand the expressions.
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExample defines
|
|
||||||
a transform example.
|
|
||||||
properties:
|
|
||||||
expects:
|
|
||||||
description: Expects is the expected output of the
|
|
||||||
entire sequence of transforms when they are run
|
|
||||||
against the input Username and Groups.
|
|
||||||
properties:
|
|
||||||
groups:
|
|
||||||
description: Groups is the expected list of group
|
|
||||||
names after the transformations have been applied.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
message:
|
|
||||||
description: Message is the expected error message
|
|
||||||
of the transforms. When Rejected is true, then
|
|
||||||
Message is the expected message for the policy
|
|
||||||
which rejected the authentication attempt. When
|
|
||||||
Rejected is true and Message is blank, then
|
|
||||||
Message will be treated as the default error
|
|
||||||
message for authentication attempts which are
|
|
||||||
rejected by a policy. When Rejected is false,
|
|
||||||
then Message is the expected error message for
|
|
||||||
some other non-policy transformation error,
|
|
||||||
such as a runtime error. When Rejected is false,
|
|
||||||
there is no default expected Message.
|
|
||||||
type: string
|
|
||||||
rejected:
|
|
||||||
description: Rejected is a boolean that indicates
|
|
||||||
whether authentication is expected to be rejected
|
|
||||||
by a policy expression after the transformations
|
|
||||||
have been applied. True means that it is expected
|
|
||||||
that the authentication would be rejected. The
|
|
||||||
default value of false means that it is expected
|
|
||||||
that the authentication would not be rejected
|
|
||||||
by any policy expression.
|
|
||||||
type: boolean
|
|
||||||
username:
|
|
||||||
description: Username is the expected username
|
|
||||||
after the transformations have been applied.
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
groups:
|
|
||||||
description: Groups is the input list of group names.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
username:
|
|
||||||
description: Username is the input username.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expects
|
|
||||||
- username
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
expressions:
|
|
||||||
description: "Expressions are an optional list of transforms
|
|
||||||
and policies to be executed in the order given during
|
|
||||||
every authentication attempt, including during every session
|
|
||||||
refresh. Each is a CEL expression. It may use the basic
|
|
||||||
CEL language as defined in https://github.com/google/cel-spec/blob/master/doc/langdef.md
|
|
||||||
plus the CEL string extensions defined in https://github.com/google/cel-go/tree/master/ext#strings.
|
|
||||||
\n The username and groups extracted from the identity
|
|
||||||
provider, and the constants defined in this CR, are available
|
|
||||||
as variables in all expressions. The username is provided
|
|
||||||
via a variable called `username` and the list of group
|
|
||||||
names is provided via a variable called `groups` (which
|
|
||||||
may be an empty list). Each user-provided constants is
|
|
||||||
provided via a variable named `strConst.varName` for string
|
|
||||||
constants and `strListConst.varName` for string list constants.
|
|
||||||
\n The only allowed types for expressions are currently
|
|
||||||
policy/v1, username/v1, and groups/v1. Each policy/v1
|
|
||||||
must return a boolean, and when it returns false, no more
|
|
||||||
expressions from the list are evaluated and the authentication
|
|
||||||
attempt is rejected. Transformations of type policy/v1
|
|
||||||
do not return usernames or group names, and therefore
|
|
||||||
cannot change the username or group names. Each username/v1
|
|
||||||
transform must return the new username (a string), which
|
|
||||||
can be the same as the old username. Transformations of
|
|
||||||
type username/v1 do not return group names, and therefore
|
|
||||||
cannot change the group names. Each groups/v1 transform
|
|
||||||
must return the new groups list (list of strings), which
|
|
||||||
can be the same as the old groups list. Transformations
|
|
||||||
of type groups/v1 do not return usernames, and therefore
|
|
||||||
cannot change the usernames. After each expression, the
|
|
||||||
new (potentially changed) username or groups get passed
|
|
||||||
to the following expression. \n Any compilation or static
|
|
||||||
type-checking failure of any expression will cause an
|
|
||||||
error status on the FederationDomain. During an authentication
|
|
||||||
attempt, any unexpected runtime evaluation errors (e.g.
|
|
||||||
division by zero) cause the authentication attempt to
|
|
||||||
fail. When all expressions evaluate successfully, then
|
|
||||||
the (potentially changed) username and group names have
|
|
||||||
been decided for that authentication attempt."
|
|
||||||
items:
|
|
||||||
description: FederationDomainTransformsExpression defines
|
|
||||||
a transform expression.
|
|
||||||
properties:
|
|
||||||
expression:
|
|
||||||
description: Expression is a CEL expression that will
|
|
||||||
be evaluated based on the Type during an authentication.
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: Message is only used when Type is policy/v1.
|
|
||||||
It defines an error message to be used when the
|
|
||||||
policy rejects an authentication attempt. When empty,
|
|
||||||
a default message will be used.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type determines the type of the expression.
|
|
||||||
It must be one of the supported types.
|
|
||||||
enum:
|
|
||||||
- policy/v1
|
|
||||||
- username/v1
|
|
||||||
- groups/v1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- expression
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- displayName
|
|
||||||
- objectRef
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
issuer:
|
issuer:
|
||||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||||
Metadata document, as well as the identifier that it will use for
|
Metadata document, as well as the identifier that it will use for
|
||||||
@ -316,8 +59,8 @@ spec:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
type: string
|
type: string
|
||||||
tls:
|
tls:
|
||||||
description: TLS specifies a secret which will contain Transport Layer
|
description: TLS configures how this FederationDomain is served over
|
||||||
Security (TLS) configuration for the FederationDomain.
|
Transport Layer Security (TLS).
|
||||||
properties:
|
properties:
|
||||||
secretName:
|
secretName:
|
||||||
description: "SecretName is an optional name of a Secret in the
|
description: "SecretName is an optional name of a Secret in the
|
||||||
@ -348,86 +91,14 @@ spec:
|
|||||||
status:
|
status:
|
||||||
description: Status of the OIDC provider.
|
description: Status of the OIDC provider.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
lastUpdateTime:
|
||||||
description: Conditions represent the observations of an FederationDomain's
|
description: LastUpdateTime holds the time at which the Status was
|
||||||
current state.
|
last updated. It is a pointer to get around some undesirable behavior
|
||||||
items:
|
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||||
description: "Condition contains details for one aspect of the current
|
format: date-time
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type: string
|
||||||
use as an array at the field path .status.conditions. For example,
|
message:
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
description: Message provides human-readable details about the Status.
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
|
||||||
lastTransitionTime:
|
|
||||||
description: lastTransitionTime is the last time the condition
|
|
||||||
transitioned from one status to another. This should be when
|
|
||||||
the underlying condition changed. If that is not known, then
|
|
||||||
using the time when the API field changed is acceptable.
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: message is a human readable message indicating
|
|
||||||
details about the transition. This may be an empty string.
|
|
||||||
maxLength: 32768
|
|
||||||
type: string
|
|
||||||
observedGeneration:
|
|
||||||
description: observedGeneration represents the .metadata.generation
|
|
||||||
that the condition was set based upon. For instance, if .metadata.generation
|
|
||||||
is currently 12, but the .status.conditions[x].observedGeneration
|
|
||||||
is 9, the condition is out of date with respect to the current
|
|
||||||
state of the instance.
|
|
||||||
format: int64
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
reason:
|
|
||||||
description: reason contains a programmatic identifier indicating
|
|
||||||
the reason for the condition's last transition. Producers
|
|
||||||
of specific condition types may define expected values and
|
|
||||||
meanings for this field, and whether the values are considered
|
|
||||||
a guaranteed API. The value should be a CamelCase string.
|
|
||||||
This field may not be empty.
|
|
||||||
maxLength: 1024
|
|
||||||
minLength: 1
|
|
||||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: status of the condition, one of True, False, Unknown.
|
|
||||||
enum:
|
|
||||||
- "True"
|
|
||||||
- "False"
|
|
||||||
- Unknown
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
|
||||||
--- Many .condition.type values are consistent across resources
|
|
||||||
like Available, but because arbitrary conditions can be useful
|
|
||||||
(see .node.status.conditions), the ability to deconflict is
|
|
||||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
|
||||||
maxLength: 316
|
|
||||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- lastTransitionTime
|
|
||||||
- message
|
|
||||||
- reason
|
|
||||||
- status
|
|
||||||
- type
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-map-keys:
|
|
||||||
- type
|
|
||||||
x-kubernetes-list-type: map
|
|
||||||
phase:
|
|
||||||
default: Pending
|
|
||||||
description: Phase summarizes the overall status of the FederationDomain.
|
|
||||||
enum:
|
|
||||||
- Pending
|
|
||||||
- Ready
|
|
||||||
- Error
|
|
||||||
type: string
|
type: string
|
||||||
secrets:
|
secrets:
|
||||||
description: Secrets contains information about this OIDC Provider's
|
description: Secrets contains information about this OIDC Provider's
|
||||||
@ -444,7 +115,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
stateEncryptionKey:
|
stateEncryptionKey:
|
||||||
description: StateSigningKey holds the name of the corev1.Secret
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for encrypting state parameters
|
in which this OIDC Provider's key for encrypting state parameters
|
||||||
@ -455,7 +125,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
stateSigningKey:
|
stateSigningKey:
|
||||||
description: StateSigningKey holds the name of the corev1.Secret
|
description: StateSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for signing state parameters
|
in which this OIDC Provider's key for signing state parameters
|
||||||
@ -466,7 +135,6 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
tokenSigningKey:
|
tokenSigningKey:
|
||||||
description: TokenSigningKey holds the name of the corev1.Secret
|
description: TokenSigningKey holds the name of the corev1.Secret
|
||||||
in which this OIDC Provider's key for signing tokens is stored.
|
in which this OIDC Provider's key for signing tokens is stored.
|
||||||
@ -476,8 +144,16 @@ spec:
|
|||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
x-kubernetes-map-type: atomic
|
|
||||||
type: object
|
type: object
|
||||||
|
status:
|
||||||
|
description: Status holds an enum that describes the state of this
|
||||||
|
OIDC Provider. Note that this Status can represent success or failure.
|
||||||
|
enum:
|
||||||
|
- Success
|
||||||
|
- Duplicate
|
||||||
|
- Invalid
|
||||||
|
- SameIssuerHostMustUseSameSecret
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
@ -486,3 +162,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcclients.config.supervisor.pinniped.dev
|
name: oidcclients.config.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: config.supervisor.pinniped.dev
|
group: config.supervisor.pinniped.dev
|
||||||
@ -128,15 +129,9 @@ spec:
|
|||||||
description: conditions represent the observations of an OIDCClient's
|
description: conditions represent the observations of an OIDCClient's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -218,3 +213,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
#! SPDX-License-Identifier: Apache-2.0
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#@ load("@ytt:data", "data")
|
#@ load("@ytt:data", "data")
|
||||||
@ -190,15 +190,6 @@ spec:
|
|||||||
- name: socket
|
- name: socket
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
#@ end
|
#@ end
|
||||||
tolerations:
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: amd64 #! Allow running on amd64 nodes.
|
|
||||||
- key: kubernetes.io/arch
|
|
||||||
effect: NoSchedule
|
|
||||||
operator: Equal
|
|
||||||
value: arm64 #! Also allow running on arm64 nodes.
|
|
||||||
#! This will help make sure our multiple pods run on different nodes, making
|
#! This will help make sure our multiple pods run on different nodes, making
|
||||||
#! our deployment "more" "HA".
|
#! our deployment "more" "HA".
|
||||||
affinity:
|
affinity:
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -106,11 +107,10 @@ spec:
|
|||||||
description: Filter is the ActiveDirectory search filter which
|
description: Filter is the ActiveDirectory search filter which
|
||||||
should be applied when searching for groups for a user. The
|
should be applied when searching for groups for a user. The
|
||||||
pattern "{}" must occur in the filter at least once and will
|
pattern "{}" must occur in the filter at least once and will
|
||||||
be dynamically replaced by the value of an attribute of the
|
be dynamically replaced by the dn (distinguished name) of the
|
||||||
user entry found as a result of the user search. Which attribute's
|
user entry found as a result of the user search. E.g. "member={}"
|
||||||
value is used to replace the placeholder(s) depends on the value
|
or "&(objectClass=groupOfNames)(member={})". For more information
|
||||||
of UserAttributeForFilter. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
||||||
For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
|
||||||
Note that the dn (distinguished name) is not an attribute of
|
Note that the dn (distinguished name) is not an attribute of
|
||||||
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
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:={})".
|
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
|
carefully read all release notes before upgrading to ensure
|
||||||
that the meaning of this field has not changed."
|
that the meaning of this field has not changed."
|
||||||
type: boolean
|
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
|
type: object
|
||||||
host:
|
host:
|
||||||
description: 'Host is the hostname of this Active Directory identity
|
description: 'Host is the hostname of this Active Directory identity
|
||||||
@ -231,15 +217,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -316,3 +296,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -95,16 +96,15 @@ spec:
|
|||||||
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
|
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
|
When not specified, no group search will be performed and authenticated
|
||||||
users will not belong to any groups from the LDAP provider.
|
users will not belong to any groups from the LDAP provider.
|
||||||
Also, when not specified, the values of Filter, UserAttributeForFilter,
|
Also, when not specified, the values of Filter and Attributes
|
||||||
Attributes, and SkipGroupRefresh are ignored.
|
are ignored.
|
||||||
type: string
|
type: string
|
||||||
filter:
|
filter:
|
||||||
description: Filter is the LDAP search filter which should be
|
description: Filter is the LDAP search filter which should be
|
||||||
applied when searching for groups for a user. The pattern "{}"
|
applied when searching for groups for a user. The pattern "{}"
|
||||||
must occur in the filter at least once and will be dynamically
|
must occur in the filter at least once and will be dynamically
|
||||||
replaced by the value of an attribute of the user entry found
|
replaced by the dn (distinguished name) of the user entry found
|
||||||
as a result of the user search. Which attribute's value is used
|
as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||||
to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
|
||||||
For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
||||||
Note that the dn (distinguished name) is not an attribute of
|
Note that the dn (distinguished name) is not an attribute of
|
||||||
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
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
|
carefully read all release notes before upgrading to ensure
|
||||||
that the meaning of this field has not changed."
|
that the meaning of this field has not changed."
|
||||||
type: boolean
|
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
|
type: object
|
||||||
host:
|
host:
|
||||||
description: 'Host is the hostname of this LDAP identity provider,
|
description: 'Host is the hostname of this LDAP identity provider,
|
||||||
@ -228,15 +214,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -313,3 +293,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.13.0
|
controller-gen.kubebuilder.io/version: v0.8.0
|
||||||
|
creationTimestamp: null
|
||||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||||
spec:
|
spec:
|
||||||
group: idp.supervisor.pinniped.dev
|
group: idp.supervisor.pinniped.dev
|
||||||
@ -194,13 +195,11 @@ spec:
|
|||||||
claim names as the values. These new claim names will be nested
|
claim names as the values. These new claim names will be nested
|
||||||
under the top-level "additionalClaims" claim in ID tokens generated
|
under the top-level "additionalClaims" claim in ID tokens generated
|
||||||
by the Supervisor when this OIDCIdentityProvider was used for
|
by the Supervisor when this OIDCIdentityProvider was used for
|
||||||
user authentication. These claims will be made available to
|
user authentication. This feature is not required for using
|
||||||
all clients. This feature is not required to use the Supervisor
|
the Supervisor to provide authentication for Kubernetes clusters,
|
||||||
to provide authentication for Kubernetes clusters, but can be
|
but can be used when using the Supervisor for other authentication
|
||||||
used when using the Supervisor for other authentication purposes.
|
purposes. When this map is empty, the "additionalClaims" claim
|
||||||
When this map is empty or the upstream claims are not available,
|
will be excluded from the ID tokens generated by the Supervisor.
|
||||||
the "additionalClaims" claim will be excluded from the ID tokens
|
|
||||||
generated by the Supervisor.
|
|
||||||
type: object
|
type: object
|
||||||
groups:
|
groups:
|
||||||
description: Groups provides the name of the ID token claim or
|
description: Groups provides the name of the ID token claim or
|
||||||
@ -258,15 +257,9 @@ spec:
|
|||||||
description: Represents the observations of an identity provider's
|
description: Represents the observations of an identity provider's
|
||||||
current state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: "Condition contains details for one aspect of the current
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
state of this API Resource. --- This struct is intended for direct
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
use as an array at the field path .status.conditions. For example,
|
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||||
\n type FooStatus struct{ // Represents the observations of a
|
|
||||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
|
||||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
|
||||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
|
||||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
|
||||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
|
||||||
properties:
|
properties:
|
||||||
lastTransitionTime:
|
lastTransitionTime:
|
||||||
description: lastTransitionTime is the last time the condition
|
description: lastTransitionTime is the last time the condition
|
||||||
@ -343,3 +336,9 @@ spec:
|
|||||||
storage: true
|
storage: true
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
||||||
|
1039
generated/1.28/README.adoc → generated/1.17/README.adoc
generated
1039
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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type JWTAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a JWT authenticator.
|
// Spec for configuring a JWT authenticator.
|
75
generated/1.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
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -12,7 +12,7 @@ type WebhookAuthenticatorStatus struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec for configuring a webhook authenticator.
|
// Spec for configuring a webhook authenticator.
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||||
@ -9,10 +9,26 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Condition) DeepCopyInto(out *Condition) {
|
||||||
|
*out = *in
|
||||||
|
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||||
|
func (in *Condition) DeepCopy() *Condition {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Condition)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -101,7 +117,7 @@ func (in *JWTAuthenticatorStatus) DeepCopyInto(out *JWTAuthenticatorStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@ -238,7 +254,7 @@ func (in *WebhookAuthenticatorStatus) DeepCopyInto(out *WebhookAuthenticatorStat
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]v1.Condition, len(*in))
|
*out = make([]Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
@ -80,28 +80,6 @@ const (
|
|||||||
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
|
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.
|
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
|
||||||
type ImpersonationProxySpec struct {
|
type ImpersonationProxySpec struct {
|
||||||
// Mode configures whether the impersonation proxy should be started:
|
// Mode configures whether the impersonation proxy should be started:
|
||||||
@ -122,13 +100,6 @@ type ImpersonationProxySpec struct {
|
|||||||
//
|
//
|
||||||
// +optional
|
// +optional
|
||||||
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
|
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.
|
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||||
@ -229,11 +229,6 @@ func (in *ImpersonationProxyServiceSpec) DeepCopy() *ImpersonationProxyServiceSp
|
|||||||
func (in *ImpersonationProxySpec) DeepCopyInto(out *ImpersonationProxySpec) {
|
func (in *ImpersonationProxySpec) DeepCopyInto(out *ImpersonationProxySpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Service.DeepCopyInto(&out.Service)
|
in.Service.DeepCopyInto(&out.Service)
|
||||||
if in.TLS != nil {
|
|
||||||
in, out := &in.TLS, &out.TLS
|
|
||||||
*out = new(ImpersonationProxyTLSSpec)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,22 +242,6 @@ func (in *ImpersonationProxySpec) DeepCopy() *ImpersonationProxySpec {
|
|||||||
return out
|
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.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TokenCredentialRequestAPIInfo) DeepCopyInto(out *TokenCredentialRequestAPIInfo) {
|
func (in *TokenCredentialRequestAPIInfo) DeepCopyInto(out *TokenCredentialRequestAPIInfo) {
|
||||||
*out = *in
|
*out = *in
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// +k8s:openapi-gen=true
|
// +k8s:openapi-gen=true
|
||||||
// +k8s:deepcopy-gen=package
|
// +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
|
// +k8s:defaulter-gen=TypeMeta
|
||||||
// +groupName=identity.concierge.pinniped.dev
|
// +groupName=identity.concierge.pinniped.dev
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by conversion-gen. DO NOT EDIT.
|
// Code generated by conversion-gen. DO NOT EDIT.
|
||||||
@ -11,7 +11,7 @@ package v1alpha1
|
|||||||
import (
|
import (
|
||||||
unsafe "unsafe"
|
unsafe "unsafe"
|
||||||
|
|
||||||
identity "go.pinniped.dev/generated/1.27/apis/concierge/identity"
|
identity "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
// Code generated by defaulter-gen. DO NOT EDIT.
|
@ -6,7 +6,7 @@ package validation
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
|
||||||
identityapi "go.pinniped.dev/generated/1.28/apis/concierge/identity"
|
identityapi "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ValidateWhoAmIRequest(whoAmIRequest *identityapi.WhoAmIRequest) field.ErrorList {
|
func ValidateWhoAmIRequest(whoAmIRequest *identityapi.WhoAmIRequest) field.ErrorList {
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// +k8s:openapi-gen=true
|
// +k8s:openapi-gen=true
|
||||||
// +k8s:deepcopy-gen=package
|
// +k8s:deepcopy-gen=package
|
||||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.26/apis/concierge/login
|
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/concierge/login
|
||||||
// +k8s:defaulter-gen=TypeMeta
|
// +k8s:defaulter-gen=TypeMeta
|
||||||
// +groupName=login.concierge.pinniped.dev
|
// +groupName=login.concierge.pinniped.dev
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by conversion-gen. DO NOT EDIT.
|
// Code generated by conversion-gen. DO NOT EDIT.
|
||||||
@ -11,7 +11,7 @@ package v1alpha1
|
|||||||
import (
|
import (
|
||||||
unsafe "unsafe"
|
unsafe "unsafe"
|
||||||
|
|
||||||
login "go.pinniped.dev/generated/1.28/apis/concierge/login"
|
login "go.pinniped.dev/generated/1.17/apis/concierge/login"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
// Code generated by defaulter-gen. DO NOT EDIT.
|
@ -1,7 +1,7 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
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:openapi-gen=true
|
||||||
// +k8s:deepcopy-gen=package
|
// +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
|
// +k8s:defaulter-gen=TypeMeta
|
||||||
// +groupName=clientsecret.supervisor.pinniped.dev
|
// +groupName=clientsecret.supervisor.pinniped.dev
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user