mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-30 01:22:30 +00:00
Compare commits
231 Commits
v0.34.0
...
jtc/backfi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d99889418 | ||
|
|
876f626e7d | ||
|
|
0dc704be9c | ||
|
|
e437832698 | ||
|
|
274ca4cb73 | ||
|
|
a99ff646a0 | ||
|
|
02eb26f135 | ||
|
|
e90f19f8ab | ||
|
|
00c2c5cf6e | ||
|
|
3386774f5f | ||
|
|
7e4330be93 | ||
|
|
f5b3e6da93 | ||
|
|
5c39374915 | ||
|
|
4fdb931141 | ||
|
|
3a02854192 | ||
|
|
63c071d6ea | ||
|
|
6dc96f4224 | ||
|
|
aa8f8f7fda | ||
|
|
f5167bb279 | ||
|
|
b84eafc173 | ||
|
|
50ed1b0cf9 | ||
|
|
1d873be184 | ||
|
|
5a0d6eddb1 | ||
|
|
31b45525ce | ||
|
|
430c73b903 | ||
|
|
cc1befbc57 | ||
|
|
68a0ad4112 | ||
|
|
9aca187559 | ||
|
|
d0fb9f3637 | ||
|
|
51d1bc32e8 | ||
|
|
e9b9dd6fa3 | ||
|
|
7e43aa4e12 | ||
|
|
de509db7be | ||
|
|
69c6676d8f | ||
|
|
2ab11dccfc | ||
|
|
d64b4677b9 | ||
|
|
f040f098dc | ||
|
|
abe3391cce | ||
|
|
6ae27c87f6 | ||
|
|
3d2446d235 | ||
|
|
4f01b3157f | ||
|
|
14e728aa0d | ||
|
|
4a266a44db | ||
|
|
900db0d3a3 | ||
|
|
8b95b141b2 | ||
|
|
5a9f2f3181 | ||
|
|
4f43f01e55 | ||
|
|
7221be5a8a | ||
|
|
83ab099b84 | ||
|
|
5f79860c8c | ||
|
|
e4f7b5d181 | ||
|
|
9619a0f226 | ||
|
|
23f414c384 | ||
|
|
4872be0a84 | ||
|
|
691307a269 | ||
|
|
6d846ad2a9 | ||
|
|
ff24c757b7 | ||
|
|
ee4663aa19 | ||
|
|
119c591500 | ||
|
|
275412e902 | ||
|
|
fe75ebe4b2 | ||
|
|
fabb80cf19 | ||
|
|
7577f20c61 | ||
|
|
f441714f93 | ||
|
|
2c9547e6a4 | ||
|
|
3bf3ed03f5 | ||
|
|
c279253e20 | ||
|
|
fa9ddf48d5 | ||
|
|
b8a9c4d1e5 | ||
|
|
b4365c100f | ||
|
|
ef4b0c9cff | ||
|
|
b625b4a076 | ||
|
|
acbe9ce23d | ||
|
|
90c95866d1 | ||
|
|
57fc177266 | ||
|
|
0366f4087f | ||
|
|
3f6d287b44 | ||
|
|
36aa701b56 | ||
|
|
fc5a776645 | ||
|
|
c2b4390bfa | ||
|
|
b371389c27 | ||
|
|
87640ca54a | ||
|
|
8322b03d63 | ||
|
|
594c3580f2 | ||
|
|
0d80c492f1 | ||
|
|
1a29cca1ca | ||
|
|
b54191f29f | ||
|
|
422e4e4785 | ||
|
|
4187cc1f61 | ||
|
|
ede9e45211 | ||
|
|
a36550d94b | ||
|
|
7c3870f3fa | ||
|
|
7ca2796774 | ||
|
|
170cc3bba4 | ||
|
|
1980912ebe | ||
|
|
1571859d67 | ||
|
|
eb4c20a6aa | ||
|
|
1154139b91 | ||
|
|
28e22d7dd2 | ||
|
|
9cfbbb541a | ||
|
|
21bce1cb92 | ||
|
|
fe045343ee | ||
|
|
df017f9267 | ||
|
|
ae5aad178d | ||
|
|
032160a85e | ||
|
|
ecd23e86ce | ||
|
|
51ae782135 | ||
|
|
54b35c30da | ||
|
|
dfe04c5a58 | ||
|
|
4423d472da | ||
|
|
c803a182be | ||
|
|
bc73505e35 | ||
|
|
0a28c818ad | ||
|
|
ce2dcbdbb3 | ||
|
|
1ebe2fcd1a | ||
|
|
c7e9ee1c61 | ||
|
|
51c86795af | ||
|
|
8dffd60f0b | ||
|
|
6bf9b64778 | ||
|
|
26ec7fa346 | ||
|
|
60bd118a9c | ||
|
|
b69507f7f3 | ||
|
|
7d59df0f86 | ||
|
|
9c0272382f | ||
|
|
2de8d9f0f3 | ||
|
|
d0905c02dd | ||
|
|
51fc86f950 | ||
|
|
76bda12760 | ||
|
|
a84b76e56a | ||
|
|
c2018717b6 | ||
|
|
f388513145 | ||
|
|
c16ebe1707 | ||
|
|
b54365c199 | ||
|
|
51d1cc7a96 | ||
|
|
c06141c871 | ||
|
|
eab3fde3af | ||
|
|
de7781b7f9 | ||
|
|
611de03e01 | ||
|
|
de722332b1 | ||
|
|
438ca437ec | ||
|
|
e21e1326b7 | ||
|
|
37e12b4024 | ||
|
|
e126ee5495 | ||
|
|
a308f3f22a | ||
|
|
c5f4cce3ae | ||
|
|
ced8686d11 | ||
|
|
76f6b725b8 | ||
|
|
f9e1dd4bec | ||
|
|
f4f393e5de | ||
|
|
2db5dda266 | ||
|
|
8cf9c59957 | ||
|
|
088556193d | ||
|
|
18d3ab3d15 | ||
|
|
dc6faa33bb | ||
|
|
0d22ae2c1a | ||
|
|
362d982906 | ||
|
|
1006dd9379 | ||
|
|
369316556a | ||
|
|
cf4b29de4b | ||
|
|
09ca7920ea | ||
|
|
9994e033b2 | ||
|
|
dd56f2b47f | ||
|
|
4df043a91c | ||
|
|
d020de4b3d | ||
|
|
dd42f35db0 | ||
|
|
a67af9455b | ||
|
|
d729c82f84 | ||
|
|
44e218194b | ||
|
|
bf1e37f149 | ||
|
|
aee56c388f | ||
|
|
fd5a10bee7 | ||
|
|
b20e890f15 | ||
|
|
4f9530eec7 | ||
|
|
615b60bd37 | ||
|
|
e61afcd109 | ||
|
|
6ac5446940 | ||
|
|
0706681180 | ||
|
|
e44d70b41d | ||
|
|
4bf810cb8f | ||
|
|
c791db4c52 | ||
|
|
e86f3cc594 | ||
|
|
be6243c446 | ||
|
|
4263ee52f3 | ||
|
|
d6f1c91b9c | ||
|
|
105dc4a249 | ||
|
|
aa80c8d0b2 | ||
|
|
7c9bdfb96e | ||
|
|
84b3c0ad31 | ||
|
|
f2538689e7 | ||
|
|
66eb7735dd | ||
|
|
33edb7ea15 | ||
|
|
f3c9be07c0 | ||
|
|
0c131f11f8 | ||
|
|
dc86c9305c | ||
|
|
36ff99882f | ||
|
|
3ed4b1c132 | ||
|
|
8fad2c5127 | ||
|
|
a25749f087 | ||
|
|
248b1ef947 | ||
|
|
feef4bf508 | ||
|
|
aa70ff13f4 | ||
|
|
8a6c64095d | ||
|
|
ea40ffef06 | ||
|
|
44d9dc7440 | ||
|
|
fedb9812bd | ||
|
|
febbee347b | ||
|
|
a7edbd19ad | ||
|
|
c39b2fe03d | ||
|
|
1e23f94b36 | ||
|
|
106a480dad | ||
|
|
587e6fbd8a | ||
|
|
dc2275099a | ||
|
|
bcb9175aa8 | ||
|
|
dd71de9aa1 | ||
|
|
1c4fe6e406 | ||
|
|
697757ba8e | ||
|
|
774df36f41 | ||
|
|
a092b68f61 | ||
|
|
2587b0a8ad | ||
|
|
ff0e849730 | ||
|
|
c25d30ae88 | ||
|
|
51bc70a11b | ||
|
|
d26e54fd89 | ||
|
|
fc6bcc2f5b | ||
|
|
96f0ea2311 | ||
|
|
261f4a4e5b | ||
|
|
f1e933e7aa | ||
|
|
590f001f17 | ||
|
|
88e17c8f86 | ||
|
|
009470883e | ||
|
|
99ad89211a |
36
.github/ISSUE_TEMPLATE/add_new_k8s_version.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/add_new_k8s_version.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Add new K8s version
|
||||
about: 'Checklist for maintainers to add new K8s minor version'
|
||||
title: 'Add new K8s version vX.X'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Note: Please update the issue title to include the new Kubernetes version number. -->
|
||||
|
||||
# Adding a new Kubernetes Version
|
||||
|
||||
## `pinniped's ci branch`
|
||||
|
||||
- [ ] Update `dockerfile-builders` pipeline
|
||||
- [ ] Update `pull-requests` pipeline
|
||||
- [ ] Update `main` pipeline
|
||||
|
||||
## `pinniped`
|
||||
|
||||
- [ ] Bump all golang dependencies (especially the `k8s.io` dependencies to use the new minor version).
|
||||
- [ ] Be sure to verify that everything compiles and unit tests pass locally. This is probably a good starting point.
|
||||
```shell
|
||||
./hack/update-go-mod/update-go-mod.sh
|
||||
./hack/module.sh unit
|
||||
./hack/prepare-for-integration-tests.sh
|
||||
```
|
||||
- [ ] Log in to github as pinniped-ci-bot, then go to [this page](https://github.com/pinniped-ci-bot?tab=packages) and change the settings for the new `k8s-code-generator-1.*` image to be publicly visible
|
||||
- [ ] Add the new K8s version to `hack/lib/kube-versions.txt` and run code generation.
|
||||
|
||||
## General Tasks
|
||||
|
||||
- [ ] Consider dropping support for any older versions of Kubernetes
|
||||
- [ ] Create stories or chores to take advantage of features in the new Kubernetes version
|
||||
- [ ] Close this issue
|
||||
31
.github/ISSUE_TEMPLATE/release_checklist.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/release_checklist.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Release checklist
|
||||
about: Checklist for maintainers to prepare for an upcoming release
|
||||
title: 'Release checklist for vX.X.X'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Note: Please update the issue title to include the planned release's version number. -->
|
||||
|
||||
# Release checklist
|
||||
|
||||
- [ ] Ensure that Pinniped's dependencies have been upgraded, to the extent desired by the team (refer to the diff output from the latest run of the [all-golang-deps-updated](https://ci.pinniped.dev/teams/main/pipelines/security-scan/jobs/all-golang-deps-updated/) CI job)
|
||||
- [ ] If you are updating golang in Pinniped, be sure to update golang in CI as well. Do a search-and-replace to update the version number everywhere in the pinniped `ci` branch.
|
||||
- [ ] If the Fosite library is being updated and the format of the content of the Supervisor's storage Secrets are changed, or if any change to our own code changes the format of the content of the Supervisor's session storage Secrets, then be sure to update the `accessTokenStorageVersion`, `authorizeCodeStorageVersion`, `oidcStorageVersion`, `pkceStorageVersion`, `refreshTokenStorageVersion`, variables in files such as `internal/fositestorage/accesstoken/accesstoken.go`. Failing tests should signal the need to update these values.
|
||||
- [ ] For go.mod direct dependencies that are v2 or above, such as `github.com/google/go-github/vXX`, check to see if there is a new major version available. Try using `hack/update-go-mod/update-majors.sh`.
|
||||
- [ ] Evaluate all `replace` directives in the `go.mod` file. Are they up to date versions? Can any `replace` directives be removed?
|
||||
- [ ] Ensure that Pinniped's codegen is up-to-date with the latest Kubernetes releases by making sure this [file](https://github.com/vmware-tanzu/pinniped/blob/main/hack/lib/kube-versions.txt) is updated compared to the latest releases listed [here for active branches](https://kubernetes.io/releases/) and [here for non-active branches](https://kubernetes.io/releases/patch-releases/#non-active-branch-history)
|
||||
- [ ] Ensure that the `k8s-code-generator` CI job definitions are up-to-date with the latest Go, K8s, and `controller-gen` versions
|
||||
- [ ] All relevant feature and docs PRs are merged
|
||||
- [ ] The [main pipeline](https://ci.pinniped.dev/teams/main/pipelines/main) is green, up to and including the `ready-to-release` job. Check that the expected git commit has passed the `ready-to-release` job.
|
||||
- [ ] Optional: a blog post for the release is written and submitted as a PR but not merged yet
|
||||
- [ ] All merged user stories are accepted (manually tested)
|
||||
- [ ] Only after all stories are accepted, manually trigger the `release` job to create a draft GitHub release
|
||||
- [ ] Manually edit the draft release notes on the [GitHub release](https://github.com/vmware-tanzu/pinniped/releases) to describe the contents of the release, using the format which was automatically added to the draft release
|
||||
- [ ] Publish (i.e. make public) the draft release
|
||||
- [ ] After making the release public, the jobs in the [main pipeline](https://ci.pinniped.dev/teams/main/pipelines/main) beyond the release job should auto-trigger, so check to make sure that they passed
|
||||
- [ ] Edit the blog post's date to make it match the actual release date, and merge the blog post PR to make it live on the website
|
||||
- [ ] Publicize the release via tweets, etc.
|
||||
- [ ] Close this issue
|
||||
103
.github/dependabot.yml
vendored
103
.github/dependabot.yml
vendored
@@ -40,3 +40,106 @@ updates:
|
||||
# directory: "/hack" # this should keep the FIPS dockerfile updated per https://github.com/dependabot/feedback/issues/145#issuecomment-414738498
|
||||
# schedule:
|
||||
# interval: "daily"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/code-coverage-uploader/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/crane/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/deployment-yaml-formatter/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/eks-deployer/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/gh-cli/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/go-lint-runner/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/integration-test-runner/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/integration-test-runner-beta/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/k8s-app-deployer/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/k8s-code-generator/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/pool-trigger-resource/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/test-bitnami-ldap/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/test-cfssl/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/test-dex/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/test-forward-proxy/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/dockerfiles/test-kubectl/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/pipelines/shared-helpers/test-binaries-image/"
|
||||
open-pull-requests-limit: 100
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: ci
|
||||
|
||||
@@ -184,6 +184,11 @@ the progress and results will appear on the Github page for that
|
||||
[pull request](https://github.com/vmware-tanzu/pinniped/pulls) as checks. Links
|
||||
will appear to view the details of each check.
|
||||
|
||||
## CI
|
||||
|
||||
Pinniped's CI configuration and code is in the [`ci`](https://github.com/vmware-tanzu/pinniped/tree/ci)
|
||||
branch of this repo. The CI results are visible to the public at https://ci.pinniped.dev.
|
||||
|
||||
## Documentation
|
||||
|
||||
Any pull request which adds a new feature or changes the behavior of any feature which was previously documented
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -3,11 +3,11 @@
|
||||
# Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
ARG BUILD_IMAGE=golang:1.23.2@sha256:a7f2fc9834049c1f5df787690026a53738e55fc097cd8a4a93faa3e06c67ee32
|
||||
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:26f9b99f2463f55f20db19feb4d96eb88b056e0f1be7016bb9296a464a89d772
|
||||
ARG BUILD_IMAGE=golang:1.23.6@sha256:927112936d6b496ed95f55f362cc09da6e3e624ef868814c56d55bd7323e0959
|
||||
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:6ec5aa99dc335666e79dc64e4a6c8b89c33a543a1967f20d360922a80dd21f02
|
||||
|
||||
# Prepare to cross-compile by always running the build stage in the build platform, not the target platform.
|
||||
FROM --platform=$BUILDPLATFORM $BUILD_IMAGE as build-env
|
||||
FROM --platform=$BUILDPLATFORM $BUILD_IMAGE AS build-env
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
@@ -21,6 +21,9 @@ ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
# If provided, must be a comma-separated list of Go build tags.
|
||||
ARG ADDITIONAL_BUILD_TAGS
|
||||
|
||||
# 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/
|
||||
@@ -29,8 +32,8 @@ RUN \
|
||||
--mount=type=cache,target=/cache/gocache \
|
||||
--mount=type=cache,target=/cache/gomodcache \
|
||||
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH && \
|
||||
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 -tags $ADDITIONAL_BUILD_TAGS -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 -tags $ADDITIONAL_BUILD_TAGS -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-supervisor && \
|
||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
46
cmd/pinniped/cmd/audit_id.go
Normal file
46
cmd/pinniped/cmd/audit_id.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go.pinniped.dev/internal/httputil/roundtripper"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
type auditIDLoggerFunc func(path string, statusCode int, auditID string)
|
||||
|
||||
func logAuditID(path string, statusCode int, auditID string) {
|
||||
plog.Info("Received auditID for failed request",
|
||||
"path", path,
|
||||
"statusCode", statusCode,
|
||||
"auditID", auditID)
|
||||
}
|
||||
|
||||
func LogAuditIDTransportWrapper(rt http.RoundTripper) http.RoundTripper {
|
||||
return logAuditIDTransportWrapper(rt, logAuditID)
|
||||
}
|
||||
|
||||
func logAuditIDTransportWrapper(rt http.RoundTripper, auditIDLoggerFunc auditIDLoggerFunc) http.RoundTripper {
|
||||
return roundtripper.WrapFunc(rt, func(r *http.Request) (*http.Response, error) {
|
||||
response, responseErr := rt.RoundTrip(r)
|
||||
|
||||
if responseErr != nil ||
|
||||
response == nil ||
|
||||
response.Header.Get("audit-ID") == "" ||
|
||||
response.Request == nil ||
|
||||
response.Request.URL == nil {
|
||||
return response, responseErr
|
||||
}
|
||||
|
||||
// Use the request path from the response's request, in case the
|
||||
// original request was modified by any other roudtrippers in the chain.
|
||||
auditIDLoggerFunc(response.Request.URL.Path,
|
||||
response.StatusCode,
|
||||
response.Header.Get("audit-ID"))
|
||||
|
||||
return response, responseErr
|
||||
})
|
||||
}
|
||||
116
cmd/pinniped/cmd/audit_id_test.go
Normal file
116
cmd/pinniped/cmd/audit_id_test.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/httputil/roundtripper"
|
||||
)
|
||||
|
||||
func TestLogAuditIDTransportWrapper(t *testing.T) {
|
||||
canonicalAuditIdHeaderName := "Audit-Id"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
response *http.Response
|
||||
responseErr error
|
||||
want func(t *testing.T, called func()) auditIDLoggerFunc
|
||||
wantCalled bool
|
||||
}{
|
||||
{
|
||||
name: "happy HTTP response - no error and no log",
|
||||
response: &http.Response{ // no headers
|
||||
StatusCode: http.StatusOK,
|
||||
Request: &http.Request{
|
||||
URL: &url.URL{
|
||||
Path: "some-path-from-response-request",
|
||||
},
|
||||
},
|
||||
},
|
||||
responseErr: nil,
|
||||
want: func(t *testing.T, called func()) auditIDLoggerFunc {
|
||||
return func(_ string, _ int, _ string) {
|
||||
called()
|
||||
}
|
||||
},
|
||||
wantCalled: false, // make it obvious
|
||||
},
|
||||
{
|
||||
name: "nil HTTP response - no error and no log",
|
||||
response: nil,
|
||||
responseErr: nil,
|
||||
want: func(t *testing.T, called func()) auditIDLoggerFunc {
|
||||
return func(_ string, _ int, _ string) {
|
||||
called()
|
||||
}
|
||||
},
|
||||
wantCalled: false, // make it obvious
|
||||
},
|
||||
{
|
||||
name: "err HTTP response - no error and no log",
|
||||
response: nil,
|
||||
responseErr: errors.New("some error"),
|
||||
want: func(t *testing.T, called func()) auditIDLoggerFunc {
|
||||
return func(_ string, _ int, _ string) {
|
||||
called()
|
||||
}
|
||||
},
|
||||
wantCalled: false, // make it obvious
|
||||
},
|
||||
{
|
||||
name: "happy HTTP response with audit-ID - logs",
|
||||
response: &http.Response{
|
||||
Header: http.Header{
|
||||
canonicalAuditIdHeaderName: []string{"some-audit-id", "some-other-audit-id-that-will-never-be-seen"},
|
||||
},
|
||||
StatusCode: http.StatusBadGateway, // statusCode does not matter
|
||||
Request: &http.Request{
|
||||
URL: &url.URL{
|
||||
Path: "some-path-from-response-request",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: func(t *testing.T, called func()) auditIDLoggerFunc {
|
||||
return func(path string, statusCode int, auditID string) {
|
||||
called()
|
||||
require.Equal(t, "some-path-from-response-request", path)
|
||||
require.Equal(t, http.StatusBadGateway, statusCode)
|
||||
require.Equal(t, "some-audit-id", auditID)
|
||||
}
|
||||
},
|
||||
wantCalled: true, // make it obvious
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
require.NotNil(t, test.want)
|
||||
|
||||
mockRequest := &http.Request{
|
||||
URL: &url.URL{
|
||||
Path: "should-never-use-this-path",
|
||||
},
|
||||
}
|
||||
var mockRt roundtripper.Func = func(r *http.Request) (*http.Response, error) {
|
||||
require.Equal(t, mockRequest, r)
|
||||
return test.response, test.responseErr
|
||||
}
|
||||
called := false
|
||||
subjectRt := logAuditIDTransportWrapper(mockRt, test.want(t, func() {
|
||||
called = true
|
||||
}))
|
||||
actualResponse, err := subjectRt.RoundTrip(mockRequest) //nolint:bodyclose // there is no Body.
|
||||
require.Equal(t, test.responseErr, err) // This roundtripper only returns mocked errors.
|
||||
require.Equal(t, test.response, actualResponse)
|
||||
require.Equal(t, test.wantCalled, called,
|
||||
"want logFunc to be called: %t, actually was called: %t", test.wantCalled, called)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,36 @@
|
||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/kubeclient"
|
||||
)
|
||||
|
||||
// getConciergeClientsetFunc is a function that can return a clientset for the Concierge API given a
|
||||
// getClientsetsFunc is a function that can return clients for the Concierge and Kubernetes APIs given a
|
||||
// clientConfig and the apiGroupSuffix with which the API is running.
|
||||
type getConciergeClientsetFunc func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error)
|
||||
type getClientsetsFunc func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error)
|
||||
|
||||
// getRealConciergeClientset returns a real implementation of a conciergeclientset.Interface.
|
||||
func getRealConciergeClientset(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
|
||||
// getRealClientsets returns real implementations of the Concierge and Kubernetes client interfaces.
|
||||
func getRealClientsets(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
|
||||
restConfig, err := clientConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
client, err := kubeclient.New(
|
||||
kubeclient.WithConfig(restConfig),
|
||||
kubeclient.WithMiddleware(groupsuffix.New(apiGroupSuffix)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return client.PinnipedConcierge, nil
|
||||
return client.PinnipedConcierge, client.Kubernetes, client.Aggregation, nil
|
||||
}
|
||||
|
||||
// newClientConfig returns a clientcmd.ClientConfig given an optional kubeconfig path override and
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -20,10 +20,12 @@ import (
|
||||
coreosoidc "github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
conciergeconfigv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
@@ -38,7 +40,7 @@ import (
|
||||
type kubeconfigDeps struct {
|
||||
getenv func(key string) string
|
||||
getPathToSelf func() (string, error)
|
||||
getClientset getConciergeClientsetFunc
|
||||
getClientsets getClientsetsFunc
|
||||
log plog.MinLogger
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@ func kubeconfigRealDeps() kubeconfigDeps {
|
||||
return kubeconfigDeps{
|
||||
getenv: os.Getenv,
|
||||
getPathToSelf: os.Executable,
|
||||
getClientset: getRealConciergeClientset,
|
||||
getClientsets: getRealClientsets,
|
||||
log: plog.New(),
|
||||
}
|
||||
}
|
||||
@@ -215,7 +217,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
return fmt.Errorf("could not load --kubeconfig/--kubeconfig-context: %w", err)
|
||||
}
|
||||
cluster := currentKubeConfig.Clusters[currentKubeconfigNames.ClusterName]
|
||||
clientset, err := deps.getClientset(clientConfig, flags.concierge.apiGroupSuffix)
|
||||
conciergeClient, kubeClient, aggregatorClient, err := deps.getClientsets(clientConfig, flags.concierge.apiGroupSuffix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not configure Kubernetes client: %w", err)
|
||||
}
|
||||
@@ -228,13 +230,15 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
}
|
||||
|
||||
if !flags.concierge.disabled {
|
||||
credentialIssuer, err := waitForCredentialIssuer(ctx, clientset, flags, deps)
|
||||
// Look up the Concierge's CredentialIssuer, and optionally wait for it to have no pending strategies showing in its status.
|
||||
credentialIssuer, err := waitForCredentialIssuer(ctx, conciergeClient, flags, deps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Decide which Concierge authenticator should be used in the resulting kubeconfig.
|
||||
authenticator, err := lookupAuthenticator(
|
||||
clientset,
|
||||
conciergeClient,
|
||||
flags.concierge.authenticatorType,
|
||||
flags.concierge.authenticatorName,
|
||||
deps.log,
|
||||
@@ -242,10 +246,15 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Discover from the CredentialIssuer how the resulting kubeconfig should be configured to talk to this Concierge.
|
||||
if err := discoverConciergeParams(credentialIssuer, &flags, cluster, deps.log); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := discoverAuthenticatorParams(authenticator, &flags, deps.log); err != nil {
|
||||
|
||||
// Discover how the resulting kubeconfig should interact with the selected authenticator.
|
||||
// For a JWTAuthenticator, this includes discovering how to talk to the OIDC issuer configured in its spec fields.
|
||||
if err := discoverAuthenticatorParams(ctx, authenticator, &flags, kubeClient, aggregatorClient, deps.log); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -255,6 +264,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
}
|
||||
|
||||
if len(flags.oidc.issuer) > 0 {
|
||||
// The OIDC provider may or may not be a Pinniped Supervisor. Find out.
|
||||
err = pinnipedSupervisorDiscovery(ctx, &flags, deps.log)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -488,7 +498,14 @@ func logStrategies(credentialIssuer *conciergeconfigv1alpha1.CredentialIssuer, l
|
||||
}
|
||||
}
|
||||
|
||||
func discoverAuthenticatorParams(authenticator metav1.Object, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
func discoverAuthenticatorParams(
|
||||
ctx context.Context,
|
||||
authenticator metav1.Object,
|
||||
flags *getKubeconfigParams,
|
||||
kubeClient kubernetes.Interface,
|
||||
aggregatorClient aggregatorclient.Interface,
|
||||
log plog.MinLogger,
|
||||
) error {
|
||||
switch auth := authenticator.(type) {
|
||||
case *authenticationv1alpha1.WebhookAuthenticator:
|
||||
// If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set
|
||||
@@ -520,19 +537,130 @@ func discoverAuthenticatorParams(authenticator metav1.Object, flags *getKubeconf
|
||||
}
|
||||
|
||||
// If the --oidc-ca-bundle flags was not set explicitly, default it to the
|
||||
// spec.tls.certificateAuthorityData field of the JWTAuthenticator.
|
||||
if len(flags.oidc.caBundle) == 0 && auth.Spec.TLS != nil && auth.Spec.TLS.CertificateAuthorityData != "" {
|
||||
decoded, err := base64.StdEncoding.DecodeString(auth.Spec.TLS.CertificateAuthorityData)
|
||||
// spec.tls.certificateAuthorityData field of the JWTAuthenticator, if that field is set, or else
|
||||
// try to discover it from the spec.tls.certificateAuthorityDataSource, if that field is set.
|
||||
if len(flags.oidc.caBundle) == 0 && auth.Spec.TLS != nil {
|
||||
err := discoverOIDCCABundle(ctx, auth, flags, kubeClient, aggregatorClient, log)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", auth.Name, err)
|
||||
return err
|
||||
}
|
||||
log.Info("discovered OIDC CA bundle", "roots", countCACerts(decoded))
|
||||
flags.oidc.caBundle = decoded
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func discoverOIDCCABundle(
|
||||
ctx context.Context,
|
||||
jwtAuthenticator *authenticationv1alpha1.JWTAuthenticator,
|
||||
flags *getKubeconfigParams,
|
||||
kubeClient kubernetes.Interface,
|
||||
aggregatorClient aggregatorclient.Interface,
|
||||
log plog.MinLogger,
|
||||
) error {
|
||||
if jwtAuthenticator.Spec.TLS.CertificateAuthorityData != "" {
|
||||
decodedCABundleData, err := base64.StdEncoding.DecodeString(jwtAuthenticator.Spec.TLS.CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", jwtAuthenticator.Name, err)
|
||||
}
|
||||
log.Info("discovered OIDC CA bundle", "roots", countCACerts(decodedCABundleData))
|
||||
flags.oidc.caBundle = decodedCABundleData
|
||||
} else if jwtAuthenticator.Spec.TLS.CertificateAuthorityDataSource != nil {
|
||||
caBundleData, err := discoverOIDCCABundleFromCertificateAuthorityDataSource(
|
||||
ctx, jwtAuthenticator, flags.concierge.apiGroupSuffix, kubeClient, aggregatorClient, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flags.oidc.caBundle = caBundleData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func discoverOIDCCABundleFromCertificateAuthorityDataSource(
|
||||
ctx context.Context,
|
||||
jwtAuthenticator *authenticationv1alpha1.JWTAuthenticator,
|
||||
apiGroupSuffix string,
|
||||
kubeClient kubernetes.Interface,
|
||||
aggregatorClient aggregatorclient.Interface,
|
||||
log plog.MinLogger,
|
||||
) ([]byte, error) {
|
||||
conciergeNamespace, err := discoverConciergeNamespace(ctx, apiGroupSuffix, aggregatorClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator %s: %w", jwtAuthenticator.Name, err)
|
||||
}
|
||||
log.Info("discovered Concierge namespace for API group suffix", "apiGroupSuffix", apiGroupSuffix)
|
||||
|
||||
var caBundleData []byte
|
||||
var keyExisted bool
|
||||
caSource := jwtAuthenticator.Spec.TLS.CertificateAuthorityDataSource
|
||||
|
||||
// Note that the Kind, Name, and Key fields must all be non-empty, and Kind must be Secret or ConfigMap, due to CRD validations.
|
||||
switch caSource.Kind {
|
||||
case authenticationv1alpha1.CertificateAuthorityDataSourceKindConfigMap:
|
||||
caBundleConfigMap, err := kubeClient.CoreV1().ConfigMaps(conciergeNamespace).Get(ctx, caSource.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error getting %s %s/%s specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource: %w",
|
||||
caSource.Kind, conciergeNamespace, caSource.Name, jwtAuthenticator.Name, err)
|
||||
}
|
||||
var caBundleDataStr string
|
||||
caBundleDataStr, keyExisted = caBundleConfigMap.Data[caSource.Key]
|
||||
caBundleData = []byte(caBundleDataStr)
|
||||
case authenticationv1alpha1.CertificateAuthorityDataSourceKindSecret:
|
||||
caBundleSecret, err := kubeClient.CoreV1().Secrets(conciergeNamespace).Get(ctx, caSource.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but encountered error getting %s %s/%s specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource: %w",
|
||||
caSource.Kind, conciergeNamespace, caSource.Name, jwtAuthenticator.Name, err)
|
||||
}
|
||||
caBundleData, keyExisted = caBundleSecret.Data[caSource.Key]
|
||||
default:
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.Kind value %q is not supported by this CLI version",
|
||||
jwtAuthenticator.Name, caSource.Kind)
|
||||
}
|
||||
|
||||
if !keyExisted {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key does not exist in %s %s/%s",
|
||||
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
|
||||
}
|
||||
|
||||
if len(caBundleData) == 0 {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key exists but has empty value in %s %s/%s",
|
||||
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
|
||||
}
|
||||
|
||||
numCACerts := countCACerts(caBundleData)
|
||||
if numCACerts == 0 {
|
||||
return nil, fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but value at key %q specified by JWTAuthenticator %s spec.tls.certificateAuthorityDataSource.key does not contain any CA certificates in %s %s/%s",
|
||||
caSource.Key, jwtAuthenticator.Name, caSource.Kind, conciergeNamespace, caSource.Name)
|
||||
}
|
||||
|
||||
log.Info("discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource", "roots", numCACerts)
|
||||
return caBundleData, nil
|
||||
}
|
||||
|
||||
func discoverConciergeNamespace(ctx context.Context, apiGroupSuffix string, aggregatorClient aggregatorclient.Interface) (string, error) {
|
||||
// Let's look for the APIService for the API group of the Concierge's TokenCredentialRequest aggregated API.
|
||||
apiGroup := "login.concierge." + apiGroupSuffix
|
||||
|
||||
// List all APIServices.
|
||||
apiServiceList, err := aggregatorClient.ApiregistrationV1().APIServices().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error listing APIServices: %w", err)
|
||||
}
|
||||
|
||||
// Find one with the expected API group name.
|
||||
for _, apiService := range apiServiceList.Items {
|
||||
if apiService.Spec.Group == apiGroup {
|
||||
if apiService.Spec.Service.Namespace != "" {
|
||||
// We are assuming that all API versions (e.g. v1alpha1) of this API group are backed by service(s)
|
||||
// in the same namespace, which is the namespace of the Concierge hosting this API suffix.
|
||||
return apiService.Spec.Service.Namespace, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find any APIService for the expected API group name which contained a namespace reference in its spec.
|
||||
return "", fmt.Errorf("could not find APIService with non-empty spec.service.namespace for API group %s", apiGroup)
|
||||
}
|
||||
|
||||
func getConciergeFrontend(credentialIssuer *conciergeconfigv1alpha1.CredentialIssuer, mode conciergeModeFlag) (*conciergeconfigv1alpha1.CredentialIssuerFrontend, error) {
|
||||
for _, strategy := range credentialIssuer.Status.Strategies {
|
||||
// Skip unhealthy strategies.
|
||||
@@ -540,26 +668,15 @@ func getConciergeFrontend(credentialIssuer *conciergeconfigv1alpha1.CredentialIs
|
||||
continue
|
||||
}
|
||||
|
||||
// Backfill the .status.strategies[].frontend field from .status.kubeConfigInfo for backwards compatibility.
|
||||
if strategy.Type == conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType && strategy.Frontend == nil && credentialIssuer.Status.KubeConfigInfo != nil {
|
||||
strategy = *strategy.DeepCopy()
|
||||
strategy.Frontend = &conciergeconfigv1alpha1.CredentialIssuerFrontend{
|
||||
Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||
TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{
|
||||
Server: credentialIssuer.Status.KubeConfigInfo.Server,
|
||||
CertificateAuthorityData: credentialIssuer.Status.KubeConfigInfo.CertificateAuthorityData,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// If the strategy frontend is still nil, skip.
|
||||
// If the strategy frontend is nil, skip.
|
||||
if strategy.Frontend == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip any unknown frontend types.
|
||||
switch strategy.Frontend.Type {
|
||||
case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, conciergeconfigv1alpha1.ImpersonationProxyFrontendType:
|
||||
case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||
conciergeconfigv1alpha1.ImpersonationProxyFrontendType:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -11,15 +11,20 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
aggregatorfake "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
@@ -65,14 +70,69 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
jwtAuthenticator := func(issuerCABundle string, issuerURL string) runtime.Object {
|
||||
caBundleInSecret := func(issuerCABundle, secretName, secretNamespace, secretDataKey string) runtime.Object {
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secretName,
|
||||
Namespace: secretNamespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
secretDataKey: []byte(issuerCABundle),
|
||||
"other": []byte("unrelated"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
caBundleInConfigmap := func(issuerCABundle, cmName, cmNamespace, cmDataKey string) runtime.Object {
|
||||
return &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: cmName,
|
||||
Namespace: cmNamespace,
|
||||
},
|
||||
Data: map[string]string{
|
||||
cmDataKey: issuerCABundle,
|
||||
"other": "unrelated",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
jwtAuthenticator := func(issuerCABundle, issuerURL string) *authenticationv1alpha1.JWTAuthenticator {
|
||||
encodedCABundle := ""
|
||||
if issuerCABundle != "" {
|
||||
encodedCABundle = base64.StdEncoding.EncodeToString([]byte(issuerCABundle))
|
||||
}
|
||||
return &authenticationv1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
||||
Spec: authenticationv1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: issuerURL,
|
||||
Audience: "test-audience",
|
||||
TLS: &authenticationv1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(issuerCABundle)),
|
||||
CertificateAuthorityData: encodedCABundle,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
jwtAuthenticatorWithCABundleDataSource := func(sourceKind, sourceName, sourceKey, issuerURL string) runtime.Object {
|
||||
authenticator := jwtAuthenticator("", issuerURL)
|
||||
authenticator.Spec.TLS.CertificateAuthorityDataSource = &authenticationv1alpha1.CertificateAuthorityDataSourceSpec{
|
||||
Kind: authenticationv1alpha1.CertificateAuthorityDataSourceKind(sourceKind),
|
||||
Name: sourceName,
|
||||
Key: sourceKey,
|
||||
}
|
||||
return authenticator
|
||||
}
|
||||
|
||||
apiService := func(group, version, serviceNamespace string) *v1.APIService {
|
||||
return &v1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: version + "." + group,
|
||||
},
|
||||
Spec: v1.APIServiceSpec{
|
||||
Group: group,
|
||||
Version: version,
|
||||
Service: &v1.ServiceReference{
|
||||
Namespace: serviceNamespace,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -145,7 +205,11 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
getPathToSelfErr error
|
||||
getClientsetErr error
|
||||
conciergeObjects func(string, string) []runtime.Object
|
||||
kubeObjects func(string) []runtime.Object
|
||||
apiServiceObjects []runtime.Object
|
||||
conciergeReactions []kubetesting.Reactor
|
||||
kubeReactions []kubetesting.Reactor
|
||||
apiServiceReactions []kubetesting.Reactor
|
||||
oidcDiscoveryResponse func(string) string
|
||||
oidcDiscoveryStatusCode int
|
||||
idpsDiscoveryResponse string
|
||||
@@ -614,18 +678,18 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
&conciergeconfigv1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||
Status: conciergeconfigv1alpha1.CredentialIssuerStatus{
|
||||
KubeConfigInfo: &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{
|
||||
Server: "https://concierge-endpoint",
|
||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
||||
},
|
||||
Strategies: []conciergeconfigv1alpha1.CredentialIssuerStrategy{{
|
||||
Type: conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||
Status: conciergeconfigv1alpha1.SuccessStrategyStatus,
|
||||
Reason: conciergeconfigv1alpha1.FetchedKeyStrategyReason,
|
||||
Message: "Successfully fetched key",
|
||||
LastUpdateTime: metav1.Now(),
|
||||
// Simulate a previous version of CredentialIssuer that's missing this Frontend field.
|
||||
Frontend: nil,
|
||||
Frontend: &conciergeconfigv1alpha1.CredentialIssuerFrontend{
|
||||
Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||
TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{
|
||||
Server: "https://concierge-endpoint.example.com",
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -657,6 +721,321 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator has invalid spec.tls.certificateAuthorityData: illegal base64 data at input byte 7` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but Secret not found",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error getting Secret test-concierge-namespace/my-ca-secret specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource: secrets "my-ca-secret" not found` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in ConfigMap, but ConfigMap not found",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error getting ConfigMap test-concierge-namespace/my-ca-configmap specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource: configmaps "my-ca-configmap" not found` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but invalid TLS bundle found in Secret",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInSecret("invalid CA bundle data", "my-ca-secret", "test-concierge-namespace", "ca.crt"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but value at key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key does not contain any CA certificates in Secret test-concierge-namespace/my-ca-secret` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but specified key not found in Secret",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInSecret(issuerCABundle, "my-ca-secret", "test-concierge-namespace", "wrong_key_name"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key does not exist in Secret test-concierge-namespace/my-ca-secret` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but specified key has empty value in Secret",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInSecret("", "my-ca-secret", "test-concierge-namespace", "ca.crt"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but key "ca.crt" specified by JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.key exists but has empty value in Secret test-concierge-namespace/my-ca-secret` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle source, but source's Kind is not supported",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Unsupported-Value", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator spec.tls.certificateAuthorityDataSource.Kind value "Unsupported-Value" is not supported by this CLI version` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but no related APIService found",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("unrelated.example.com", "v1alpha1", "test-concierge-namespace"),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: could not find APIService with non-empty spec.service.namespace for API group login.concierge.pinniped.dev` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but related APIService has empty namespace in spec",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", ""),
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: could not find APIService with non-empty spec.service.namespace for API group login.concierge.pinniped.dev` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret, but error when listing APIServices",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
apiServiceReactions: []kubetesting.Reactor{
|
||||
&kubetesting.SimpleReactor{
|
||||
Verb: "*",
|
||||
Resource: "apiservices",
|
||||
Reaction: func(kubetesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("some list error")
|
||||
},
|
||||
},
|
||||
},
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
}
|
||||
},
|
||||
wantError: true,
|
||||
wantStderr: func(issuerCABundle string, issuerURL string) testutil.RequireErrorStringFunc {
|
||||
return testutil.WantExactErrorString(`Error: tried to autodiscover --oidc-ca-bundle, but encountered error discovering namespace of Concierge for JWTAuthenticator test-authenticator: error listing APIServices: some list error` + "\n")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator, invalid substring in audience",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
@@ -1601,6 +1980,257 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in Secret",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--skip-validation",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("Secret", "my-ca-secret", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInSecret(issuerCABundle, "my-ca-secret", "test-concierge-namespace", "ca.crt"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha2", "test-concierge-namespace"),
|
||||
},
|
||||
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
|
||||
}
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in ConfigMap",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--skip-validation",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInConfigmap(issuerCABundle, "my-ca-configmap", "test-concierge-namespace", "ca.crt"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha1", "test-concierge-namespace"),
|
||||
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha2", "test-concierge-namespace"),
|
||||
},
|
||||
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "pinniped.dev"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
|
||||
}
|
||||
},
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=pinniped.dev
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect JWT authenticator with CA bundle in ConfigMap with a custom API group suffix",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||
"--concierge-api-group-suffix=acme.com",
|
||||
"--skip-validation",
|
||||
}
|
||||
},
|
||||
conciergeObjects: func(issuerCABundle string, issuerURL string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
credentialIssuer(),
|
||||
jwtAuthenticatorWithCABundleDataSource("ConfigMap", "my-ca-configmap", "ca.crt", issuerURL),
|
||||
}
|
||||
},
|
||||
kubeObjects: func(issuerCABundle string) []runtime.Object {
|
||||
return []runtime.Object{
|
||||
caBundleInConfigmap(issuerCABundle, "my-ca-configmap", "test-concierge-namespace", "ca.crt"),
|
||||
}
|
||||
},
|
||||
apiServiceObjects: []runtime.Object{
|
||||
apiService("login.concierge.acme.com", "v1alpha1", "test-concierge-namespace"),
|
||||
apiService("unrelated.pinniped.dev", "v1alpha1", "unrelated-namespace"),
|
||||
apiService("login.concierge.pinniped.dev", "v1alpha2", "another-unrelated-namespace"),
|
||||
},
|
||||
oidcDiscoveryResponse: onlyIssuerOIDCDiscoveryResponse,
|
||||
wantLogs: func(issuerCABundle string, issuerURL string) []string {
|
||||
return []string{
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered CredentialIssuer {"name": "test-credential-issuer"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge operating in TokenCredentialRequest API mode`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge endpoint {"endpoint": "https://fake-server-url-value"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge certificate authority bundle {"roots": 0}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered JWTAuthenticator {"name": "test-authenticator"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC issuer {"issuer": "` + issuerURL + `"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC audience {"audience": "test-audience"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered Concierge namespace for API group suffix {"apiGroupSuffix": "acme.com"}`,
|
||||
`2099-08-08T13:57:36.123456Z info cmd/kubeconfig.go:<line> discovered OIDC CA bundle from JWTAuthenticator spec.tls.certificateAuthorityDataSource {"roots": 1}`,
|
||||
}
|
||||
},
|
||||
wantAPIGroupSuffix: "acme.com",
|
||||
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||
return here.Docf(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
server: https://fake-server-url-value
|
||||
name: kind-cluster-pinniped
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kind-cluster-pinniped
|
||||
user: kind-user-pinniped
|
||||
name: kind-context-pinniped
|
||||
current-context: kind-context-pinniped
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kind-user-pinniped
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- login
|
||||
- oidc
|
||||
- --enable-concierge
|
||||
- --concierge-api-group-suffix=acme.com
|
||||
- --concierge-authenticator-name=test-authenticator
|
||||
- --concierge-authenticator-type=jwt
|
||||
- --concierge-endpoint=https://fake-server-url-value
|
||||
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||
- --issuer=%s
|
||||
- --client-id=pinniped-cli
|
||||
- --scopes=offline_access,openid,pinniped:request-audience,username,groups
|
||||
- --ca-bundle-data=%s
|
||||
- --request-audience=test-audience
|
||||
command: '.../path/to/pinniped'
|
||||
env: []
|
||||
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||
for more details
|
||||
provideClusterInfo: true
|
||||
`,
|
||||
issuerURL,
|
||||
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "autodetect nothing, set a bunch of options",
|
||||
args: func(issuerCABundle string, issuerURL string) []string {
|
||||
@@ -3212,6 +3842,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var issuerEndpointPtr *string
|
||||
@@ -3246,6 +3877,37 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
}), nil)
|
||||
issuerEndpointPtr = ptr.To(testServer.URL)
|
||||
|
||||
getClientsetFunc := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
|
||||
if tt.wantAPIGroupSuffix == "" {
|
||||
require.Equal(t, "pinniped.dev", apiGroupSuffix) // "pinniped.dev" = api group suffix default
|
||||
} else {
|
||||
require.Equal(t, tt.wantAPIGroupSuffix, apiGroupSuffix)
|
||||
}
|
||||
if tt.getClientsetErr != nil {
|
||||
return nil, nil, nil, tt.getClientsetErr
|
||||
}
|
||||
fakeAggregatorClient := aggregatorfake.NewSimpleClientset(tt.apiServiceObjects...)
|
||||
fakeKubeClient := fake.NewClientset()
|
||||
if tt.kubeObjects != nil {
|
||||
kubeObjects := tt.kubeObjects(string(testServerCA))
|
||||
fakeKubeClient = fake.NewClientset(kubeObjects...)
|
||||
}
|
||||
fakeConciergeClient := conciergefake.NewSimpleClientset()
|
||||
if tt.conciergeObjects != nil {
|
||||
fakeConciergeClient = conciergefake.NewSimpleClientset(tt.conciergeObjects(string(testServerCA), testServer.URL)...)
|
||||
}
|
||||
if len(tt.conciergeReactions) > 0 {
|
||||
fakeConciergeClient.ReactionChain = slices.Concat(tt.conciergeReactions, fakeConciergeClient.ReactionChain)
|
||||
}
|
||||
if len(tt.kubeReactions) > 0 {
|
||||
fakeKubeClient.ReactionChain = slices.Concat(tt.kubeReactions, fakeKubeClient.ReactionChain)
|
||||
}
|
||||
if len(tt.apiServiceReactions) > 0 {
|
||||
fakeAggregatorClient.ReactionChain = slices.Concat(tt.apiServiceReactions, fakeAggregatorClient.ReactionChain)
|
||||
}
|
||||
return fakeConciergeClient, fakeKubeClient, fakeAggregatorClient, nil
|
||||
}
|
||||
|
||||
var log bytes.Buffer
|
||||
|
||||
cmd := kubeconfigCommand(kubeconfigDeps{
|
||||
@@ -3258,25 +3920,8 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
}
|
||||
return ".../path/to/pinniped", nil
|
||||
},
|
||||
getClientset: func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
|
||||
if tt.wantAPIGroupSuffix == "" {
|
||||
require.Equal(t, "pinniped.dev", apiGroupSuffix) // "pinniped.dev" = api group suffix default
|
||||
} else {
|
||||
require.Equal(t, tt.wantAPIGroupSuffix, apiGroupSuffix)
|
||||
}
|
||||
if tt.getClientsetErr != nil {
|
||||
return nil, tt.getClientsetErr
|
||||
}
|
||||
fake := conciergefake.NewSimpleClientset()
|
||||
if tt.conciergeObjects != nil {
|
||||
fake = conciergefake.NewSimpleClientset(tt.conciergeObjects(string(testServerCA), testServer.URL)...)
|
||||
}
|
||||
if len(tt.conciergeReactions) > 0 {
|
||||
fake.ReactionChain = slices.Concat(tt.conciergeReactions, fake.ReactionChain)
|
||||
}
|
||||
return fake, nil
|
||||
},
|
||||
log: plog.TestConsoleLogger(t, &log),
|
||||
getClientsets: getClientsetFunc,
|
||||
log: plog.TestConsoleLogger(t, &log),
|
||||
})
|
||||
require.NotNil(t, cmd)
|
||||
|
||||
@@ -3293,14 +3938,10 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
var expectedLogs string
|
||||
if tt.wantLogs != nil {
|
||||
temp := tt.wantLogs(string(testServerCA), testServer.URL)
|
||||
if len(temp) > 0 {
|
||||
expectedLogs = strings.Join(tt.wantLogs(string(testServerCA), testServer.URL), "\n") + "\n"
|
||||
}
|
||||
wantLogs := tt.wantLogs(string(testServerCA), testServer.URL)
|
||||
testutil.RequireLogLines(t, wantLogs, &log)
|
||||
}
|
||||
require.Equal(t, expectedLogs, log.String())
|
||||
|
||||
expectedStdout := ""
|
||||
if tt.wantStdout != nil {
|
||||
|
||||
@@ -224,6 +224,7 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
||||
conciergeclient.WithBase64CABundle(flags.conciergeCABundle),
|
||||
conciergeclient.WithAuthenticator(flags.conciergeAuthenticatorType, flags.conciergeAuthenticatorName),
|
||||
conciergeclient.WithAPIGroupSuffix(flags.conciergeAPIGroupSuffix),
|
||||
conciergeclient.WithTransportWrapper(LogAuditIDTransportWrapper),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Concierge parameters: %w", err)
|
||||
|
||||
@@ -274,8 +274,8 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
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",
|
||||
wantLogs: []string{
|
||||
nowStr + ` cmd/login_oidc.go:267 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:287 No concierge configured, skipping token credential exchange`,
|
||||
nowStr + ` cmd/login_oidc.go:268 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:288 No concierge configured, skipping token credential exchange`,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -319,10 +319,10 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantOptionsCount: 12,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
|
||||
wantLogs: []string{
|
||||
nowStr + ` cmd/login_oidc.go:267 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:277 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` cmd/login_oidc.go:285 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` cmd/login_oidc.go:292 caching cluster credential for future use.`,
|
||||
nowStr + ` cmd/login_oidc.go:268 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:278 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` cmd/login_oidc.go:286 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` cmd/login_oidc.go:293 caching cluster credential for future use.`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ func runStaticLogin(cmd *cobra.Command, deps staticLoginDeps, flags staticLoginP
|
||||
conciergeclient.WithBase64CABundle(flags.conciergeCABundle),
|
||||
conciergeclient.WithAuthenticator(flags.conciergeAuthenticatorType, flags.conciergeAuthenticatorName),
|
||||
conciergeclient.WithAPIGroupSuffix(flags.conciergeAPIGroupSuffix),
|
||||
conciergeclient.WithTransportWrapper(LogAuditIDTransportWrapper),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Concierge parameters: %w", err)
|
||||
|
||||
@@ -147,7 +147,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
Error: could not complete Concierge credential exchange: some concierge error
|
||||
`),
|
||||
wantLogs: []string{
|
||||
nowStr + ` 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 + ` cmd/login_static.go:160 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -25,14 +25,14 @@ import (
|
||||
)
|
||||
|
||||
type whoamiDeps struct {
|
||||
getenv func(key string) string
|
||||
getClientset getConciergeClientsetFunc
|
||||
getenv func(key string) string
|
||||
getClientsets getClientsetsFunc
|
||||
}
|
||||
|
||||
func whoamiRealDeps() whoamiDeps {
|
||||
return whoamiDeps{
|
||||
getenv: os.Getenv,
|
||||
getClientset: getRealConciergeClientset,
|
||||
getenv: os.Getenv,
|
||||
getClientsets: getRealClientsets,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func newWhoamiCommand(deps whoamiDeps) *cobra.Command {
|
||||
|
||||
func runWhoami(output io.Writer, deps whoamiDeps, flags *whoamiFlags) error {
|
||||
clientConfig := newClientConfig(flags.kubeconfigPath, flags.kubeconfigContextOverride)
|
||||
clientset, err := deps.getClientset(clientConfig, flags.apiGroupSuffix)
|
||||
conciergeClient, _, _, err := deps.getClientsets(clientConfig, flags.apiGroupSuffix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not configure Kubernetes client: %w", err)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func runWhoami(output io.Writer, deps whoamiDeps, flags *whoamiFlags) error {
|
||||
defer cancelFunc()
|
||||
}
|
||||
|
||||
whoAmI, err := clientset.IdentityV1alpha1().WhoAmIRequests().Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||
whoAmI, err := conciergeClient.IdentityV1alpha1().WhoAmIRequests().Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
hint := ""
|
||||
if apierrors.IsNotFound(err) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2023-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -11,8 +11,10 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
|
||||
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
@@ -290,14 +292,15 @@ func TestWhoami(t *testing.T) {
|
||||
wantStderr: "Error: could not complete WhoAmIRequest (is the Pinniped WhoAmI API running and healthy?): whoamirequests.identity.concierge.pinniped.dev \"whatever\" not found\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
getClientset := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) {
|
||||
getClientsetFunc := func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, kubernetes.Interface, aggregatorclient.Interface, error) {
|
||||
if test.gettingClientsetErr != nil {
|
||||
return nil, test.gettingClientsetErr
|
||||
return nil, nil, nil, test.gettingClientsetErr
|
||||
}
|
||||
clientset := conciergefake.NewSimpleClientset()
|
||||
clientset.PrependReactor("create", "whoamirequests", func(_ kubetesting.Action) (bool, runtime.Object, error) {
|
||||
conciergeClient := conciergefake.NewSimpleClientset()
|
||||
conciergeClient.PrependReactor("create", "whoamirequests", func(_ kubetesting.Action) (bool, runtime.Object, error) {
|
||||
if test.callingAPIErr != nil {
|
||||
return true, nil, test.callingAPIErr
|
||||
}
|
||||
@@ -316,13 +319,14 @@ func TestWhoami(t *testing.T) {
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
return clientset, nil
|
||||
return conciergeClient, nil, nil, nil
|
||||
}
|
||||
|
||||
cmd := newWhoamiCommand(whoamiDeps{
|
||||
getenv: func(key string) string {
|
||||
return test.env[key]
|
||||
},
|
||||
getClientset: getClientset,
|
||||
getClientsets: getClientsetFunc,
|
||||
})
|
||||
|
||||
stdout, stderr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -103,6 +103,8 @@ data:
|
||||
tls:
|
||||
onedottwo:
|
||||
allowedCiphers: (@= str(data.values.allowed_ciphers_for_tls_onedottwo) @)
|
||||
audit:
|
||||
logUsernamesAndGroups: (@= data.values.audit.log_usernames_and_groups @)
|
||||
---
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
apiVersion: v1
|
||||
|
||||
@@ -231,3 +231,15 @@ no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.
|
||||
#! An empty array is perfectly valid, as is any array of strings.
|
||||
allowed_ciphers_for_tls_onedottwo:
|
||||
- ""
|
||||
|
||||
#@schema/title "Audit logging configuration"
|
||||
#@schema/desc "Customize the content of audit log events."
|
||||
audit:
|
||||
|
||||
#@schema/title "Log usernames and groups"
|
||||
#@ log_usernames_and_groups_desc = "Enables or disables printing usernames and group names in audit logs. Options are 'enabled' or 'disabled'. \
|
||||
#@ If enabled, usernames are group names may be printed in audit log events. \
|
||||
#@ If disabled, usernames and group names will be redacted from audit logs because they might contain personally identifiable information."
|
||||
#@schema/desc log_usernames_and_groups_desc
|
||||
#@schema/validation one_of=["enabled", "disabled"]
|
||||
log_usernames_and_groups: disabled
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
@@ -57,6 +57,10 @@ _: #@ template.replace(data.values.custom_labels)
|
||||
#@ "onedottwo": {
|
||||
#@ "allowedCiphers": data.values.allowed_ciphers_for_tls_onedottwo
|
||||
#@ }
|
||||
#@ },
|
||||
#@ "audit": {
|
||||
#@ "logUsernamesAndGroups": data.values.audit.log_usernames_and_groups,
|
||||
#@ "logInternalPaths": data.values.audit.log_internal_paths
|
||||
#@ }
|
||||
#@ }
|
||||
#@ if data.values.log_level:
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: githubidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -220,3 +220,23 @@ endpoints: { }
|
||||
#! An empty array is perfectly valid, as is any array of strings.
|
||||
allowed_ciphers_for_tls_onedottwo:
|
||||
- ""
|
||||
|
||||
#@schema/title "Audit logging configuration"
|
||||
#@schema/desc "Customize the content of audit log events."
|
||||
audit:
|
||||
|
||||
#@schema/title "Log usernames and groups"
|
||||
#@ log_usernames_and_groups_desc = "Enables or disables printing usernames and group names in audit logs. Options are 'enabled' or 'disabled'. \
|
||||
#@ If enabled, usernames are group names may be printed in audit log events. \
|
||||
#@ If disabled, usernames and group names will be redacted from audit logs because they might contain personally identifiable information."
|
||||
#@schema/desc log_usernames_and_groups_desc
|
||||
#@schema/validation one_of=["enabled", "disabled"]
|
||||
log_usernames_and_groups: disabled
|
||||
|
||||
#@schema/title "Log HTTPS requests for internal paths"
|
||||
#@ log_internal_paths = "Enables or disables request logging for internal paths in audit logs. Options are 'enabled' or 'disabled'. \
|
||||
#@ If enabled, requests to certain paths that are typically only used internal to the cluster (e.g. /healthz) will be enabled, which can be very verbose. \
|
||||
#@ If disabled, requests to those paths will not be audit logged."
|
||||
#@schema/desc log_internal_paths
|
||||
#@schema/validation one_of=["enabled", "disabled"]
|
||||
log_internal_paths: disabled
|
||||
|
||||
62
generated/1.25/README.adoc
generated
62
generated/1.25/README.adoc
generated
@@ -65,7 +65,6 @@ certificate bundle. +
|
||||
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
|
||||
@@ -429,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|
||||
|===
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
|
||||
==== CredentialIssuerKubeConfigInfo
|
||||
|
||||
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This type is deprecated and will be removed in a future version.
|
||||
|
||||
.Appears In:
|
||||
****
|
||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
|
||||
****
|
||||
|
||||
[cols="25a,75a", options="header"]
|
||||
|===
|
||||
| Field | Description
|
||||
| *`server`* __string__ | The K8s API server URL. +
|
||||
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerspec"]
|
||||
@@ -481,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|
||||
|===
|
||||
| Field | Description
|
||||
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
|
||||
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
|
||||
This field is deprecated and will be removed in a future version. +
|
||||
|===
|
||||
|
||||
|
||||
@@ -566,7 +544,6 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
||||
| Field | Description
|
||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
||||
|
||||
|
||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty +
|
||||
value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status. +
|
||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. +
|
||||
@@ -609,11 +586,9 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will +
|
||||
be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
||||
|
||||
|
||||
This field must be non-empty when spec.impersonationProxy.service.type is "None". +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate. +
|
||||
|===
|
||||
|
||||
@@ -624,11 +599,9 @@ If this field is empty, the impersonation proxy will generate its own TLS certif
|
||||
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.
|
||||
|
||||
@@ -812,13 +785,11 @@ the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer i
|
||||
https://example.com/foo, then your authorization endpoint will look like +
|
||||
https://example.com/foo/some/path/to/auth/endpoint). +
|
||||
|
||||
|
||||
See +
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. +
|
||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, +
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to +
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names. +
|
||||
@@ -831,7 +802,6 @@ rejection policies. Even though a user was able to authenticate with the identit
|
||||
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 +
|
||||
@@ -880,21 +850,17 @@ the TLS serving certificate for the HTTPS endpoints served by this FederationDom
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use +
|
||||
for TLS. +
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. +
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same +
|
||||
SecretName value even if they have different port numbers. +
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is +
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). +
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to +
|
||||
use the default TLS certificate, which is configured elsewhere. +
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. +
|
||||
|===
|
||||
|
||||
@@ -919,14 +885,12 @@ 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. +
|
||||
@@ -939,7 +903,6 @@ 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 +
|
||||
@@ -1109,7 +1072,6 @@ Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking
|
||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this +
|
||||
client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to +
|
||||
authenticate users. This grant must always be listed. +
|
||||
@@ -1120,7 +1082,6 @@ which is a step in the process to be able to get a cluster credential for the us
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience. +
|
||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). +
|
||||
This scope must always be listed. +
|
||||
@@ -1532,21 +1493,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
@@ -1797,10 +1755,8 @@ GitHubClaims allows customization of the username and groups claims.
|
||||
| Field | Description
|
||||
| *`username`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-idp-v1alpha1-githubusernameattribute[$$GitHubUsernameAttribute$$]__ | Username configures which property of the GitHub user record shall determine the username in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "id", "login", or "login:id". Defaults to "login:id". +
|
||||
|
||||
|
||||
GitHub's user login attributes can only contain alphanumeric characters and non-repeating hyphens, +
|
||||
and may not start or end with hyphens. GitHub users are allowed to change their login name, +
|
||||
although it is inconvenient. If a GitHub user changed their login name from "foo" to "bar", +
|
||||
@@ -1808,41 +1764,32 @@ then a second user might change their name from "baz" to "foo" in order to take
|
||||
username of the first user. For this reason, it is not as safe to make authorization decisions +
|
||||
based only on the user's login attribute. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these usernames are presented to Kubernetes. +
|
||||
|
||||
|
||||
Defaults to "login:id", which is the user login attribute, followed by a colon, followed by the unique and +
|
||||
unchanging integer ID number attribute. This blends human-readable login names with the unchanging ID value +
|
||||
from GitHub. Colons are not allowed in GitHub login attributes or ID numbers, so this is a reasonable +
|
||||
choice to concatenate the two values. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[Get the authenticated user](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user). +
|
||||
| *`groups`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-idp-v1alpha1-githubgroupnameattribute[$$GitHubGroupNameAttribute$$]__ | Groups configures which property of the GitHub team record shall determine the group names in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "name" or "slug". Defaults to "slug". +
|
||||
|
||||
|
||||
GitHub team names can contain upper and lower case characters, whitespace, and punctuation (e.g. "Kube admins!"). +
|
||||
|
||||
|
||||
GitHub team slugs are lower case alphanumeric characters and may contain dashes and underscores (e.g. "kube-admins"). +
|
||||
|
||||
|
||||
Group names as presented to Kubernetes will always be prefixed by the GitHub organization name followed by a +
|
||||
forward slash (e.g. "my-org/my-team"). GitHub organization login names can only contain alphanumeric characters +
|
||||
or single hyphens, so the first forward slash `/` will be the separator between the organization login name and +
|
||||
the team name or slug. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these group names are presented to Kubernetes. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[List teams for the authenticated user](https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user). +
|
||||
|===
|
||||
@@ -1865,7 +1812,6 @@ for web-based login flows.
|
||||
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the clientID and +
|
||||
clientSecret for an GitHub App or GitHub OAuth2 client. +
|
||||
|
||||
|
||||
This secret must be of type "secrets.pinniped.dev/github-client" with keys "clientID" and "clientSecret". +
|
||||
|===
|
||||
|
||||
@@ -1890,7 +1836,6 @@ names to present to Kubernetes. See the response schema for
|
||||
GitHubIdentityProvider describes the configuration of an upstream GitHub identity provider.
|
||||
This upstream provider can be configured with either a GitHub App or a GitHub OAuth2 App.
|
||||
|
||||
|
||||
Right now, only web-based logins are supported, for both the pinniped-cli client and clients configured
|
||||
as OIDCClients.
|
||||
|
||||
@@ -1977,10 +1922,8 @@ GitHubIdentityProviderStatus is the status of an GitHub identity provider.
|
||||
| *`policy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-supervisor-idp-v1alpha1-githuballowedauthorganizationspolicy[$$GitHubAllowedAuthOrganizationsPolicy$$]__ | Allowed values are "OnlyUsersFromAllowedOrganizations" or "AllGitHubUsers". +
|
||||
Defaults to "OnlyUsersFromAllowedOrganizations". +
|
||||
|
||||
|
||||
Must be set to "AllGitHubUsers" if the allowed field is empty. +
|
||||
|
||||
|
||||
This field only exists to ensure that Pinniped administrators are aware that an empty list of +
|
||||
allowedOrganizations means all GitHub users are allowed to log in. +
|
||||
| *`allowed`* __string array__ | Allowed, when specified, indicates that only users with membership in at least one of the listed +
|
||||
@@ -1988,12 +1931,10 @@ GitHub organizations may log in. In addition, the group membership presented to
|
||||
teams within the listed GitHub organizations. Additional login rules or group filtering can optionally be +
|
||||
provided as policy expression on any Pinniped Supervisor FederationDomain that includes this IDP. +
|
||||
|
||||
|
||||
The configured GitHub App or GitHub OAuth App must be allowed to see membership in the listed organizations, +
|
||||
otherwise Pinniped will not be aware that the user belongs to the listed organization or any teams +
|
||||
within that organization. +
|
||||
|
||||
|
||||
If no organizations are listed, you must set organizations: AllGitHubUsers. +
|
||||
|===
|
||||
|
||||
@@ -2095,21 +2036,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: githubidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
62
generated/1.26/README.adoc
generated
62
generated/1.26/README.adoc
generated
@@ -65,7 +65,6 @@ certificate bundle. +
|
||||
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
|
||||
@@ -429,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|
||||
|===
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
|
||||
==== CredentialIssuerKubeConfigInfo
|
||||
|
||||
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This type is deprecated and will be removed in a future version.
|
||||
|
||||
.Appears In:
|
||||
****
|
||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
|
||||
****
|
||||
|
||||
[cols="25a,75a", options="header"]
|
||||
|===
|
||||
| Field | Description
|
||||
| *`server`* __string__ | The K8s API server URL. +
|
||||
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerspec"]
|
||||
@@ -481,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|
||||
|===
|
||||
| Field | Description
|
||||
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
|
||||
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
|
||||
This field is deprecated and will be removed in a future version. +
|
||||
|===
|
||||
|
||||
|
||||
@@ -566,7 +544,6 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
||||
| Field | Description
|
||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
||||
|
||||
|
||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty +
|
||||
value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status. +
|
||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. +
|
||||
@@ -609,11 +586,9 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will +
|
||||
be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
||||
|
||||
|
||||
This field must be non-empty when spec.impersonationProxy.service.type is "None". +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate. +
|
||||
|===
|
||||
|
||||
@@ -624,11 +599,9 @@ If this field is empty, the impersonation proxy will generate its own TLS certif
|
||||
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.
|
||||
|
||||
@@ -812,13 +785,11 @@ the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer i
|
||||
https://example.com/foo, then your authorization endpoint will look like +
|
||||
https://example.com/foo/some/path/to/auth/endpoint). +
|
||||
|
||||
|
||||
See +
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. +
|
||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, +
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to +
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names. +
|
||||
@@ -831,7 +802,6 @@ rejection policies. Even though a user was able to authenticate with the identit
|
||||
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 +
|
||||
@@ -880,21 +850,17 @@ the TLS serving certificate for the HTTPS endpoints served by this FederationDom
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use +
|
||||
for TLS. +
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. +
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same +
|
||||
SecretName value even if they have different port numbers. +
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is +
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). +
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to +
|
||||
use the default TLS certificate, which is configured elsewhere. +
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. +
|
||||
|===
|
||||
|
||||
@@ -919,14 +885,12 @@ 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. +
|
||||
@@ -939,7 +903,6 @@ 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 +
|
||||
@@ -1109,7 +1072,6 @@ Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking
|
||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this +
|
||||
client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to +
|
||||
authenticate users. This grant must always be listed. +
|
||||
@@ -1120,7 +1082,6 @@ which is a step in the process to be able to get a cluster credential for the us
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience. +
|
||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). +
|
||||
This scope must always be listed. +
|
||||
@@ -1532,21 +1493,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
@@ -1797,10 +1755,8 @@ GitHubClaims allows customization of the username and groups claims.
|
||||
| Field | Description
|
||||
| *`username`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-idp-v1alpha1-githubusernameattribute[$$GitHubUsernameAttribute$$]__ | Username configures which property of the GitHub user record shall determine the username in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "id", "login", or "login:id". Defaults to "login:id". +
|
||||
|
||||
|
||||
GitHub's user login attributes can only contain alphanumeric characters and non-repeating hyphens, +
|
||||
and may not start or end with hyphens. GitHub users are allowed to change their login name, +
|
||||
although it is inconvenient. If a GitHub user changed their login name from "foo" to "bar", +
|
||||
@@ -1808,41 +1764,32 @@ then a second user might change their name from "baz" to "foo" in order to take
|
||||
username of the first user. For this reason, it is not as safe to make authorization decisions +
|
||||
based only on the user's login attribute. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these usernames are presented to Kubernetes. +
|
||||
|
||||
|
||||
Defaults to "login:id", which is the user login attribute, followed by a colon, followed by the unique and +
|
||||
unchanging integer ID number attribute. This blends human-readable login names with the unchanging ID value +
|
||||
from GitHub. Colons are not allowed in GitHub login attributes or ID numbers, so this is a reasonable +
|
||||
choice to concatenate the two values. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[Get the authenticated user](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user). +
|
||||
| *`groups`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-idp-v1alpha1-githubgroupnameattribute[$$GitHubGroupNameAttribute$$]__ | Groups configures which property of the GitHub team record shall determine the group names in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "name" or "slug". Defaults to "slug". +
|
||||
|
||||
|
||||
GitHub team names can contain upper and lower case characters, whitespace, and punctuation (e.g. "Kube admins!"). +
|
||||
|
||||
|
||||
GitHub team slugs are lower case alphanumeric characters and may contain dashes and underscores (e.g. "kube-admins"). +
|
||||
|
||||
|
||||
Group names as presented to Kubernetes will always be prefixed by the GitHub organization name followed by a +
|
||||
forward slash (e.g. "my-org/my-team"). GitHub organization login names can only contain alphanumeric characters +
|
||||
or single hyphens, so the first forward slash `/` will be the separator between the organization login name and +
|
||||
the team name or slug. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these group names are presented to Kubernetes. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[List teams for the authenticated user](https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user). +
|
||||
|===
|
||||
@@ -1865,7 +1812,6 @@ for web-based login flows.
|
||||
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the clientID and +
|
||||
clientSecret for an GitHub App or GitHub OAuth2 client. +
|
||||
|
||||
|
||||
This secret must be of type "secrets.pinniped.dev/github-client" with keys "clientID" and "clientSecret". +
|
||||
|===
|
||||
|
||||
@@ -1890,7 +1836,6 @@ names to present to Kubernetes. See the response schema for
|
||||
GitHubIdentityProvider describes the configuration of an upstream GitHub identity provider.
|
||||
This upstream provider can be configured with either a GitHub App or a GitHub OAuth2 App.
|
||||
|
||||
|
||||
Right now, only web-based logins are supported, for both the pinniped-cli client and clients configured
|
||||
as OIDCClients.
|
||||
|
||||
@@ -1977,10 +1922,8 @@ GitHubIdentityProviderStatus is the status of an GitHub identity provider.
|
||||
| *`policy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-supervisor-idp-v1alpha1-githuballowedauthorganizationspolicy[$$GitHubAllowedAuthOrganizationsPolicy$$]__ | Allowed values are "OnlyUsersFromAllowedOrganizations" or "AllGitHubUsers". +
|
||||
Defaults to "OnlyUsersFromAllowedOrganizations". +
|
||||
|
||||
|
||||
Must be set to "AllGitHubUsers" if the allowed field is empty. +
|
||||
|
||||
|
||||
This field only exists to ensure that Pinniped administrators are aware that an empty list of +
|
||||
allowedOrganizations means all GitHub users are allowed to log in. +
|
||||
| *`allowed`* __string array__ | Allowed, when specified, indicates that only users with membership in at least one of the listed +
|
||||
@@ -1988,12 +1931,10 @@ GitHub organizations may log in. In addition, the group membership presented to
|
||||
teams within the listed GitHub organizations. Additional login rules or group filtering can optionally be +
|
||||
provided as policy expression on any Pinniped Supervisor FederationDomain that includes this IDP. +
|
||||
|
||||
|
||||
The configured GitHub App or GitHub OAuth App must be allowed to see membership in the listed organizations, +
|
||||
otherwise Pinniped will not be aware that the user belongs to the listed organization or any teams +
|
||||
within that organization. +
|
||||
|
||||
|
||||
If no organizations are listed, you must set organizations: AllGitHubUsers. +
|
||||
|===
|
||||
|
||||
@@ -2095,21 +2036,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: githubidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
62
generated/1.27/README.adoc
generated
62
generated/1.27/README.adoc
generated
@@ -65,7 +65,6 @@ certificate bundle. +
|
||||
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
|
||||
@@ -429,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|
||||
|===
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
|
||||
==== CredentialIssuerKubeConfigInfo
|
||||
|
||||
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This type is deprecated and will be removed in a future version.
|
||||
|
||||
.Appears In:
|
||||
****
|
||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
|
||||
****
|
||||
|
||||
[cols="25a,75a", options="header"]
|
||||
|===
|
||||
| Field | Description
|
||||
| *`server`* __string__ | The K8s API server URL. +
|
||||
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerspec"]
|
||||
@@ -481,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|
||||
|===
|
||||
| Field | Description
|
||||
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
|
||||
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
|
||||
This field is deprecated and will be removed in a future version. +
|
||||
|===
|
||||
|
||||
|
||||
@@ -566,7 +544,6 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
||||
| Field | Description
|
||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
||||
|
||||
|
||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty +
|
||||
value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status. +
|
||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. +
|
||||
@@ -609,11 +586,9 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will +
|
||||
be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
||||
|
||||
|
||||
This field must be non-empty when spec.impersonationProxy.service.type is "None". +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate. +
|
||||
|===
|
||||
|
||||
@@ -624,11 +599,9 @@ If this field is empty, the impersonation proxy will generate its own TLS certif
|
||||
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.
|
||||
|
||||
@@ -812,13 +785,11 @@ the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer i
|
||||
https://example.com/foo, then your authorization endpoint will look like +
|
||||
https://example.com/foo/some/path/to/auth/endpoint). +
|
||||
|
||||
|
||||
See +
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. +
|
||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, +
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to +
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names. +
|
||||
@@ -831,7 +802,6 @@ rejection policies. Even though a user was able to authenticate with the identit
|
||||
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 +
|
||||
@@ -880,21 +850,17 @@ the TLS serving certificate for the HTTPS endpoints served by this FederationDom
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use +
|
||||
for TLS. +
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. +
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same +
|
||||
SecretName value even if they have different port numbers. +
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is +
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). +
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to +
|
||||
use the default TLS certificate, which is configured elsewhere. +
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. +
|
||||
|===
|
||||
|
||||
@@ -919,14 +885,12 @@ 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. +
|
||||
@@ -939,7 +903,6 @@ 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 +
|
||||
@@ -1109,7 +1072,6 @@ Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking
|
||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this +
|
||||
client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to +
|
||||
authenticate users. This grant must always be listed. +
|
||||
@@ -1120,7 +1082,6 @@ which is a step in the process to be able to get a cluster credential for the us
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience. +
|
||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). +
|
||||
This scope must always be listed. +
|
||||
@@ -1532,21 +1493,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
@@ -1797,10 +1755,8 @@ GitHubClaims allows customization of the username and groups claims.
|
||||
| Field | Description
|
||||
| *`username`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-idp-v1alpha1-githubusernameattribute[$$GitHubUsernameAttribute$$]__ | Username configures which property of the GitHub user record shall determine the username in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "id", "login", or "login:id". Defaults to "login:id". +
|
||||
|
||||
|
||||
GitHub's user login attributes can only contain alphanumeric characters and non-repeating hyphens, +
|
||||
and may not start or end with hyphens. GitHub users are allowed to change their login name, +
|
||||
although it is inconvenient. If a GitHub user changed their login name from "foo" to "bar", +
|
||||
@@ -1808,41 +1764,32 @@ then a second user might change their name from "baz" to "foo" in order to take
|
||||
username of the first user. For this reason, it is not as safe to make authorization decisions +
|
||||
based only on the user's login attribute. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these usernames are presented to Kubernetes. +
|
||||
|
||||
|
||||
Defaults to "login:id", which is the user login attribute, followed by a colon, followed by the unique and +
|
||||
unchanging integer ID number attribute. This blends human-readable login names with the unchanging ID value +
|
||||
from GitHub. Colons are not allowed in GitHub login attributes or ID numbers, so this is a reasonable +
|
||||
choice to concatenate the two values. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[Get the authenticated user](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user). +
|
||||
| *`groups`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-idp-v1alpha1-githubgroupnameattribute[$$GitHubGroupNameAttribute$$]__ | Groups configures which property of the GitHub team record shall determine the group names in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "name" or "slug". Defaults to "slug". +
|
||||
|
||||
|
||||
GitHub team names can contain upper and lower case characters, whitespace, and punctuation (e.g. "Kube admins!"). +
|
||||
|
||||
|
||||
GitHub team slugs are lower case alphanumeric characters and may contain dashes and underscores (e.g. "kube-admins"). +
|
||||
|
||||
|
||||
Group names as presented to Kubernetes will always be prefixed by the GitHub organization name followed by a +
|
||||
forward slash (e.g. "my-org/my-team"). GitHub organization login names can only contain alphanumeric characters +
|
||||
or single hyphens, so the first forward slash `/` will be the separator between the organization login name and +
|
||||
the team name or slug. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these group names are presented to Kubernetes. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[List teams for the authenticated user](https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user). +
|
||||
|===
|
||||
@@ -1865,7 +1812,6 @@ for web-based login flows.
|
||||
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the clientID and +
|
||||
clientSecret for an GitHub App or GitHub OAuth2 client. +
|
||||
|
||||
|
||||
This secret must be of type "secrets.pinniped.dev/github-client" with keys "clientID" and "clientSecret". +
|
||||
|===
|
||||
|
||||
@@ -1890,7 +1836,6 @@ names to present to Kubernetes. See the response schema for
|
||||
GitHubIdentityProvider describes the configuration of an upstream GitHub identity provider.
|
||||
This upstream provider can be configured with either a GitHub App or a GitHub OAuth2 App.
|
||||
|
||||
|
||||
Right now, only web-based logins are supported, for both the pinniped-cli client and clients configured
|
||||
as OIDCClients.
|
||||
|
||||
@@ -1977,10 +1922,8 @@ GitHubIdentityProviderStatus is the status of an GitHub identity provider.
|
||||
| *`policy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-supervisor-idp-v1alpha1-githuballowedauthorganizationspolicy[$$GitHubAllowedAuthOrganizationsPolicy$$]__ | Allowed values are "OnlyUsersFromAllowedOrganizations" or "AllGitHubUsers". +
|
||||
Defaults to "OnlyUsersFromAllowedOrganizations". +
|
||||
|
||||
|
||||
Must be set to "AllGitHubUsers" if the allowed field is empty. +
|
||||
|
||||
|
||||
This field only exists to ensure that Pinniped administrators are aware that an empty list of +
|
||||
allowedOrganizations means all GitHub users are allowed to log in. +
|
||||
| *`allowed`* __string array__ | Allowed, when specified, indicates that only users with membership in at least one of the listed +
|
||||
@@ -1988,12 +1931,10 @@ GitHub organizations may log in. In addition, the group membership presented to
|
||||
teams within the listed GitHub organizations. Additional login rules or group filtering can optionally be +
|
||||
provided as policy expression on any Pinniped Supervisor FederationDomain that includes this IDP. +
|
||||
|
||||
|
||||
The configured GitHub App or GitHub OAuth App must be allowed to see membership in the listed organizations, +
|
||||
otherwise Pinniped will not be aware that the user belongs to the listed organization or any teams +
|
||||
within that organization. +
|
||||
|
||||
|
||||
If no organizations are listed, you must set organizations: AllGitHubUsers. +
|
||||
|===
|
||||
|
||||
@@ -2095,21 +2036,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: githubidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
62
generated/1.28/README.adoc
generated
62
generated/1.28/README.adoc
generated
@@ -65,7 +65,6 @@ certificate bundle. +
|
||||
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
|
||||
@@ -429,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|
||||
|===
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
|
||||
==== CredentialIssuerKubeConfigInfo
|
||||
|
||||
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This type is deprecated and will be removed in a future version.
|
||||
|
||||
.Appears In:
|
||||
****
|
||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
|
||||
****
|
||||
|
||||
[cols="25a,75a", options="header"]
|
||||
|===
|
||||
| Field | Description
|
||||
| *`server`* __string__ | The K8s API server URL. +
|
||||
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerspec"]
|
||||
@@ -481,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|
||||
|===
|
||||
| Field | Description
|
||||
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
|
||||
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
|
||||
This field is deprecated and will be removed in a future version. +
|
||||
|===
|
||||
|
||||
|
||||
@@ -566,7 +544,6 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
||||
| Field | Description
|
||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
||||
|
||||
|
||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty +
|
||||
value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status. +
|
||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. +
|
||||
@@ -609,11 +586,9 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will +
|
||||
be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
||||
|
||||
|
||||
This field must be non-empty when spec.impersonationProxy.service.type is "None". +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate. +
|
||||
|===
|
||||
|
||||
@@ -624,11 +599,9 @@ If this field is empty, the impersonation proxy will generate its own TLS certif
|
||||
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.
|
||||
|
||||
@@ -812,13 +785,11 @@ the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer i
|
||||
https://example.com/foo, then your authorization endpoint will look like +
|
||||
https://example.com/foo/some/path/to/auth/endpoint). +
|
||||
|
||||
|
||||
See +
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. +
|
||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, +
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to +
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names. +
|
||||
@@ -831,7 +802,6 @@ rejection policies. Even though a user was able to authenticate with the identit
|
||||
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 +
|
||||
@@ -880,21 +850,17 @@ the TLS serving certificate for the HTTPS endpoints served by this FederationDom
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use +
|
||||
for TLS. +
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. +
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same +
|
||||
SecretName value even if they have different port numbers. +
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is +
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). +
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to +
|
||||
use the default TLS certificate, which is configured elsewhere. +
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. +
|
||||
|===
|
||||
|
||||
@@ -919,14 +885,12 @@ 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. +
|
||||
@@ -939,7 +903,6 @@ 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 +
|
||||
@@ -1109,7 +1072,6 @@ Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking
|
||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this +
|
||||
client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to +
|
||||
authenticate users. This grant must always be listed. +
|
||||
@@ -1120,7 +1082,6 @@ which is a step in the process to be able to get a cluster credential for the us
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience. +
|
||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). +
|
||||
This scope must always be listed. +
|
||||
@@ -1532,21 +1493,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
@@ -1797,10 +1755,8 @@ GitHubClaims allows customization of the username and groups claims.
|
||||
| Field | Description
|
||||
| *`username`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-idp-v1alpha1-githubusernameattribute[$$GitHubUsernameAttribute$$]__ | Username configures which property of the GitHub user record shall determine the username in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "id", "login", or "login:id". Defaults to "login:id". +
|
||||
|
||||
|
||||
GitHub's user login attributes can only contain alphanumeric characters and non-repeating hyphens, +
|
||||
and may not start or end with hyphens. GitHub users are allowed to change their login name, +
|
||||
although it is inconvenient. If a GitHub user changed their login name from "foo" to "bar", +
|
||||
@@ -1808,41 +1764,32 @@ then a second user might change their name from "baz" to "foo" in order to take
|
||||
username of the first user. For this reason, it is not as safe to make authorization decisions +
|
||||
based only on the user's login attribute. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these usernames are presented to Kubernetes. +
|
||||
|
||||
|
||||
Defaults to "login:id", which is the user login attribute, followed by a colon, followed by the unique and +
|
||||
unchanging integer ID number attribute. This blends human-readable login names with the unchanging ID value +
|
||||
from GitHub. Colons are not allowed in GitHub login attributes or ID numbers, so this is a reasonable +
|
||||
choice to concatenate the two values. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[Get the authenticated user](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user). +
|
||||
| *`groups`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-idp-v1alpha1-githubgroupnameattribute[$$GitHubGroupNameAttribute$$]__ | Groups configures which property of the GitHub team record shall determine the group names in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "name" or "slug". Defaults to "slug". +
|
||||
|
||||
|
||||
GitHub team names can contain upper and lower case characters, whitespace, and punctuation (e.g. "Kube admins!"). +
|
||||
|
||||
|
||||
GitHub team slugs are lower case alphanumeric characters and may contain dashes and underscores (e.g. "kube-admins"). +
|
||||
|
||||
|
||||
Group names as presented to Kubernetes will always be prefixed by the GitHub organization name followed by a +
|
||||
forward slash (e.g. "my-org/my-team"). GitHub organization login names can only contain alphanumeric characters +
|
||||
or single hyphens, so the first forward slash `/` will be the separator between the organization login name and +
|
||||
the team name or slug. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these group names are presented to Kubernetes. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[List teams for the authenticated user](https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user). +
|
||||
|===
|
||||
@@ -1865,7 +1812,6 @@ for web-based login flows.
|
||||
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the clientID and +
|
||||
clientSecret for an GitHub App or GitHub OAuth2 client. +
|
||||
|
||||
|
||||
This secret must be of type "secrets.pinniped.dev/github-client" with keys "clientID" and "clientSecret". +
|
||||
|===
|
||||
|
||||
@@ -1890,7 +1836,6 @@ names to present to Kubernetes. See the response schema for
|
||||
GitHubIdentityProvider describes the configuration of an upstream GitHub identity provider.
|
||||
This upstream provider can be configured with either a GitHub App or a GitHub OAuth2 App.
|
||||
|
||||
|
||||
Right now, only web-based logins are supported, for both the pinniped-cli client and clients configured
|
||||
as OIDCClients.
|
||||
|
||||
@@ -1977,10 +1922,8 @@ GitHubIdentityProviderStatus is the status of an GitHub identity provider.
|
||||
| *`policy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-supervisor-idp-v1alpha1-githuballowedauthorganizationspolicy[$$GitHubAllowedAuthOrganizationsPolicy$$]__ | Allowed values are "OnlyUsersFromAllowedOrganizations" or "AllGitHubUsers". +
|
||||
Defaults to "OnlyUsersFromAllowedOrganizations". +
|
||||
|
||||
|
||||
Must be set to "AllGitHubUsers" if the allowed field is empty. +
|
||||
|
||||
|
||||
This field only exists to ensure that Pinniped administrators are aware that an empty list of +
|
||||
allowedOrganizations means all GitHub users are allowed to log in. +
|
||||
| *`allowed`* __string array__ | Allowed, when specified, indicates that only users with membership in at least one of the listed +
|
||||
@@ -1988,12 +1931,10 @@ GitHub organizations may log in. In addition, the group membership presented to
|
||||
teams within the listed GitHub organizations. Additional login rules or group filtering can optionally be +
|
||||
provided as policy expression on any Pinniped Supervisor FederationDomain that includes this IDP. +
|
||||
|
||||
|
||||
The configured GitHub App or GitHub OAuth App must be allowed to see membership in the listed organizations, +
|
||||
otherwise Pinniped will not be aware that the user belongs to the listed organization or any teams +
|
||||
within that organization. +
|
||||
|
||||
|
||||
If no organizations are listed, you must set organizations: AllGitHubUsers. +
|
||||
|===
|
||||
|
||||
@@ -2095,21 +2036,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
4
generated/1.28/apis/go.mod
generated
4
generated/1.28/apis/go.mod
generated
@@ -4,6 +4,6 @@ module go.pinniped.dev/generated/1.28/apis
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
k8s.io/api v0.28.14
|
||||
k8s.io/apimachinery v0.28.14
|
||||
k8s.io/api v0.28.15
|
||||
k8s.io/apimachinery v0.28.15
|
||||
)
|
||||
|
||||
8
generated/1.28/apis/go.sum
generated
8
generated/1.28/apis/go.sum
generated
@@ -297,10 +297,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.28.14 h1:7DXeMrQq+BJI6H7WtSMC8l1gM4QZWtWN65UbN+qZ9Uc=
|
||||
k8s.io/api v0.28.14/go.mod h1:ROk/G6/7IZf14AL1WkpZdq//5khE1EtLNxkcEpSXNFM=
|
||||
k8s.io/apimachinery v0.28.14 h1:n2l8jNNOmUUDXpa8ljHCEUSeIChby1BKyqoL0AtpmGw=
|
||||
k8s.io/apimachinery v0.28.14/go.mod h1:zUG757HaKs6Dc3iGtKjzIpBfqTM4yiRsEe3/E7NX15o=
|
||||
k8s.io/api v0.28.15 h1:u+Sze8gI+DayQxndS0htiJf8yVooHyUx/H4jEehtmNs=
|
||||
k8s.io/api v0.28.15/go.mod h1:SJuOJTphYG05iJC9UKnUTNkY84Mvveu1P7adCgWqjCg=
|
||||
k8s.io/apimachinery v0.28.15 h1:Jg15ZoCcAgnhSRKVS6tQyUZaX9c3i08bl2qAz8XE3bI=
|
||||
k8s.io/apimachinery v0.28.15/go.mod h1:zUG757HaKs6Dc3iGtKjzIpBfqTM4yiRsEe3/E7NX15o=
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
4
generated/1.28/client/go.mod
generated
4
generated/1.28/client/go.mod
generated
@@ -7,7 +7,7 @@ replace go.pinniped.dev/generated/1.28/apis => ../apis
|
||||
|
||||
require (
|
||||
go.pinniped.dev/generated/1.28/apis v0.0.0
|
||||
k8s.io/apimachinery v0.28.14
|
||||
k8s.io/client-go v0.28.14
|
||||
k8s.io/apimachinery v0.28.15
|
||||
k8s.io/client-go v0.28.15
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9
|
||||
)
|
||||
|
||||
12
generated/1.28/client/go.sum
generated
12
generated/1.28/client/go.sum
generated
@@ -334,12 +334,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.28.14 h1:7DXeMrQq+BJI6H7WtSMC8l1gM4QZWtWN65UbN+qZ9Uc=
|
||||
k8s.io/api v0.28.14/go.mod h1:ROk/G6/7IZf14AL1WkpZdq//5khE1EtLNxkcEpSXNFM=
|
||||
k8s.io/apimachinery v0.28.14 h1:n2l8jNNOmUUDXpa8ljHCEUSeIChby1BKyqoL0AtpmGw=
|
||||
k8s.io/apimachinery v0.28.14/go.mod h1:zUG757HaKs6Dc3iGtKjzIpBfqTM4yiRsEe3/E7NX15o=
|
||||
k8s.io/client-go v0.28.14 h1:wfPRgz07MvLMxcHfN8kAc4Qcwduc4My25A3CBU7OqBQ=
|
||||
k8s.io/client-go v0.28.14/go.mod h1:HGfdb7BqkX4hRpNyVLHNQKWDU03W6a38LfIHD7QGJpI=
|
||||
k8s.io/api v0.28.15 h1:u+Sze8gI+DayQxndS0htiJf8yVooHyUx/H4jEehtmNs=
|
||||
k8s.io/api v0.28.15/go.mod h1:SJuOJTphYG05iJC9UKnUTNkY84Mvveu1P7adCgWqjCg=
|
||||
k8s.io/apimachinery v0.28.15 h1:Jg15ZoCcAgnhSRKVS6tQyUZaX9c3i08bl2qAz8XE3bI=
|
||||
k8s.io/apimachinery v0.28.15/go.mod h1:zUG757HaKs6Dc3iGtKjzIpBfqTM4yiRsEe3/E7NX15o=
|
||||
k8s.io/client-go v0.28.15 h1:+g6Ub+i6tacV3tYJaoyK6bizpinPkamcEwsiKyHcIxc=
|
||||
k8s.io/client-go v0.28.15/go.mod h1:/4upIpTbhWQVSXKDqTznjcAegj2Bx73mW/i0aennJrY=
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: githubidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
|
||||
62
generated/1.29/README.adoc
generated
62
generated/1.29/README.adoc
generated
@@ -65,7 +65,6 @@ certificate bundle. +
|
||||
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
|
||||
@@ -429,25 +428,6 @@ This field is only set when Type is "ImpersonationProxy". +
|
||||
|===
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"]
|
||||
==== CredentialIssuerKubeConfigInfo
|
||||
|
||||
CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This type is deprecated and will be removed in a future version.
|
||||
|
||||
.Appears In:
|
||||
****
|
||||
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]
|
||||
****
|
||||
|
||||
[cols="25a,75a", options="header"]
|
||||
|===
|
||||
| Field | Description
|
||||
| *`server`* __string__ | The K8s API server URL. +
|
||||
| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. +
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerspec"]
|
||||
@@ -481,8 +461,6 @@ CredentialIssuerStatus describes the status of the Concierge.
|
||||
|===
|
||||
| Field | Description
|
||||
| *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. +
|
||||
| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. +
|
||||
This field is deprecated and will be removed in a future version. +
|
||||
|===
|
||||
|
||||
|
||||
@@ -566,7 +544,6 @@ ImpersonationProxyServiceSpec describes how the Concierge should provision a Ser
|
||||
| Field | Description
|
||||
| *`type`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-impersonationproxyservicetype[$$ImpersonationProxyServiceType$$]__ | Type specifies the type of Service to provision for the impersonation proxy. +
|
||||
|
||||
|
||||
If the type is "None", then the "spec.impersonationProxy.externalEndpoint" field must be set to a non-empty +
|
||||
value so that the Concierge can properly advertise the endpoint in the CredentialIssuer's status. +
|
||||
| *`loadBalancerIP`* __string__ | LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service. +
|
||||
@@ -609,11 +586,9 @@ ImpersonationProxySpec describes the intended configuration of the Concierge imp
|
||||
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will +
|
||||
be served using the external name of the LoadBalancer service or the cluster service DNS name. +
|
||||
|
||||
|
||||
This field must be non-empty when spec.impersonationProxy.service.type is "None". +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-impersonationproxytlsspec[$$ImpersonationProxyTLSSpec$$]__ | TLS contains information about how the Concierge impersonation proxy should serve TLS. +
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate. +
|
||||
|===
|
||||
|
||||
@@ -624,11 +599,9 @@ If this field is empty, the impersonation proxy will generate its own TLS certif
|
||||
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.
|
||||
|
||||
@@ -812,13 +785,11 @@ the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer i
|
||||
https://example.com/foo, then your authorization endpoint will look like +
|
||||
https://example.com/foo/some/path/to/auth/endpoint). +
|
||||
|
||||
|
||||
See +
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. +
|
||||
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-config-v1alpha1-federationdomaintlsspec[$$FederationDomainTLSSpec$$]__ | TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. +
|
||||
| *`identityProviders`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-config-v1alpha1-federationdomainidentityprovider[$$FederationDomainIdentityProvider$$] array__ | IdentityProviders is the list of identity providers available for use by this FederationDomain. +
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server, +
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to +
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names. +
|
||||
@@ -831,7 +802,6 @@ rejection policies. Even though a user was able to authenticate with the identit
|
||||
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 +
|
||||
@@ -880,21 +850,17 @@ the TLS serving certificate for the HTTPS endpoints served by this FederationDom
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use +
|
||||
for TLS. +
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. +
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. +
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same +
|
||||
SecretName value even if they have different port numbers. +
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is +
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). +
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to +
|
||||
use the default TLS certificate, which is configured elsewhere. +
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. +
|
||||
|===
|
||||
|
||||
@@ -919,14 +885,12 @@ 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. +
|
||||
@@ -939,7 +903,6 @@ 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 +
|
||||
@@ -1109,7 +1072,6 @@ Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking
|
||||
| *`allowedGrantTypes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-config-v1alpha1-granttype[$$GrantType$$] array__ | allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this +
|
||||
client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to +
|
||||
authenticate users. This grant must always be listed. +
|
||||
@@ -1120,7 +1082,6 @@ which is a step in the process to be able to get a cluster credential for the us
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience. +
|
||||
| *`allowedScopes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-config-v1alpha1-scope[$$Scope$$] array__ | allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client. +
|
||||
|
||||
|
||||
Must only contain the following values: +
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat). +
|
||||
This scope must always be listed. +
|
||||
@@ -1532,21 +1493,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
@@ -1797,10 +1755,8 @@ GitHubClaims allows customization of the username and groups claims.
|
||||
| Field | Description
|
||||
| *`username`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-idp-v1alpha1-githubusernameattribute[$$GitHubUsernameAttribute$$]__ | Username configures which property of the GitHub user record shall determine the username in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "id", "login", or "login:id". Defaults to "login:id". +
|
||||
|
||||
|
||||
GitHub's user login attributes can only contain alphanumeric characters and non-repeating hyphens, +
|
||||
and may not start or end with hyphens. GitHub users are allowed to change their login name, +
|
||||
although it is inconvenient. If a GitHub user changed their login name from "foo" to "bar", +
|
||||
@@ -1808,41 +1764,32 @@ then a second user might change their name from "baz" to "foo" in order to take
|
||||
username of the first user. For this reason, it is not as safe to make authorization decisions +
|
||||
based only on the user's login attribute. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these usernames are presented to Kubernetes. +
|
||||
|
||||
|
||||
Defaults to "login:id", which is the user login attribute, followed by a colon, followed by the unique and +
|
||||
unchanging integer ID number attribute. This blends human-readable login names with the unchanging ID value +
|
||||
from GitHub. Colons are not allowed in GitHub login attributes or ID numbers, so this is a reasonable +
|
||||
choice to concatenate the two values. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[Get the authenticated user](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user). +
|
||||
| *`groups`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-idp-v1alpha1-githubgroupnameattribute[$$GitHubGroupNameAttribute$$]__ | Groups configures which property of the GitHub team record shall determine the group names in Kubernetes. +
|
||||
|
||||
|
||||
Can be either "name" or "slug". Defaults to "slug". +
|
||||
|
||||
|
||||
GitHub team names can contain upper and lower case characters, whitespace, and punctuation (e.g. "Kube admins!"). +
|
||||
|
||||
|
||||
GitHub team slugs are lower case alphanumeric characters and may contain dashes and underscores (e.g. "kube-admins"). +
|
||||
|
||||
|
||||
Group names as presented to Kubernetes will always be prefixed by the GitHub organization name followed by a +
|
||||
forward slash (e.g. "my-org/my-team"). GitHub organization login names can only contain alphanumeric characters +
|
||||
or single hyphens, so the first forward slash `/` will be the separator between the organization login name and +
|
||||
the team name or slug. +
|
||||
|
||||
|
||||
If desired, an admin could configure identity transformation expressions on the Pinniped Supervisor's +
|
||||
FederationDomain to further customize how these group names are presented to Kubernetes. +
|
||||
|
||||
|
||||
See the response schema for +
|
||||
[List teams for the authenticated user](https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user). +
|
||||
|===
|
||||
@@ -1865,7 +1812,6 @@ for web-based login flows.
|
||||
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the clientID and +
|
||||
clientSecret for an GitHub App or GitHub OAuth2 client. +
|
||||
|
||||
|
||||
This secret must be of type "secrets.pinniped.dev/github-client" with keys "clientID" and "clientSecret". +
|
||||
|===
|
||||
|
||||
@@ -1890,7 +1836,6 @@ names to present to Kubernetes. See the response schema for
|
||||
GitHubIdentityProvider describes the configuration of an upstream GitHub identity provider.
|
||||
This upstream provider can be configured with either a GitHub App or a GitHub OAuth2 App.
|
||||
|
||||
|
||||
Right now, only web-based logins are supported, for both the pinniped-cli client and clients configured
|
||||
as OIDCClients.
|
||||
|
||||
@@ -1977,10 +1922,8 @@ GitHubIdentityProviderStatus is the status of an GitHub identity provider.
|
||||
| *`policy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-supervisor-idp-v1alpha1-githuballowedauthorganizationspolicy[$$GitHubAllowedAuthOrganizationsPolicy$$]__ | Allowed values are "OnlyUsersFromAllowedOrganizations" or "AllGitHubUsers". +
|
||||
Defaults to "OnlyUsersFromAllowedOrganizations". +
|
||||
|
||||
|
||||
Must be set to "AllGitHubUsers" if the allowed field is empty. +
|
||||
|
||||
|
||||
This field only exists to ensure that Pinniped administrators are aware that an empty list of +
|
||||
allowedOrganizations means all GitHub users are allowed to log in. +
|
||||
| *`allowed`* __string array__ | Allowed, when specified, indicates that only users with membership in at least one of the listed +
|
||||
@@ -1988,12 +1931,10 @@ GitHub organizations may log in. In addition, the group membership presented to
|
||||
teams within the listed GitHub organizations. Additional login rules or group filtering can optionally be +
|
||||
provided as policy expression on any Pinniped Supervisor FederationDomain that includes this IDP. +
|
||||
|
||||
|
||||
The configured GitHub App or GitHub OAuth App must be allowed to see membership in the listed organizations, +
|
||||
otherwise Pinniped will not be aware that the user belongs to the listed organization or any teams +
|
||||
within that organization. +
|
||||
|
||||
|
||||
If no organizations are listed, you must set organizations: AllGitHubUsers. +
|
||||
|===
|
||||
|
||||
@@ -2095,21 +2036,18 @@ group membership is often used to bind authorization policies, it is important +
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity +
|
||||
provider. +
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a +
|
||||
significant performance impact on the identity provider and/or the supervisor. +
|
||||
The best approach to handle performance impacts is to tweak the group query +
|
||||
to be more performant, for example by disabling nested group search or by +
|
||||
using a more targeted group search base. +
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to +
|
||||
have group memberships remain static for approximately a day, then set +
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization +
|
||||
policies that are bound to group membership will not notice if a user has +
|
||||
been removed from a particular group until their next login. +
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered +
|
||||
in the future. Consumers of this configuration should carefully read all +
|
||||
release notes before upgrading to ensure that the meaning of this field has +
|
||||
|
||||
@@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct {
|
||||
type CredentialIssuerStatus struct {
|
||||
// List of integration strategies that were attempted by Pinniped.
|
||||
Strategies []CredentialIssuerStrategy `json:"strategies"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
|
||||
@@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
@@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
4
generated/1.29/apis/go.mod
generated
4
generated/1.29/apis/go.mod
generated
@@ -4,8 +4,8 @@ module go.pinniped.dev/generated/1.29/apis
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
k8s.io/api v0.29.9
|
||||
k8s.io/apimachinery v0.29.9
|
||||
k8s.io/api v0.29.13
|
||||
k8s.io/apimachinery v0.29.13
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
8
generated/1.29/apis/go.sum
generated
8
generated/1.29/apis/go.sum
generated
@@ -75,10 +75,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.29.9 h1:FwdflpNsfMUYUOblMZNWJ4K/q0OSL5A4jGa0iOgcJco=
|
||||
k8s.io/api v0.29.9/go.mod h1:fNhmzRfKaSEHCmczA/jRx6CiDKhYOnFLJBERMJAXEk8=
|
||||
k8s.io/apimachinery v0.29.9 h1:YZ8HUid1TzQVz94cnNlsQjLdH0VoAhWSqz7t0q6B12A=
|
||||
k8s.io/apimachinery v0.29.9/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
|
||||
k8s.io/api v0.29.13 h1:VkMIbjJw1t2VgTatg8ggzI93LOfFa8z8SzAYzXtWuEg=
|
||||
k8s.io/api v0.29.13/go.mod h1:fBWhXqqE25b46PZEVA2DXN2EuhNg1ZT3VRyb5JitLG8=
|
||||
k8s.io/apimachinery v0.29.13 h1:a7I4uQtlfaL+UTRGFhl8lLd2nHBR7qt+axhQLtpLYMg=
|
||||
k8s.io/apimachinery v0.29.13/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
|
||||
@@ -209,6 +209,7 @@ type FederationDomainSpec struct {
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'"
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
6
generated/1.29/client/go.mod
generated
6
generated/1.29/client/go.mod
generated
@@ -7,8 +7,8 @@ replace go.pinniped.dev/generated/1.29/apis => ../apis
|
||||
|
||||
require (
|
||||
go.pinniped.dev/generated/1.29/apis v0.0.0
|
||||
k8s.io/apimachinery v0.29.9
|
||||
k8s.io/client-go v0.29.9
|
||||
k8s.io/apimachinery v0.29.13
|
||||
k8s.io/client-go v0.29.13
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ require (
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/api v0.29.9 // indirect
|
||||
k8s.io/api v0.29.13 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
|
||||
12
generated/1.29/client/go.sum
generated
12
generated/1.29/client/go.sum
generated
@@ -134,12 +134,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.29.9 h1:FwdflpNsfMUYUOblMZNWJ4K/q0OSL5A4jGa0iOgcJco=
|
||||
k8s.io/api v0.29.9/go.mod h1:fNhmzRfKaSEHCmczA/jRx6CiDKhYOnFLJBERMJAXEk8=
|
||||
k8s.io/apimachinery v0.29.9 h1:YZ8HUid1TzQVz94cnNlsQjLdH0VoAhWSqz7t0q6B12A=
|
||||
k8s.io/apimachinery v0.29.9/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
|
||||
k8s.io/client-go v0.29.9 h1:4f/Wz6li3rEyIPFj32XAQMtOGMM1tg7KQi1oeS6ibPg=
|
||||
k8s.io/client-go v0.29.9/go.mod h1:2N1drQEZ5yiYrWVaE2Un8JiISUhl47D8pyZlYLszke4=
|
||||
k8s.io/api v0.29.13 h1:VkMIbjJw1t2VgTatg8ggzI93LOfFa8z8SzAYzXtWuEg=
|
||||
k8s.io/api v0.29.13/go.mod h1:fBWhXqqE25b46PZEVA2DXN2EuhNg1ZT3VRyb5JitLG8=
|
||||
k8s.io/apimachinery v0.29.13 h1:a7I4uQtlfaL+UTRGFhl8lLd2nHBR7qt+axhQLtpLYMg=
|
||||
k8s.io/apimachinery v0.29.13/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
|
||||
k8s.io/client-go v0.29.13 h1:M2scR9NWGlzI2YoIxTgwx2N3OA+dXqN87zsM4tvewmA=
|
||||
k8s.io/client-go v0.29.13/go.mod h1:BBzF0Pr78Y8DM20j22E6tOMwTBpFaKnSnn6N0pNe4VE=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -134,24 +134,6 @@ spec:
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -289,6 +289,9 @@ spec:
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
x-kubernetes-validations:
|
||||
- message: issuer must be an HTTPS URL
|
||||
rule: isURL(self) && url(self).getScheme() == 'https'
|
||||
tls:
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.16.4
|
||||
controller-gen.kubebuilder.io/version: v0.17.1
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user