Compare commits

...

584 Commits

Author SHA1 Message Date
anjalitelang
454b792afb Update ROADMAP.md
Changing the roadmap based on current priorities.
2021-09-16 08:46:03 -04:00
Ryan Richard
cb4085bfd9 Merge pull request #840 from vmware-tanzu/mod_tidy
ran `go mod tidy`
2021-09-15 14:47:22 -07:00
Ryan Richard
9b0dc92025 Merge branch 'main' into mod_tidy 2021-09-15 14:47:12 -07:00
Ryan Richard
7859a7b5c2 Merge pull request #839 from vmware-tanzu/deployment_selectors
Improve the selectors of Deployments and Services
2021-09-15 14:46:31 -07:00
Ryan Richard
bdcf468e52 Add log statement for when kube cert agent key has been loaded
Because it makes things easier to debug on a real cluster
2021-09-15 14:02:46 -07:00
Monis Khan
efaca05999 prevent kapp from altering the selector of our services
This makes it so that our service selector will match exactly the
YAML we specify instead of including an extra "kapp.k14s.io/app" key.
This will take us closer to the standard kubectl behavior which is
desirable since we want to avoid future bugs that only manifest when
kapp is not used.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-09-15 16:08:49 -04:00
Monis Khan
316e6171d4 Enable aggregator routing on kind clusters
This should make it easier for us to to notice if something is wrong
with our service (especially in any future kubectl tests we add).

Signed-off-by: Monis Khan <mok@vmware.com>
2021-09-15 15:09:15 -04:00
Ryan Richard
04544b3d3c Update TestKubeCertAgent to use new "v3" label value 2021-09-15 11:09:07 -07:00
Ryan Richard
85102b0118 ran go mod tidy 2021-09-15 09:21:46 -07:00
Ryan Richard
55de160551 Bump the version number of the kube cert agent label
Not required, but within the spirit of using the version number.
Since the existing kube cert agent deployment will get deleted anyway
during an upgrade, it shouldn't hurt to change the version number.
New installations will get the new version number on the new kube cert
agent deployment.
2021-09-14 15:27:15 -07:00
Ryan Richard
cec9f3c4d7 Improve the selectors of Deployments and Services
Fixes #801. The solution is complicated by the fact that the Selector
field of Deployments is immutable. It would have been easy to just
make the Selectors of the main Concierge Deployment, the Kube cert agent
Deployment, and the various Services use more specific labels, but
that would break upgrades. Instead, we make the Pod template labels and
the Service selectors more specific, because those not immutable, and
then handle the Deployment selectors in a special way.

For the main Concierge and Supervisor Deployments, we cannot change
their selectors, so they remain "app: app_name", and we make other
changes to ensure that only the intended pods are selected. We keep the
original "app" label on those pods and remove the "app" label from the
pods of the Kube cert agent Deployment. By removing it from the Kube
cert agent pods, there is no longer any chance that they will
accidentally get selected by the main Concierge Deployment.

For the Kube cert agent Deployment, we can change the immutable selector
by deleting and recreating the Deployment. The new selector uses only
the unique label that has always been applied to the pods of that
deployment. Upon recreation, these pods no longer have the "app" label,
so they will not be selected by the main Concierge Deployment's
selector.

The selector of all Services have been updated to use new labels to
more specifically target the intended pods. For the Concierge Services,
this will prevent them from accidentally including the Kube cert agent
pods. For the Supervisor Services, we follow the same convention just
to be consistent and to help future-proof the Supervisor app in case it
ever has a second Deployment added to it.

The selector of the auto-created impersonation proxy Service was
also previously using the "app" label. There is no change to this
Service because that label will now select the correct pods, since
the Kube cert agent pods no longer have that label. It would be possible
to update that selector to use the new more specific label, but then we
would need to invent a way to pass that label into the controller, so
it seemed like more work than was justified.
2021-09-14 13:35:10 -07:00
Ryan Richard
16f562e81c Merge pull request #838 from vmware-tanzu/dependabot/docker/golang-1.17.1
Bump golang from 1.17.0 to 1.17.1
2021-09-13 14:30:15 -07:00
dependabot[bot]
92ccc0ec84 Bump golang from 1.17.0 to 1.17.1
Bumps golang from 1.17.0 to 1.17.1.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 01:13:32 +00:00
Margo Crawford
74175f2518 Merge pull request #836 from vmware-tanzu/search-base-caching
Make sure search base in the validatedSettings cache is properly updated when the bind secret changes
2021-09-10 11:42:03 -07:00
Margo Crawford
0a1ee9e37c Remove unused functions 2021-09-08 10:34:42 -07:00
Margo Crawford
05f5bac405 ValidatedSettings is all or nothing
If either the search base or the tls settings is invalid, just
recheck everything.
2021-09-07 13:09:35 -07:00
Margo Crawford
0195894a50 Test fix for ldap upstream watcher 2021-09-07 13:09:35 -07:00
Margo Crawford
27c1d2144a Make sure search base in the validatedSettings cache is properly updated when the bind secret changes 2021-09-07 13:09:35 -07:00
Matt Moyer
88aba645b8 Merge pull request #837 from mattmoyer/so-long-and-thanks-for-all-the-fish
So long and thanks for all the fish 🦭
2021-09-03 10:49:35 -07:00
Matt Moyer
402c213183 So long and thanks for all the fish 🦭
Today is my last day working full time on Pinniped (for now). This change removes me from the MAINTAINERS.md and the website.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-09-03 12:38:53 -05:00
Mo Khan
17acc7caa6 Merge pull request #834 from anjaltelang/main
Add release note reference in the v0.11.0 Blog Post
2021-09-02 19:16:08 -04:00
Matt Moyer
6b7a230ca5 Merge pull request #835 from mattmoyer/fix-readonly-fields
Fix broken "read only" fields added in v0.11.0.
2021-09-02 15:23:26 -07:00
Matt Moyer
c7a8c429ed Add a dry-run 'kubectl apply' in prepare-for-integration-tests.sh so we can be sure that our manifests pass API validation.
We had this for some components, but not the ones that mattered the most.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-09-02 16:55:28 -05:00
Matt Moyer
f0a1555aca Fix broken "read only" fields added in v0.11.0.
These fields were changed as a minor hardening attempt when we switched to Distroless, but I bungled the field names and we never noticed because Kapp doesn't apply API validations.

This change fixes the field names so they act as was originally intended. We should also follow up with a change that validates all of our installation manifest in CI.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-09-02 16:12:39 -05:00
Anjali Telang
ccd338fa50 Merge branch 'main' of github.com:anjaltelang/pinniped into main 2021-09-02 14:54:48 -04:00
Anjali Telang
4e7214c6b5 Rephrased again
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-09-02 14:54:14 -04:00
Anjali Telang
2297ee4b81 Merge branch 'main' of github.com:anjaltelang/pinniped into main 2021-09-02 14:52:01 -04:00
Anjali Telang
85daec4748 Rephrased
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-09-02 14:51:36 -04:00
Anjali Telang
cf014656af Add Reference to release notes in the v0.11.0 Blog post
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-09-02 14:44:53 -04:00
Matt Moyer
b3b3c2303f Merge pull request #831 from anjaltelang/main
Add community info and resolve some minor issues
2021-09-02 09:02:24 -07:00
Matt Moyer
0ff66c718b Merge pull request #832 from vmware-tanzu/dependabot/docker/distroless/static-be5d77c
Bump distroless/static from `c9f9b04` to `be5d77c`
2021-09-02 05:40:51 -07:00
dependabot[bot]
1bb8a43e04 Bump distroless/static from c9f9b04 to be5d77c
Bumps distroless/static from `c9f9b04` to `be5d77c`.

---
updated-dependencies:
- dependency-name: distroless/static
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-02 03:00:24 +00:00
anjalitelang
655bbce42a Update ROADMAP.md
Updated September roadmap to reflect work on Improving Security Posture. Added CLI SSO as Future roadmap item.
2021-09-01 21:35:47 -04:00
Mo Khan
9258745ec7 Fix roadmap table formatting
We seem to have missed a `|` at the start of the table.
2021-09-01 15:33:23 -04:00
Anjali Telang
fcffab9a4c Add community info and resolve some minor issues
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-09-01 13:23:26 -04:00
Ryan Richard
92f7f12bab Update latest release tag in site/config.yaml, used by docs 2021-08-31 16:47:40 -07:00
Ryan Richard
7c40185676 Merge pull request #825 from anjaltelang/main
Add Blog post for v0.11.0 release
2021-08-31 16:46:23 -07:00
Pinny
abf19f649d Update CLI docs for v0.11.0 release 2021-08-31 23:40:00 +00:00
Pinny
0a2a716796 Update CLI docs for v0.10.0 release 2021-08-31 23:21:54 +00:00
Anjali Telang
a27e398923 Changed date and cleaned up some more AD format
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-08-31 15:02:57 -04:00
Ryan Richard
b19af2e135 Merge pull request #829 from enj/enj/i/wait_shutdown
Ensure concierge and supervisor gracefully exit
2021-08-31 11:30:35 -07:00
Ryan Richard
883007aa1b Merge pull request #756 from vmware-tanzu/ad-identity-provider-docs
Document how to configure the ActiveDirectoryIdentityProvider
2021-08-31 10:48:25 -07:00
Anjali Telang
ba1470ea9d Add AD changes
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-08-30 21:04:48 -04:00
Monis Khan
0d285ce993 Ensure concierge and supervisor gracefully exit
Changes made to both components:

1. Logs are always flushed on process exit
2. Informer cache sync can no longer hang process start up forever

Changes made to concierge:

1. Add pre-shutdown hook that waits for controllers to exit cleanly
2. Informer caches are synced in post-start hook

Changes made to supervisor:

1. Add shutdown code that waits for controllers to exit cleanly
2. Add shutdown code that waits for active connections to become idle

Waiting for controllers to exit cleanly is critical as this allows
the leader election logic to release the lock on exit.  This reduces
the time needed for the next leader to be elected.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-30 20:29:52 -04:00
Matt Moyer
e43bd59688 Merge pull request #830 from mattmoyer/update-youtube-demo-link
Update YouTube demo link to our official page.
2021-08-30 14:30:15 -07:00
Matt Moyer
0c8d885c26 Update YouTube demo link to our official page.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-08-30 16:29:32 -05:00
Anjali Telang
23fb84029b changes made on ryan's review comments
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-08-28 15:59:04 -04:00
Mo Khan
d2dfe3634a Merge pull request #828 from enj/enj/i/supervisor_graceful_exit
supervisor: ensure graceful exit
2021-08-28 13:40:13 -04:00
Monis Khan
5489f68e2f supervisor: ensure graceful exit
The kubelet will send the SIGTERM signal when it wants a process to
exit.  After a grace period, it will send the SIGKILL signal to
force the process to terminate.  The concierge has always handled
both SIGINT and SIGTERM as indicators for it to gracefully exit
(i.e. stop watches, controllers, etc).  This change updates the
supervisor to do the same (previously it only handled SIGINT).  This
is required to allow the leader election lock release logic to run.
Otherwise it can take a few minutes for new pods to acquire the
lease since they believe it is already held.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-28 11:23:11 -04:00
Ryan Richard
4eb500cc41 Merge pull request #826 from vmware-tanzu/simplify_readme
Simplify the main README.md to reduce duplication with website
2021-08-27 16:40:53 -07:00
Ryan Richard
871a9fb0c6 Simplify the main README.md to reduce duplication with website 2021-08-27 15:52:51 -07:00
Anjali Telang
4cb0152ea1 Merge branch 'main' of github.com:anjaltelang/pinniped into main 2021-08-27 17:15:55 -04:00
Anjali Telang
42af8acd1e Fixed yaml format for Aud
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-08-27 17:14:53 -04:00
Anjali Telang
df014dadc3 Remove unnecessary space after image 2021-08-27 17:07:02 -04:00
Anjali Telang
bb657e7432 Blog for v0.11.0
Signed-off-by: Anjali Telang <atelang@vmware.com>
2021-08-27 17:00:34 -04:00
Mo Khan
d580695faa Merge pull request #824 from enj/enj/t/disruptive_hang
test/integration: use short timeouts with distinct requests to prevent hangs
2021-08-27 16:38:39 -04:00
Monis Khan
ba80b691e1 test/integration: use short timeouts with distinct requests to prevent hangs
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 16:10:36 -04:00
Mo Khan
41c017c9da Merge pull request #821 from enj/enj/t/increase_disruptive_test_timeout
test/integration: increase timeout on disruptive tests
2021-08-27 15:24:43 -04:00
Monis Khan
5078cdbc90 test/integration: increase timeout on disruptive tests
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 14:56:51 -04:00
Margo Crawford
e5718351ba Merge pull request #695 from vmware-tanzu/active-directory-identity-provider
Active directory identity provider
2021-08-27 08:39:12 -07:00
Mo Khan
36ff0d52da Merge pull request #818 from enj/enj/i/bump_go1.17
Bump to Go 1.17.0
2021-08-27 10:30:51 -04:00
Monis Khan
ad3086b8f1 Downgrade go mod compat to 1.16 for golangci-lint
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 10:03:48 -04:00
Monis Khan
6c29f347b4 go 1.17 bump: fix unit test failures
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 09:46:58 -04:00
Monis Khan
a86949d0be Use go 1.17 module lazy loading
See https://golang.org/doc/go1.17#go-command for details.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 09:46:58 -04:00
Monis Khan
44f03af4b9 Bump to Go 1.17.0
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 09:00:49 -04:00
Mo Khan
ce5cfde11e Merge pull request #816 from enj/enj/i/bump_1.22.1
Bump Kube to v0.22.1
2021-08-27 08:40:23 -04:00
Monis Khan
40d70bf1fc Bump Kube to v0.22.1
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-27 07:36:12 -04:00
Margo Crawford
19100d68ef Merge branch 'main' of github.com:vmware-tanzu/pinniped into active-directory-identity-provider 2021-08-26 20:42:16 -07:00
Mo Khan
1d44aa945d Merge pull request #814 from mayankbh/topic/bmayank/inherit-hostnetwork
Allow use of hostNetwork for kube-cert-agent
2021-08-26 21:13:29 -04:00
Mayank Bhatt
68547f767d Copy hostNetwork field for kube-cert-agent
For clusters where the control plane nodes aren't running a CNI, the
kube-cert-agent pods deployed by concierge cannot be scheduled as they
don't know to use `hostNetwork: true`. This change allows embedding the
host network setting in the Concierge configuration. (by copying it from
the kube-controller-manager pod spec when generating the kube-cert-agent
Deployment)

Also fixed a stray double comma in one of the nearby tests.
2021-08-26 17:09:59 -07:00
Margo Crawford
44e5e9d8c9 Add sentence about api docs 2021-08-26 17:02:56 -07:00
Margo Crawford
43694777d5 Change some comments on API docs, fix lint error by ignoring it 2021-08-26 16:55:43 -07:00
Ryan Richard
f579b1cb9f Merge pull request #812 from vmware-tanzu/resources_section_web_site
Add "Resources" section to pinniped.dev web site
2021-08-26 16:23:36 -07:00
Margo Crawford
2d32e0fa7d Merge branch 'main' of github.com:vmware-tanzu/pinniped into active-directory-identity-provider 2021-08-26 16:21:08 -07:00
Margo Crawford
6f221678df Change sAMAccountName env vars to userPrincipalName
and add E2E ActiveDirectory test
also fixed regexes in supervisor_login_test to be anchored to the
beginning and end
2021-08-26 16:18:05 -07:00
Ryan Richard
e24040b0a9 add link to CNCF presentation slides 2021-08-26 15:52:04 -07:00
Mo Khan
1d269d2f6d Merge pull request #815 from enj/enj/t/integration_parallel_disruptive
test/integration: mark certain tests as disruptive
2021-08-26 17:32:14 -04:00
Monis Khan
d4a7f0b3e1 test/integration: mark certain tests as disruptive
This prevents them from running with any other test, including other
parallel tests.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-26 15:11:47 -04:00
Mo Khan
d22099ac33 Merge pull request #808 from enj/enj/t/integration_parallel
test/integration: run parallel tests concurrently with serial tests
2021-08-26 14:34:18 -04:00
Monis Khan
e2cf9f6b74 leader election test: approximate that followers have observed change
Instead of blindly waiting long enough for a disruptive change to
have been observed by the old leader and followers, we instead rely
on the approximation that checkOnlyLeaderCanWrite provides - i.e.
only a single actor believes they are the leader.  This does not
account for clients that were in the followers list before and after
the disruptive change, but it serves as a reasonable approximation.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-26 12:59:52 -04:00
Monis Khan
74daa1da64 test/integration: run parallel tests concurrently with serial tests
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-26 12:59:52 -04:00
Ryan Richard
475da05185 Merge pull request #810 from vmware-tanzu/docs_gitops_example
Install docs use more GitOps-friendly style
2021-08-25 16:46:58 -07:00
Ryan Richard
86bfd4f5e4 Number each install step using "1." 2021-08-25 16:37:36 -07:00
Ryan Richard
d453bf3403 Add "Resources" section to pinniped.dev web site 2021-08-25 16:25:53 -07:00
Mo Khan
2b9b034bd2 Merge pull request #811 from vmware-tanzu/test_shell_container_image
Replace one-off usages of busybox and debian images in integration tests
2021-08-25 19:13:13 -04:00
Ryan Richard
d20cab10b9 Replace one-off usages of busybox and debian images in integration tests
Those images that are pulled from Dockerhub will cause pull failures
on some test clusters due to Dockerhub rate limiting.

Because we already have some images that we use for testing, and
because those images are already pre-loaded onto our CI clusters
to make the tests faster, use one of those images and always specify
PullIfNotPresent to avoid pulling the image again during the integration
test.
2021-08-25 15:12:07 -07:00
Ryan Richard
399737e7c6 Install docs use more GitOps-friendly style 2021-08-25 14:33:48 -07:00
Margo Crawford
1c5a2b8892 Add a couple more unit tests 2021-08-25 11:33:42 -07:00
Mo Khan
c17e7bec49 Merge pull request #800 from enj/enj/i/leader_election_release
leader election: fix small race duration lease release
2021-08-25 10:29:19 -04:00
Monis Khan
c71ffdcd1e leader election: use better duration defaults
OpenShift has good defaults for these duration fields that we can
use instead of coming up with them ourselves:

e14e06ba8d/pkg/config/leaderelection/leaderelection.go (L87-L109)

Copied here for easy future reference:

// We want to be able to tolerate 60s of kube-apiserver disruption without causing pod restarts.
// We want the graceful lease re-acquisition fairly quick to avoid waits on new deployments and other rollouts.
// We want a single set of guidance for nearly every lease in openshift.  If you're special, we'll let you know.
// 1. clock skew tolerance is leaseDuration-renewDeadline == 30s
// 2. kube-apiserver downtime tolerance is == 78s
//      lastRetry=floor(renewDeadline/retryPeriod)*retryPeriod == 104
//      downtimeTolerance = lastRetry-retryPeriod == 78s
// 3. worst non-graceful lease acquisition is leaseDuration+retryPeriod == 163s
// 4. worst graceful lease acquisition is retryPeriod == 26s
if ret.LeaseDuration.Duration == 0 {
	ret.LeaseDuration.Duration = 137 * time.Second
}

if ret.RenewDeadline.Duration == 0 {
	// this gives 107/26=4 retries and allows for 137-107=30 seconds of clock skew
	// if the kube-apiserver is unavailable for 60s starting just before t=26 (the first renew),
	// then we will retry on 26s intervals until t=104 (kube-apiserver came back up at 86), and there will
	// be 33 seconds of extra time before the lease is lost.
	ret.RenewDeadline.Duration = 107 * time.Second
}
if ret.RetryPeriod.Duration == 0 {
	ret.RetryPeriod.Duration = 26 * time.Second
}

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-24 16:21:53 -04:00
Margo Crawford
c590c8ff41 Merge branch 'main' of github.com:vmware-tanzu/pinniped into active-directory-identity-provider 2021-08-24 12:19:29 -07:00
Monis Khan
c0617ceda4 leader election: in-memory leader status is stopped before release
This change fixes a small race condition that occurred when the
current leader failed to renew its lease.  Before this change, the
leader would first release the lease via the Kube API and then would
update its in-memory status to reflect that change.  Now those
events occur in the reverse (i.e. correct) order.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-24 15:02:56 -04:00
Mo Khan
f7751d13fe Merge pull request #778 from vmware-tanzu/oidc_password_grant
Optionally allow OIDC password grant for CLI-based login experience
2021-08-24 13:02:07 -04:00
Mo Khan
3077034b2d Merge branch 'main' into oidc_password_grant 2021-08-24 12:23:52 -04:00
Mo Khan
89cef2ea6c Merge pull request #796 from enj/enj/i/leader_election_flake
leader election test: fix flake related to invalid assumption
2021-08-20 19:06:51 -04:00
Ryan Richard
211f4b23d1 Log auth endpoint errors with stack traces 2021-08-20 14:41:02 -07:00
Monis Khan
132ec0d2ad leader election test: fix flake related to invalid assumption
Even though a client may hold the leader election lock in the Kube
lease API, that does not mean it has had a chance to update its
internal state to reflect that.  Thus we retry the checks in
checkOnlyLeaderCanWrite a few times to allow the client to catch up.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-20 17:04:26 -04:00
Mo Khan
ae505d8009 Merge pull request #788 from enj/enj/i/leader_election
Add Leader Election Middleware
2021-08-20 12:58:27 -04:00
Monis Khan
c356710f1f Add leader election middleware
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-20 12:18:25 -04:00
Matt Moyer
b9d186e8a3 Merge pull request #786 from mattmoyer/cleanup-go-mod
Cleanup `go.mod` replace directives that are no longer needed.
2021-08-20 08:43:36 -07:00
Matt Moyer
03a8160a91 Remove replace directive for dgrijalva/jwt-go.
We no longer have a transitive dependency on this older repository, so we don't need the replace directive anymore.

There is a new fork of this that we should move to (https://github.com/golang-jwt/jwt), but we can't easily do that until a couple of our direct dependencies upgrade.

This is a revert of d162cb9adf.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-08-20 10:15:55 -05:00
Matt Moyer
f379eee7a3 Drop replace directive for oleiade/reflections.
This is reverting 8358c26107.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-08-20 10:15:55 -05:00
Matt Moyer
4f5312807b Undo dep hacks to work around gRPC example module.
This is essentially reverting 87c7e89b13.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-08-20 10:15:54 -05:00
Margo Crawford
cec3c2133a Update with new default values 2021-08-19 16:27:43 -07:00
Margo Crawford
05afae60c2 Review comments--
- Change list of attributeParsingOverrides to a map
- Add unit test for sAMAccountName as group name without the override
- Change some comments in the the type definition.
2021-08-19 14:21:18 -07:00
Ryan Richard
6239a567a8 remove one nolint:unparam comment 2021-08-19 10:57:00 -07:00
Ryan Richard
e4d418a076 Merge branch 'main' into oidc_password_grant 2021-08-19 10:55:54 -07:00
Ryan Richard
c4727d57c8 Merge pull request #789 from vmware-tanzu/remove_unparam_linter
Remove `unparam` linter
2021-08-19 10:55:04 -07:00
Ryan Richard
b4a39ba3c4 Remove unparam linter
We decided that this linter does not provide very useful feedback
for our project.
2021-08-19 10:20:24 -07:00
Ryan Richard
cf627a82cb Merge branch 'main' into oidc_password_grant 2021-08-19 10:00:11 -07:00
Ryan Richard
42d31a7085 Update login.md doc to mention OIDC CLI-based flow 2021-08-19 09:59:47 -07:00
anjalitelang
02b8ed7e0b Update ROADMAP.md
Removing features listed for July as they are shipped.
2021-08-19 12:19:31 -04:00
Margo Crawford
5e9087263d Increase timeout for activedirectoryidentityprovider to be loaded 2021-08-18 16:24:05 -07:00
Margo Crawford
a20aee5f18 Update test assertions to reflect userPrincipalName as username 2021-08-18 13:18:53 -07:00
Margo Crawford
1d18908055 Fix test error-- execcredential now has interactive:false
for activedirectoryidentityprovider test, which didn't exist on main
when #770 was merged to update the other tests to use 1.22.
2021-08-18 12:55:26 -07:00
Margo Crawford
1c5da35527 Merge remote-tracking branch 'origin' into active-directory-identity-provider 2021-08-18 12:44:12 -07:00
Ryan Richard
61c21d2977 Refactor some authorize and callback error handling, and add more tests 2021-08-18 12:06:46 -07:00
Margo Crawford
90e6298e29 Update text on CRD templates to reflect new defaults 2021-08-18 10:39:01 -07:00
Ryan Richard
04b8f0b455 Extract Supervisor authorize endpoint string constants into apis pkg 2021-08-18 10:20:33 -07:00
Margo Crawford
8657b0e3e7 Cleanup new group attribute behavior and add test coverage 2021-08-18 10:11:18 -07:00
Ryan Richard
0089540b07 Extract Supervisor IDP discovery endpoint string constants into apis pkg 2021-08-17 17:50:02 -07:00
Margo Crawford
26c47d564f Make new combined sAMAccountName@domain attribute the group name
Also change default username attribute to userPrincipalName
2021-08-17 16:53:26 -07:00
Ryan Richard
62c6d53a21 Merge branch 'main' into oidc_password_grant 2021-08-17 15:23:29 -07:00
Ryan Richard
96474b3d99 Extract Supervisor IDP discovery endpoint types into apis package 2021-08-17 15:23:03 -07:00
Ryan Richard
964d16110e Some refactors based on PR feedback from @enj 2021-08-17 13:14:09 -07:00
Matt Moyer
d57637ee56 Merge pull request #783 from enj/enj/t/ignore_test_pods
test/integration: ignore restarts associated with test pods
2021-08-17 11:00:19 -07:00
Mo Khan
8ce4bb6dc1 Merge pull request #784 from enj/enj/r/specific_private
dynamiccert: prevent misuse of NewServingCert
2021-08-17 13:56:23 -04:00
Ryan Richard
a7c88b599c Merge branch 'main' into oidc_password_grant 2021-08-17 10:45:00 -07:00
Monis Khan
e0901f4fe5 dynamiccert: prevent misuse of NewServingCert
The Kube API server code that we use will cast inputs in an attempt
to see if they implement optional interfaces.  This change adds a
simple wrapper struct to prevent such casts from causing us any
issues.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-17 12:58:32 -04:00
Monis Khan
cf25c308cd test/integration: ignore restarts associated with test pods
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-17 12:57:41 -04:00
Mo Khan
9d11be899c Merge pull request #785 from enj/enj/i/no_proxy_env
Provide good defaults for NO_PROXY
2021-08-17 12:55:12 -04:00
Monis Khan
66ddcf98d3 Provide good defaults for NO_PROXY
This change updates the default NO_PROXY for the supervisor to not
proxy requests to the Kubernetes API and other Kubernetes endpoints
such as Kubernetes services.

It also adds https_proxy and no_proxy settings for the concierge
with the same default.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-17 10:03:19 -04:00
Ryan Richard
3fb683f64e Update expected error message in e2e integration test 2021-08-16 15:40:34 -07:00
Ryan Richard
52409f86e8 Merge branch 'main' into oidc_password_grant 2021-08-16 15:17:55 -07:00
Ryan Richard
91c8a3ebed Extract private helper in auth_handler.go 2021-08-16 15:17:30 -07:00
Ryan Richard
52cb0bbc07 More unit tests and small error handling changes for OIDC password grant 2021-08-16 14:27:40 -07:00
Mo Khan
eb2a68fec0 Merge pull request #782 from vmware-tanzu/dependabot/go_modules/github.com/go-ldap/ldap/v3-3.4.1
Bump github.com/go-ldap/ldap/v3 from 3.3.0 to 3.4.1
2021-08-16 17:20:06 -04:00
dependabot[bot]
e05a46b7f5 Bump github.com/go-ldap/ldap/v3 from 3.3.0 to 3.4.1
Bumps [github.com/go-ldap/ldap/v3](https://github.com/go-ldap/ldap) from 3.3.0 to 3.4.1.
- [Release notes](https://github.com/go-ldap/ldap/releases)
- [Commits](https://github.com/go-ldap/ldap/compare/v3.3.0...v3.4.1)

---
updated-dependencies:
- dependency-name: github.com/go-ldap/ldap/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-16 20:46:25 +00:00
Mo Khan
46304c8137 Merge pull request #775 from enj/enj/i/dynamiccert_no_unload
impersonatorconfig: only unload dynamiccert when proxy is disabled
2021-08-16 16:36:03 -04:00
Monis Khan
7a812ac5ed impersonatorconfig: only unload dynamiccert when proxy is disabled
In the upstream dynamiccertificates package, we rely on two pieces
of code:

1. DynamicServingCertificateController.newTLSContent which calls
   - clientCA.CurrentCABundleContent
   - servingCert.CurrentCertKeyContent
2. unionCAContent.VerifyOptions which calls
   - unionCAContent.CurrentCABundleContent

This results in calls to our tlsServingCertDynamicCertProvider and
impersonationSigningCertProvider.  If we Unset these providers, we
subtly break these consumers.  At best this results in test slowness
and flakes while we wait for reconcile loops to converge.  At worst,
it results in actual errors during runtime.  For example, we
previously would Unset the impersonationSigningCertProvider on any
sync loop error (even a transient one caused by a network blip or
a conflict between writes from different replicas of the concierge).
This would cause us to transiently fail to issue new certificates
from the token credential require API.  It would also cause us to
transiently fail to authenticate previously issued client certs
(which results in occasional Unauthorized errors in CI).

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-16 16:07:46 -04:00
Ryan Richard
71d6281e39 Merge branch 'main' into oidc_password_grant 2021-08-16 09:30:13 -07:00
Mo Khan
bb30569e41 Merge pull request #780 from enj/enj/i/browser_stderr
cli: prevent browser output from breaking ExecCredential output
2021-08-16 10:34:33 -04:00
Monis Khan
942c55cf51 cli: prevent browser output from breaking ExecCredential output
This change updates the pinniped CLI entrypoint to prevent browser
processes that we spawn from polluting our std out stream.

For example, chrome will print the following message to std out:

Opening in existing browser session.

Which leads to the following incomprehensible error message from
kubectl:

Unable to connect to the server: getting credentials:
decoding stdout: couldn't get version/kind; json parse error:
json: cannot unmarshal string into Go value of type struct
{ APIVersion string "json:\"apiVersion,omitempty\"";
  Kind string "json:\"kind,omitempty\"" }

This would only occur on the initial login when we opened the
browser.  Since credentials would be cached afterwards, kubectl
would work as expected for future invocations as no browser was
opened.

I could not think of a good way to actually test this change.  There
is a clear gap in our integration tests - we never actually launch a
browser in the exact same way a user does - we instead open a chrome
driver at the login URL as a subprocess of the integration test
binary and not the pinniped CLI.  Thus even if the chrome driver was
writing to std out, we would not notice any issues.

It is also unclear if there is a good way to prevent future related
bugs since std out is global to the process.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-16 09:13:57 -04:00
Ryan Richard
50085a505b First unit test for auth endpoint's password grant and related refactor 2021-08-12 17:53:14 -07:00
Ryan Richard
69964fc788 New unit tests updated for Kube 1.22 ExecCredential changes from main
After merging the new Kube 1.22 ExecCredential changes from main into
this feature branch, some of the new units test on this feature branch
needed to be update to account for the new ExecCredential "interactive"
field.
2021-08-12 13:35:56 -07:00
Ryan Richard
5b96d014b4 Merge branch 'main' into oidc_password_grant 2021-08-12 11:12:57 -07:00
Ryan Richard
84c3c3aa9c Optionally allow OIDC password grant for CLI-based login experience
- Add `AllowPasswordGrant` boolean field to OIDCIdentityProvider's spec
- The oidc upstream watcher controller copies the value of
  `AllowPasswordGrant` into the configuration of the cached provider
- Add password grant to the UpstreamOIDCIdentityProviderI interface
  which is implemented by the cached provider instance for use in the
  authorization endpoint
- Enhance the IDP discovery endpoint to return the supported "flows"
  for each IDP ("cli_password" and/or "browser_authcode")
- Enhance `pinniped get kubeconfig` to help the user choose the desired
  flow for the selected IDP, and to write the flow into the resulting
  kubeconfg
- Enhance `pinniped login oidc` to have a flow flag to tell it which
  client-side flow it should use for auth (CLI-based or browser-based)
- In the Dex config, allow the resource owner password grant, which Dex
  implements to also return ID tokens, for use in integration tests
- Enhance the authorize endpoint to perform password grant when
  requested by the incoming headers. This commit does not include unit
  tests for the enhancements to the authorize endpoint, which will come
  in the next commit
- Extract some shared helpers from the callback endpoint to share the
  code with the authorize endpoint
- Add new integration tests
2021-08-12 10:45:39 -07:00
anjalitelang
592563124b Update ROADMAP.md
Updated the roadmap to reflect the Non-Interactive Password based Login support we delivered in July for LDAP and TBD in Aug for OIDC
2021-08-12 11:08:27 -04:00
Mo Khan
c4d7e5c124 Merge pull request #770 from enj/enj/i/bump_1.22.0
Bump to Go 1.16.7 and Kube v0.22.0
2021-08-10 12:29:35 -04:00
Monis Khan
34fd0ea2e2 impersonation proxy: assert nested UID impersonation is disallowed
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-10 00:03:33 -04:00
Monis Khan
5678fc6196 login: update tests for new client exec code
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 19:16:55 -04:00
Monis Khan
4a17e1e736 impersonator: update tests for new Impersonate-Uid code
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 19:16:54 -04:00
Monis Khan
724acdca1d Update tests for new CSR duration code
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 19:16:50 -04:00
Monis Khan
a027f1ae2c jwtcachefiller: update to use CAContentProvider
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 19:16:25 -04:00
Monis Khan
d2891554a4 remove google.golang.org/grpc pin
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 19:16:14 -04:00
Monis Khan
25b4d82d87 Bump to Go 1.16.7 and Kube v0.22.0
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-09 15:32:13 -04:00
Mo Khan
01ddc7ac36 Merge pull request #738 from mattmoyer/distroless
Switch to a slimmer distroless base image
2021-08-09 15:31:17 -04:00
Matt Moyer
58bbffded4 Switch to a slimmer distroless base image.
At a high level, it switches us to a distroless base container image, but that also includes several related bits:

- Add a writable /tmp but make the rest of our filesystems read-only at runtime.

- Condense our main server binaries into a single pinniped-server binary. This saves a bunch of space in
  the image due to duplicated library code. The correct behavior is dispatched based on `os.Args[0]`, and
  the `pinniped-server` binary is symlinked to `pinniped-concierge` and `pinniped-supervisor`.

- Strip debug symbols from our binaries. These aren't really useful in a distroless image anyway and all the
  normal stuff you'd expect to work, such as stack traces, still does.

- Add a separate `pinniped-concierge-kube-cert-agent` binary with "sleep" and "print" functionality instead of
  using builtin /bin/sleep and /bin/cat for the kube-cert-agent. This is split from the main server binary
  because the loading/init time of the main server binary was too large for the tiny resource footprint we
  established in our kube-cert-agent PodSpec. Using a separate binary eliminates this issue and the extra
  binary adds only around 1.5MiB of image size.

- Switch the kube-cert-agent code to use a JSON `{"tls.crt": "<b64 cert>", "tls.key": "<b64 key>"}` format.
  This is more robust to unexpected input formatting than the old code, which simply concatenated the files
  with some extra newlines and split on whitespace.

- Update integration tests that made now-invalid assumptions about the `pinniped-server` image.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-08-09 15:05:13 -04:00
Matt Moyer
a464c81711 Bump latest version on website.
We accidentally missed this in the v0.10.0 release process. The new YAML field here should make it easier to automate this step, which seems like a really good idea.
2021-08-03 09:21:54 -05:00
Mo Khan
f18cbcd9a6 Merge pull request #763 from enj/enj/i/eks_slow_test
concierge_impersonation_proxy_test: run slowly for EKS
2021-08-01 18:21:54 -04:00
Monis Khan
ac7d65c4a8 concierge_impersonation_proxy_test: run slowly for EKS
Signed-off-by: Monis Khan <mok@vmware.com>
2021-08-01 18:19:53 -04:00
Matt Moyer
65fa47cbcd Link to the release from our v0.10.0 blog post.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-30 16:35:38 -05:00
Matt Moyer
a06b38d2cd Merge pull request #760 from mattmoyer/add-v0.10.0-blog-post
Add v0.10.0 blog post.
2021-07-30 16:21:36 -05:00
Matt Moyer
7773fb8afe Add v0.10.0 blog post.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-30 15:30:56 -05:00
Matt Moyer
f4badb3961 Merge pull request #758 from mattmoyer/use-plain-authcode-prompt
Fix broken TTY after manual auth code prompt.
2021-07-30 13:50:27 -05:00
Matt Moyer
1e32530d7b Fix broken TTY after manual auth code prompt.
This may be a temporary fix. It switches the manual auth code prompt to use `promptForValue()` instead of `promptForSecret()`. The `promptForSecret()` function no longer supports cancellation (the v0.9.2 behavior) and the method of cancelling in `promptForValue()` is now based on running the blocking read in a background goroutine, which is allowed to block forever or leak (which is not important for our CLI use case).

This means that the authorization code is now visible in the user's terminal, but this is really not a big deal because of PKCE and the limited lifetime of an auth code.

The main goroutine now correctly waits for the "manual prompt" goroutine to clean up, which now includes printing the extra newline that would normally have been entered by the user in the manual flow.

The text of the manual login prompt is updated to be more concise and less scary (don't use the word "fail").

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-30 12:45:44 -05:00
Matt Moyer
0ab8e14e4a Merge pull request #755 from mattmoyer/update-installation-docs
Update installation documentation
2021-07-29 17:54:23 -05:00
Mo Khan
f1109afa79 Merge pull request #757 from enj/enj/t/dns_hacks
concierge_impersonation_proxy_test: check all forms of DNS
2021-07-29 15:51:22 -04:00
Monis Khan
22be97eeda concierge_impersonation_proxy_test: check all forms of DNS
Signed-off-by: Monis Khan <mok@vmware.com>
2021-07-29 13:35:37 -04:00
Matt Moyer
d23f3c9428 Update ROADMAP.md 2021-07-29 10:22:43 -05:00
Matt Moyer
c3e037b24e Fix a broken link in .../docs/howto/configure-supervisor.md.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-29 09:56:00 -05:00
Matt Moyer
62afb34877 Fix command typo and expand description of values.yaml a bit.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-29 08:45:19 -05:00
Matt Moyer
fd5ed2e5da Rework "install" sections of our docs.
- Remove all the "latest" links and replace them with our new shortcode so they point at the latest release in a more explicit way.
  This also eliminates one of the sections in our Concierge and Supervisor install guides, since you're always installing a specific version.

- Provide instructions for installing with both kapp (one step) and kubectl (two steps for the Concierge).

- Minor wording changes. Mainly we are now a bit less verbose about reminding people they can choose a different version (once per page instead of in each step).

- When we give an example `kapp deploy` command, don't suggest `--yes` and `--diff-changes`.
  Users can still use these but it seems overly verbose for an example command.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-29 08:45:19 -05:00
Matt Moyer
ca82609d1a Create a site parameter and shortcode for "latestversion".
This gives us a single line of YAML to edit when we want to bump our docs to the latest version number.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-29 08:45:18 -05:00
Margo Crawford
a6dc5b912f Document how to configure the ActiveDirectoryIdentityProvider 2021-07-28 14:35:29 -07:00
Ryan Richard
d73093a694 Avoid failures due to impersonation Service having unrelated annotations 2021-07-28 14:19:14 -07:00
Matt Moyer
85560299e0 Merge pull request #754 from mattmoyer/fix-TestLegacyPodCleaner-flake
Relax the timeout for TestLegacyPodCleaner a bit.
2021-07-28 12:43:08 -06:00
Matt Moyer
b42b1c1110 Relax the timeout for TestLegacyPodCleaner a bit.
This test is asynchronously waiting for the controller to do something, and in some of our test environments it will take a bit longer than we'd previously allowed.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-28 13:08:57 -05:00
Matt Moyer
84733405d0 Merge pull request #753 from mattmoyer/fix-e2e-test-assertion
Fix backwards condition in E2E test assertion.
2021-07-28 12:07:00 -06:00
Matt Moyer
48c8fabb5c Fix backwards condition in E2E test assertion.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-28 12:40:07 -05:00
Matt Moyer
1f51159d22 Merge pull request #752 from mattmoyer/fix-impersonator-config-controller-informers
Add ClusterIP service to impersonator-config-controller informer.
2021-07-28 11:28:30 -06:00
Matt Moyer
5f679059d5 Add ClusterIP service to impersonator-config-controller informer.
Prior to this fix, this controller did not correctly react to changes to the ClusterIP service. It would still eventually react with a long delay due to our 5 minute resync interval.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-28 11:57:18 -05:00
Ryan Richard
8afbb4eb4f Merge pull request #744 from vmware-tanzu/dependabot/go_modules/github.com/tdewolff/minify/v2-2.9.20
Bump github.com/tdewolff/minify/v2 from 2.9.19 to 2.9.20
2021-07-28 09:08:22 -07:00
Ryan Richard
c9b4598fa0 Merge pull request #745 from vmware-tanzu/dependabot/go_modules/github.com/creack/pty-1.1.14
Bump github.com/creack/pty from 1.1.13 to 1.1.14
2021-07-28 09:08:03 -07:00
Mo Khan
ef33846d7d Merge pull request #747 from enj/enj/i/delete_race
certs_expirer: be specific about what secret to delete
2021-07-28 10:32:17 -04:00
Monis Khan
8b4ed86071 certs_expirer: be specific about what secret to delete
This change fixes a race that can occur because we have multiple
writers with no leader election lock.

1. TestAPIServingCertificateAutoCreationAndRotation/automatic
   expires the current serving certificate
2. CertsExpirerController 1 deletes expired serving certificate
3. CertsExpirerController 2 starts deletion of expired serving
   certificate but has not done so yet
4. CertsManagerController 1 creates new serving certificate
5. TestAPIServingCertificateAutoCreationAndRotation/automatic
   records the new serving certificate
6. CertsExpirerController 2 finishes deletion, and thus deletes the
   newly created serving certificate instead of the old one
7. CertsManagerController 2 creates new serving certificate
8. TestAPIServingCertificateAutoCreationAndRotation/automatic keeps
   running and eventually times out because it is expecting the
   serving certificate created by CertsManagerController 2 to match
   the value it recorded from CertsManagerController 1 (which will
   never happen since that certificate was incorrectly deleted).

Signed-off-by: Monis Khan <mok@vmware.com>
2021-07-28 09:56:05 -04:00
Mo Khan
8b74dd824b Merge pull request #748 from mattmoyer/fix-css-text-wrapping
Fix form_post CSS styling in Firefox and Safari.
2021-07-28 09:55:39 -04:00
Matt Moyer
727035a2dc Fix form_post CSS styling in Firefox and Safari.
This functioned fine, but did not have the intended visual appearance when it came to how the text of the auth code wrapped inside the copy button in the manual flow.

The new styling behaves correctly on at least Chrome, Firefox, and Safari on macOS.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-28 08:09:20 -05:00
dependabot[bot]
fc82fde585 Bump github.com/tdewolff/minify/v2 from 2.9.19 to 2.9.20
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.9.19 to 2.9.20.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.9.19...v2.9.20)

---
updated-dependencies:
- dependency-name: github.com/tdewolff/minify/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-28 00:03:48 +00:00
dependabot[bot]
f352db8072 Bump github.com/creack/pty from 1.1.13 to 1.1.14
Bumps [github.com/creack/pty](https://github.com/creack/pty) from 1.1.13 to 1.1.14.
- [Release notes](https://github.com/creack/pty/releases)
- [Commits](https://github.com/creack/pty/compare/v1.1.13...v1.1.14)

---
updated-dependencies:
- dependency-name: github.com/creack/pty
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-28 00:03:39 +00:00
Margo Crawford
f075d95183 Merge branch 'main' of github.com:vmware-tanzu/pinniped into active-directory-identity-provider 2021-07-27 15:16:52 -07:00
Matt Moyer
22a66c1192 Merge pull request #746 from mattmoyer/fix-windows-build
Fix CLI compilation on Windows.
2021-07-27 16:15:01 -06:00
Margo Crawford
474266f918 Merge branch 'main' of github.com:vmware-tanzu/pinniped into active-directory-identity-provider 2021-07-27 15:06:58 -07:00
Matt Moyer
8e8af51955 Fix CLI compilation on Windows.
It turns out that `syscall.Stdin` is of type `int` on Linux and macOS, but not on Windows (it's `syscall.Handle`). This should now be portable and do all the require type casting on every platform.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-27 16:10:05 -05:00
Ryan Richard
d5759c9951 Merge pull request #739 from vmware-tanzu/merge_impersonator_service_annotations
Carefully merge desired annotations into impersonation proxy Service
2021-07-27 12:40:31 -07:00
Ryan Richard
bf99348faf Merge branch 'main' into merge_impersonator_service_annotations 2021-07-27 12:40:02 -07:00
Mo Khan
2789af79f6 Merge pull request #742 from enj/enj/i/bump_1.21.3
Bump to Go 1.16.6 and Kube v0.21.3
2021-07-27 15:34:37 -04:00
Ryan Richard
71cae75758 Merge branch 'main' into merge_impersonator_service_annotations 2021-07-27 11:57:16 -07:00
Ryan Richard
90db3ad51b Merge pull request #730 from vmware-tanzu/cli_username_password_env_vars
LDAP logins via CLI read from `PINNIPED_USERNAME` and `PINNIPED_PASSWORD` env vars
2021-07-27 11:56:40 -07:00
Monis Khan
32c9aa5087 Bump to Go 1.16.6 and Kube v0.21.3
Signed-off-by: Monis Khan <mok@vmware.com>
2021-07-27 14:18:08 -04:00
Margo Crawford
bbaa820278 parsing objectGUID as human-readable string version 2021-07-27 11:08:23 -07:00
Margo Crawford
287a5d225a Change SearchBaseFound condition success reason to be a string constant 2021-07-27 10:23:05 -07:00
Ryan Richard
f17f7c0c6a Small refactors in impersonator_config.go suggested by @mattmoyer 2021-07-26 17:46:06 -07:00
Ryan Richard
54c5bcc9a1 Merge branch 'main' into merge_impersonator_service_annotations 2021-07-26 17:25:52 -07:00
Ryan Richard
58ab57201f Suppress lint errors 2021-07-26 17:20:49 -07:00
Ryan Richard
f4829178b3 Use sentence case for headers in docs
Following some common developer style guides such as
Google
https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings
and Microsoft
https://docs.microsoft.com/en-us/style-guide/scannable-content/headings#formatting-headings
2021-07-26 17:18:44 -07:00
Ryan Richard
295f013580 Merge branch 'main' into cli_username_password_env_vars 2021-07-26 17:04:46 -07:00
Margo Crawford
53b58f65b2 Add integration test for wrong password with ldap 2021-07-26 16:32:46 -07:00
Margo Crawford
cc3875f048 PR feedback 2021-07-26 16:03:12 -07:00
Ryan Richard
d8e1521457 Merge pull request #741 from vmware-tanzu/dockerignore
dockerignore gets same contents as gitignore
2021-07-26 12:47:26 -07:00
Ryan Richard
e150111b27 dockerignore gets same contents as gitignore 2021-07-26 11:28:25 -07:00
Ryan Richard
9e27c28b39 Fix TestImpersonationProxy integration test changes from previous commit
Forgot to account for our new booking annotation on the impersonator's
Service.
2021-07-23 14:23:24 -07:00
Margo Crawford
5d23068690 Removed a todo that was resolved 2021-07-23 13:01:41 -07:00
Margo Crawford
1050f39789 Integration test deactivated ad account 2021-07-23 13:01:41 -07:00
Margo Crawford
00978c15f7 Update wording for ActiveDirectoryIdentityProvider crd 2021-07-23 13:01:41 -07:00
Margo Crawford
8ea1bd3dfb Make prepare-for-integration-tests active directory setup accessible for anyone 2021-07-23 13:01:41 -07:00
Margo Crawford
91085e68f9 Refactoring defaulting logic 2021-07-23 13:01:41 -07:00
Margo Crawford
f99f7be836 Default values for ad usersearch and groupsearch 2021-07-23 13:01:41 -07:00
Margo Crawford
890d9c3216 resolve some todos about error handling search base discovery results 2021-07-23 13:01:41 -07:00
Margo Crawford
cb0ee07b51 Fetch AD search base from defaultNamingContext when not specified 2021-07-23 13:01:41 -07:00
Margo Crawford
8e1d70562d Remove shared variables from ldap upstream observer 2021-07-23 13:01:41 -07:00
Margo Crawford
5d8d7246c2 Refactor active directory and ldap controllers to share almost everything
Signed-off-by: Ryan Richard <richardry@vmware.com>
2021-07-23 13:01:41 -07:00
Ryan Richard
3b4f521596 Changed TestLDAPUpstream.TestUsernameAttributeName back to TestUserMailAttributeName
Also added TestUserSAMAccountNameValue

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-07-23 13:01:40 -07:00
Margo Crawford
e5c8cbb3a4 One line fix for lint error. Forgot a period in a comment.
Signed-off-by: Ryan Richard <richardry@vmware.com>
2021-07-23 13:01:40 -07:00
Margo Crawford
7696f4256d Move defaulting of ad username and uid attributes to controller
Now the controller uses upstreamldap so there is less duplication,
since they are very similar.

Signed-off-by: Ryan Richard <richardry@vmware.com>
2021-07-23 13:01:40 -07:00
Ryan Richard
aaa4861373 Custom API Group overlay for AD
Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-07-23 13:01:40 -07:00
Margo Crawford
b3d0b28bd0 Integration test fixes, fixing objectGUID handling 2021-07-23 13:01:40 -07:00
Margo Crawford
5c283d941c Helper script for running active directory tests 2021-07-23 13:01:40 -07:00
Margo Crawford
94e90a5d26 groups related env variables for AD 2021-07-23 13:01:40 -07:00
Margo Crawford
be6f9f83ce RBAC rules for activedirectoryidentityprovider 2021-07-23 13:01:40 -07:00
Margo Crawford
3b8edb84a5 WIP on active directory integration test 2021-07-23 13:01:40 -07:00
Margo Crawford
8fb35c6569 Active Directory cli options 2021-07-23 13:01:40 -07:00
Margo Crawford
3899292e89 Advertise Active Directory idps 2021-07-23 13:01:40 -07:00
Margo Crawford
b06de69f6a ActiveDirectoryIdentityProvider
- Create CRD
- Create implementation of AD-specific user search defaults
2021-07-23 13:01:40 -07:00
Ryan Richard
ac4bc02817 Enhance integration test for CredentialIssuer spec annotations 2021-07-23 09:46:40 -07:00
Ryan Richard
708164b878 Carefully merge desired annotations into impersonation proxy Service
Don't overwrite annotations that might have come from a human user or
from some other non-Pinniped controller.
2021-07-22 17:09:50 -07:00
Ryan Richard
e30cf6e51a Merge branch 'main' into cli_username_password_env_vars 2021-07-22 09:29:03 -07:00
Matt Moyer
ee30b78117 Update ROADMAP.md
Bump "Wider Concierge cluster support" to August.
2021-07-22 10:30:45 -05:00
Ryan Richard
64aba7e703 Add new howto guide login.md 2021-07-21 12:10:47 -07:00
Matt Moyer
c6c3a80a86 Merge pull request #733 from mattmoyer/switch-tools-images
Switch to GHCR tools images for local tests, with `imagePullPolicy: IfNotPresent`.
2021-07-21 11:47:37 -06:00
Margo Crawford
a7af63ca3a Merge pull request #729 from rdimitrov/dimitrovr/add-dex-docs
Add documentation for configuring Supervisor with Dex and Github
2021-07-21 08:48:49 -07:00
Matt Moyer
ae72d30cec Switch to GHCR tools images for local tests, with imagePullPolicy: IfNotPresent.
This is more consistent with our CI environment.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-21 09:21:05 -05:00
Nanci Lancaster
fec59eb1bf Merge pull request #731 from microwavables/main
Removed Andrew Keesler, Pablo Schumaker from site, moved them to emeritus status on maintainers file,
2021-07-20 15:37:04 -07:00
Radoslav Dimitrov
f6273b0604 Update the Prerequisites section and add a note about the groups scope
Add Dex to the prerequisites and add a note that to query for the groups
scope the user must set the organizations Dex should search against.
Otherwise the groups claim would be empty. This is because of the format
group claims are represented, i.e. "org:team".

Signed-off-by: Radoslav Dimitrov <dimitrovr@vmware.com>
2021-07-20 13:49:45 +03:00
Ryan Richard
deb699a84a e2e test: PINNIPED_USERNAME/PINNIPED_PASSWORD env vars during LDAP login 2021-07-19 17:08:52 -07:00
Ryan Richard
cac45fd999 LDAP logins read from PINNIPED_USERNAME and PINNIPED_PASSWORD env vars
For CLI-based auth, such as with LDAP upstream identity providers, the
user may use these environment variables to avoid getting interactively
prompted for username and password.
2021-07-19 16:20:59 -07:00
Radoslav Dimitrov
0bdd1bc68f Add documentation for configuring Supervisor with Dex and Github
The following guide describes the process of configuring Supervisor
with Dex and identify users through their Github account. Issue #415

Signed-off-by: Radoslav Dimitrov <dimitrovr@vmware.com>
2021-07-19 16:00:43 +03:00
Mo Khan
4605846499 Merge pull request #724 from vmware-tanzu/fix_git_sha_in_version_info
Copy .git dir during Docker build; used to bake git sha into binary
2021-07-16 14:34:33 -04:00
Ryan Richard
4670890a82 Add .git dir to Docker; used to bake git sha into binary 2021-07-16 09:51:46 -07:00
Margo Crawford
d204b46c18 Merge pull request #721 from vmware-tanzu/resolve-load-balancer-dns
wait for lb dns to resolve in the impersonation proxy integration test
2021-07-15 17:02:08 -07:00
Ryan Richard
b3208f0ca6 wait for lb dns to resolve in the impersonation proxy integration test
this will hopefully fix some flakes where aws provisioned a host for the
load balancer but the tests weren't able to resolve it.

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-07-15 16:39:15 -07:00
Ryan Richard
be7bf9c193 Merge pull request #718 from vmware-tanzu/workaround_for_flaky_unit_test
TestAgentController unit test is flaky, try to add workaround
2021-07-15 14:17:11 -07:00
Ryan Richard
2bba39d723 TestAgentController unit test is flaky, try to add workaround
TestAgentController really runs the controller and evaluates multiple
calls to the controller's Sync with real informers caching updates.
There is a large amount of non-determinism in this unit test, and it
does not always behave the same way. Because it makes assertions about
the specific errors that should be returned by Sync, it was not
accounting for some errors that are only returned by Sync once in a
while depending on the exact (unpredictable) order of operations.

This commit doesn't fix the non-determinism in the test, but rather
tries to work around it by also allowing other (undesired but
inevitable) error messages to appear in the list of actual error
messages returned by the calls to the Sync function.

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-07-15 13:41:31 -07:00
anjalitelang
dc567d0d1f Update ROADMAP.md
Added https://github.com/vmware-tanzu/pinniped/issues/577 to Roadmap
2021-07-15 12:29:51 -04:00
Ryan Richard
143837c136 Merge pull request #714 from vmware-tanzu/ytt_install_doc_fix
ytt install docs suggest that you checkout the release tag
2021-07-14 12:52:23 -07:00
Ryan Richard
11eb18d348 ytt install docs suggest that you checkout the release tag
Previously, the ytt install docs suggested that you use ytt templates
from the HEAD of main with the container image from the latest public
release, which could result in a mismatch.
2021-07-14 10:59:51 -07:00
Ryan Richard
d5cf5b91d6 Merge pull request #711 from vmware-tanzu/e2e_test_clear_cookies
Clear the browser cookies between each TestE2EFullIntegration subtest
2021-07-13 16:43:57 -07:00
Ryan Richard
48b58e2fad Clear the browser cookies between each TestE2EFullIntegration test
It seems like page.ClearCookies() only clears cookies for the current
domain, so there doesn't seem to be a function to clear all browser
cookies. Instead, we'll just start a whole new browser each test.
They start fast enough that it shouldn't be a problem.
2021-07-13 16:20:02 -07:00
Ryan Richard
7ef3d42e01 Merge pull request #704 from mattmoyer/deflake-serving-certificate-rotation-test
Make TestAPIServingCertificateAutoCreationAndRotation less flaky.
2021-07-13 14:58:54 -07:00
Ryan Richard
33461ddc14 Merge branch 'main' into deflake-serving-certificate-rotation-test 2021-07-13 14:04:34 -07:00
Mo Khan
238c9e6743 Merge pull request #709 from vmware-tanzu/dependabot/go_modules/github.com/tdewolff/minify/v2-2.9.19
Bump github.com/tdewolff/minify/v2 from 2.9.18 to 2.9.19
2021-07-12 14:48:16 -04:00
dependabot[bot]
25cda4f3e6 Bump github.com/tdewolff/minify/v2 from 2.9.18 to 2.9.19
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.9.18 to 2.9.19.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.9.18...v2.9.19)

---
updated-dependencies:
- dependency-name: github.com/tdewolff/minify/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 01:20:59 +00:00
Matt Moyer
c71703e4db Merge pull request #707 from mattmoyer/fix-okta-cli-integration-test
Fix TestCLILoginOIDC when running against Okta, and lower CLI server shutdown timeout.
2021-07-09 14:30:19 -07:00
Matt Moyer
5527566a36 Fix TestCLILoginOIDC when running directly against Okta.
Our actual CLI code behaved correctly, but this test made some invalid assumptions about the "upstream" IDP we're testing. It assumed that the upstream didn't support `response_mode=form_post`, but Okta does. This means that when we end up on the localhost callback page, there are no URL query parameters.

Adjusting this regex makes the test pass as expected.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 16:29:42 -05:00
Matt Moyer
b6580b303a Reduce CLI callback shutdown timeout (5s -> 500ms).
I found that there are some situations with `response_mode=form_post` where Chrome will open additional speculative TCP connections. These connections will be idle so they block server shutdown until the (previously 5s) timeout. Lowering this to 500ms should be safe and makes any added latency at login much less noticeable.

More information about Chrome's TCP-level behavior here: https://bugs.chromium.org/p/chromium/issues/detail?id=116982#c5

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 16:29:29 -05:00
Matt Moyer
405a27ba90 Merge pull request #687 from mattmoyer/add-response-mode-form-post
Add support for "response_mode=form_post" in Supervisor and CLI.
2021-07-09 10:37:59 -07:00
Matt Moyer
43f66032a9 Extend TestE2EFullIntegration to test manual OIDC flow.
Using the same fake TTY trick we used to test LDAP login, this new subtest runs through the "manual"/"jump box" login flow. It runs the login with a `--skip-listen` flag set, causing the CLI to skip opening the localhost listener. We can then wait for the login URL to be printed, visit it with the browser and log in, and finally simulate "manually" copying the auth code from the browser and entering it into the waiting CLI prompt.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:45 -05:00
Matt Moyer
91a1fec5cf Add hidden --skip-listen flag for pinniped login oidc.
This flag is (for now) meant only to facilitate end-to-end testing, allowing us to force the "manual" login flow. If it ends up being useful we can un-hide it, but this seemed like the safest option to start with.

There is also a corresponding `--oidc-skip-listen` on the `pinniped get kubeconfig` command.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
d0b37a7c90 Adjust TestFormPostHTML to work on Linux chromedriver.
For some reason our headless Chrome test setup behaves slightly differently on Linux and macOS hosts. On Linux, the emoji characters are not recognized as valid text, so they are URL encoded. This change updates the test to cope with both cases correctly.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
5029495fdb Add manual paste flow to pinniped login oidc command.
This adds a new login flow that allows manually pasting the authorization code instead of receiving a browser-based callback.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
ac6ff1a03c Deprecate oidcclient.WithBrowserOpen() option, add simpler oidcclient.WithSkipBrowserOpen().
This is a more restrictive library interface that more closely matches the use cases of our new form_post login flow.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
95ee9f0b00 Add ctx params to promptForValue() and promptForSecret().
This allows the prompts to be cancelled, which we need to be able to do in the case where we prompt for a manually-pasted auth code but the automatic callback succeeds.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
9fba8d2203 Adjust TestE2EFullIntegration for new form_post flow.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
428f389c7d Add missing t.Helper() on RequireEventuallyf().
This gives us nicer test assertion failure messages.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:44 -05:00
Matt Moyer
71d4e05fb6 Add custom response_mode=form_post HTML template.
This is a new pacakge internal/oidc/provider/formposthtml containing a number of static files embedded using the relatively recent Go "//go:embed" functionality introduced in Go 1.16 (https://blog.golang.org/go1.16).

The Javascript and CSS files are minifiied and injected to make a single self-contained HTML response. There is a special Content-Security-Policy helper to calculate hash-based script-src and style-src rules.

This new code is covered by a new integration test that exercises the JS/HTML functionality in a real browser outside of the rest of the Supervisor.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
1904f8ddc3 In browsertest.Open(), capture console INFO logs.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
6b801056b5 Add testlib.RandBytes() helper.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
674cd4a88c Adjust our securityheader pkg to support form_post.
Our Supervisor callback handler now needs to load JS and CSS from the provider endpoint, and this JS needs to make a `fetch()` call across origins (to post the form to the CLI callback). This requires a custom Content-Security-Policy compared to other pages we render.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
7217cf4892 In form_post mode, expect params via POST'ed form.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
40c931bdc5 When supported, use "response_mode=form_post" in client.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
2823d4d1e3 Add "response_modes_supported" to Supervisor discovery response.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
6d83ecb420 Unit test response_mode=form_post in internal/oidc/callback.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:43 -05:00
Matt Moyer
c27eb17f23 Add "response_mode=form_post" to CLI client.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 12:08:42 -05:00
Matt Moyer
58363bca2c Merge pull request #705 from mattmoyer/deflake-impersonation-websocket-test
Make TestImpersonationProxy less flaky.
2021-07-09 10:06:14 -07:00
Matt Moyer
3bf39797bb Merge pull request #706 from mattmoyer/fix-api-doc-comment
Fix typo in generated API docs (s/mode/type/).
2021-07-09 10:05:05 -07:00
Matt Moyer
3a840cee76 Make TestAPIServingCertificateAutoCreationAndRotation less flaky.
This test would occasionally flake for me when running locally. This change moves more of the assertions into the "eventually" loop, so they can temporarily fail as long as they converge on the expected values.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 11:29:02 -05:00
Matt Moyer
04e9897d51 Make TestImpersonationProxy less flaky.
This test did not tolerate this connection failing, which can happen for any number of flaky networking-related reasons. This change moves the connection setup into an "eventually" retry loop so it's allowed to fail temporarily as long as it eventually connects.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 11:28:33 -05:00
Matt Moyer
ff9095f9c4 Fix typo in generated API docs (s/mode/type/).
This CredentialIssuer field is called `spec.impersonationProxy.service.type`, not `spec.impersonationProxy.service.mode`.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-07-09 11:28:02 -05:00
Matt Moyer
2e18c88e33 Merge pull request #684 from christianang/oidc-upstream-watcher-supports-proxy
Add IPv6 support to FederationDomain spec.issuer field.
2021-07-09 09:14:39 -07:00
Matt Moyer
9f91c6c884 Merge branch 'main' into oidc-upstream-watcher-supports-proxy 2021-07-09 07:24:52 -07:00
Ryan Richard
59fd1997f4 Merge pull request #703 from vmware-tanzu/ldap-client-int-tests-only-on-kind
Run the LDAP client's integration tests only on Kind
2021-07-08 12:55:03 -07:00
Ryan Richard
74f3ce5dcd Merge branch 'main' into ldap-client-int-tests-only-on-kind 2021-07-08 12:54:56 -07:00
Ryan Richard
d403c8b44b Merge pull request #702 from vmware-tanzu/supervisor-https-proxy-fix-timeout
Fix broken upstream OIDC discovery timeout added in previous commit
2021-07-08 12:54:39 -07:00
Ryan Richard
e130da6daa Add unit test assertion for new OIDC client request timeout 2021-07-08 11:47:49 -07:00
Ryan Richard
2f7dbed321 Try increasing the "eventually" timeouts in one integration test
There were 10 second timeouts in
`TestAPIServingCertificateAutoCreationAndRotation` which fail often
on CI. Maybe increasing the timeouts will help?
2021-07-08 11:17:22 -07:00
Ryan Richard
709c10227f Run the LDAP client's integration tests only on Kind
TestSimultaneousLDAPRequestsOnSingleProvider proved to be unreliable
on AKS due to some kind of kubectl port-forward issue, so only
run the LDAP client's integration tests on Kind. They are testing
the integration between the client code and the OpenLDAP test server,
not testing anything about Kubernetes, so running only on Kind should
give us sufficient test coverage.
2021-07-08 11:10:53 -07:00
Ryan Richard
f0d120a6ca Fix broken upstream OIDC discovery timeout added in previous commit
After noticing that the upstream OIDC discovery calls can hang
indefinitely, I had tried to impose a one minute timeout on them
by giving them a timeout context. However, I hadn't noticed that the
context also gets passed into the JWKS fetching object, which gets
added to our cache and used later. Therefore the timeout context
was added to the cache and timed out while sitting in the cache,
causing later JWKS fetchers to fail.

This commit is trying again to impose a reasonable timeout on these
discovery and JWKS calls, but this time by using http.Client's Timeout
field, which is documented to be a timeout for *each* request/response
cycle, so hopefully this is a more appropriate way to impose a timeout
for this use case. The http.Client instance ends up in the cache on
the JWKS fetcher object, so the timeout should apply to each JWKS
request as well.

Requests that can hang forever are effectively a server-side resource
leak, which could theoretically be taken advantage of in a denial of
service attempt, so it would be nice to avoid having them.
2021-07-08 09:44:02 -07:00
Ryan Richard
1f5480cd5c Merge pull request #701 from vmware-tanzu/supervisor-https-proxy
Add `https_proxy` and `no_proxy` settings for the Supervisor
2021-07-07 14:57:38 -07:00
Ryan Richard
f1e63c55d4 Add https_proxy and no_proxy settings for the Supervisor
- Add new optional ytt params for the Supervisor deployment.
- When the Supervisor is making calls to an upstream OIDC provider,
  use these variables if they were provided.
- These settings are integration tested in the main CI pipeline by
  sometimes setting them on deployments in certain cases, and then
  letting the existing integration tests (e.g. TestE2EFullIntegration)
  provide the coverage, so there are no explicit changes to the
  integration tests themselves in this commit.
2021-07-07 12:50:13 -07:00
Matt Moyer
562951b77a Merge branch 'main' into oidc-upstream-watcher-supports-proxy 2021-07-06 11:30:09 -07:00
Matt Moyer
dbd2cb4563 Merge pull request #696 from vmware-tanzu/dependabot/go_modules/github.com/spf13/cobra-1.2.1
Bump github.com/spf13/cobra from 1.2.0 to 1.2.1
2021-07-06 07:04:02 -07:00
dependabot[bot]
1c746feafe Bump github.com/spf13/cobra from 1.2.0 to 1.2.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-05 01:28:57 +00:00
Ryan Richard
49683975ab Merge pull request #689 from vmware-tanzu/trivial_refactor
Extract some trivial helpers for identical code usages
2021-07-02 14:56:26 -07:00
Ryan Richard
4be26fc1a6 Merge branch 'main' into trivial_refactor 2021-07-02 13:48:27 -07:00
Matt Moyer
f590a3a88b Merge pull request #692 from vmware-tanzu/dependabot/go_modules/github.com/spf13/cobra-1.2.0
Bump github.com/spf13/cobra from 1.1.3 to 1.2.0
2021-07-02 07:24:55 -07:00
dependabot[bot]
e26486bd41 Bump github.com/spf13/cobra from 1.1.3 to 1.2.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.3 to 1.2.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.1.3...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 01:11:11 +00:00
Matt Moyer
5c2e890ecd Add "Extended IDP support" to the roadmap. 2021-07-01 10:48:13 -05:00
Matt Moyer
715cf7748a Add "Identity transforms" feature to roadmap. 2021-07-01 10:17:40 -05:00
Matt Moyer
e0456b4485 Update ROADMAP given current state of work 2021-07-01 10:05:30 -05:00
Ryan Richard
629bf61655 Extract some trivial helpers for identical code usages 2021-06-30 15:02:14 -07:00
Matt Moyer
738e6aa3cc Merge pull request #685 from vmware-tanzu/dependabot/go_modules/github.com/gofrs/flock-0.8.1
Bump github.com/gofrs/flock from 0.8.0 to 0.8.1
2021-06-30 10:53:39 -07:00
Guangyuan Wang
76dc39ac2d Use hostname instead of host and split on ":"
Co-authored-by: Christian Ang <angc@vmware.com>
Co-authored-by: Tyler Schultz <tschultz@vmware.com>
2021-06-28 23:03:05 +00:00
dependabot[bot]
43fee6bb94 Bump github.com/gofrs/flock from 0.8.0 to 0.8.1
Bumps [github.com/gofrs/flock](https://github.com/gofrs/flock) from 0.8.0 to 0.8.1.
- [Release notes](https://github.com/gofrs/flock/releases)
- [Commits](https://github.com/gofrs/flock/compare/v0.8.0...v0.8.1)

---
updated-dependencies:
- dependency-name: github.com/gofrs/flock
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-28 01:28:52 +00:00
Christian Ang
8026729c43 Use net.JoinHostPort instead of Sprintf
Co-authored-by: Guangyuan Wang <wguangyuan@vmware.com>
2021-06-24 23:19:11 +00:00
Guangyuan Wang
d19d63ad7d Set Proxy on oidc upstream watcher transport
- this allows the oidc upsream watcher to honor the
HTTP_PROXY,HTTPS_PROXY,NO_PROXY environment variables

Co-authored-by: Christian Ang <angc@vmware.com>
2021-06-24 22:35:16 +00:00
Mo Khan
a6141e911c Merge pull request #683 from enj/enj/i/credentialrequest_notafter
credentialrequest: use safer approximation for ExpirationTimestamp
2021-06-23 11:55:29 -04:00
Monis Khan
5ff2be973c credentialrequest: use safer approximation for ExpirationTimestamp
We want the value of time.Now() to be calculated before the call to
IssueClientCertPEM to prevent the ExpirationTimestamp from being
later than the notAfter timestamp on the issued certificate.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-23 11:07:00 -04:00
Matt Moyer
73201ba575 Merge pull request #682 from vmware-tanzu/dependabot/docker/debian-10.10-slim
Bump debian from 10.9-slim to 10.10-slim
2021-06-22 19:39:13 -07:00
dependabot[bot]
125d891cd5 Bump debian from 10.9-slim to 10.10-slim
Bumps debian from 10.9-slim to 10.10-slim.

---
updated-dependencies:
- dependency-name: debian
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 01:02:44 +00:00
Matt Moyer
682a47f739 Merge pull request #680 from mattmoyer/update-k8s-1.21.2
Update to Kubernetes 1.21.2 runtime components.
2021-06-22 10:23:14 -07:00
Matt Moyer
594e47efdf Update to Kubernetes 1.21.2 runtime components.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-22 11:55:22 -05:00
Mo Khan
f09a45382e Merge pull request #681 from enj/enj/i/fix_bad_name
Fix bad test package name
2021-06-22 12:54:29 -04:00
Monis Khan
d78b845575 Fix bad test package name
Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-22 11:23:19 -04:00
Mo Khan
1929b47dda Merge pull request #674 from mattmoyer/new-eventual-assertion-helpers
Improve our integration test "Eventually" assertions.
2021-06-22 11:15:06 -04:00
Matt Moyer
3efa7bdcc2 Improve our integration test "Eventually" assertions.
This fixes some rare test flakes caused by a data race inherent in the way we use `assert.Eventually()` with extra variables for followup assertions. This function is tricky to use correctly because it runs the passed function in a separate goroutine, and you have no guarantee that any shared variables are in a coherent state when the `assert.Eventually()` call returns. Even if you add manual mutexes, it's tricky to get the semantics right. This has been a recurring pain point and the cause of several test flakes.

This change introduces a new `library.RequireEventually()` that works by internally constructing a per-loop `*require.Assertions` and running everything on a single goroutine (using `wait.PollImmediate()`). This makes it very easy to write eventual assertions.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-17 16:56:03 -05:00
Matt Moyer
6a9eb87c35 Update ROADMAP.md 2021-06-17 10:17:04 -05:00
Matt Moyer
3eba3e07c6 Merge pull request #669 from vmware-tanzu/dependabot/go_modules/github.com/golang/mock-1.6.0
Bump github.com/golang/mock from 1.5.0 to 1.6.0
2021-06-15 18:49:23 -07:00
dependabot[bot]
9f06869f76 Bump github.com/golang/mock from 1.5.0 to 1.6.0
Bumps [github.com/golang/mock](https://github.com/golang/mock) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/golang/mock/releases)
- [Changelog](https://github.com/golang/mock/blob/master/.goreleaser.yml)
- [Commits](https://github.com/golang/mock/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/golang/mock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-16 01:22:04 +00:00
Matt Moyer
3f41261580 Merge pull request #673 from mattmoyer/refactor-static-client-struct-second-attempt
Use a custom type for our static CLI client.
2021-06-15 17:37:08 -07:00
Matt Moyer
551249fb69 Use a custom type for our static CLI client (smaller change).
Before this change, we used the `fosite.DefaultOpenIDConnectClient{}` struct, which implements the  `fosite.Client` and `fosite.OpenIDConnectClient` interfaces. For a future change, we also need to implement some additional optional interfaces, so we can no longer use the provided default types. Instead, we now use a custom `clientregistry.Client{}` struct, which implements all the requisite interfaces and can be extended to handle the new functionality (in a future change).

There is also a new `clientregistry.StaticRegistry{}` struct, which implements the `fosite.ClientManager` and looks up our single static client. We could potentially extend this in the future with a registry backed by Kubernetes API, for example.

This should be 100% refactor, with no user-observable change.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-15 15:31:48 -05:00
Mo Khan
1a610022cf Merge pull request #671 from enj/enj/i/eks_rbac
TestServiceAccountPermissions: handle extra permissions on EKS
2021-06-15 11:46:24 -04:00
Monis Khan
524ff21b7f TestServiceAccountPermissions: handle extra permissions on EKS
Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-15 11:17:59 -04:00
Matt Moyer
913c140be8 Update the latest version number in the docs.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-15 09:46:51 -05:00
Mo Khan
e06c696bea Merge pull request #670 from enj/enj/f/impersonator_always_authz
impersonator: always authorize every request
2021-06-14 16:16:12 -04:00
Monis Khan
269db6b7c2 impersonator: always authorize every request
This change updates the impersonator to always authorize every
request instead of relying on the Kuberentes API server to perform
the check on the impersonated request.  This protects us from
scenarios where we fail to correctly impersonate the user due to
some bug in our proxy logic.  We still rely completely on the API
server to perform admission checks on the impersonated requests.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-14 12:53:09 -04:00
Monis Khan
addf632e7c impersonator: add docs regarding limited serivce account
Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-11 15:37:55 -04:00
Mo Khan
87489da316 Merge pull request #667 from enj/enj/f/impersonator_distinct_sa
impersonator: run as a distinct SA with minimal permissions
2021-06-11 15:36:28 -04:00
Monis Khan
898f2bf942 impersonator: run as a distinct SA with minimal permissions
This change updates the impersonation proxy code to run as a
distinct service account that only has permission to impersonate
identities.  Thus any future vulnerability that causes the
impersonation headers to be dropped will fail closed instead of
escalating to the concierge's default service account which has
significantly more permissions.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-11 12:13:53 -04:00
Matt Moyer
918c50f6a7 Merge pull request #666 from vmware-tanzu/dependabot/go_modules/gopkg.in/square/go-jose.v2-2.6.0
Bump gopkg.in/square/go-jose.v2 from 2.5.1 to 2.6.0
2021-06-10 15:06:55 -07:00
Matt Moyer
9ca82116f1 Update ROADMAP.md 2021-06-10 12:45:23 -05:00
Matt Moyer
564c1f8ae5 Update ROADMAP.md 2021-06-10 10:27:20 -05:00
dependabot[bot]
c88aad873b Bump gopkg.in/square/go-jose.v2 from 2.5.1 to 2.6.0
Bumps [gopkg.in/square/go-jose.v2](https://github.com/square/go-jose) from 2.5.1 to 2.6.0.
- [Release notes](https://github.com/square/go-jose/releases)
- [Commits](https://github.com/square/go-jose/compare/v2.5.1...v2.6.0)

---
updated-dependencies:
- dependency-name: gopkg.in/square/go-jose.v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-08 05:41:45 +00:00
Mo Khan
9d27e6b4c6 Merge pull request #665 from enj/enj/i/impersonator_dead_code
impersonator: remove redundant deleteKnownImpersonationHeaders logic
2021-06-04 16:12:08 -04:00
Monis Khan
5b327a2b37 impersonator: remove redundant deleteKnownImpersonationHeaders logic
WithImpersonation already deletes impersonation headers and has done
so since the early days:

https://github.com/kubernetes/kubernetes/pull/36769

ensureNoImpersonationHeaders will still reject any request that has
impersonation headers set so we will always fail closed.

Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-04 15:22:01 -04:00
Matt Moyer
7114988eec Merge pull request #663 from vmware-tanzu/dependabot/docker/golang-1.16.5
Bump golang from 1.16.4 to 1.16.5
2021-06-04 09:20:44 -05:00
Mo Khan
3a47060256 Merge pull request #645 from enj/enj/f/anon_impersonation_proxy
impersonator: honor anonymous authentication being disabled
2021-06-04 09:28:14 -04:00
Benjamin A. Petersen
492f6cfddf impersonator: honor anonymous authentication being disabled
When anonymous authentication is disabled, the impersonation proxy
will no longer authenticate anonymous requests other than calls to
the token credential request API (this API is used to retrieve
credentials and thus must be accessed anonymously).

Signed-off-by: Benjamin A. Petersen <ben@benjaminapetersen.me>
Signed-off-by: Monis Khan <mok@vmware.com>
2021-06-04 09:00:56 -04:00
dependabot[bot]
f417f706b9 Bump golang from 1.16.4 to 1.16.5
Bumps golang from 1.16.4 to 1.16.5.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-04 06:00:24 +00:00
Matt Moyer
02335e2ade Bump the latest version referenced in the docs.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-03 17:25:32 -05:00
Matt Moyer
9b9e733a7d Merge pull request #662 from mattmoyer/parameterize-test-images
Parameterize our test images in ytt.
2021-06-03 15:53:13 -05:00
Matt Moyer
df78e00df3 Parameterize our test images in ytt.
These are images we use for local and some CI testing.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-03 15:25:09 -05:00
Matt Moyer
b5ed4e6a13 Merge pull request #660 from mattmoyer/fix-credentialissuer-service-type-field-typo
Fix typo in CredentialIssuer ytt template.
2021-06-03 14:01:14 -05:00
Matt Moyer
500b444bad Merge pull request #657 from vmware-tanzu/fix-ldap-supervisor-login-test-flake
Avoid a rare flake in TestSupervisorLogin.
2021-06-03 13:31:15 -05:00
Matt Moyer
d3e2859238 Merge pull request #658 from vmware-tanzu/fix-impersonation-notfound-handling
Tolerate NotFound when deleting services in `impersonatorconfig`.
2021-06-03 13:30:54 -05:00
Matt Moyer
5686591420 Avoid a rare flake in TestSupervisorLogin.
There was nothing to guarantee that _all_ Supervisor pods would be ready to handle this request. We saw a rare test flake where the LDAPIdentityProvider was marked as ready but one of the Supervisor pods didn't have it loaded yet and returned an HTTP 422 error (`Unprocessable Entity: No upstream providers are configured`).

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-03 12:13:56 -05:00
Matt Moyer
6903196c18 Fix a data race in TestImpersonationProxy.
The `require.Eventually()` function runs the body of the check in a separate goroutine, so it's not safe to use other `require` assertions as we did here. Our `library.RequireEventuallyWithoutError()` function does not spawn a goroutine, so it's safer to use here.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-03 12:07:19 -05:00
Matt Moyer
af4cd1b515 Tolerate NotFound when deleting services in impersonatorconfig.
When a CredentialIssuer is switched from one service type to another (or switched to disabled mode), the `impersonatorconfig` controller will delete the previous Service, if any. Normally one Concierge pod will succeed to delete this initially and any other pods will see a NotFound error.

Before this change, the NotFound would bubble up and cause the strategy to enter a ErrorDuringSetup status until the next reconcile loop. We now handle this case without reporting an error.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-03 12:07:19 -05:00
Matt Moyer
2acfafd5a5 Merge pull request #656 from vmware-tanzu/fix-credentialissuer-test-flake
Remove an invalid test assertion in TestCredentialIssuer.
2021-06-03 12:03:22 -05:00
anjalitelang
a5067cdbb3 Update ROADMAP.md
Updating Roadmap for June to reflect Device Code Flow and AD support
2021-06-03 12:33:36 -04:00
Matt Moyer
5aa08756e0 Fix typo in CredentialIssuer ytt template.
This typo wasn't caught in testing because 1) the Kubernetes API ignores the unknown field and 2) the `type` field defaults to `LoadBalancer` anyway, so things behave as expected.

Even though this doesn't cause any large problems, it's quite confusing.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 14:48:18 -05:00
Matt Moyer
0e66b0b165 Remove an invalid test assertion in TestCredentialIssuer.
The LastUpdateTime is no longer updated on every resync. It only changes if the underlying status has changed, so that it effectively shows when the transition happened.

This change happened in ab750f48aa, but we missed this test. It only fails when it has been more than ten minutes since the CredentialIssuer transitioned into a healthy state, but that can happen in our long-running CI environments.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 12:05:02 -05:00
Matt Moyer
87660611d2 Tweak blog post to add a shoutout.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 11:28:54 -05:00
Matt Moyer
9968c0d234 Fix my fix 🤦🏻 . 2021-06-02 11:06:03 -05:00
Matt Moyer
193fcb87bb Fix a typo on the "Community Meetings" time.
We had "PT" twice, when one of them should have been "ET".
2021-06-02 11:05:29 -05:00
Ryan Richard
a08e4ec043 Update architecture.md 2021-06-02 08:54:04 -07:00
Matt Moyer
e38a7548cc Link the v0.9.0 release from the blog post.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 10:24:17 -05:00
Pinny
b5dea42bbe Update CLI docs for v0.9.0 release 2021-06-02 15:22:13 +00:00
Matt Moyer
d06fe15a68 Merge pull request #655 from mattmoyer/update-docs-for-v0.9.0
Update docs for v0.9.0
2021-06-02 10:07:02 -05:00
Matt Moyer
e6301f0e74 Update latest version number in docs.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 10:05:07 -05:00
Matt Moyer
aca33e45fb Fix blog post date to match actual v0.9.0 release.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-02 10:02:59 -05:00
Matt Moyer
46825b1c9f Merge pull request #653 from mattmoyer/fix-impersonation-test-flake
Fix another impersonation test flake related to `kubectl logs --tail` line count + test refactor.
2021-06-01 16:51:16 -05:00
Matt Moyer
2ee3cec5ed Refactor TestImpersonationProxy "apply annotation" test for clarity.
This test felt overly complex and some of the cleanup logic wasn't 100% correct (it didn't clean up in all cases).

The new code is essentially the same flow but hopefully easier to read.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-01 15:50:51 -05:00
Matt Moyer
75d92079e4 Allow some flexibility in "kubectl logs --tail=10" test.
We see that occasionally kubectl returns 11 lines (probably related to https://github.com/kubernetes/kubernetes/issues/72628).

This test doesn't need to be so picky, so now it allows +/- one line from the expected count.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-01 15:50:51 -05:00
Matt Moyer
0be77c3bf2 Merge pull request #651 from vmware-tanzu/dependabot/go_modules/github.com/creack/pty-1.1.13
Bump github.com/creack/pty from 1.1.12 to 1.1.13
2021-06-01 15:50:38 -05:00
dependabot[bot]
d4a6a61560 Bump github.com/creack/pty from 1.1.12 to 1.1.13
Bumps [github.com/creack/pty](https://github.com/creack/pty) from 1.1.12 to 1.1.13.
- [Release notes](https://github.com/creack/pty/releases)
- [Commits](https://github.com/creack/pty/compare/v1.1.12...v1.1.13)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-01 20:15:47 +00:00
Ryan Richard
abc3df8df9 Merge pull request #637 from vmware-tanzu/ldap_docs
LDAP docs
2021-06-01 12:59:58 -07:00
Ryan Richard
5932bce54d Merge branch 'main' into ldap_docs 2021-06-01 12:59:38 -07:00
Matt Moyer
41ff3e0917 Merge pull request #652 from mattmoyer/fix-impersonation-test-flake
In TestImpersonationProxy tests, avoid mutating anything in parallel block of tests.
2021-06-01 14:41:07 -05:00
Matt Moyer
f62c6e806d In TestImpersonationProxy tests, avoid mutating anything in parallel block of tests.
We had this one test that mutated the CredentialIssuer, which could cause the impersonation proxy to blip on one or both of the running concierge pods. This would sometimes break other concurrently running tests.

Instead, this bit of code is split into a separate non-concurrent test.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-06-01 14:02:27 -05:00
Ryan Richard
79e3980f1f Fix nil function deference in an integration test from previous commit 2021-05-28 17:06:01 -07:00
Ryan Richard
8f2e8b8a6c Merge branch 'main' into ldap_docs 2021-05-28 16:20:02 -07:00
Ryan Richard
e4fda80fcc Merge pull request #650 from mattmoyer/do-not-log-usernames-that-might-be-passwords
In LDAP, do not log username until we know the user exists.
2021-05-28 16:16:32 -07:00
Ryan Richard
5263e0bae5 Merge branch 'main' into do-not-log-usernames-that-might-be-passwords 2021-05-28 16:16:01 -07:00
Ryan Richard
b8205006ca Enable skipping of LDAP int tests when a firewall will block them 2021-05-28 16:13:20 -07:00
Matt Moyer
7ee1f8c441 In LDAP, do not log username until we know the user exists.
This prevents accidentally logging a password if the user enters it into the username field by mistake.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-28 16:57:48 -05:00
Ryan Richard
854903c4ed Merge pull request #649 from vmware-tanzu/change_ldap_groupname_default
Default `groupSearch.attributes.groupName` to "dn" instead of "cn" in LDAPIdentityProvider spec
2021-05-28 14:04:37 -07:00
Ryan Richard
cedbe82bbb Default groupSearch.attributes.groupName to "dn" instead of "cn"
- DNs are more unique than CNs, so it feels like a safer default
2021-05-28 13:27:11 -07:00
Matt Moyer
a741041737 Merge pull request #648 from mattmoyer/2021-05-28-dep-upgrades
Upgrade Go dependencies (fosite and klog).
2021-05-28 14:31:58 -05:00
Matt Moyer
83f418e7f2 Upgrade k8s.io/klog/v2 to v2.9.0.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-28 12:53:37 -05:00
Matt Moyer
e25de9e559 Update ID token tests for latest Fosite.
The new version has different behavior for the `nonce` claim, which is now omitted if it would be empty (see https://github.com/ory/fosite/pull/570).

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-28 12:53:37 -05:00
Matt Moyer
87c7e89b13 Upgrade github.com/ory/fosite to v0.40.2.
This required a weird hack because some of the Fosite tests (or a transitive dependency of them) depends on a newer version of gRPC that's incompatible with the Kubernetes runtime version we use. It wasn't as simple as just replacing the gRPC module with an older version, because in the latest versions of gRPC, they split out the "examples" packages into their own module. This new module name doesn't exist at the old version.

Ultimately, the workaround was to make a fake "examples" module locally. This module can be empty because we never actually depend on that code (it's only used in transitive dependency tests).

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-28 12:53:37 -05:00
Ryan Richard
4722422aae Fix OIDC assertion bug in TestSupervisorLogin introduced by LDAP branch 2021-05-28 10:37:46 -07:00
Matt Moyer
a39b328778 Merge pull request #626 from vmware-tanzu/credentialissuer-spec-api
Add spec fields to Credentialissuer API to configure impersonation proxy behavior
2021-05-27 17:48:45 -05:00
Matt Moyer
343238fa9b Merge branch 'credentialissuer-spec-api-docs' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-27 17:12:08 -05:00
Matt Moyer
a69fe68362 Merge branch 'main' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-27 17:11:40 -05:00
Matt Moyer
01713c7ce1 Don't reconcile Service ports in impersonatorconfig.
These are tricky because a real load balancer controller (e.g., on GKE) will overwrite and set NodePort, so we can't blindly set the desired state of this fields.

For now, we will just skip reconciling these. In the future, we could be more clever about merging them together with the current state.

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-27 17:10:25 -05:00
Matt Moyer
ab750f48aa When merging CredentialIssuer updates, don't overwrite LastUpdated.
If the only thing that has changed about a strategy is the LastUpdated timestamp, then we should not update the object.

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-27 17:09:12 -05:00
Ryan Richard
d7d8630e08 Merge branch 'main' into ldap_docs 2021-05-27 14:30:02 -07:00
Ryan Richard
cd7f5741d8 Incorporate feedback into LDAP blog post 2021-05-27 14:29:40 -07:00
Ryan Richard
c8dc03b06a Merge pull request #647 from vmware-tanzu/ldap_binary_uids
Use base64 binary-encoded value as UID for LDAP
2021-05-27 14:28:21 -07:00
Ryan Richard
83001d8cce Fix typo in LDAP blog post 2021-05-27 14:13:07 -07:00
Ryan Richard
d2251d2ea7 Use base64 binary-encoded value as UID for LDAP
This is to allow the use of binary LDAP entry attributes as the UID.
For example, a user might like to configure AD’s objectGUID or maybe
objectSid attributes as the UID attribute.

This negatively impacts the readability of the UID when it did not come
from a binary value, but we're considering this an okay trade-off to
keep things simple for now. In the future, we may offer more
customizable encoding options for binary attributes.

These UIDs are currently only used in the downstream OIDC `sub` claim.
They do not effect the user's identity on the Kubernetes cluster,
which is only based on their mapped username and group memberships from
the upstream identity provider. We are not currently supporting any
special encoding for those username and group name LDAP attributes, so
their values in the LDAP entry must be ASCII or UTF-8 in order for them
to be interpreted correctly.
2021-05-27 13:47:10 -07:00
Margo Crawford
f330b52076 Update values.yaml to include CredentialIssuer ImpersonationProxy spec. 2021-05-27 13:36:18 -07:00
Matt Moyer
af2af567be Merge branch 'main' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-27 15:13:36 -05:00
Ryan Richard
ec2956d54e Forgot to mention the CLI in the LDAP blog post 2021-05-27 13:05:45 -07:00
Ryan Richard
35cf1a00c8 Merge pull request #643 from vmware-tanzu/ldap_base_in_sub
Add user search base to downstream subject for upstream LDAP
2021-05-27 12:23:27 -07:00
Ryan Richard
0d43105759 Blog post for LDAP release 2021-05-27 12:06:01 -07:00
Matt Moyer
67d5c91713 Wait for successful TCR in TestImpersonationProxy.
This test setup should tolerate when the TokenCredentialRequest API isn't quite ready to authenticate the user or issue a cert.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-27 13:03:07 -05:00
Ryan Richard
81148866e0 URL query escape the upstream OIDC subject in the downstream subject URL 2021-05-27 09:25:48 -07:00
Matt Moyer
349d3dad83 Make temporary errors return Pending in impersonatorconfig.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-27 11:13:10 -05:00
Matt Moyer
049abfb94c Remove a "fail fast" check from TestImpersonationProxy.
This check is no longer valid, because there can be ephemeral, recoverable errors that show as ErrorDuringSetup.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-27 09:22:47 -05:00
Ryan Richard
033e1f0399 Add user search base to downstream subject for upstream LDAP
- Also add some tests about UTF-8 characters in LDAP attributes
2021-05-26 17:04:20 -07:00
Margo Crawford
d2d0dae4ed Wait for credentialissuer to be updated and always use proxy on clusterip test 2021-05-26 15:58:46 -07:00
Matt Moyer
0a47aa4843 Adjust log levels in impersonatorconfig controller.
Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-26 16:47:02 -05:00
Matt Moyer
d780bf64bc Remove references to impersonationConfigMap.
Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-26 15:24:59 -05:00
Matt Moyer
b57878ebc5 Remove TODO from impersonator.go.
We're now tracking this in an issue: https://github.com/vmware-tanzu/pinniped/issues/642

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-26 15:08:29 -05:00
Matt Moyer
1932b03c39 Refactor createOrUpdateService() method.
This updates the code to use a different mechanism for driving desired state:

- Read existing object
- If it does not exist, create desired object
- If it does exist, make a copy and set all the desired fields
- Do a deepequal to see if an update is necessary.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-26 15:03:04 -05:00
Matt Moyer
be8118ec2e Re-enable parallelism on TestImpersonatorConfigControllerSync.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-26 12:57:51 -05:00
Matt Moyer
1a4687a40a Switch impersonatorconfig to all singleton queues.
We also no longer need an initial event, since we don't do anything unless the CredentialIssuer exists, so we'll always be triggered at the appropriate time.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-26 12:54:40 -05:00
Matt Moyer
b13c494f93 Migrate off global logger in impersonatorconfig.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-26 12:44:05 -05:00
Margo Crawford
e5a61f3b95 IPv6 address in unit tests for ClusterIPs 2021-05-26 10:30:33 -07:00
Ryan Richard
9621ad9d2c More doc updates 2021-05-26 10:08:03 -07:00
Margo Crawford
f2021f1b53 Merge branch 'credentialissuer-spec-api' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-25 17:06:26 -07:00
Margo Crawford
e2fad6932f multiple cluster ips 2021-05-25 17:01:42 -07:00
Ryan Richard
9ee11d2a49 Merge branch 'main' into ldap_docs 2021-05-25 16:19:06 -07:00
Ryan Richard
bf39f930d4 Some light docs wordsmithing and reordering of the sidebar 2021-05-25 16:15:45 -07:00
Matt Moyer
450ce6a4aa Switch impersonatorconfig to new endpointaddr package.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-25 17:44:25 -05:00
Matt Moyer
c970dd1fb0 Merge branch 'main' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-25 17:32:58 -05:00
Matt Moyer
18a2a27a06 Merge pull request #640 from mattmoyer/endpointaddr
Refactor "endpoint address" parsing code into shared package.
2021-05-25 17:22:31 -05:00
Anjali Telang
47582e3290 Documentation for using Jumpcloud as LDAP provider with Pinniped Supervisor 2021-05-25 17:52:32 -04:00
Matt Moyer
89eff28549 Convert LDAP code to use endpointaddr package.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-25 16:17:27 -05:00
Matt Moyer
d9a3992b3b Add endpointaddr pkg for parsing host+port inputs.
This type of field appears in more than one of our APIs, so this package will provide a single source of truth for validating and parsing inputs.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-25 16:17:26 -05:00
Margo Crawford
75dd98a965 Integration test for impersonation proxy cluster ip 2021-05-25 13:50:50 -07:00
Matt Moyer
61362f8187 Merge pull request #639 from vmware-tanzu/dependabot/go_modules/github.com/google/go-cmp-0.5.6
Bump github.com/google/go-cmp from 0.5.5 to 0.5.6
2021-05-25 11:04:08 -05:00
dependabot[bot]
f89f2281d8 Bump github.com/google/go-cmp from 0.5.5 to 0.5.6
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.5.5 to 0.5.6.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.5.5...v0.5.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-25 05:51:17 +00:00
Ryan Richard
f5b11a0239 New docs: 1) Concierge with Supervisor, and 2) Supervisor with OpenLDAP 2021-05-24 19:08:25 -07:00
Ryan Richard
5e8945c616 Merge pull request #632 from vmware-tanzu/ldap_additional_unit_test
Add another unit test for the LDAP client code
2021-05-24 14:26:13 -07:00
Ryan Richard
2331c2dae2 Merge branch 'main' into ldap_additional_unit_test 2021-05-24 14:24:48 -07:00
Ryan Richard
2014f4623d Move require.NoError() to t.Cleanup() 2021-05-24 14:24:09 -07:00
Matt Moyer
fabc08b01b Merge branch 'main' of github.com:vmware-tanzu/pinniped into credentialissuer-spec-api 2021-05-24 15:49:13 -05:00
Matt Moyer
468463ce1d Merge pull request #635 from mattmoyer/fix-docs-version-to-better-default
Replace all references to "a specific version" with v0.8.0.
2021-05-24 14:25:48 -05:00
Matt Moyer
520eb43bfd Replace all references to "a specific version" with v0.8.0.
The documentation was a bit confusing before, and it was easy to accidentally install a very outdated version if you weren't reading carefully.

We could consider writing a post-release CI job to update these references automatically (perhaps using a Hugo macro?), but for now a manual update seems sufficient.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-24 11:50:16 -05:00
Margo Crawford
5de9bac4ac Oof... good I wrote an integration test because that's not how updating works!
Now updating the existing service in kubernetes but with the new
annotations
2021-05-24 09:41:49 -07:00
Matt Moyer
523a8d432f Merge pull request #616 from vmware-tanzu/okta-supervisor-docs
Add doc for configuring the supervisor with okta
2021-05-24 10:34:02 -05:00
Matt Moyer
1ab1d41735 Minor cleanups on the new Supervisor+Okta docs page.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-24 10:31:06 -05:00
Margo Crawford
36168122cc Add doc for configuring the supervisor with okta 2021-05-24 10:30:50 -05:00
Margo Crawford
150e879a68 Add tests for deleting services 2021-05-21 13:47:06 -07:00
Ryan Richard
b16e84d90a Add another unit test for the LDAP client code 2021-05-21 12:44:01 -07:00
Margo Crawford
722aa72206 Integration test tests update functionality 2021-05-21 10:19:33 -07:00
Matt Moyer
2d0cb16239 Merge pull request #631 from mattmoyer/remove-openapi-codegen
Stop generating zz_generated.openapi.go files.
2021-05-21 12:19:09 -05:00
Margo Crawford
b4bb0db6e5 Refactor some shared code between load balancer and cluster ip creation 2021-05-21 09:57:46 -07:00
Matt Moyer
fd9d9b8c73 Stop generating zz_generated.openapi.go files.
It turns out we no longer need these and can skip this bit of code generation.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 11:16:59 -05:00
Matt Moyer
44f6fd4437 Merge pull request #630 from mattmoyer/20210521-dependency-updates
Upgrade Go module dependencies
2021-05-21 11:12:03 -05:00
Matt Moyer
f0d5923091 Downgrade k8s.io/kube-openapi back to a previous version.
9b07d72531...00de3ae54c

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:42:39 -05:00
Matt Moyer
85ebaa96d5 Upgrade k8s.io/kube-openapi dependency.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:11:26 -05:00
Matt Moyer
cf5bc9f1b4 Upgrade k8s.io/utils dependency.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:07:41 -05:00
Matt Moyer
0d02ba6af3 Upgrade k8s.io/gengo dependency.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:07:00 -05:00
Matt Moyer
74a569fa82 Upgrade golang.org/x/* module dependencies.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:06:29 -05:00
Matt Moyer
01c0514057 Upgrade github.com/pkg/browser.
This some some kind of improvement on Windows.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 10:00:19 -05:00
Matt Moyer
0d42c1e9fe Update to Kubernetes 1.21.1 runtime components.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-21 09:57:41 -05:00
Margo Crawford
4606f1d8bd More error handling for cluster ip 2021-05-20 16:21:10 -07:00
Ryan Richard
1307c49212 Merge pull request #620 from vmware-tanzu/ldap_starttls
Support `StartTLS` for `LDAPIdentityProvider`s
2021-05-20 16:16:37 -07:00
Ryan Richard
b01665386d Use latest container image of our fork of bitnami-docker-openldap 2021-05-20 15:49:34 -07:00
Margo Crawford
599d70d6dc Wire generatedClusterIPServiceName through from NamesConfig 2021-05-20 14:11:35 -07:00
Ryan Richard
901ddd1870 Merge branch 'main' into ldap_starttls 2021-05-20 13:40:56 -07:00
Ryan Richard
8b549f66d4 Add integration test for LDAP StartTLS 2021-05-20 13:39:48 -07:00
Ryan Richard
4780c39640 Merge pull request #618 from vmware-tanzu/initial_ldap_group_support
Initial support for upstream LDAP group membership
2021-05-20 13:10:23 -07:00
Ryan Richard
7e76b66639 LDAP upstream watcher controller tries using both TLS and StartTLS
- Automatically try to fall back to using StartTLS when using TLS
  doesn't work. Only complain when both don't work.
- Remember (in-memory) which one worked and keeping using that one
  in the future (unless the pod restarts).
2021-05-20 12:46:33 -07:00
Ryan Richard
fff90ed2ca Merge branch 'main' into initial_ldap_group_support 2021-05-20 12:36:04 -07:00
Margo Crawford
62651eddb0 Took care of some impersonation cluster ip related todos 2021-05-20 11:57:07 -07:00
Matt Moyer
ec25259901 Update impersonatorconfig controller to use new CredentialIssuer update helper.
Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-20 12:26:07 -05:00
Matt Moyer
e4dd83887a Merge remote-tracking branch 'origin/main' into credentialissuer-spec-api 2021-05-20 10:53:53 -05:00
Matt Moyer
562942cdbf Merge pull request #627 from mattmoyer/use-informers-for-credentialissuer-updates
Create CredentialIssuer at install, not runtime.
2021-05-20 10:13:41 -05:00
Ryan Richard
025b37f839 upstreamldap.New() now supports a StartTLS config option
- This enhances our LDAP client code to make it possible to optionally
  dial an LDAP server without TLS and then use StartTLS to upgrade
  the connection to TLS.
- The controller for LDAPIdentityProviders is not using this option
  yet. That will come in a future commit.
2021-05-19 17:17:44 -07:00
Margo Crawford
63c39454f6 WIP on impersonation clusterip service 2021-05-19 17:00:28 -07:00
Matt Moyer
657488fe90 Create CredentialIssuer at install, not runtime.
Previously, our controllers would automatically create a CredentialIssuer with a singleton name. The helpers we had for this also used "raw" client access and did not take advantage of the informer cache pattern.

With this change, the CredentialIssuer is always created at install time in the ytt YAML. The controllers now only update the existing CredentialIssuer status, and they do so using the informer cache as much as possible.

This change is targeted at only the kubecertagent controller to start. The impersonatorconfig controller will be updated in a following PR along with other changes.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-19 17:15:25 -05:00
Margo Crawford
9e61640c92 LoadBalancerIP updated dynamically 2021-05-19 14:16:15 -07:00
Ryan Richard
94d6b76958 Merge branch 'initial_ldap_group_support' into ldap_starttls 2021-05-19 13:12:56 -07:00
Ryan Richard
424c112bbc Merge branch 'main' into initial_ldap_group_support 2021-05-19 13:12:17 -07:00
Margo Crawford
3bb95f1de2 Give kubeclient_test some default values for credentialissuer spec 2021-05-19 11:56:54 -07:00
Margo Crawford
0b66321902 Changes to make the linter pass 2021-05-19 11:05:35 -07:00
Matt Moyer
297a484948 Add more validation and update tests for impersonationProxy as pointer.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-19 12:42:31 -05:00
Matt Moyer
13372a43e6 Update generated code from previous commit. 2021-05-19 11:41:35 -05:00
Matt Moyer
54e0b83146 Update API so that impersonationProxy spec is a pointer. 2021-05-19 11:41:17 -05:00
Margo Crawford
94c370ac85 Annotations for impersonation load balancer 2021-05-18 16:54:59 -07:00
Ryan Richard
b5063e59ab Merge branch 'initial_ldap_group_support' into ldap_starttls 2021-05-18 16:39:59 -07:00
Ryan Richard
a6f95cfff1 Configure openldap to disallow non-TLS clients
- For testing purposes, we would like to ensure that when we connect
  to the LDAP server we cannot accidentally avoid using TLS or StartTLS.
- Also enabled the openldap `memberOf` overlay in case we want to
  support group search using `memberOf` in the future.
- This required changes to the docker.io/bitnami/openldap container
  image, so we're using our own fork for now. Will submit a PR to
  bitnami/openldap to see if they will accept it (or something similar)
  upstream.
2021-05-18 16:38:12 -07:00
Margo Crawford
eaea3471ec Validation for service type none and external endpoint none
Also added a few more test cases for provisioning a load balancer
2021-05-18 13:50:52 -07:00
Matt Moyer
4a785e73e6 WIP fixing impersonatorconfig tests 2021-05-18 14:54:04 -05:00
Margo Crawford
51f1a0ec13 WIP: not using impersonator.config just credentialissuer directly
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 12:16:27 -07:00
Matt Moyer
9af3cb1115 Change impersonation integration test to use CredentialIssuer spec
rather than a configmap

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-05-18 09:51:11 -07:00
Matt Moyer
18ccf11905 Update impersonatorconfig controller to use CredentialIssuer API instead of ConfigMap.
Signed-off-by: Margo Crawford <margaretc@vmware.com>
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 09:50:35 -07:00
Matt Moyer
1a131e64fe Start deploying an initial CredentialIssuer in our install YAML.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 11:12:18 -05:00
Matt Moyer
e885114221 Add generated code from adding spec fields to CredentialIssuer.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 11:12:18 -05:00
Matt Moyer
26da763962 Add spec fields to CredentialIssuer.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 11:12:18 -05:00
Matt Moyer
4a456446ff Update doc comments for types_credentialissuer.go.tmpl.
Update to follow https://golang.org/doc/effective_go#commentary:

> The first sentence should be a one-sentence summary that starts with the name being declared.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-18 11:12:18 -05:00
Matt Moyer
efeb25b8eb Merge pull request #619 from vmware-tanzu/dependabot/go_modules/github.com/creack/pty-1.1.12
Bump github.com/creack/pty from 1.1.11 to 1.1.12
2021-05-18 09:16:27 -05:00
dependabot[bot]
f595e81dbb Bump github.com/creack/pty from 1.1.11 to 1.1.12
Bumps [github.com/creack/pty](https://github.com/creack/pty) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/creack/pty/releases)
- [Commits](https://github.com/creack/pty/compare/v1.1.11...v1.1.12)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-18 05:56:45 +00:00
Mo Khan
0f5f72829b Merge pull request #594 from enj/enj/i/tcr_strict_user_info
cred req: disallow lossy user info translations
2021-05-17 19:28:21 -04:00
Monis Khan
f40fd29c7c local-user-authenticator: stop setting UID
Signed-off-by: Monis Khan <mok@vmware.com>
2021-05-17 19:03:45 -04:00
Monis Khan
35479e2978 cred req: disallow lossy user info translations
Signed-off-by: Monis Khan <mok@vmware.com>
2021-05-17 19:03:44 -04:00
Ryan Richard
742b70d6a4 Merge branch 'main' into initial_ldap_group_support 2021-05-17 14:24:56 -07:00
Ryan Richard
dab5ff3788 ldap_client_test.go: Forgot to change an assertion related to groups 2021-05-17 14:21:57 -07:00
Ryan Richard
99099fd32f Yet more debugging of tests which only fail in main CI 2021-05-17 14:20:41 -07:00
Ryan Richard
65cab53a11 Merge branch 'main' into initial_ldap_group_support 2021-05-17 14:12:20 -07:00
Ryan Richard
8c660f09bc More debugging of tests which only fail in main CI 2021-05-17 13:53:17 -07:00
Ryan Richard
ac431ddc6d Add more to failure message in test which only fails in main CI 2021-05-17 12:57:34 -07:00
Ryan Richard
3e1e8880f7 Initial support for upstream LDAP group membership
Reflect the upstream group membership into the Supervisor's
downstream tokens, so they can be added to the user's
identity on the workload clusters.

LDAP group search is configurable on the
LDAPIdentityProvider resource.
2021-05-17 11:10:26 -07:00
Ryan Richard
14b8fcc472 Merge pull request #555 from vmware-tanzu/initial_ldap
Initial `LDAPIdentityProvider` support for the Supervisor and CLI
2021-05-17 10:40:50 -07:00
Ryan Richard
20b1c41bf5 Experiment to see if we can ignore read /dev/ptmx: input/output error
This error seems to always happen on linux, but never on MacOS.
2021-05-13 16:02:24 -07:00
Ryan Richard
f5bf8978a3 Cache ResourceVersion of the validated bind Secret in memory
...instead of caching it in the text of the Condition message
2021-05-13 15:22:36 -07:00
Ryan Richard
514ee5b883 Merge branch 'main' into initial_ldap 2021-05-13 14:24:10 -07:00
Margo Crawford
39d7f8b6eb Merge pull request #614 from vmware-tanzu/gc-bug-tests
Tests for garbage collection behavior for access and refresh tokens
2021-05-13 13:08:07 -07:00
Ryan Richard
609883c49e Update TestSupervisorOIDCDiscovery for versioned IDP discovery endpoint 2021-05-13 13:07:31 -07:00
Ryan Richard
f15fc66e06 pinniped get kubeconfig refactor to use oidc.NewProvider for discovery
- Note that this adds an extra check of the response, which is that
  the issuer string in the response must match issuer of the requested
  URL.
- Some of the error messages also changed to match the errors provided
  by oidc.NewProvider
2021-05-13 12:27:42 -07:00
Margo Crawford
6479015caf Remove timeout so this test doesnt take forever 2021-05-13 10:23:44 -07:00
Ryan Richard
67dca688d7 Add an API version to the Supervisor IDP discovery endpoint
Also rename one of the new functional opts in login.go to more
accurately reflect the intention of the opt.
2021-05-13 10:05:56 -07:00
Margo Crawford
b391d5ae02 Also check that the authcode storage is around for a while 2021-05-12 14:22:14 -07:00
Ryan Richard
29ca8acab4 oidc_upstream_watcher.go: two methods become private funcs 2021-05-12 14:05:08 -07:00
Ryan Richard
1ae3c6a1ad Split package upstreamwatchers into four packages 2021-05-12 14:00:39 -07:00
Ryan Richard
22092e9aed Missed a usage of int64Ptr in previous commit 2021-05-12 14:00:26 -07:00
Margo Crawford
874f938fc7 unit test for garbage collection time for refresh and access tokens 2021-05-12 13:55:54 -07:00
Ryan Richard
4804c837d4 Insignificant change in ldap_upstream_watcher_test.go 2021-05-12 13:37:01 -07:00
Ryan Richard
f0652c1ce1 Replace all usages of strPtr() with pointer.StringPtr() 2021-05-12 13:20:00 -07:00
Ryan Richard
044443f315 Rename X-Pinniped-Idp-* headers to Pinniped-*
See RFC6648 which asks that people stop using `X-` on header names.
Also Matt preferred not mentioning "IDP" in the header name.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-12 13:06:08 -07:00
Ryan Richard
9ca72fcd30 login.go: Respect overallTimeout for LDAP login-related http requests
Signed-off-by: Matt Moyer <moyerm@vmware.com>
2021-05-12 12:57:10 -07:00
Ryan Richard
3008d1a85c Log slow LDAP authentication attempts for debugging purposes 2021-05-12 11:59:48 -07:00
Ryan Richard
6c2a775c9b Use proxy for pinniped get kubeconfig in hack/prepare-supervisor-on-kind.sh
Because the command now calls the discovery endpoint,
so it needs to go through the proxy to resolve the
hostname.
2021-05-12 11:34:16 -07:00
Ryan Richard
41d3e3b6ec Fix lint error in e2e_test.go 2021-05-12 11:24:00 -07:00
Ryan Richard
20b86ac0a9 Merge pull request #589 from vmware-tanzu/ldap-get-kubeconfig
WIP: Support for Supervisor upstream LDAP IDPs in `pinniped get kubeconfig`
2021-05-12 10:10:49 -07:00
Margo Crawford
df0e715bb7 Add integration test that waits for access token expiry 2021-05-12 09:05:13 -07:00
Ryan Richard
6723ed9fd8 Add end-to-end integration test for CLI-based LDAP login 2021-05-11 13:55:46 -07:00
Ryan Richard
f98aa96ed3 Merge branch 'initial_ldap' into ldap-get-kubeconfig 2021-05-11 11:10:25 -07:00
Ryan Richard
675bbb2aba Merge branch 'main' into initial_ldap 2021-05-11 11:09:37 -07:00
Ryan Richard
e25eb05450 Move Supervisor IDP discovery to its own new endpoint 2021-05-11 10:31:33 -07:00
Pinny
dbde150c38 Update CLI docs for v0.8.0 release 2021-05-10 22:01:16 +00:00
Ryan Richard
c0fcd27594 Fix typo in test/integration/e2e_test.go
Co-authored-by: Mo Khan <i@monis.app>
2021-05-10 12:51:56 -07:00
Margo Crawford
778c194cc4 Autodetection with multiple idps in discovery document
Signed-off-by: Ryan Richard <richardry@vmware.com>
2021-04-30 17:14:28 -07:00
Margo Crawford
a8754b5658 Refactor: extract helper func from runGetKubeconfig()
- Reduces the cyclomatic complexity of the function

Signed-off-by: Ryan Richard <richardry@vmware.com>
2021-04-30 15:00:54 -07:00
Ryan Richard
1c66ffd5ff WIP: add supervisor upstream flags to pinniped get kubeconfig
- And perform auto-discovery when the flags are not set
- Several TODOs remain which will be addressed in the next commit

Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-04-30 14:28:03 -07:00
Ryan Richard
10c4cb4493 Merge branch 'initial_ldap' into ldap-get-kubeconfig 2021-04-28 14:28:32 -07:00
Ryan Richard
36819989a3 Remove DryRunAuthenticationUsername from LDAPIdentityProviderSpec
Signed-off-by: Margo Crawford <margaretc@vmware.com>
2021-04-28 14:26:57 -07:00
Ryan Richard
4bd83add35 Add Supervisor upstream IDP discovery on the server-side 2021-04-28 13:14:21 -07:00
Ryan Richard
5c62a9d0bd More adjustments based on PR feedback 2021-04-27 16:54:26 -07:00
Ryan Richard
263a33cc85 Some updates based on PR review 2021-04-27 12:43:09 -07:00
Ryan Richard
b3b108500a Merge branch 'main' into initial_ldap 2021-04-27 10:12:43 -07:00
Ryan Richard
9b818dbf10 Remove another 10s sleep related to JWTAuthenticator initialization 2021-04-22 16:59:42 -07:00
Ryan Richard
6a350aa4e1 Fix some LDAP CA bundle handling
- Make PINNIPED_TEST_LDAP_LDAPS_CA_BUNDLE optional for integration tests
- When there is no CA bundle provided, be careful to use nil instead of
  an empty bundle, because nil means to use the OS defaults
2021-04-22 16:58:48 -07:00
Ryan Richard
ddc632b99c Show the error_description when it is included in authorization response 2021-04-19 18:08:52 -07:00
Ryan Richard
c176d15aa7 Add Supervisor upstream LDAP login to the Pinniped CLI
- Also enhance prepare-supervisor-on-kind.sh to allow setup of
  a working LDAP upstream IDP.
2021-04-19 17:59:46 -07:00
Ryan Richard
c79930f419 Merge branch 'main' into initial_ldap 2021-04-16 18:33:02 -07:00
Ryan Richard
4c2a0b4872 Add new command-line flags to the login oidc command
- Also some light prefactoring in login.go to make room for LDAP-style
  login, which is not implemented yet in this commit. TODOs are added.
- And fix a test pollution problem in login_oidc_test.go where it was
  using a real on-disk CLI cache file, so the tests were polluted by
  the contents of that file and would sometimes cause each other to
  fail.
2021-04-16 18:30:31 -07:00
Ryan Richard
e9d5743845 Add authentication dry run validation to LDAPIdentityProvider
Also force the LDAP server pod to restart whenever the LDIF file
changes, so whenever you redeploy the tools deployment with a new test
user password the server will be updated.
2021-04-16 14:04:05 -07:00
Ryan Richard
83085aa3d6 Retest the server connection when the bind Secret has changed
Unfortunately, Secrets do not seem to have a Generation field, so we
use the ResourceVersion field instead. This means that any change to
the Secret will cause us to retry the connection to the LDAP server,
even if the username and password fields in the Secret were not
changed. Seems like an okay trade-off for this early draft of the
controller compared to a more complex implementation.
2021-04-15 17:45:15 -07:00
Ryan Richard
8e438e22e9 Only test the server connection when the spec has changed
This early version of the controller is not intended to act as an
ongoing health check for your upstream LDAP server. It will connect
to the LDAP server to essentially "lint" your configuration once.
It will do it again only when you change your configuration. To account
for transient errors, it will keep trying to connect to the server
until it succeeds once.

This commit does not include looking for changes in the associated bind
user username/password Secret.
2021-04-15 16:46:27 -07:00
Ryan Richard
b9ce84fd68 Test the LDAP config by connecting to the server in the controller 2021-04-15 14:44:43 -07:00
Ryan Richard
da7216c1ef Merge branch 'main' into initial_ldap 2021-04-15 10:27:59 -07:00
Ryan Richard
e6e6497022 Introduce upstreamldap.New to prevent changes to the underlying config
Makes it easier to support using the same upstreamldap.Provider from
multiple goroutines safely.
2021-04-15 10:25:35 -07:00
Ryan Richard
5c28d36c9b Redact some params of URLs in logs to avoid printing sensitive info 2021-04-15 07:59:38 -07:00
Ryan Richard
12a3636351 base64 once instead of thrice 2021-04-14 20:39:01 -07:00
Ryan Richard
939b6b12cc ldap_client_test.go: refactor to use the LDAP server on the K8s cluster 2021-04-14 17:49:40 -07:00
Ryan Richard
8d75825635 Merge branch 'main' into initial_ldap 2021-04-14 17:47:26 -07:00
Ryan Richard
e0fe184c89 Relax cpu limit on ldap server a little to make it start faster
- Allowing it to use more CPU during startup decreases startup time
  from about 25 seconds (on my laptop) down to about 1 second.
2021-04-14 08:35:04 -07:00
Ryan Richard
a6e1a949d2 ldap_client_test.go: mark as integration test so units skip it 2021-04-14 08:12:15 -07:00
Ryan Richard
47b66ceaa7 Passing integration test for LDAP login! 🚀 2021-04-13 18:11:16 -07:00
Ryan Richard
6bba529b10 RBAC rules for ldapidentityproviders to grant permissions to controller 2021-04-13 17:26:53 -07:00
Ryan Richard
14ff5ee4ff ldap_upstream_watcher.go: decode and validate CertificateAuthorityData 2021-04-13 17:16:57 -07:00
Ryan Richard
51263a0f07 Return unauthenticated instead of error for bad username or password
- Bad usernames and passwords aren't really errors, since they are
  based on end-user input.
- Other kinds of authentication failures are caused by bad configuration
  so still treat those as errors.
- Empty usernames and passwords are already prevented by our endpoint
  handler, but just to be safe make sure they cause errors inside the
  authenticator too.
2021-04-13 16:22:13 -07:00
Ryan Richard
fec3d92f26 Add integration test for upstreamldap.Provider
- The unit tests for upstreamldap.Provider need to mock the LDAP server,
  so add an integration test which allows us to get fast feedback for
  this code against a real LDAP server.
- Automatically wrap the user search filter in parenthesis if it is not
  already wrapped in parens.
- More special handling for using "dn" as the username or UID attribute
  name.
- Also added some more comments to types_ldapidentityprovider.go.tmpl
2021-04-13 15:23:14 -07:00
Ryan Richard
7b8c86b38e Handle error cases during LDAP user search and bind 2021-04-13 08:38:04 -07:00
Ryan Richard
f0c4305e53 Started implementation of LDAP user search and bind 2021-04-12 17:50:25 -07:00
Ryan Richard
e24d5891dd ldap_upstream_watcher_test.go: add another unit test 2021-04-12 14:12:51 -07:00
Ryan Richard
25c1f0d523 Add Conditions to LDAPIdentityProvider's Status and start to fill them
- The ldap_upstream_watcher.go controller validates the bind secret and
  uses the Conditions to report errors. Shares some condition reporting
  logic with its sibling controller oidc_upstream_watcher.go, to the
  extent which is convenient without generics in golang.
2021-04-12 13:53:21 -07:00
Ryan Richard
05571abb74 Add a little more logic to ldap_upstream_watcher.go 2021-04-12 11:23:08 -07:00
Ryan Richard
05daa9eff5 More LDAP WIP: started controller and LDAP server connection code
Both are unfinished works in progress.
2021-04-09 18:49:43 -07:00
Ryan Richard
7781a2e17a Some renames in pkg upstreamwatcher to make room for a second controller 2021-04-09 08:43:19 -07:00
Andrew Keesler
4ab704b7de ldap: add initial stub upstream LDAP connection package
Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2021-04-09 11:38:53 -04:00
Ryan Richard
f6ded84f07 Implement upstream LDAP support in auth_handler.go
- When the upstream IDP is an LDAP IDP and the user's LDAP username and
  password are received as new custom headers, then authenticate the
  user and, if authentication was successful, return a redirect with
  an authcode. Handle errors according to the OAuth/OIDC specs.
- Still does not support having multiple upstream IDPs defined at the
  same time, which was an existing limitation of this endpoint.
- Does not yet include the actual LDAP authentication, which is
  hidden behind an interface from the point of view of auth_handler.go
- Move the oidctestutil package to the testutil directory.
- Add an interface for Fosite storage to avoid a cyclical test
  dependency.
- Add GetURL() to the UpstreamLDAPIdentityProviderI interface.
- Extract test helpers to be shared between callback_handler_test.go
  and auth_handler_test.go because the authcode and fosite storage
  assertions should be identical.
- Backfill Content-Type assertions in callback_handler_test.go.

Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2021-04-08 17:28:01 -07:00
Ryan Richard
064e3144a2 auth_handler.go: pre-factor to make room for upstream LDAP IDPs 2021-04-07 17:05:25 -07:00
Ryan Richard
1f5978aa1a Supervisor pre-factor to make room for upstream LDAP identity providers 2021-04-07 16:12:13 -07:00
Ryan Richard
1c55c857f4 Start to fill out LDAPIdentityProvider's fields and TestSupervisorLogin
- Add some fields to LDAPIdentityProvider that we will need to be able
  to search for users during login
- Enhance TestSupervisorLogin to test logging in using an upstream LDAP
  identity provider. Part of this new test is skipped for now because
  we haven't written the corresponding production code to make it
  pass yet.
- Some refactoring and enhancement to env.go and the corresponding env
  vars to support the new upstream LDAP provider integration tests.
- Use docker.io/bitnami/openldap for our test LDAP server instead of our
  own fork now that they have fixed the bug that we reported.

Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2021-04-07 12:56:09 -07:00
Ryan Richard
2b6859b161 Add stub LDAP API type and integration test
The goal here was to start on an integration test to get us closer to the red
test that we want so we can start working on LDAP.

Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2021-04-06 13:10:01 -04:00
Ryan Richard
9968d501f4 Merge branch 'main' into initial_ldap 2021-04-05 15:15:05 -07:00
Ryan Richard
702f9965ab Deploy an OpenLDAP server for integration tests
Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2021-04-05 15:05:53 -07:00
399 changed files with 46107 additions and 20719 deletions

View File

@@ -1,12 +1,23 @@
./.*
./*.md
./*.yaml
./apis
./deploy
./Dockerfile
./generated/1.1*
./internal/mocks
./LICENSE
./site/
./test
**/*_test.go
# This is effectively a copy of the .gitignore file.
# The whole git repo, including the .git directory, should get copied into the Docker build context,
# to enable the use of hack/get-ldflags.sh inside the Dockerfile.
# When you change the .gitignore file, please consider also changing this file.
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# GoLand
.idea
# MacOS Desktop Services Store
.DS_Store

6
.gitignore vendored
View File

@@ -1,3 +1,6 @@
# When you change this file, please consider also changing the .dockerignore file.
# See comments at the top of .dockerignore for more information.
# Binaries for programs and plugins
*.exe
*.exe~
@@ -11,9 +14,6 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# GoLand
.idea

View File

@@ -47,7 +47,6 @@ linters:
- scopelint
- sqlclosecheck
- unconvert
- unparam
- whitespace
issues:

View File

@@ -10,15 +10,28 @@ Please see the [Code of Conduct](./CODE_OF_CONDUCT.md).
See [SCOPE.md](./SCOPE.md) for some guidelines about what we consider in and out of scope for Pinniped.
## Roadmap
The near-term and mid-term roadmap for the work planned for the project [maintainers](MAINTAINERS.md) is documented in [ROADMAP.md](ROADMAP.md).
## Community Meetings
Pinniped is better because of our contributors and maintainers. It is because of you that we can bring great software to the community. Please join us during our online community meetings, occuring every first and third Thursday of the month at 9AM PT / 12PM PT. Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09) to attend and add any agenda items you wish to discuss to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view). Join our [Google Group](https://groups.google.com/u/1/g/project-pinniped) to receive invites to this meeting.
Pinniped is better because of our contributors and [maintainers](MAINTAINERS.md). It is because of you that we can bring great
software to the community. Please join us during our online community meetings,
occurring every first and third Thursday of the month at 9 AM PT / 12 PM PT.
Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09)
to attend and add any agenda items you wish to discuss
to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view).
Join our [Google Group](https://groups.google.com/g/project-pinniped) to receive invites to this meeting.
If the meeting day falls on a US holiday, please consider that occurrence of the meeting to be canceled.
## Discussion
Got a question, comment, or idea? Please don't hesitate to reach out via the GitHub [Discussions](https://github.com/vmware-tanzu/pinniped/discussions) tab at the top of this page or reach out in Kubernetes Slack Workspace within the [#pinniped channel](https://kubernetes.slack.com/archives/C01BW364RJA).
Got a question, comment, or idea? Please don't hesitate to reach out
via GitHub [Discussions](https://github.com/vmware-tanzu/pinniped/discussions),
GitHub [Issues](https://github.com/vmware-tanzu/pinniped/issues),
or in the Kubernetes Slack Workspace within the [#pinniped channel](https://kubernetes.slack.com/archives/C01BW364RJA).
## Issues
@@ -45,7 +58,7 @@ guidelines in the issue and pull request templates.
To suggest a feature, please first open an
[issue](https://github.com/vmware-tanzu/pinniped/issues/new?template=feature-proposal.md)
and tag it with `proposal`, or create a new [Discussion](https://github.com/vmware-tanzu/pinniped/discussions).
The project team will work with you on your feature request.
The project [maintainers](MAINTAINERS.md) will work with you on your feature request.
Once the feature request has been validated, a [pull request](https://github.com/vmware-tanzu/pinniped/compare)
can be opened to implement the feature.
@@ -53,6 +66,10 @@ can be opened to implement the feature.
For specifics on what to include in your feature request, please follow the
guidelines in the issue and pull request templates.
### Reporting security vulnerabilities
Please follow the procedure described in [SECURITY.md](SECURITY.md).
## CLA
We welcome contributions from everyone but we can only accept them if you sign

View File

@@ -3,7 +3,7 @@
# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
FROM golang:1.16.4 as build-env
FROM golang:1.17.1 as build-env
WORKDIR /work
COPY . .
@@ -16,26 +16,18 @@ RUN \
--mount=type=cache,target=/cache/gocache \
--mount=type=cache,target=/cache/gomodcache \
mkdir out && \
GOCACHE=/cache/gocache \
GOMODCACHE=/cache/gomodcache \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
go build -v -ldflags "$(hack/get-ldflags.sh)" -o out \
./cmd/pinniped-concierge/... \
./cmd/pinniped-supervisor/... \
./cmd/local-user-authenticator/...
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=linux GOARCH=amd64 && \
go build -v -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/main.go && \
go build -v -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/main.go && \
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
# Use a Debian slim image to grab a reasonable default CA bundle.
FROM debian:10.9-slim AS get-ca-bundle-env
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/* /var/cache/debconf/*
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
FROM gcr.io/distroless/static:nonroot@sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4
# Use a runtime image based on Debian slim.
FROM debian:10.9-slim
COPY --from=get-ca-bundle-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
# Copy the binaries from the build-env stage.
COPY --from=build-env /work/out/ /usr/local/bin/
# Copy the server binary from the build-env stage.
COPY --from=build-env /usr/local/bin /usr/local/bin
# Document the ports
EXPOSE 8080 8443
@@ -44,4 +36,4 @@ EXPOSE 8080 8443
USER 1001:1001
# Set the entrypoint
ENTRYPOINT ["/usr/local/bin/pinniped-concierge"]
ENTRYPOINT ["/usr/local/bin/pinniped-server"]

View File

@@ -4,16 +4,21 @@ This is the current list of maintainers for the Pinniped project.
| Maintainer | GitHub ID | Affiliation |
| --------------- | --------- | ----------- |
| Andrew Keesler | [ankeesler](https://github.com/ankeesler) | [VMware](https://www.github.com/vmware/) |
| Margo Crawford | [margocrawf](https://github.com/margocrawf) | [VMware](https://www.github.com/vmware/) |
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) | [VMware](https://www.github.com/vmware/) |
| Mo Khan | [enj](https://github.com/enj) | [VMware](https://www.github.com/vmware/) |
| Pablo Schuhmacher | [pabloschuhmacher](https://github.com/pabloschuhmacher) | [VMware](https://www.github.com/vmware/) |
| Anjali Telang | [anjaltelang](https://github.com/anjaltelang) | [VMware](https://www.github.com/vmware/) |
| Ryan Richard | [cfryanr](https://github.com/cfryanr) | [VMware](https://www.github.com/vmware/) |
## Emeritus Maintainers
* Andrew Keesler, [ankeesler](https://github.com/ankeesler)
* Pablo Schuhmacher, [pabloschuhmacher](https://github.com/pabloschuhmacher)
* Matt Moyer, [mattmoyer](https://github.com/mattmoyer)
## Pinniped Contributors & Stakeholders
| Feature Area | Lead |
| ----------------------------- | :---------------------: |
| Technical Lead | Matt Moyer (mattmoyer) |
| Product Management | Pablo Schuhmacher (pabloschuhmacher) |
| Technical Lead | Mo Khan (enj) |
| Product Management | Anjali Telang (anjaltelang) |
| Community Management | Nanci Lancaster (microwavables) |

View File

@@ -1,63 +1,51 @@
<img src="site/content/docs/img/pinniped_logo.svg" alt="Pinniped Logo" width="100%"/>
<a href="https://pinniped.dev" target="_blank">
<img src="site/content/docs/img/pinniped_logo.svg" alt="Pinniped Logo" width="100%"/>
</a>
## Overview
Pinniped provides identity services to Kubernetes.
Pinniped allows cluster administrators to easily plug in external identity
providers (IDPs) into Kubernetes clusters. This is achieved via a uniform
install procedure across all types and origins of Kubernetes clusters,
declarative configuration via Kubernetes APIs, enterprise-grade integrations
with IDPs, and distribution-specific integration strategies.
- Easily plug in external identity providers into Kubernetes clusters while offering a simple install and configuration experience. Leverage first class integration with Kubernetes and kubectl command-line.
- Give users a consistent, unified login experience across all your clusters, including on-premises and managed cloud environments.
- Securely integrate with an enterprise IDP using standard protocols or use secure, externally managed identities instead of relying on simple, shared credentials.
### Example use cases
* Your team uses a large enterprise IDP, and has many clusters that they
manage. Pinniped provides:
* Seamless and robust integration with the IDP
* Easy installation across clusters of any type and origin
* A simplified login flow across all clusters
* Your team shares a single cluster. Pinniped provides:
* Simple configuration to integrate an IDP
* Individual, revocable identities
### Architecture
The Pinniped Supervisor component offers identity federation to enable a user to
access multiple clusters with a single daily login to their external IDP. The
Pinniped Supervisor supports various external [IDP
types](https://github.com/vmware-tanzu/pinniped/tree/main/generated/1.20#k8s-api-idp-supervisor-pinniped-dev-v1alpha1).
The Pinniped Concierge component offers credential exchange to enable a user to
exchange an external credential for a short-lived, cluster-specific
credential. Pinniped supports various [authentication
methods](https://github.com/vmware-tanzu/pinniped/tree/main/generated/1.20#authenticationconciergepinnipeddevv1alpha1)
and implements different integration strategies for various Kubernetes
distributions to make authentication possible.
The Pinniped Concierge can be configured to hook into the Pinniped Supervisor's
federated credentials, or it can authenticate users directly via external IDP
credentials.
To learn more, see [architecture](https://pinniped.dev/docs/background/architecture/).
To learn more, please visit the Pinniped project's website, https://pinniped.dev.
## Getting started with Pinniped
Care to kick the tires? It's easy to [install and try Pinniped](https://pinniped.dev/docs/).
## Community meetings
Pinniped is better because of our contributors and maintainers. It is because of you that we can bring great software to the community. Please join us during our online community meetings, occurring every first and third Thursday of the month at 9 AM PT / 12 PM PT. Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09) to attend and add any agenda items you wish to discuss to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view). Join our [Google Group](https://groups.google.com/g/project-pinniped) to receive invites to this meeting.
If the meeting day falls on a US holiday, please consider that occurrence of the meeting to be canceled.
## Discussion
Got a question, comment, or idea? Please don't hesitate to reach out via the GitHub [Discussions](https://github.com/vmware-tanzu/pinniped/discussions) tab at the top of this page or reach out in Kubernetes Slack Workspace within the [#pinniped channel](https://kubernetes.slack.com/archives/C01BW364RJA).
Got a question, comment, or idea? Please don't hesitate to reach out
via GitHub [Discussions](https://github.com/vmware-tanzu/pinniped/discussions),
GitHub [Issues](https://github.com/vmware-tanzu/pinniped/issues),
or in the Kubernetes Slack Workspace within the [#pinniped channel](https://kubernetes.slack.com/archives/C01BW364RJA).
## Contributions
Contributions are welcome. Before contributing, please see the [contributing guide](CONTRIBUTING.md).
Want to get involved? Contributions are welcome.
Please see the [contributing guide](CONTRIBUTING.md) for more information about reporting bugs, requesting features,
building and testing the code, submitting PRs, and other contributor topics.
## Community meetings
Pinniped is better because of our contributors and [maintainers](MAINTAINERS.md). It is because of you that we can bring great
software to the community. Please join us during our online community meetings,
occurring every first and third Thursday of the month at 9 AM PT / 12 PM PT.
Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09)
to attend and add any agenda items you wish to discuss
to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view).
Join our [Google Group](https://groups.google.com/g/project-pinniped) to receive invites to this meeting.
If the meeting day falls on a US holiday, please consider that occurrence of the meeting to be canceled.
## Adopters
Some organizations and products using Pinniped are featured in [ADOPTERS.md](ADOPTERS.md).
Add your own organization or product [here](https://github.com/vmware-tanzu/pinniped/discussions/152).
## Reporting security vulnerabilities
@@ -67,4 +55,4 @@ Please follow the procedure described in [SECURITY.md](SECURITY.md).
Pinniped is open source and licensed under Apache License Version 2.0. See [LICENSE](LICENSE).
Copyright 2020 the Pinniped contributors. All Rights Reserved.
Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.

View File

@@ -33,18 +33,21 @@ The following table includes the current roadmap for Pinniped. If you have any q
Last Updated: April 2021
Theme|Description|Timeline|
Last Updated: Sept 2021
|Theme|Description|Timeline|
|--|--|--|
|LDAP Support|Extends upstream IDP protocols|May 2021|
|Improved Documentation|Reorganizing and improving Pinniped docs; new how-to guides and tutorials|May 2021|
|Multiple IDPs|Support for multiple upstream IDPs to be configured simultaneously|Jun 2021|
|Wider Concierge cluster support|Support for more cluster types in the Concierge|Jul 2021|
|Improving Security Posture|Offer the best security posture for Kubernetes cluster authentication|Exploring/Ongoing|
|Improving Security Posture|Supervisor token refresh fails when the upstream refresh token no longer works|Sept 2021|
|Wider Concierge cluster support|Support for OpenShift cluster types in the Concierge|Sept 2021|
|Multiple IDP support|Support multiple IDPs configured on a single Supervisor|Exploring/Ongoing|
|Identity transforms|Support prefixing, filtering, or performing coarse-grained checks on upstream users and groups|Exploring/Ongoing|
|CLI SSO|Support Kerberos based authentication on CLI |Exploring/Ongoing|
|Extended IDP support|Support more types of identity providers on the Supervisor|Exploring/Ongoing|
|Improved Documentation|Reorganizing and improving Pinniped docs; new how-to guides and tutorials|Exploring/Ongoing|
|Improve our CI/CD systems|Upgrade tests; make Kind more efficient and reliable for CI ; Windows tests; performance tests; scale tests; soak tests|Exploring/Ongoing|
|CLI Improvements|Improving CLI UX for setting up Supervisor IDPs|Exploring/Ongoing|
|Telemetry|Adding some useful phone home metrics as well as some vanity metrics|Exploring/Ongoing|
|Observability|Expose Pinniped metrics through Prometheus Integration|Exploring/Ongoing|
|Device Code Flow|Add support for OAuth 2.0 Device Authorization Grant in the Pinniped CLI and Supervisor|Exploring/Ongoing|
|Supervisor with New Clients|Enable registering new clients with Supervisor|Exploring/Ongoing|

View File

@@ -3,17 +3,23 @@
package v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// StrategyType enumerates a type of "strategy" used to implement credential access on a cluster.
// +kubebuilder:validation:Enum=KubeClusterSigningCertificate;ImpersonationProxy
type StrategyType string
// FrontendType enumerates a type of "frontend" used to provide access to users of a cluster.
// +kubebuilder:validation:Enum=TokenCredentialRequestAPI;ImpersonationProxy
type FrontendType string
// StrategyStatus enumerates whether a strategy is working on a cluster.
// +kubebuilder:validation:Enum=Success;Error
type StrategyStatus string
// StrategyReason enumerates the detailed reason why a strategy is in a particular status.
// +kubebuilder:validation:Enum=Listening;Pending;Disabled;ErrorDuringSetup;CouldNotFetchKey;CouldNotGetClusterInfo;FetchedKey
type StrategyReason string
@@ -36,7 +42,91 @@ const (
FetchedKeyStrategyReason = StrategyReason("FetchedKey")
)
// Status of a credential issuer.
// CredentialIssuerSpec describes the intended configuration of the Concierge.
type CredentialIssuerSpec struct {
// ImpersonationProxy describes the intended configuration of the Concierge impersonation proxy.
ImpersonationProxy *ImpersonationProxySpec `json:"impersonationProxy"`
}
// ImpersonationProxyMode enumerates the configuration modes for the impersonation proxy.
//
// +kubebuilder:validation:Enum=auto;enabled;disabled
type ImpersonationProxyMode string
const (
// ImpersonationProxyModeDisabled explicitly disables the impersonation proxy.
ImpersonationProxyModeDisabled = ImpersonationProxyMode("disabled")
// ImpersonationProxyModeEnabled explicitly enables the impersonation proxy.
ImpersonationProxyModeEnabled = ImpersonationProxyMode("enabled")
// ImpersonationProxyModeAuto enables or disables the impersonation proxy based upon the cluster in which it is running.
ImpersonationProxyModeAuto = ImpersonationProxyMode("auto")
)
// ImpersonationProxyServiceType enumerates the types of service that can be provisioned for the impersonation proxy.
//
// +kubebuilder:validation:Enum=LoadBalancer;ClusterIP;None
type ImpersonationProxyServiceType string
const (
// ImpersonationProxyServiceTypeLoadBalancer provisions a service of type LoadBalancer.
ImpersonationProxyServiceTypeLoadBalancer = ImpersonationProxyServiceType("LoadBalancer")
// ImpersonationProxyServiceTypeClusterIP provisions a service of type ClusterIP.
ImpersonationProxyServiceTypeClusterIP = ImpersonationProxyServiceType("ClusterIP")
// ImpersonationProxyServiceTypeNone does not automatically provision any service.
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
)
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
type ImpersonationProxySpec struct {
// Mode configures whether the impersonation proxy should be started:
// - "disabled" explicitly disables the impersonation proxy. This is the default.
// - "enabled" explicitly enables the impersonation proxy.
// - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
Mode ImpersonationProxyMode `json:"mode"`
// Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
//
// +kubebuilder:default:={"type": "LoadBalancer"}
Service ImpersonationProxyServiceSpec `json:"service"`
// 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".
//
// +optional
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
}
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
type ImpersonationProxyServiceSpec struct {
// 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.
//
// +kubebuilder:default:="LoadBalancer"
Type ImpersonationProxyServiceType `json:"type,omitempty"`
// LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service.
// This is not supported on all cloud providers.
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=255
// +optional
LoadBalancerIP string `json:"loadBalancerIP,omitempty"`
// Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
//
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}
// CredentialIssuerStatus describes the status of the Concierge.
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
@@ -47,7 +137,8 @@ type CredentialIssuerStatus struct {
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// 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
@@ -59,7 +150,7 @@ type CredentialIssuerKubeConfigInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Status of an integration strategy that was attempted by Pinniped.
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
type CredentialIssuerStrategy struct {
// Type of integration attempted.
Type StrategyType `json:"type"`
@@ -81,6 +172,7 @@ type CredentialIssuerStrategy struct {
Frontend *CredentialIssuerFrontend `json:"frontend,omitempty"`
}
// CredentialIssuerFrontend describes how to connect using a particular integration strategy.
type CredentialIssuerFrontend struct {
// Type describes which frontend mechanism clients can use with a strategy.
Type FrontendType `json:"type"`
@@ -118,7 +210,7 @@ type ImpersonationProxyInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Describes the configuration status of a Pinniped credential issuer.
// CredentialIssuer describes the configuration and status of the Pinniped Concierge credential issuer.
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -128,12 +220,18 @@ type CredentialIssuer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Status of the credential issuer.
// Spec describes the intended configuration of the Concierge.
//
// +optional
Spec CredentialIssuerSpec `json:"spec"`
// CredentialIssuerStatus describes the status of the Concierge.
//
// +optional
Status CredentialIssuerStatus `json:"status"`
}
// List of CredentialIssuer objects.
// CredentialIssuerList is a list of CredentialIssuer objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type CredentialIssuerList struct {
metav1.TypeMeta `json:",inline"`

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -32,6 +32,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&OIDCIdentityProvider{},
&OIDCIdentityProviderList{},
&LDAPIdentityProvider{},
&LDAPIdentityProviderList{},
&ActiveDirectoryIdentityProvider{},
&ActiveDirectoryIdentityProviderList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@@ -0,0 +1,182 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ActiveDirectoryIdentityProviderPhase string
const (
// ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources.
ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending"
// ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state.
ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready"
// ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state.
ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error"
)
// Status of an Active Directory identity provider.
type ActiveDirectoryIdentityProviderStatus struct {
// Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type ActiveDirectoryIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type ActiveDirectoryIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in Active Directory entry whose value shall become the username
// of the user after a successful authentication.
// Optional, when empty this defaults to "userPrincipalName".
// +optional
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely
// identify the user within this ActiveDirectory provider after a successful authentication.
// Optional, when empty this defaults to "objectGUID".
// +optional
UID string `json:"uid,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, this defaults to a custom field that looks like "sAMAccountName@domain",
// where domain is constructed from the domain components of the group DN.
// +optional
GroupName string `json:"groupName,omitempty"`
}
type ActiveDirectoryIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for users.
// It may make sense to specify a subtree as a search base if you wish to exclude some users
// or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will be
// '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
// This means that the user is a person, is not a computer, the sAMAccountType is for a normal user account,
// and is not shown in advanced view only
// (which would likely mean its a system created service account with advanced permissions).
// Also, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as
// the result of the user search.
// +optional
Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for groups.
// It may make sense to specify a subtree as a search base if you wish to exclude some groups
// for security reasons or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the filter were specified as
// "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
// This searches nested groups by default.
// Note that nested group search can be slow for some Active Directory servers. To disable it,
// you can set the filter to
// "(&(objectClass=group)(member={})"
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
// the result of the group search.
// +optional
Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an ActiveDirectory identity provider.
type ActiveDirectoryIdentityProviderSpec struct {
// Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in Active Directory.
UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.
GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type ActiveDirectoryIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec ActiveDirectoryIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"`
}
// List of ActiveDirectoryIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ActiveDirectoryIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ActiveDirectoryIdentityProvider `json:"items"`
}

View File

@@ -0,0 +1,171 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type LDAPIdentityProviderPhase string
const (
// LDAPPhasePending is the default phase for newly-created LDAPIdentityProvider resources.
LDAPPhasePending LDAPIdentityProviderPhase = "Pending"
// LDAPPhaseReady is the phase for an LDAPIdentityProvider resource in a healthy state.
LDAPPhaseReady LDAPIdentityProviderPhase = "Ready"
// LDAPPhaseError is the phase for an LDAPIdentityProvider in an unhealthy state.
LDAPPhaseError LDAPIdentityProviderPhase = "Error"
)
// Status of an LDAP identity provider.
type LDAPIdentityProviderStatus struct {
// Phase summarizes the overall status of the LDAPIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase LDAPIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type LDAPIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an LDAP bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type LDAPIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in the LDAP entry whose value shall become the username
// of the user after a successful authentication. This would typically be the same attribute name used in
// the user search filter, although it can be different. E.g. "mail" or "uid" or "userPrincipalName".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn". When this field
// is set to "dn" then the LDAPIdentityProviderUserSearch's Filter field cannot be blank, since the default
// value of "dn={}" would not work.
// +kubebuilder:validation:MinLength=1
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the LDAP entry which whose value shall be used to uniquely
// identify the user within this LDAP provider after a successful authentication. E.g. "uidNumber" or "objectGUID".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn".
// +kubebuilder:validation:MinLength=1
UID string `json:"uid,omitempty"`
}
type LDAPIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the LDAP entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name).
// +optional
GroupName string `json:"groupName,omitempty"`
}
type LDAPIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// +kubebuilder:validation:MinLength=1
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as the value from
// Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be
// explicitly specified, since the default value of "dn={}" would not work.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the LDAP entry which was found as
// the result of the user search.
// +optional
Attributes LDAPIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type LDAPIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and
// authenticated users will not belong to any groups from the LDAP provider. Also, when not specified,
// the values of Filter and Attributes are ignored.
// +optional
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as "member={}".
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
// the result of the group search.
// +optional
Attributes LDAPIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an LDAP identity provider.
type LDAPIdentityProviderSpec struct {
// Host is the hostname of this LDAP identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the LDAP server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind LDAPIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in the LDAP provider.
UserSearch LDAPIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in the LDAP provider.
GroupSearch LDAPIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// LDAPIdentityProvider describes the configuration of an upstream Lightweight Directory Access
// Protocol (LDAP) identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type LDAPIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec LDAPIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status LDAPIdentityProviderStatus `json:"status,omitempty"`
}
// List of LDAPIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type LDAPIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []LDAPIdentityProvider `json:"items"`
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -39,9 +39,31 @@ type OIDCIdentityProviderStatus struct {
// request parameters.
type OIDCAuthorizationConfig struct {
// AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization
// request flow with an OIDC identity provider. By default only the "openid" scope will be requested.
// request flow with an OIDC identity provider.
// In the case of a Resource Owner Password Credentials Grant flow, AdditionalScopes are the scopes
// in addition to "openid" that will be requested as part of the token request (see also the allowPasswordGrant field).
// By default, only the "openid" scope will be requested.
// +optional
AdditionalScopes []string `json:"additionalScopes,omitempty"`
// AllowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant
// (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a
// username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow.
// The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be
// supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password
// Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose
// to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the
// cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be
// convenient for users, especially for identities from your OIDC provider which are not intended to represent a human
// actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it,
// you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this
// OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password
// Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords
// (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other
// web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins.
// AllowPasswordGrant defaults to false.
// +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
}
// OIDCClaims provides a mapping from upstream claims into identities.

View File

@@ -0,0 +1,66 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// IDPType are the strings that can be returned by the Supervisor identity provider discovery endpoint
// as the "type" of each returned identity provider.
type IDPType string
// IDPFlow are the strings that can be returned by the Supervisor identity provider discovery endpoint
// in the array of allowed client "flows" for each returned identity provider.
type IDPFlow string
const (
IDPTypeOIDC IDPType = "oidc"
IDPTypeLDAP IDPType = "ldap"
IDPTypeActiveDirectory IDPType = "activedirectory"
IDPFlowCLIPassword IDPFlow = "cli_password"
IDPFlowBrowserAuthcode IDPFlow = "browser_authcode"
)
// Equals is a convenience function for comparing an IDPType to a string.
func (r IDPType) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPType to a string.
func (r IDPType) String() string {
return string(r)
}
// Equals is a convenience function for comparing an IDPFlow to a string.
func (r IDPFlow) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPFlow to a string.
func (r IDPFlow) String() string {
return string(r)
}
// OIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type OIDCDiscoveryResponse struct {
SupervisorDiscovery OIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// OIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type OIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// IDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type IDPDiscoveryResponse struct {
PinnipedIDPs []PinnipedIDP `json:"pinniped_identity_providers"`
}
// PinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type PinnipedIDP struct {
Name string `json:"name"`
Type IDPType `json:"type"`
Flows []IDPFlow `json:"flows,omitempty"`
}

View File

@@ -0,0 +1,25 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package oidc
// Constants related to the Supervisor FederationDomain's authorization and token endpoints.
const (
// AuthorizeUsernameHeaderName is the name of the HTTP header which can be used to transmit a username
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizeUsernameHeaderName = "Pinniped-Username"
// AuthorizePasswordHeaderName is the name of the HTTP header which can be used to transmit a password
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizePasswordHeaderName = "Pinniped-Password" //nolint:gosec // this is not a credential
// AuthorizeUpstreamIDPNameParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the name of the desired identity provider.
AuthorizeUpstreamIDPNameParamName = "pinniped_idp_name"
// AuthorizeUpstreamIDPTypeParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the type of the desired identity provider.
AuthorizeUpstreamIDPTypeParamName = "pinniped_idp_type"
)

View File

@@ -0,0 +1,55 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package main is the combined entrypoint for the Pinniped "kube-cert-agent" component.
package main
import (
"encoding/base64"
"encoding/json"
"io"
"io/ioutil"
"log"
"math"
"os"
"time"
)
//nolint: gochecknoglobals // these are swapped during unit tests.
var (
getenv = os.Getenv
fail = log.Fatalf
sleep = time.Sleep
out = io.Writer(os.Stdout)
)
func main() {
if len(os.Args) < 2 {
fail("missing subcommand")
}
switch os.Args[1] {
case "sleep":
sleep(math.MaxInt64)
case "print":
certBytes, err := ioutil.ReadFile(getenv("CERT_PATH"))
if err != nil {
fail("could not read CERT_PATH: %v", err)
}
keyBytes, err := ioutil.ReadFile(getenv("KEY_PATH"))
if err != nil {
fail("could not read KEY_PATH: %v", err)
}
if err := json.NewEncoder(out).Encode(&struct {
Cert string `json:"tls.crt"`
Key string `json:"tls.key"`
}{
Cert: base64.StdEncoding.EncodeToString(certBytes),
Key: base64.StdEncoding.EncodeToString(keyBytes),
}); err != nil {
fail("failed to write output: %v", err)
}
default:
fail("invalid subcommand %q", os.Args[1])
}
}

View File

@@ -0,0 +1,128 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"bytes"
"fmt"
"log"
"os"
"testing"
"time"
"github.com/stretchr/testify/require"
)
type errWriter struct{}
func (e errWriter) Write([]byte) (int, error) { return 0, fmt.Errorf("some write error") }
func TestEntrypoint(t *testing.T) {
for _, tt := range []struct {
name string
args []string
env map[string]string
failOutput bool
wantSleep time.Duration
wantLog string
wantOutJSON string
wantFail bool
}{
{
name: "missing args",
args: []string{},
wantLog: "missing subcommand\n",
wantFail: true,
},
{
name: "invalid subcommand",
args: []string{"/path/to/binary", "invalid"},
wantLog: "invalid subcommand \"invalid\"\n",
wantFail: true,
},
{
name: "valid sleep",
args: []string{"/path/to/binary", "sleep"},
wantSleep: 2562047*time.Hour + 47*time.Minute + 16*time.Second + 854775807*time.Nanosecond, // math.MaxInt64 nanoseconds, approximately 290 years
},
{
name: "missing cert file",
args: []string{"/path/to/binary", "print"},
env: map[string]string{
"CERT_PATH": "./does/not/exist",
"KEY_PATH": "./testdata/test.key",
},
wantFail: true,
wantLog: "could not read CERT_PATH: open ./does/not/exist: no such file or directory\n",
},
{
name: "missing key file",
args: []string{"/path/to/binary", "print"},
env: map[string]string{
"CERT_PATH": "./testdata/test.crt",
"KEY_PATH": "./does/not/exist",
},
wantFail: true,
wantLog: "could not read KEY_PATH: open ./does/not/exist: no such file or directory\n",
},
{
name: "fail to write output",
args: []string{"/path/to/binary", "print"},
env: map[string]string{
"CERT_PATH": "./testdata/test.crt",
"KEY_PATH": "./testdata/test.key",
},
failOutput: true,
wantFail: true,
wantLog: "failed to write output: some write error\n",
},
{
name: "successful print",
args: []string{"/path/to/binary", "print"},
env: map[string]string{
"CERT_PATH": "./testdata/test.crt",
"KEY_PATH": "./testdata/test.key",
},
wantOutJSON: `{
"tls.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01EY3lOVEl4TURReE9Gb1hEVE13TURjeU16SXhNRFF4T0Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDNLCmhZdjJnSVExRHd6aDJjV01pZCtvZkFudkxJZlYyWHY2MXZUTEdwclVJK1hVcUI0L2d0ZjZYNlVObjBMZXR0Mm4KZDhwNHd5N2h3NzNoVS9nZ2R2bVdKdnFCclNqYzNKR2Z5K2tqNjZmS1hYK1BUbGJMN1Fid2lSdmNTcUlYSVdsVgpsSEh4RUNXckVEOGpDdWx3L05WcWZvb2svaDVpTlVDVDl5c3dTSnIvMGZJbWlWbm9UbElvRVlHMmVDTmVqWjVjCmczOXVEM1pUcWQ5WnhXd1NMTG5JKzJrcEpuWkJQY2QxWlE4QVFxekRnWnRZUkNxYWNuNWdja1FVS1pXS1FseG8KRWZ0NmcxWEhKb3VBV0FadzdoRXRrMHY4ckcwL2VLRjd3YW14Rmk2QkZWbGJqV0JzQjRUOXJBcGJkQldUS2VDSgpIdjhmdjVSTUZTenBUM3V6VE84Q0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFDaDVSaGJ4cUplK1ovZ2MxN2NaaEtObWRpd3UKSTJwTHAzUUJmd3ZOK1dibWFqencvN3JZaFkwZDhKWVZUSnpYU0NQV2k2VUFLeEF0WE9MRjhXSUlmOWkzOW42Ugp1S09CR1cxNEZ6ekd5UkppRDNxYUcvSlR2RVcrU0xod2w2OE5kcjVMSFNuYnVnQXFxMzFhYmNReTZabDl2NUE4CkpLQzk3TGovU244cmo3b3BLeTRXM29xN05DUXNBYjB6aDRJbGxSRjZVdlNuSnlTZnNnN3hkWEhIcHhZREh0T1MKWGNPdTV5U1VJWlRnRmU5UmZlVVpsR1o1eG4wY2tNbFE3cVcyV3gxcTBPVld3NXVzNE50a0dxS3JIRzRUbjFYNwp1d28vWXl0bjVzRHhyRHYxL29paTZBWk9Dc1RQcmU0b0Qzd3o0bm1WekNWSmNncnFINFEyNGhUOFdOZz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
"tls.key": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBdmNxRmkvYUFoRFVQRE9IWnhZeUozNmg4Q2U4c2g5WFplL3JXOU1zYW10UWo1ZFNvCkhqK0MxL3BmcFEyZlF0NjIzYWQzeW5qREx1SER2ZUZUK0NCMitaWW0rb0d0S056Y2taL0w2U1BycDhwZGY0OU8KVnN2dEJ2Q0pHOXhLb2hjaGFWV1VjZkVRSmFzUVB5TUs2WEQ4MVdwK2lpVCtIbUkxUUpQM0t6Qkltdi9SOGlhSgpXZWhPVWlnUmdiWjRJMTZObmx5RGYyNFBkbE9wMzFuRmJCSXN1Y2o3YVNrbWRrRTl4M1ZsRHdCQ3JNT0JtMWhFCktwcHlmbUJ5UkJRcGxZcENYR2dSKzNxRFZjY21pNEJZQm5EdUVTMlRTL3lzYlQ5NG9YdkJxYkVXTG9FVldWdU4KWUd3SGhQMnNDbHQwRlpNcDRJa2UveCsvbEV3VkxPbFBlN05NN3dJREFRQUJBb0lCQUZDMXRVRW1ITlVjTTBCSgpNM0Q5S1F6Qis2M0YxbXdWbHgxUU9PVjFFZVZSM2NvNU94MVI2UFNyOXN5Y0ZHUTlqZ3FJMHpwNVRKZTlUcDZMCkdraGtsZlBoMU1Xbks5bzZ3bG56V0tYV3JycDJKbmkrbXBQeXVPUEFtcTRNYW5pdjJYZVArMGJST3dxcHlvanYKQUE3eUM3TStUSDIyNlpKR05WczNFVjkrY3dIbWwweXV6QmZJSm4vcnYvdzJnK1dSS00vTUMwUzdrMmQ4YlJsQQpOeWNLVkdBR0JoS1RsdGpvVllPZWg2YUhFcFNqSzh6ZmFlUGpvNWRZSnZvVklsaTYwWUNnY0pPVS84alhUK05wCjFGbTd0UnZBdGozcFVwMFNxZGFmMlJVemg5amZKcDJWRkNIdVNKNlRQcUFyT3lRb2p0TWNUSEYwVGlXN3hySFAKeE9DUklBRUNnWUVBd0dCUFU3dmR0aE1KQmcrT1JVb0dRUWFJdFRlSnZRd0lxSnZiS0Qyb3NwNGpoUzFkR1pCdwpXMzBHS0VjL2dkOEpOdE9xOUJCbk1pY1BGN2hrdHV5K2JTUHY0MVhQdWQ2N3JTU083VHN3MjBDMTBnRlJxMDZCCnpJSldGQVVxSzNJa3ZWYzNWRG10U0xTRG94NFFaL0JkcWFNbFE1eTVKQ3NDNWtUaG1rWkZsTzhDZ1lFQS9JOVgKWUhpNlJpb01KRTFmcU9ISkw0RERqbGV6bWN1UnJEN2ZFNUluS2J0SloySmhHWU9YL0MwS1huSFRPV1RDRHh4TgpGQnZwdkQ2WHY1bzNQaEI5WjZrMmZxdko0R1M4dXJrRy9LVTR4Y0MrYmFrKzlhdmE4b2FpU3FHMTZ6RDlOSDJQCmpKNjBOcmJMbDFKMHBVOWZpd3VGVlVLSjRoRFpPZk45UnFZZHlBRUNnWUFWd284V2hKaUdnTTZ6ZmN6MDczT1gKcFZxUFRQSHFqVkxwWjMrNXBJZlJkR3ZHSTZSMVFNNUV1dmFZVmI3TVBPTTQ3V1pYNXdjVk9DL1AyZzZpVmxNUAoyMUhHSUMyMzg0YTlCZmFZeE9vNDBxLytTaUhudzZDUTlta3dLSWxsa3Fxdk5BOVJHcGtNTVViMmkyOEZvcjJsCmM0dkNneGE2RFpkdFhuczZUUnFQeHdLQmdDZlk1Y3hPdi9UNkJWaGs3TWJVZU0ySjMxREIvWkF5VWhWL0Jlc3MKa0FsQmgxOU1ZazJJT1o2TDdLcmlBcFYzbERhV0hJTWp0RWtEQnlZdnlxOThJbzBNWVpDeXdmTXBjYTEwSytvSQpsMkI3L0krSXVHcENaeFVFc081ZGZUcFNUR0RQdnFwTkQ5bmlGVlVXcVZpN29UTnE2ZXA5eVF0bDVTQURqcXhxCjRTQUJBb0dBSW0waFVnMXd0Y1M0NmNHTHk2UElrUE01dG9jVFNnaHR6NHZGc3VrL2k0UUE5R0JvQk8yZ0g2dHkKK2tKSG1lYVh0MmRtZ3lTcDBRQVdpdDVVbGNlRXVtQjBOWG5BZEpaUXhlR1NGU3lZa0RXaHdYZDh3RGNlS28vMQpMZkNVNkRrOElOL1NzcHBWVVdYUTJybE9SdnhsckhlQ2lvOG8wa1M5WWl1NTVXTVlnNGc9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg=="
}`,
},
} {
tt := tt
t.Run(tt.name, func(t *testing.T) {
var logBuf bytes.Buffer
testLog := log.New(&logBuf, "", 0)
exited := "exiting via fatal"
fail = func(format string, v ...interface{}) {
testLog.Printf(format, v...)
panic(exited)
}
var sawSleep time.Duration
sleep = func(d time.Duration) { sawSleep = d }
var sawOutput bytes.Buffer
out = &sawOutput
if tt.failOutput {
out = &errWriter{}
}
os.Args = tt.args
getenv = func(key string) string { return tt.env[key] }
if tt.wantFail {
require.PanicsWithValue(t, exited, main)
} else {
require.NotPanics(t, main)
}
require.Equal(t, tt.wantSleep.String(), sawSleep.String())
require.Equal(t, tt.wantLog, logBuf.String())
if tt.wantOutJSON == "" {
require.Empty(t, sawOutput.String())
} else {
require.JSONEq(t, tt.wantOutJSON, sawOutput.String())
}
})
}
}

View File

@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIwMDcyNTIxMDQxOFoXDTMwMDcyMzIxMDQxOFowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3K
hYv2gIQ1Dwzh2cWMid+ofAnvLIfV2Xv61vTLGprUI+XUqB4/gtf6X6UNn0Lett2n
d8p4wy7hw73hU/ggdvmWJvqBrSjc3JGfy+kj66fKXX+PTlbL7QbwiRvcSqIXIWlV
lHHxECWrED8jCulw/NVqfook/h5iNUCT9yswSJr/0fImiVnoTlIoEYG2eCNejZ5c
g39uD3ZTqd9ZxWwSLLnI+2kpJnZBPcd1ZQ8AQqzDgZtYRCqacn5gckQUKZWKQlxo
Eft6g1XHJouAWAZw7hEtk0v8rG0/eKF7wamxFi6BFVlbjWBsB4T9rApbdBWTKeCJ
Hv8fv5RMFSzpT3uzTO8CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACh5RhbxqJe+Z/gc17cZhKNmdiwu
I2pLp3QBfwvN+Wbmajzw/7rYhY0d8JYVTJzXSCPWi6UAKxAtXOLF8WIIf9i39n6R
uKOBGW14FzzGyRJiD3qaG/JTvEW+SLhwl68Ndr5LHSnbugAqq31abcQy6Zl9v5A8
JKC97Lj/Sn8rj7opKy4W3oq7NCQsAb0zh4IllRF6UvSnJySfsg7xdXHHpxYDHtOS
XcOu5ySUIZTgFe9RfeUZlGZ5xn0ckMlQ7qW2Wx1q0OVWw5us4NtkGqKrHG4Tn1X7
uwo/Yytn5sDxrDv1/oii6AZOCsTPre4oD3wz4nmVzCVJcgrqH4Q24hT8WNg=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvcqFi/aAhDUPDOHZxYyJ36h8Ce8sh9XZe/rW9MsamtQj5dSo
Hj+C1/pfpQ2fQt623ad3ynjDLuHDveFT+CB2+ZYm+oGtKNzckZ/L6SPrp8pdf49O
VsvtBvCJG9xKohchaVWUcfEQJasQPyMK6XD81Wp+iiT+HmI1QJP3KzBImv/R8iaJ
WehOUigRgbZ4I16NnlyDf24PdlOp31nFbBIsucj7aSkmdkE9x3VlDwBCrMOBm1hE
KppyfmByRBQplYpCXGgR+3qDVccmi4BYBnDuES2TS/ysbT94oXvBqbEWLoEVWVuN
YGwHhP2sClt0FZMp4Ike/x+/lEwVLOlPe7NM7wIDAQABAoIBAFC1tUEmHNUcM0BJ
M3D9KQzB+63F1mwVlx1QOOV1EeVR3co5Ox1R6PSr9sycFGQ9jgqI0zp5TJe9Tp6L
GkhklfPh1MWnK9o6wlnzWKXWrrp2Jni+mpPyuOPAmq4Maniv2XeP+0bROwqpyojv
AA7yC7M+TH226ZJGNVs3EV9+cwHml0yuzBfIJn/rv/w2g+WRKM/MC0S7k2d8bRlA
NycKVGAGBhKTltjoVYOeh6aHEpSjK8zfaePjo5dYJvoVIli60YCgcJOU/8jXT+Np
1Fm7tRvAtj3pUp0Sqdaf2RUzh9jfJp2VFCHuSJ6TPqArOyQojtMcTHF0TiW7xrHP
xOCRIAECgYEAwGBPU7vdthMJBg+ORUoGQQaItTeJvQwIqJvbKD2osp4jhS1dGZBw
W30GKEc/gd8JNtOq9BBnMicPF7hktuy+bSPv41XPud67rSSO7Tsw20C10gFRq06B
zIJWFAUqK3IkvVc3VDmtSLSDox4QZ/BdqaMlQ5y5JCsC5kThmkZFlO8CgYEA/I9X
YHi6RioMJE1fqOHJL4DDjlezmcuRrD7fE5InKbtJZ2JhGYOX/C0KXnHTOWTCDxxN
FBvpvD6Xv5o3PhB9Z6k2fqvJ4GS8urkG/KU4xcC+bak+9ava8oaiSqG16zD9NH2P
jJ60NrbLl1J0pU9fiwuFVUKJ4hDZOfN9RqYdyAECgYAVwo8WhJiGgM6zfcz073OX
pVqPTPHqjVLpZ3+5pIfRdGvGI6R1QM5EuvaYVb7MPOM47WZX5wcVOC/P2g6iVlMP
21HGIC2384a9BfaYxOo40q/+SiHnw6CQ9mkwKIllkqqvNA9RGpkMMUb2i28For2l
c4vCgxa6DZdtXns6TRqPxwKBgCfY5cxOv/T6BVhk7MbUeM2J31DB/ZAyUhV/Bess
kAlBh19MYk2IOZ6L7KriApV3lDaWHIMjtEkDByYvyq98Io0MYZCywfMpca10K+oI
l2B7/I+IuGpCZxUEsO5dfTpSTGDPvqpND9niFVUWqVi7oTNq6ep9yQtl5SADjqxq
4SABAoGAIm0hUg1wtcS46cGLy6PIkPM5tocTSghtz4vFsuk/i4QA9GBoBO2gH6ty
+kJHmeaXt2dmgySp0QAWit5UlceEumB0NXnAdJZQxeGSFSyYkDWhwXd8wDceKo/1
LfCU6Dk8IN/SsppVUWXQ2rlORvxlrHeCio8o0kS9Yiu55WMYg4g=
-----END RSA PRIVATE KEY-----

View File

@@ -1,35 +0,0 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"os"
"time"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/pkg/version"
"k8s.io/client-go/rest"
"k8s.io/component-base/logs"
"k8s.io/klog/v2"
"go.pinniped.dev/internal/concierge/server"
)
func main() {
logs.InitLogs()
defer logs.FlushLogs()
// Dump out the time since compile (mostly useful for benchmarking our local development cycle latency).
var timeSinceCompile time.Duration
if buildDate, err := time.Parse(time.RFC3339, version.Get().BuildDate); err == nil {
timeSinceCompile = time.Since(buildDate).Round(time.Second)
}
klog.Infof("Running %s at %#v (%s since build)", rest.DefaultKubernetesUserAgent(), version.Get(), timeSinceCompile)
ctx := genericapiserver.SetupSignalContext()
if err := server.New(ctx, os.Args[1:], os.Stdout, os.Stderr).Run(); err != nil {
klog.Fatal(err)
}
}

View File

@@ -0,0 +1,41 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package main is the combined entrypoint for all Pinniped server components.
//
// It dispatches to the appropriate Main() entrypoint based the name it is invoked as (os.Args[0]). In our server
// container image, this binary is symlinked to several names such as `/usr/local/bin/pinniped-concierge`.
package main
import (
"os"
"path/filepath"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
concierge "go.pinniped.dev/internal/concierge/server"
lua "go.pinniped.dev/internal/localuserauthenticator"
supervisor "go.pinniped.dev/internal/supervisor/server"
)
//nolint: gochecknoglobals // these are swapped during unit tests.
var (
fail = klog.Fatalf
subcommands = map[string]func(){
"pinniped-concierge": concierge.Main,
"pinniped-supervisor": supervisor.Main,
"local-user-authenticator": lua.Main,
}
)
func main() {
if len(os.Args) == 0 {
fail("missing os.Args")
}
binary := filepath.Base(os.Args[0])
if subcommands[binary] == nil {
fail("must be invoked as one of %v, not %q", sets.StringKeySet(subcommands).List(), binary)
}
subcommands[binary]()
}

View File

@@ -0,0 +1,72 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"bytes"
"log"
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestEntrypoint(t *testing.T) {
for _, tt := range []struct {
name string
args []string
wantOutput string
wantFail bool
wantArgs []string
}{
{
name: "missing args",
args: []string{},
wantOutput: "missing os.Args\n",
wantFail: true,
},
{
name: "invalid subcommand",
args: []string{"/path/to/invalid", "some", "args"},
wantOutput: "must be invoked as one of [another-test-binary valid-test-binary], not \"invalid\"\n",
wantFail: true,
},
{
name: "valid",
args: []string{"/path/to/valid-test-binary", "foo", "bar"},
wantArgs: []string{"/path/to/valid-test-binary", "foo", "bar"},
},
} {
tt := tt
t.Run(tt.name, func(t *testing.T) {
var logBuf bytes.Buffer
testLog := log.New(&logBuf, "", 0)
exited := "exiting via fatal"
fail = func(format string, v ...interface{}) {
testLog.Printf(format, v...)
panic(exited)
}
// Make a test command that records os.Args when it's invoked.
var gotArgs []string
subcommands = map[string]func(){
"valid-test-binary": func() { gotArgs = os.Args },
"another-test-binary": func() {},
}
os.Args = tt.args
if tt.wantFail {
require.PanicsWithValue(t, exited, main)
} else {
require.NotPanics(t, main)
}
if tt.wantArgs != nil {
require.Equal(t, tt.wantArgs, gotArgs)
}
if tt.wantOutput != "" {
require.Equal(t, tt.wantOutput, logBuf.String())
}
})
}
}

View File

@@ -8,8 +8,10 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
@@ -26,9 +28,11 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/transport"
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
"go.pinniped.dev/internal/groupsuffix"
)
@@ -58,10 +62,14 @@ type getKubeconfigOIDCParams struct {
listenPort uint16
scopes []string
skipBrowser bool
skipListen bool
sessionCachePath string
debugSessionCache bool
caBundle caBundleFlag
requestAudience string
upstreamIDPName string
upstreamIDPType string
upstreamIDPFlow string
}
type getKubeconfigConciergeParams struct {
@@ -124,10 +132,14 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
f.Uint16Var(&flags.oidc.listenPort, "oidc-listen-port", 0, "TCP port for localhost listener (authorization code flow only)")
f.StringSliceVar(&flags.oidc.scopes, "oidc-scopes", []string{oidc.ScopeOfflineAccess, oidc.ScopeOpenID, "pinniped:request-audience"}, "OpenID Connect scopes to request during login")
f.BoolVar(&flags.oidc.skipBrowser, "oidc-skip-browser", false, "During OpenID Connect login, skip opening the browser (just print the URL)")
f.BoolVar(&flags.oidc.skipListen, "oidc-skip-listen", false, "During OpenID Connect login, skip starting a localhost callback listener (manual copy/paste flow only)")
f.StringVar(&flags.oidc.sessionCachePath, "oidc-session-cache", "", "Path to OpenID Connect session cache file")
f.Var(&flags.oidc.caBundle, "oidc-ca-bundle", "Path to TLS certificate authority bundle (PEM format, optional, can be repeated)")
f.BoolVar(&flags.oidc.debugSessionCache, "oidc-debug-session-cache", false, "Print debug logs related to the OpenID Connect session cache")
f.StringVar(&flags.oidc.requestAudience, "oidc-request-audience", "", "Request a token with an alternate audience using RFC8693 token exchange")
f.StringVar(&flags.oidc.upstreamIDPName, "upstream-identity-provider-name", "", "The name of the upstream identity provider used during login with a Supervisor")
f.StringVar(&flags.oidc.upstreamIDPType, "upstream-identity-provider-type", "", fmt.Sprintf("The type of the upstream identity provider used during login with a Supervisor (e.g. '%s', '%s', '%s')", idpdiscoveryv1alpha1.IDPTypeOIDC, idpdiscoveryv1alpha1.IDPTypeLDAP, idpdiscoveryv1alpha1.IDPTypeActiveDirectory))
f.StringVar(&flags.oidc.upstreamIDPFlow, "upstream-identity-provider-flow", "", fmt.Sprintf("The type of client flow to use with the upstream identity provider during login with a Supervisor (e.g. '%s', '%s')", idpdiscoveryv1alpha1.IDPFlowCLIPassword, idpdiscoveryv1alpha1.IDPFlowBrowserAuthcode))
f.StringVar(&flags.kubeconfigPath, "kubeconfig", os.Getenv("KUBECONFIG"), "Path to kubeconfig file")
f.StringVar(&flags.kubeconfigContextOverride, "kubeconfig-context", "", "Kubeconfig context name (default: current active context)")
f.BoolVar(&flags.skipValidate, "skip-validation", false, "Skip final validation of the kubeconfig (default: false)")
@@ -137,6 +149,9 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
mustMarkHidden(cmd, "oidc-debug-session-cache")
// --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
mustMarkHidden(cmd, "oidc-skip-listen")
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
mustMarkHidden(cmd, "concierge-namespace")
@@ -165,19 +180,6 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
return fmt.Errorf("invalid API group suffix: %w", err)
}
execConfig := clientcmdapi.ExecConfig{
APIVersion: clientauthenticationv1beta1.SchemeGroupVersion.String(),
Args: []string{},
Env: []clientcmdapi.ExecEnvVar{},
}
var err error
execConfig.Command, err = deps.getPathToSelf()
if err != nil {
return fmt.Errorf("could not determine the Pinniped executable path: %w", err)
}
execConfig.ProvideClusterInfo = true
clientConfig := newClientConfig(flags.kubeconfigPath, flags.kubeconfigContextOverride)
currentKubeConfig, err := clientConfig.RawConfig()
if err != nil {
@@ -221,6 +223,49 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
if err := discoverAuthenticatorParams(authenticator, &flags, deps.log); err != nil {
return err
}
// Point kubectl at the concierge endpoint.
cluster.Server = flags.concierge.endpoint
cluster.CertificateAuthorityData = flags.concierge.caBundle
}
// If there is an issuer, and if any upstream IDP flags are not already set, then try to discover Supervisor upstream IDP details.
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input. Maybe they know something
// that we can't know, like the name of an IDP that they are going to define in the future.
if len(flags.oidc.issuer) > 0 && (flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "") {
if err := discoverSupervisorUpstreamIDP(ctx, &flags); err != nil {
return err
}
}
execConfig, err := newExecConfig(deps, flags)
if err != nil {
return err
}
kubeconfig := newExecKubeconfig(cluster, execConfig, newKubeconfigNames)
if err := validateKubeconfig(ctx, flags, kubeconfig, deps.log); err != nil {
return err
}
return writeConfigAsYAML(out, kubeconfig)
}
func newExecConfig(deps kubeconfigDeps, flags getKubeconfigParams) (*clientcmdapi.ExecConfig, error) {
execConfig := &clientcmdapi.ExecConfig{
APIVersion: clientauthenticationv1beta1.SchemeGroupVersion.String(),
Args: []string{},
Env: []clientcmdapi.ExecEnvVar{},
ProvideClusterInfo: true,
}
var err error
execConfig.Command, err = deps.getPathToSelf()
if err != nil {
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
}
if !flags.concierge.disabled {
// Append the flags to configure the Concierge credential exchange at runtime.
execConfig.Args = append(execConfig.Args,
"--enable-concierge",
@@ -230,10 +275,6 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
"--concierge-endpoint="+flags.concierge.endpoint,
"--concierge-ca-bundle-data="+base64.StdEncoding.EncodeToString(flags.concierge.caBundle),
)
// Point kubectl at the concierge endpoint.
cluster.Server = flags.concierge.endpoint
cluster.CertificateAuthorityData = flags.concierge.caBundle
}
// If --credential-cache is set, pass it through.
@@ -244,7 +285,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
// If one of the --static-* flags was passed, output a config that runs `pinniped login static`.
if flags.staticToken != "" || flags.staticTokenEnvName != "" {
if flags.staticToken != "" && flags.staticTokenEnvName != "" {
return fmt.Errorf("only one of --static-token and --static-token-env can be specified")
return nil, fmt.Errorf("only one of --static-token and --static-token-env can be specified")
}
execConfig.Args = append([]string{"login", "static"}, execConfig.Args...)
if flags.staticToken != "" {
@@ -253,18 +294,13 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
if flags.staticTokenEnvName != "" {
execConfig.Args = append(execConfig.Args, "--token-env="+flags.staticTokenEnvName)
}
kubeconfig := newExecKubeconfig(cluster, &execConfig, newKubeconfigNames)
if err := validateKubeconfig(ctx, flags, kubeconfig, deps.log); err != nil {
return err
}
return writeConfigAsYAML(out, kubeconfig)
return execConfig, nil
}
// Otherwise continue to parse the OIDC-related flags and output a config that runs `pinniped login oidc`.
execConfig.Args = append([]string{"login", "oidc"}, execConfig.Args...)
if flags.oidc.issuer == "" {
return fmt.Errorf("could not autodiscover --oidc-issuer and none was provided")
return nil, fmt.Errorf("could not autodiscover --oidc-issuer and none was provided")
}
execConfig.Args = append(execConfig.Args,
"--issuer="+flags.oidc.issuer,
@@ -274,6 +310,9 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
if flags.oidc.skipBrowser {
execConfig.Args = append(execConfig.Args, "--skip-browser")
}
if flags.oidc.skipListen {
execConfig.Args = append(execConfig.Args, "--skip-listen")
}
if flags.oidc.listenPort != 0 {
execConfig.Args = append(execConfig.Args, "--listen-port="+strconv.Itoa(int(flags.oidc.listenPort)))
}
@@ -289,11 +328,17 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
if flags.oidc.requestAudience != "" {
execConfig.Args = append(execConfig.Args, "--request-audience="+flags.oidc.requestAudience)
}
kubeconfig := newExecKubeconfig(cluster, &execConfig, newKubeconfigNames)
if err := validateKubeconfig(ctx, flags, kubeconfig, deps.log); err != nil {
return err
if flags.oidc.upstreamIDPName != "" {
execConfig.Args = append(execConfig.Args, "--upstream-identity-provider-name="+flags.oidc.upstreamIDPName)
}
return writeConfigAsYAML(out, kubeconfig)
if flags.oidc.upstreamIDPType != "" {
execConfig.Args = append(execConfig.Args, "--upstream-identity-provider-type="+flags.oidc.upstreamIDPType)
}
if flags.oidc.upstreamIDPFlow != "" {
execConfig.Args = append(execConfig.Args, "--upstream-identity-provider-flow="+flags.oidc.upstreamIDPFlow)
}
return execConfig, nil
}
type kubeconfigNames struct{ ContextName, UserName, ClusterName string }
@@ -688,3 +733,214 @@ func hasPendingStrategy(credentialIssuer *configv1alpha1.CredentialIssuer) bool
}
return false
}
func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigParams) error {
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
if err != nil {
return err
}
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(ctx, flags.oidc.issuer, httpClient)
if err != nil {
return err
}
if pinnipedIDPsEndpoint == "" {
// The issuer is not advertising itself as a Pinniped Supervisor which supports upstream IDP discovery.
return nil
}
discoveredUpstreamIDPs, err := discoverAllAvailableSupervisorUpstreamIDPs(ctx, pinnipedIDPsEndpoint, httpClient)
if err != nil {
return err
}
if len(discoveredUpstreamIDPs) == 0 {
// Discovered that the Supervisor does not have any upstream IDPs defined. Continue without putting one into the
// kubeconfig. This kubeconfig will only work if the user defines one (and only one) OIDC IDP in the Supervisor
// later and wants to use the default client flow for OIDC (browser-based auth).
return nil
}
selectedIDPName, selectedIDPType, discoveredIDPFlows, err := selectUpstreamIDPNameAndType(discoveredUpstreamIDPs, flags.oidc.upstreamIDPName, flags.oidc.upstreamIDPType)
if err != nil {
return err
}
selectedIDPFlow, err := selectUpstreamIDPFlow(discoveredIDPFlows, selectedIDPName, selectedIDPType, flags.oidc.upstreamIDPFlow)
if err != nil {
return err
}
flags.oidc.upstreamIDPName = selectedIDPName
flags.oidc.upstreamIDPType = selectedIDPType.String()
flags.oidc.upstreamIDPFlow = selectedIDPFlow.String()
return nil
}
func newDiscoveryHTTPClient(caBundleFlag caBundleFlag) (*http.Client, error) {
t := &http.Transport{
TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12},
Proxy: http.ProxyFromEnvironment,
}
httpClient := &http.Client{Transport: t}
if caBundleFlag != nil {
rootCAs := x509.NewCertPool()
ok := rootCAs.AppendCertsFromPEM(caBundleFlag)
if !ok {
return nil, fmt.Errorf("unable to fetch OIDC discovery data from issuer: could not parse CA bundle")
}
t.TLSClientConfig.RootCAs = rootCAs
}
httpClient.Transport = transport.DebugWrappers(httpClient.Transport)
return httpClient, nil
}
func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpClient *http.Client) (string, error) {
discoveredProvider, err := oidc.NewProvider(oidc.ClientContext(ctx, httpClient), issuer)
if err != nil {
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
}
var body idpdiscoveryv1alpha1.OIDCDiscoveryResponse
err = discoveredProvider.Claims(&body)
if err != nil {
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
}
return body.SupervisorDiscovery.PinnipedIDPsEndpoint, nil
}
func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]idpdiscoveryv1alpha1.PinnipedIDP, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, pinnipedIDPsEndpoint, nil)
if err != nil {
return nil, fmt.Errorf("while forming request to IDP discovery URL: %w", err)
}
response, err := httpClient.Do(request)
if err != nil {
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: %w", err)
}
defer func() {
_ = response.Body.Close()
}()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: unexpected http response status: %s", response.Status)
}
rawBody, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not read response body: %w", err)
}
var body idpdiscoveryv1alpha1.IDPDiscoveryResponse
err = json.Unmarshal(rawBody, &body)
if err != nil {
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not parse response JSON: %w", err)
}
return body.PinnipedIDPs, nil
}
func selectUpstreamIDPNameAndType(pinnipedIDPs []idpdiscoveryv1alpha1.PinnipedIDP, specifiedIDPName, specifiedIDPType string) (string, idpdiscoveryv1alpha1.IDPType, []idpdiscoveryv1alpha1.IDPFlow, error) {
pinnipedIDPsString, _ := json.Marshal(pinnipedIDPs)
var discoveredFlows []idpdiscoveryv1alpha1.IDPFlow
switch {
case specifiedIDPName != "" && specifiedIDPType != "":
// The user specified both name and type, so check to see if there exists an exact match.
for _, idp := range pinnipedIDPs {
if idp.Name == specifiedIDPName && idp.Type.Equals(specifiedIDPType) {
return specifiedIDPName, idp.Type, idp.Flows, nil
}
}
return "", "", nil, fmt.Errorf(
"no Supervisor upstream identity providers with name %q of type %q were found. "+
"Found these upstreams: %s", specifiedIDPName, specifiedIDPType, pinnipedIDPsString)
case specifiedIDPType != "":
// The user specified only a type, so check if there is only one of that type found.
discoveredName := ""
var discoveredType idpdiscoveryv1alpha1.IDPType
for _, idp := range pinnipedIDPs {
if idp.Type.Equals(specifiedIDPType) {
if discoveredName != "" {
return "", "", nil, fmt.Errorf(
"multiple Supervisor upstream identity providers of type %q were found, "+
"so the --upstream-identity-provider-name flag must be specified. "+
"Found these upstreams: %s",
specifiedIDPType, pinnipedIDPsString)
}
discoveredName = idp.Name
discoveredType = idp.Type
discoveredFlows = idp.Flows
}
}
if discoveredName == "" {
return "", "", nil, fmt.Errorf(
"no Supervisor upstream identity providers of type %q were found. "+
"Found these upstreams: %s", specifiedIDPType, pinnipedIDPsString)
}
return discoveredName, discoveredType, discoveredFlows, nil
case specifiedIDPName != "":
// The user specified only a name, so check if there is only one of that name found.
var discoveredType idpdiscoveryv1alpha1.IDPType
for _, idp := range pinnipedIDPs {
if idp.Name == specifiedIDPName {
if discoveredType != "" {
return "", "", nil, fmt.Errorf(
"multiple Supervisor upstream identity providers with name %q were found, "+
"so the --upstream-identity-provider-type flag must be specified. Found these upstreams: %s",
specifiedIDPName, pinnipedIDPsString)
}
discoveredType = idp.Type
discoveredFlows = idp.Flows
}
}
if discoveredType == "" {
return "", "", nil, fmt.Errorf(
"no Supervisor upstream identity providers with name %q were found. "+
"Found these upstreams: %s", specifiedIDPName, pinnipedIDPsString)
}
return specifiedIDPName, discoveredType, discoveredFlows, nil
case len(pinnipedIDPs) == 1:
// The user did not specify any name or type, but there is only one found, so select it.
return pinnipedIDPs[0].Name, pinnipedIDPs[0].Type, pinnipedIDPs[0].Flows, nil
default:
// The user did not specify any name or type, and there is more than one found.
return "", "", nil, fmt.Errorf(
"multiple Supervisor upstream identity providers were found, "+
"so the --upstream-identity-provider-name/--upstream-identity-provider-type flags must be specified. "+
"Found these upstreams: %s",
pinnipedIDPsString)
}
}
func selectUpstreamIDPFlow(discoveredIDPFlows []idpdiscoveryv1alpha1.IDPFlow, selectedIDPName string, selectedIDPType idpdiscoveryv1alpha1.IDPType, specifiedFlow string) (idpdiscoveryv1alpha1.IDPFlow, error) {
switch {
case len(discoveredIDPFlows) == 0:
// No flows listed by discovery means that we are talking to an old Supervisor from before this feature existed.
// If the user specified a flow on the CLI flag then use it without validation, otherwise skip flow selection
// and return empty string.
return idpdiscoveryv1alpha1.IDPFlow(specifiedFlow), nil
case specifiedFlow != "":
// The user specified a flow, so validate that it is available for the selected IDP.
for _, flow := range discoveredIDPFlows {
if flow.Equals(specifiedFlow) {
// Found it, so use it as specified by the user.
return flow, nil
}
}
return "", fmt.Errorf(
"no client flow %q for Supervisor upstream identity provider %q of type %q were found. "+
"Found these flows: %v",
specifiedFlow, selectedIDPName, selectedIDPType, discoveredIDPFlows)
case len(discoveredIDPFlows) == 1:
// The user did not specify a flow, but there is only one found, so select it.
return discoveredIDPFlows[0], nil
default:
// The user did not specify a flow, and more than one was found.
return "", fmt.Errorf(
"multiple client flows for Supervisor upstream identity provider %q of type %q were found, "+
"so the --upstream-identity-provider-flow flag must be specified. "+
"Found these flows: %v",
selectedIDPName, selectedIDPType, discoveredIDPFlows)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cmd

View File

@@ -14,6 +14,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/coreos/go-oidc/v3/oidc"
@@ -23,6 +24,7 @@ import (
"k8s.io/client-go/transport"
"k8s.io/klog/v2/klogr"
idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
"go.pinniped.dev/internal/execcredcache"
"go.pinniped.dev/internal/groupsuffix"
"go.pinniped.dev/internal/plog"
@@ -54,23 +56,27 @@ func oidcLoginCommandRealDeps() oidcLoginCommandDeps {
}
type oidcLoginFlags struct {
issuer string
clientID string
listenPort uint16
scopes []string
skipBrowser bool
sessionCachePath string
caBundlePaths []string
caBundleData []string
debugSessionCache bool
requestAudience string
conciergeEnabled bool
conciergeAuthenticatorType string
conciergeAuthenticatorName string
conciergeEndpoint string
conciergeCABundle string
conciergeAPIGroupSuffix string
credentialCachePath string
issuer string
clientID string
listenPort uint16
scopes []string
skipBrowser bool
skipListen bool
sessionCachePath string
caBundlePaths []string
caBundleData []string
debugSessionCache bool
requestAudience string
conciergeEnabled bool
conciergeAuthenticatorType string
conciergeAuthenticatorName string
conciergeEndpoint string
conciergeCABundle string
conciergeAPIGroupSuffix string
credentialCachePath string
upstreamIdentityProviderName string
upstreamIdentityProviderType string
upstreamIdentityProviderFlow string
}
func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
@@ -89,6 +95,7 @@ func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
cmd.Flags().Uint16Var(&flags.listenPort, "listen-port", 0, "TCP port for localhost listener (authorization code flow only)")
cmd.Flags().StringSliceVar(&flags.scopes, "scopes", []string{oidc.ScopeOfflineAccess, oidc.ScopeOpenID, "pinniped:request-audience"}, "OIDC scopes to request during login")
cmd.Flags().BoolVar(&flags.skipBrowser, "skip-browser", false, "Skip opening the browser (just print the URL)")
cmd.Flags().BoolVar(&flags.skipListen, "skip-listen", false, "Skip starting a localhost callback listener (manual copy/paste flow only)")
cmd.Flags().StringVar(&flags.sessionCachePath, "session-cache", filepath.Join(mustGetConfigDir(), "sessions.yaml"), "Path to session cache file")
cmd.Flags().StringSliceVar(&flags.caBundlePaths, "ca-bundle", nil, "Path to TLS certificate authority bundle (PEM format, optional, can be repeated)")
cmd.Flags().StringSliceVar(&flags.caBundleData, "ca-bundle-data", nil, "Base64 encoded TLS certificate authority bundle (base64 encoded PEM format, optional, can be repeated)")
@@ -102,7 +109,12 @@ func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
cmd.Flags().StringVar(&flags.conciergeCABundle, "concierge-ca-bundle-data", "", "CA bundle to use when connecting to the Concierge")
cmd.Flags().StringVar(&flags.conciergeAPIGroupSuffix, "concierge-api-group-suffix", groupsuffix.PinnipedDefaultSuffix, "Concierge API group suffix")
cmd.Flags().StringVar(&flags.credentialCachePath, "credential-cache", filepath.Join(mustGetConfigDir(), "credentials.yaml"), "Path to cluster-specific credentials cache (\"\" disables the cache)")
cmd.Flags().StringVar(&flags.upstreamIdentityProviderName, "upstream-identity-provider-name", "", "The name of the upstream identity provider used during login with a Supervisor")
cmd.Flags().StringVar(&flags.upstreamIdentityProviderType, "upstream-identity-provider-type", idpdiscoveryv1alpha1.IDPTypeOIDC.String(), fmt.Sprintf("The type of the upstream identity provider used during login with a Supervisor (e.g. '%s', '%s', '%s')", idpdiscoveryv1alpha1.IDPTypeOIDC, idpdiscoveryv1alpha1.IDPTypeLDAP, idpdiscoveryv1alpha1.IDPTypeActiveDirectory))
cmd.Flags().StringVar(&flags.upstreamIdentityProviderFlow, "upstream-identity-provider-flow", "", fmt.Sprintf("The type of client flow to use with the upstream identity provider during login with a Supervisor (e.g. '%s', '%s')", idpdiscoveryv1alpha1.IDPFlowBrowserAuthcode, idpdiscoveryv1alpha1.IDPFlowCLIPassword))
// --skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
mustMarkHidden(cmd, "skip-listen")
mustMarkHidden(cmd, "debug-session-cache")
mustMarkRequired(cmd, "issuer")
cmd.RunE = func(cmd *cobra.Command, args []string) error { return runOIDCLogin(cmd, deps, flags) }
@@ -113,7 +125,7 @@ func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
return cmd
}
func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLoginFlags) error {
func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLoginFlags) error { //nolint:funlen
pLogger, err := SetLogLevel(deps.lookupEnv)
if err != nil {
plog.WarningErr("Received error while setting log level", err)
@@ -147,6 +159,20 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
opts = append(opts, oidcclient.WithRequestAudience(flags.requestAudience))
}
if flags.upstreamIdentityProviderName != "" {
opts = append(opts, oidcclient.WithUpstreamIdentityProvider(
flags.upstreamIdentityProviderName, flags.upstreamIdentityProviderType))
}
flowOpts, err := flowOptions(
idpdiscoveryv1alpha1.IDPType(flags.upstreamIdentityProviderType),
idpdiscoveryv1alpha1.IDPFlow(flags.upstreamIdentityProviderFlow),
)
if err != nil {
return err
}
opts = append(opts, flowOpts...)
var concierge *conciergeclient.Client
if flags.conciergeEnabled {
var err error
@@ -161,12 +187,14 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
}
}
// --skip-browser replaces the default "browser open" function with one that prints to stderr.
// --skip-browser skips opening the browser.
if flags.skipBrowser {
opts = append(opts, oidcclient.WithBrowserOpen(func(url string) error {
cmd.PrintErr("Please log in: ", url, "\n")
return nil
}))
opts = append(opts, oidcclient.WithSkipBrowserOpen())
}
// --skip-listen skips starting the localhost callback listener.
if flags.skipListen {
opts = append(opts, oidcclient.WithSkipListen())
}
if len(flags.caBundlePaths) > 0 || len(flags.caBundleData) > 0 {
@@ -224,6 +252,46 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
return json.NewEncoder(cmd.OutOrStdout()).Encode(cred)
}
func flowOptions(requestedIDPType idpdiscoveryv1alpha1.IDPType, requestedFlow idpdiscoveryv1alpha1.IDPFlow) ([]oidcclient.Option, error) {
useCLIFlow := []oidcclient.Option{oidcclient.WithCLISendingCredentials()}
switch requestedIDPType {
case idpdiscoveryv1alpha1.IDPTypeOIDC:
switch requestedFlow {
case idpdiscoveryv1alpha1.IDPFlowCLIPassword:
return useCLIFlow, nil
case idpdiscoveryv1alpha1.IDPFlowBrowserAuthcode, "":
return nil, nil // browser authcode flow is the default Option, so don't need to return an Option here
default:
return nil, fmt.Errorf(
"--upstream-identity-provider-flow value not recognized for identity provider type %q: %s (supported values: %s)",
requestedIDPType, requestedFlow, strings.Join([]string{idpdiscoveryv1alpha1.IDPFlowBrowserAuthcode.String(), idpdiscoveryv1alpha1.IDPFlowCLIPassword.String()}, ", "))
}
case idpdiscoveryv1alpha1.IDPTypeLDAP, idpdiscoveryv1alpha1.IDPTypeActiveDirectory:
switch requestedFlow {
case idpdiscoveryv1alpha1.IDPFlowCLIPassword, "":
return useCLIFlow, nil
case idpdiscoveryv1alpha1.IDPFlowBrowserAuthcode:
fallthrough // not supported for LDAP providers, so fallthrough to error case
default:
return nil, fmt.Errorf(
"--upstream-identity-provider-flow value not recognized for identity provider type %q: %s (supported values: %s)",
requestedIDPType, requestedFlow, []string{idpdiscoveryv1alpha1.IDPFlowCLIPassword.String()})
}
default:
// Surprisingly cobra does not support this kind of flag validation. See https://github.com/spf13/pflag/issues/236
return nil, fmt.Errorf(
"--upstream-identity-provider-type value not recognized: %s (supported values: %s)",
requestedIDPType,
strings.Join([]string{
idpdiscoveryv1alpha1.IDPTypeOIDC.String(),
idpdiscoveryv1alpha1.IDPTypeLDAP.String(),
idpdiscoveryv1alpha1.IDPTypeActiveDirectory.String(),
}, ", "),
)
}
}
func makeClient(caBundlePaths []string, caBundleData []string) (*http.Client, error) {
pool := x509.NewCertPool()
for _, p := range caBundlePaths {

View File

@@ -60,23 +60,26 @@ func TestLoginOIDCCommand(t *testing.T) {
oidc --issuer ISSUER [flags]
Flags:
--ca-bundle strings Path to TLS certificate authority bundle (PEM format, optional, can be repeated)
--ca-bundle-data strings Base64 encoded TLS certificate authority bundle (base64 encoded PEM format, optional, can be repeated)
--client-id string OpenID Connect client ID (default "pinniped-cli")
--concierge-api-group-suffix string Concierge API group suffix (default "pinniped.dev")
--concierge-authenticator-name string Concierge authenticator name
--concierge-authenticator-type string Concierge authenticator type (e.g., 'webhook', 'jwt')
--concierge-ca-bundle-data string CA bundle to use when connecting to the Concierge
--concierge-endpoint string API base for the Concierge endpoint
--credential-cache string Path to cluster-specific credentials cache ("" disables the cache) (default "` + cfgDir + `/credentials.yaml")
--enable-concierge Use the Concierge to login
-h, --help help for oidc
--issuer string OpenID Connect issuer URL
--listen-port uint16 TCP port for localhost listener (authorization code flow only)
--request-audience string Request a token with an alternate audience using RFC8693 token exchange
--scopes strings OIDC scopes to request during login (default [offline_access,openid,pinniped:request-audience])
--session-cache string Path to session cache file (default "` + cfgDir + `/sessions.yaml")
--skip-browser Skip opening the browser (just print the URL)
--ca-bundle strings Path to TLS certificate authority bundle (PEM format, optional, can be repeated)
--ca-bundle-data strings Base64 encoded TLS certificate authority bundle (base64 encoded PEM format, optional, can be repeated)
--client-id string OpenID Connect client ID (default "pinniped-cli")
--concierge-api-group-suffix string Concierge API group suffix (default "pinniped.dev")
--concierge-authenticator-name string Concierge authenticator name
--concierge-authenticator-type string Concierge authenticator type (e.g., 'webhook', 'jwt')
--concierge-ca-bundle-data string CA bundle to use when connecting to the Concierge
--concierge-endpoint string API base for the Concierge endpoint
--credential-cache string Path to cluster-specific credentials cache ("" disables the cache) (default "` + cfgDir + `/credentials.yaml")
--enable-concierge Use the Concierge to login
-h, --help help for oidc
--issuer string OpenID Connect issuer URL
--listen-port uint16 TCP port for localhost listener (authorization code flow only)
--request-audience string Request a token with an alternate audience using RFC8693 token exchange
--scopes strings OIDC scopes to request during login (default [offline_access,openid,pinniped:request-audience])
--session-cache string Path to session cache file (default "` + cfgDir + `/sessions.yaml")
--skip-browser Skip opening the browser (just print the URL)
--upstream-identity-provider-flow string The type of client flow to use with the upstream identity provider during login with a Supervisor (e.g. 'browser_authcode', 'cli_password')
--upstream-identity-provider-name string The name of the upstream identity provider used during login with a Supervisor
--upstream-identity-provider-type string The type of the upstream identity provider used during login with a Supervisor (e.g. 'oidc', 'ldap', 'activedirectory') (default "oidc")
`),
},
{
@@ -138,11 +141,146 @@ func TestLoginOIDCCommand(t *testing.T) {
Error: invalid Concierge parameters: invalid API group suffix: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
`),
},
{
name: "invalid upstream type",
args: []string{
"--issuer", "test-issuer",
"--upstream-identity-provider-type", "invalid",
},
wantError: true,
wantStderr: here.Doc(`
Error: --upstream-identity-provider-type value not recognized: invalid (supported values: oidc, ldap, activedirectory)
`),
},
{
name: "oidc upstream type with default flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "oidc",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
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",
},
{
name: "oidc upstream type with CLI flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "oidc",
"--upstream-identity-provider-flow", "cli_password",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantOptionsCount: 5,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
},
{
name: "oidc upstream type with browser flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "oidc",
"--upstream-identity-provider-flow", "browser_authcode",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
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",
},
{
name: "oidc upstream type with unsupported flow is an error",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "oidc",
"--upstream-identity-provider-flow", "foobar",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantError: true,
wantStderr: here.Doc(`
Error: --upstream-identity-provider-flow value not recognized for identity provider type "oidc": foobar (supported values: browser_authcode, cli_password)
`),
},
{
name: "ldap upstream type with default flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "ldap",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantOptionsCount: 5,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
},
{
name: "activedirectory upstream type with default flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "activedirectory",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantOptionsCount: 5,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
},
{
name: "ldap upstream type with CLI flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "ldap",
"--upstream-identity-provider-flow", "cli_password",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantOptionsCount: 5,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
},
{
name: "ldap upstream type with unsupported flow is an error",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "ldap",
"--upstream-identity-provider-flow", "browser_authcode", // "browser_authcode" is only supported for OIDC upstreams
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantError: true,
wantStderr: here.Doc(`
Error: --upstream-identity-provider-flow value not recognized for identity provider type "ldap": browser_authcode (supported values: [cli_password])
`),
},
{
name: "active directory upstream type with CLI flow is allowed",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "activedirectory",
"--upstream-identity-provider-flow", "cli_password",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantOptionsCount: 5,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
},
{
name: "active directory upstream type with unsupported flow is an error",
args: []string{
"--issuer", "test-issuer",
"--client-id", "test-client-id",
"--upstream-identity-provider-type", "activedirectory",
"--upstream-identity-provider-flow", "browser_authcode", // "browser_authcode" is only supported for OIDC upstreams
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
wantError: true,
wantStderr: here.Doc(`
Error: --upstream-identity-provider-flow value not recognized for identity provider type "activedirectory": browser_authcode (supported values: [cli_password])
`),
},
{
name: "login error",
args: []string{
"--client-id", "test-client-id",
"--issuer", "test-issuer",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
loginErr: fmt.Errorf("some login error"),
wantOptionsCount: 4,
@@ -160,6 +298,7 @@ func TestLoginOIDCCommand(t *testing.T) {
"--concierge-authenticator-type", "jwt",
"--concierge-authenticator-name", "test-authenticator",
"--concierge-endpoint", "https://127.0.0.1:1234/",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
conciergeErr: fmt.Errorf("some concierge error"),
wantOptionsCount: 4,
@@ -173,14 +312,14 @@ func TestLoginOIDCCommand(t *testing.T) {
args: []string{
"--client-id", "test-client-id",
"--issuer", "test-issuer",
"--credential-cache", "", // must specify --credential-cache or else the cache file on disk causes test pollution
},
env: map[string]string{"PINNIPED_DEBUG": "true"},
wantOptionsCount: 4,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
wantLogs: []string{
"\"level\"=0 \"msg\"=\"Pinniped login: Performing OIDC login\" \"client id\"=\"test-client-id\" \"issuer\"=\"test-issuer\"",
"\"level\"=0 \"msg\"=\"Pinniped login: No concierge configured, skipping token credential exchange\"",
"\"level\"=0 \"msg\"=\"Pinniped login: caching cluster credential for future use.\"",
},
},
{
@@ -189,6 +328,7 @@ func TestLoginOIDCCommand(t *testing.T) {
"--client-id", "test-client-id",
"--issuer", "test-issuer",
"--skip-browser",
"--skip-listen",
"--listen-port", "1234",
"--debug-session-cache",
"--request-audience", "cluster-1234",
@@ -200,11 +340,13 @@ func TestLoginOIDCCommand(t *testing.T) {
"--concierge-endpoint", "https://127.0.0.1:1234/",
"--concierge-ca-bundle-data", base64.StdEncoding.EncodeToString(testCA.Bundle()),
"--concierge-api-group-suffix", "some.suffix.com",
"--credential-cache", testutil.TempDir(t) + "/credentials.yaml",
"--credential-cache", testutil.TempDir(t) + "/credentials.yaml", // must specify --credential-cache or else the cache file on disk causes test pollution
"--upstream-identity-provider-name", "some-upstream-name",
"--upstream-identity-provider-type", "ldap",
},
env: map[string]string{"PINNIPED_DEBUG": "true"},
wantOptionsCount: 8,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"token":"exchanged-token"}}` + "\n",
wantOptionsCount: 11,
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
wantLogs: []string{
"\"level\"=0 \"msg\"=\"Pinniped login: Performing OIDC login\" \"client id\"=\"test-client-id\" \"issuer\"=\"test-issuer\"",
"\"level\"=0 \"msg\"=\"Pinniped login: Exchanging token for cluster credential\" \"authenticator name\"=\"test-authenticator\" \"authenticator type\"=\"webhook\" \"endpoint\"=\"https://127.0.0.1:1234/\"",

View File

@@ -119,7 +119,7 @@ func TestLoginStaticCommand(t *testing.T) {
env: map[string]string{
"TEST_TOKEN_ENV": "test-token",
},
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"token":"test-token"}}` + "\n",
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"test-token"}}` + "\n",
},
{
name: "concierge failure",
@@ -159,7 +159,7 @@ func TestLoginStaticCommand(t *testing.T) {
"--token", "test-token",
},
env: map[string]string{"PINNIPED_DEBUG": "true"},
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"token":"test-token"}}` + "\n",
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"test-token"}}` + "\n",
},
}
for _, tt := range tests {

View File

@@ -3,7 +3,20 @@
package main
import "go.pinniped.dev/cmd/pinniped/cmd"
import (
"os"
"github.com/pkg/browser"
"go.pinniped.dev/cmd/pinniped/cmd"
)
//nolint: gochecknoinits
func init() {
// browsers like chrome like to write to our std out which breaks our JSON ExecCredential output
// thus we redirect the browser's std out to our std err
browser.Stdout = os.Stderr
}
func main() {
cmd.Execute()

View File

@@ -21,7 +21,8 @@ spec:
- name: v1alpha1
schema:
openAPIV3Schema:
description: Describes the configuration status of a Pinniped credential issuer.
description: CredentialIssuer describes the configuration and status of the
Pinniped Concierge credential issuer.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@@ -35,8 +36,73 @@ spec:
type: string
metadata:
type: object
spec:
description: Spec describes the intended configuration of the Concierge.
properties:
impersonationProxy:
description: ImpersonationProxy describes the intended configuration
of the Concierge impersonation proxy.
properties:
externalEndpoint:
description: "ExternalEndpoint describes the HTTPS endpoint where
the proxy will be exposed. If not set, the proxy will be served
using the external name of the LoadBalancer service or the cluster
service DNS name. \n This field must be non-empty when spec.impersonationProxy.service.type
is \"None\"."
type: string
mode:
description: 'Mode configures whether the impersonation proxy
should be started: - "disabled" explicitly disables the impersonation
proxy. This is the default. - "enabled" explicitly enables the
impersonation proxy. - "auto" enables or disables the impersonation
proxy based upon the cluster in which it is running.'
enum:
- auto
- enabled
- disabled
type: string
service:
default:
type: LoadBalancer
description: Service describes the configuration of the Service
provisioned to expose the impersonation proxy to clients.
properties:
annotations:
additionalProperties:
type: string
description: Annotations specifies zero or more key/value
pairs to set as annotations on the provisioned Service.
type: object
loadBalancerIP:
description: LoadBalancerIP specifies the IP address to set
in the spec.loadBalancerIP field of the provisioned Service.
This is not supported on all cloud providers.
maxLength: 255
minLength: 1
type: string
type:
default: LoadBalancer
description: "Type specifies the type of Service to provision
for the impersonation proxy. \n If the type is \"None\",
then the \"spec.impersonationProxy.externalEndpoint\" field
must be set to a non-empty value so that the Concierge can
properly advertise the endpoint in the CredentialIssuer's
status."
enum:
- LoadBalancer
- ClusterIP
- None
type: string
type: object
required:
- mode
- service
type: object
required:
- impersonationProxy
type: object
status:
description: Status of the credential issuer.
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: Information needed to form a valid Pinniped-based kubeconfig
@@ -60,8 +126,8 @@ spec:
description: List of integration strategies that were attempted by
Pinniped.
items:
description: Status of an integration strategy that was attempted
by Pinniped.
description: CredentialIssuerStrategy describes the status of an
integration strategy that was attempted by Pinniped.
properties:
frontend:
description: Frontend describes how clients can connect using

View File

@@ -3,7 +3,8 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:json", "json")
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel", "pinnipedDevAPIGroupWithPrefix")
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel", "pinnipedDevAPIGroupWithPrefix")
#@ load("@ytt:template", "template")
#@ if not data.values.into_namespace:
---
@@ -29,6 +30,18 @@ metadata:
labels: #@ labels()
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
namespace: #@ namespace()
labels: #@ labels()
annotations:
#! we need to create this service account before we create the secret
kapp.k14s.io/change-group: "impersonation-proxy.concierge.pinniped.dev/serviceaccount"
secrets: #! make sure the token controller does not create any other secrets
- name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
---
apiVersion: v1
kind: ConfigMap
metadata:
name: #@ defaultResourceNameWithSuffix("config")
@@ -49,8 +62,8 @@ data:
servingCertificateSecret: (@= defaultResourceNameWithSuffix("api-tls-serving-certificate") @)
credentialIssuer: (@= defaultResourceNameWithSuffix("config") @)
apiService: (@= defaultResourceNameWithSuffix("api") @)
impersonationConfigMap: (@= defaultResourceNameWithSuffix("impersonation-proxy-config") @)
impersonationLoadBalancerService: (@= defaultResourceNameWithSuffix("impersonation-proxy-load-balancer") @)
impersonationClusterIPService: (@= defaultResourceNameWithSuffix("impersonation-proxy-cluster-ip") @)
impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @)
impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @)
impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @)
@@ -96,10 +109,16 @@ metadata:
spec:
replicas: #@ data.values.replicas
selector:
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
matchLabels: #@ defaultLabel()
template:
metadata:
labels: #@ defaultLabel()
labels:
#! This has always included defaultLabel(), which is used by this Deployment's selector.
_: #@ template.replace(defaultLabel())
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
_: #@ template.replace(deploymentPodLabel())
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
spec:
@@ -119,6 +138,8 @@ spec:
image: #@ data.values.image_repo + ":" + data.values.image_tag
#@ end
imagePullPolicy: IfNotPresent
securityContext:
readOnlyRootFilesystem: true
resources:
requests:
cpu: "100m"
@@ -126,14 +147,31 @@ spec:
limits:
cpu: "100m"
memory: "128Mi"
args:
command:
- pinniped-concierge
- --config=/etc/config/pinniped.yaml
- --downward-api-path=/etc/podinfo
volumeMounts:
- name: tmp
mountPath: /tmp
- name: config-volume
mountPath: /etc/config
readOnly: true
- name: podinfo
mountPath: /etc/podinfo
readOnly: true
- name: impersonation-proxy
mountPath: /var/run/secrets/impersonation-proxy.concierge.pinniped.dev/serviceaccount
readOnly: true
env:
#@ if data.values.https_proxy:
- name: HTTPS_PROXY
value: #@ data.values.https_proxy
#@ end
#@ if data.values.https_proxy and data.values.no_proxy:
- name: NO_PROXY
value: #@ data.values.no_proxy
#@ end
livenessProbe:
httpGet:
path: /healthz
@@ -153,9 +191,19 @@ spec:
periodSeconds: 10
failureThreshold: 3
volumes:
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 100Mi
- name: config-volume
configMap:
name: #@ defaultResourceNameWithSuffix("config")
- name: impersonation-proxy
secret:
secretName: #@ defaultResourceNameWithSuffix("impersonation-proxy")
items: #! make sure our pod does not start until the token controller has a chance to populate the secret
- key: token
path: token
- name: podinfo
downwardAPI:
items:
@@ -184,7 +232,7 @@ spec:
- weight: 50
podAffinityTerm:
labelSelector:
matchLabels: #@ defaultLabel()
matchLabels: #@ deploymentPodLabel()
topologyKey: kubernetes.io/hostname
---
apiVersion: v1
@@ -194,9 +242,12 @@ metadata:
name: #@ defaultResourceNameWithSuffix("api")
namespace: #@ namespace()
labels: #@ labels()
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: ClusterIP
selector: #@ defaultLabel()
selector: #@ deploymentPodLabel()
ports:
- protocol: TCP
port: 443
@@ -208,9 +259,12 @@ metadata:
name: #@ defaultResourceNameWithSuffix("proxy")
namespace: #@ namespace()
labels: #@ labels()
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: ClusterIP
selector: #@ defaultLabel()
selector: #@ deploymentPodLabel()
ports:
- protocol: TCP
port: 443
@@ -247,3 +301,34 @@ spec:
name: #@ defaultResourceNameWithSuffix("api")
namespace: #@ namespace()
port: 443
---
apiVersion: #@ pinnipedDevAPIGroupWithPrefix("config.concierge") + "/v1alpha1"
kind: CredentialIssuer
metadata:
name: #@ defaultResourceNameWithSuffix("config")
labels: #@ labels()
spec:
impersonationProxy:
mode: #@ data.values.impersonation_proxy_spec.mode
#@ if data.values.impersonation_proxy_spec.external_endpoint:
externalEndpoint: #@ data.values.impersonation_proxy_spec.external_endpoint
#@ end
service:
type: #@ data.values.impersonation_proxy_spec.service.type
#@ if data.values.impersonation_proxy_spec.service.load_balancer_ip:
loadBalancerIP: #@ data.values.impersonation_proxy_spec.service.load_balancer_ip
#@ end
annotations: #@ data.values.impersonation_proxy_spec.service.annotations
---
apiVersion: v1
kind: Secret
metadata:
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
namespace: #@ namespace()
labels: #@ labels()
annotations:
#! wait until the SA exists to create this secret so that the token controller does not delete it
#! we have this secret at the end so that kubectl will create the service account first
kapp.k14s.io/change-rule: "upsert after upserting impersonation-proxy.concierge.pinniped.dev/serviceaccount"
kubernetes.io/service-account.name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
type: kubernetes.io/service-account-token

View File

@@ -25,9 +25,14 @@
#@ end
#@ def defaultLabel():
#! Note that the name of this label's key is also assumed by kubecertagent.go and impersonator_config.go
app: #@ data.values.app_name
#@ end
#@ def deploymentPodLabel():
deployment.pinniped.dev: concierge
#@ end
#@ def labels():
_: #@ template.replace(defaultLabel())
_: #@ template.replace(data.values.custom_labels)

View File

@@ -28,12 +28,6 @@ rules:
resources: [ securitycontextconstraints ]
verbs: [ use ]
resourceNames: [ nonroot ]
- apiGroups: [ "" ]
resources: [ "users", "groups", "serviceaccounts" ]
verbs: [ "impersonate" ]
- apiGroups: [ "authentication.k8s.io" ]
resources: [ "*" ] #! What we really want is userextras/* but the RBAC authorizer only supports */subresource, not resource/*
verbs: [ "impersonate" ]
- apiGroups: [ "" ]
resources: [ nodes ]
verbs: [ list ]
@@ -64,6 +58,35 @@ roleRef:
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
apiGroup: rbac.authorization.k8s.io
#! Give minimal permissions to impersonation proxy service account
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
labels: #@ labels()
rules:
- apiGroups: [ "" ]
resources: [ "users", "groups", "serviceaccounts" ]
verbs: [ "impersonate" ]
- apiGroups: [ "authentication.k8s.io" ]
resources: [ "*" ] #! What we really want is userextras/* but the RBAC authorizer only supports */subresource, not resource/*
verbs: [ "impersonate" ]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
labels: #@ labels()
subjects:
- kind: ServiceAccount
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
namespace: #@ namespace()
roleRef:
kind: ClusterRole
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
apiGroup: rbac.authorization.k8s.io
#! Give permission to the kube-cert-agent Pod to run privileged.
---
apiVersion: rbac.authorization.k8s.io/v1
@@ -122,7 +145,7 @@ rules:
#! We need to be able to create and update deployments in our namespace so we can manage the kube-cert-agent Deployment.
- apiGroups: [ apps ]
resources: [ deployments ]
verbs: [ create, get, list, patch, update, watch ]
verbs: [ create, get, list, patch, update, watch, delete ]
#! We need to be able to get replicasets so we can form the correct owner references on our generated objects.
- apiGroups: [ apps ]
resources: [ replicasets ]
@@ -130,6 +153,9 @@ rules:
- apiGroups: [ "" ]
resources: [ configmaps ]
verbs: [ list, get, watch ]
- apiGroups: [ coordination.k8s.io ]
resources: [ leases ]
verbs: [ create, get, update ]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1

View File

@@ -63,3 +63,41 @@ run_as_group: 1001 #! run_as_group specifies the group ID that will own the proc
#! authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then
#! Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
api_group_suffix: pinniped.dev
#! Customize CredentialIssuer.spec.impersonationProxy to change how the concierge
#! handles impersonation.
impersonation_proxy_spec:
#! options are "auto", "disabled" or "enabled".
#! If auto, the impersonation proxy will run only if the cluster signing key is not available
#! and the other strategy does not work.
#! If disabled, the impersonation proxy will never run, which could mean that the concierge
#! doesn't work at all.
#! If enabled, the impersonation proxy will always run regardless of other strategies available.
mode: auto
#! The endpoint which the client should use to connect to the impersonation proxy.
#! If left unset, the client will default to connecting based on the ClusterIP or LoadBalancer
#! endpoint.
external_endpoint:
service:
#! Options are "LoadBalancer", "ClusterIP" and "None".
#! LoadBalancer automatically provisions a Service of type LoadBalancer pointing at
#! the impersonation proxy. Some cloud providers will allocate
#! a public IP address by default even on private clusters.
#! ClusterIP automatically provisions a Service of type ClusterIP pointing at the
#! impersonation proxy.
#! None does not provision either and assumes that you have set the external_endpoint
#! and set up your own ingress to connect to the impersonation proxy.
type: LoadBalancer
#! The annotations that should be set on the ClusterIP or LoadBalancer Service.
annotations:
{service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "4000"}
#! When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP.
load_balancer_ip:
#! Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers.
#! These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS,
#! e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks.
#! The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
#! Optional.
https_proxy: #! e.g. http://proxy.example.com
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local" #! do not proxy Kubernetes endpoints

View File

@@ -63,8 +63,8 @@ spec:
image: #@ data.values.image_repo + ":" + data.values.image_tag
#@ end
imagePullPolicy: IfNotPresent
command: #! override the default entrypoint
- /usr/local/bin/local-user-authenticator
command:
- local-user-authenticator
---
apiVersion: v1
kind: Service
@@ -73,6 +73,9 @@ metadata:
namespace: local-user-authenticator
labels:
app: local-user-authenticator
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: ClusterIP
selector:

View File

@@ -3,7 +3,8 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:json", "json")
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel")
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel")
#@ load("@ytt:template", "template")
#@ if not data.values.into_namespace:
---
@@ -59,10 +60,16 @@ metadata:
spec:
replicas: #@ data.values.replicas
selector:
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
matchLabels: #@ defaultLabel()
template:
metadata:
labels: #@ defaultLabel()
labels:
#! This has always included defaultLabel(), which is used by this Deployment's selector.
_: #@ template.replace(defaultLabel())
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
#! without accidentally selecting pods from any future Deployments which might also want to use the defaultLabel().
_: #@ template.replace(deploymentPodLabel())
spec:
securityContext:
runAsUser: #@ data.values.run_as_user
@@ -80,11 +87,12 @@ spec:
image: #@ data.values.image_repo + ":" + data.values.image_tag
#@ end
imagePullPolicy: IfNotPresent
command: #! override the default entrypoint
- /usr/local/bin/pinniped-supervisor
args:
command:
- pinniped-supervisor
- /etc/podinfo
- /etc/config/pinniped.yaml
securityContext:
readOnlyRootFilesystem: true
resources:
requests:
cpu: "100m"
@@ -95,13 +103,24 @@ spec:
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
- name: podinfo
mountPath: /etc/podinfo
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 8443
protocol: TCP
env:
#@ if data.values.https_proxy:
- name: HTTPS_PROXY
value: #@ data.values.https_proxy
#@ end
#@ if data.values.https_proxy and data.values.no_proxy:
- name: NO_PROXY
value: #@ data.values.no_proxy
#@ end
livenessProbe:
httpGet:
path: /healthz
@@ -144,5 +163,5 @@ spec:
- weight: 50
podAffinityTerm:
labelSelector:
matchLabels: #@ defaultLabel()
matchLabels: #@ deploymentPodLabel()
topologyKey: kubernetes.io/hostname

View File

@@ -28,6 +28,10 @@
app: #@ data.values.app_name
#@ end
#@ def deploymentPodLabel():
deployment.pinniped.dev: supervisor
#@ end
#@ def labels():
_: #@ template.replace(defaultLabel())
_: #@ template.replace(data.values.custom_labels)

View File

@@ -0,0 +1,281 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.0
creationTimestamp: null
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
spec:
group: idp.supervisor.pinniped.dev
names:
categories:
- pinniped
- pinniped-idp
- pinniped-idps
kind: ActiveDirectoryIdentityProvider
listKind: ActiveDirectoryIdentityProviderList
plural: activedirectoryidentityproviders
singular: activedirectoryidentityprovider
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.host
name: Host
type: string
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ActiveDirectoryIdentityProvider describes the configuration of
an upstream Microsoft Active Directory identity provider.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec for configuring the identity provider.
properties:
bind:
description: Bind contains the configuration for how to provide access
credentials during an initial bind to the ActiveDirectory server
to be allowed to perform searches and binds to validate a user's
credentials during a user's authentication attempt.
properties:
secretName:
description: SecretName contains the name of a namespace-local
Secret object that provides the username and password for an
Active Directory bind user. This account will be used to perform
LDAP searches. The Secret should be of type "kubernetes.io/basic-auth"
which includes "username" and "password" keys. The username
value should be the full dn (distinguished name) of your bind
account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
The password must be non-empty.
minLength: 1
type: string
required:
- secretName
type: object
groupSearch:
description: GroupSearch contains the configuration for searching
for a user's group membership in ActiveDirectory.
properties:
attributes:
description: Attributes specifies how the group's information
should be read from each ActiveDirectory entry which was found
as the result of the group search.
properties:
groupName:
description: GroupName specifies the name of the attribute
in the Active Directory entries whose value shall become
a group name in the user's list of groups after a successful
authentication. The value of this field is case-sensitive
and must match the case of the attribute name returned by
the ActiveDirectory server in the user's entry. E.g. "cn"
for common name. Distinguished names can be used by specifying
lower-case "dn". Optional. When not specified, this defaults
to a custom field that looks like "sAMAccountName@domain",
where domain is constructed from the domain components of
the group DN.
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
Optional, when not specified it will be based on the result
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
The default behavior searches your entire domain for groups.
It may make sense to specify a subtree as a search base if you
wish to exclude some groups for security reasons or to make
searches faster.
type: string
filter:
description: Filter is the ActiveDirectory search filter which
should be applied when searching for groups for a user. The
pattern "{}" must occur in the filter at least once and will
be dynamically replaced by the dn (distinguished name) of the
user entry found as a result of the user search. E.g. "member={}"
or "&(objectClass=groupOfNames)(member={})". For more information
about ActiveDirectory filters, see https://ldap.com/ldap-filters.
Note that the dn (distinguished name) is not an attribute of
an entry, so "dn={}" cannot be used. Optional. When not specified,
the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
This searches nested groups by default. Note that nested group
search can be slow for some Active Directory servers. To disable
it, you can set the filter to "(&(objectClass=group)(member={})"
type: string
type: object
host:
description: 'Host is the hostname of this Active Directory identity
provider, i.e., where to connect. For example: ldap.example.com:636.'
minLength: 1
type: string
tls:
description: TLS contains the connection settings for how to establish
the connection to the Host.
properties:
certificateAuthorityData:
description: X.509 Certificate Authority (base64-encoded PEM bundle).
If omitted, a default set of system roots will be trusted.
type: string
type: object
userSearch:
description: UserSearch contains the configuration for searching for
a user by name in Active Directory.
properties:
attributes:
description: Attributes specifies how the user's information should
be read from the ActiveDirectory entry which was found as the
result of the user search.
properties:
uid:
description: UID specifies the name of the attribute in the
ActiveDirectory entry which whose value shall be used to
uniquely identify the user within this ActiveDirectory provider
after a successful authentication. Optional, when empty
this defaults to "objectGUID".
type: string
username:
description: Username specifies the name of the attribute
in Active Directory entry whose value shall become the username
of the user after a successful authentication. Optional,
when empty this defaults to "userPrincipalName".
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
Optional, when not specified it will be based on the result
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
The default behavior searches your entire domain for users.
It may make sense to specify a subtree as a search base if you
wish to exclude some users or to make searches faster.
type: string
filter:
description: Filter is the search filter which should be applied
when searching for users. The pattern "{}" must occur in the
filter at least once and will be dynamically replaced by the
username for which the search is being run. E.g. "mail={}" or
"&(objectClass=person)(uid={})". For more information about
LDAP filters, see https://ldap.com/ldap-filters. Note that the
dn (distinguished name) is not an attribute of an entry, so
"dn={}" cannot be used. Optional. When not specified, the default
will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
This means that the user is a person, is not a computer, the
sAMAccountType is for a normal user account, and is not shown
in advanced view only (which would likely mean its a system
created service account with advanced permissions). Also, either
the sAMAccountName, the userPrincipalName, or the mail attribute
matches the input username.
type: string
type: object
required:
- host
type: object
status:
description: Status of the identity provider.
properties:
conditions:
description: Represents the observations of an identity provider's
current state.
items:
description: Condition status of a resource (mirrored from the metav1.Condition
type added in Kubernetes 1.19). In a future API version we can
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
phase:
default: Pending
description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
enum:
- Pending
- Ready
- Error
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -0,0 +1,278 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.0
creationTimestamp: null
name: ldapidentityproviders.idp.supervisor.pinniped.dev
spec:
group: idp.supervisor.pinniped.dev
names:
categories:
- pinniped
- pinniped-idp
- pinniped-idps
kind: LDAPIdentityProvider
listKind: LDAPIdentityProviderList
plural: ldapidentityproviders
singular: ldapidentityprovider
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.host
name: Host
type: string
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: LDAPIdentityProvider describes the configuration of an upstream
Lightweight Directory Access Protocol (LDAP) identity provider.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec for configuring the identity provider.
properties:
bind:
description: Bind contains the configuration for how to provide access
credentials during an initial bind to the LDAP server to be allowed
to perform searches and binds to validate a user's credentials during
a user's authentication attempt.
properties:
secretName:
description: SecretName contains the name of a namespace-local
Secret object that provides the username and password for an
LDAP bind user. This account will be used to perform LDAP searches.
The Secret should be of type "kubernetes.io/basic-auth" which
includes "username" and "password" keys. The username value
should be the full dn (distinguished name) of your bind account,
e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password
must be non-empty.
minLength: 1
type: string
required:
- secretName
type: object
groupSearch:
description: GroupSearch contains the configuration for searching
for a user's group membership in the LDAP provider.
properties:
attributes:
description: Attributes specifies how the group's information
should be read from each LDAP entry which was found as the result
of the group search.
properties:
groupName:
description: GroupName specifies the name of the attribute
in the LDAP entries whose value shall become a group name
in the user's list of groups after a successful authentication.
The value of this field is case-sensitive and must match
the case of the attribute name returned by the LDAP server
in the user's entry. E.g. "cn" for common name. Distinguished
names can be used by specifying lower-case "dn". Optional.
When not specified, the default will act as if the GroupName
were specified as "dn" (distinguished name).
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
When not specified, no group search will be performed and authenticated
users will not belong to any groups from the LDAP provider.
Also, when not specified, the values of Filter and Attributes
are ignored.
type: string
filter:
description: Filter is the LDAP search filter which should be
applied when searching for groups for a user. The pattern "{}"
must occur in the filter at least once and will be dynamically
replaced by the dn (distinguished name) of the user entry found
as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
For more information about LDAP filters, see https://ldap.com/ldap-filters.
Note that the dn (distinguished name) is not an attribute of
an entry, so "dn={}" cannot be used. Optional. When not specified,
the default will act as if the Filter were specified as "member={}".
type: string
type: object
host:
description: 'Host is the hostname of this LDAP identity provider,
i.e., where to connect. For example: ldap.example.com:636.'
minLength: 1
type: string
tls:
description: TLS contains the connection settings for how to establish
the connection to the Host.
properties:
certificateAuthorityData:
description: X.509 Certificate Authority (base64-encoded PEM bundle).
If omitted, a default set of system roots will be trusted.
type: string
type: object
userSearch:
description: UserSearch contains the configuration for searching for
a user by name in the LDAP provider.
properties:
attributes:
description: Attributes specifies how the user's information should
be read from the LDAP entry which was found as the result of
the user search.
properties:
uid:
description: UID specifies the name of the attribute in the
LDAP entry which whose value shall be used to uniquely identify
the user within this LDAP provider after a successful authentication.
E.g. "uidNumber" or "objectGUID". The value of this field
is case-sensitive and must match the case of the attribute
name returned by the LDAP server in the user's entry. Distinguished
names can be used by specifying lower-case "dn".
minLength: 1
type: string
username:
description: Username specifies the name of the attribute
in the LDAP entry whose value shall become the username
of the user after a successful authentication. This would
typically be the same attribute name used in the user search
filter, although it can be different. E.g. "mail" or "uid"
or "userPrincipalName". The value of this field is case-sensitive
and must match the case of the attribute name returned by
the LDAP server in the user's entry. Distinguished names
can be used by specifying lower-case "dn". When this field
is set to "dn" then the LDAPIdentityProviderUserSearch's
Filter field cannot be blank, since the default value of
"dn={}" would not work.
minLength: 1
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
minLength: 1
type: string
filter:
description: Filter is the LDAP search filter which should be
applied when searching for users. The pattern "{}" must occur
in the filter at least once and will be dynamically replaced
by the username for which the search is being run. E.g. "mail={}"
or "&(objectClass=person)(uid={})". For more information about
LDAP filters, see https://ldap.com/ldap-filters. Note that the
dn (distinguished name) is not an attribute of an entry, so
"dn={}" cannot be used. Optional. When not specified, the default
will act as if the Filter were specified as the value from Attributes.Username
appended by "={}". When the Attributes.Username is set to "dn"
then the Filter must be explicitly specified, since the default
value of "dn={}" would not work.
type: string
type: object
required:
- host
type: object
status:
description: Status of the identity provider.
properties:
conditions:
description: Represents the observations of an identity provider's
current state.
items:
description: Condition status of a resource (mirrored from the metav1.Condition
type added in Kubernetes 1.19). In a future API version we can
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
phase:
default: Pending
description: Phase summarizes the overall status of the LDAPIdentityProvider.
enum:
- Pending
- Ready
- Error
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -59,11 +59,44 @@ spec:
additionalScopes:
description: AdditionalScopes are the scopes in addition to "openid"
that will be requested as part of the authorization request
flow with an OIDC identity provider. By default only the "openid"
scope will be requested.
flow with an OIDC identity provider. In the case of a Resource
Owner Password Credentials Grant flow, AdditionalScopes are
the scopes in addition to "openid" that will be requested as
part of the token request (see also the allowPasswordGrant field).
By default, only the "openid" scope will be requested.
items:
type: string
type: array
allowPasswordGrant:
description: AllowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see
https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to
authenticate to the OIDC provider using a username and password
without a web browser, in addition to the usual browser-based
OIDC Authorization Code Flow. The Resource Owner Password Credentials
Grant is not officially part of the OIDC specification, so it
may not be supported by your OIDC provider. If your OIDC provider
supports returning ID tokens from a Resource Owner Password
Credentials Grant token request, then you can choose to set
this field to true. This will allow end users to choose to present
their username and password to the kubectl CLI (using the Pinniped
plugin) to authenticate to the cluster, without using a web
browser to log in as is customary in OIDC Authorization Code
Flow. This may be convenient for users, especially for identities
from your OIDC provider which are not intended to represent
a human actor, such as service accounts performing actions in
a CI/CD environment. Even if your OIDC provider supports it,
you may wish to disable this behavior by setting this field
to false when you prefer to only allow users of this OIDCIdentityProvider
to log in via the browser-based OIDC Authorization Code Flow.
Using the Resource Owner Password Credentials Grant means that
the Pinniped CLI and Pinniped Supervisor will directly handle
your end users' passwords (similar to LDAPIdentityProvider),
and you will not be able to require multi-factor authentication
or use the other web-based login features of your OIDC provider
during Resource Owner Password Credentials Grant logins. AllowPasswordGrant
defaults to false.
type: boolean
type: object
claims:
description: Claims provides the names of token claims that will be

View File

@@ -32,6 +32,22 @@ rules:
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
resources: [oidcidentityproviders/status]
verbs: [get, patch, update]
- apiGroups:
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
resources: [ldapidentityproviders]
verbs: [get, list, watch]
- apiGroups:
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
resources: [ldapidentityproviders/status]
verbs: [get, patch, update]
- apiGroups:
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
resources: [activedirectoryidentityproviders]
verbs: [get, list, watch]
- apiGroups:
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
resources: [activedirectoryidentityproviders/status]
verbs: [get, patch, update]
#! We want to be able to read pods/replicasets/deployment so we can learn who our deployment is to set
#! as an owner reference.
- apiGroups: [""]
@@ -40,6 +56,9 @@ rules:
- apiGroups: [apps]
resources: [replicasets,deployments]
verbs: [get]
- apiGroups: [ coordination.k8s.io ]
resources: [ leases ]
verbs: [ create, get, update ]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1

View File

@@ -1,8 +1,8 @@
#! Copyright 2020 the Pinniped contributors. All Rights Reserved.
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
#! SPDX-License-Identifier: Apache-2.0
#@ load("@ytt:data", "data")
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix")
#@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix")
#@ if data.values.service_http_nodeport_port or data.values.service_https_nodeport_port:
---
@@ -12,10 +12,12 @@ metadata:
name: #@ defaultResourceNameWithSuffix("nodeport")
namespace: #@ namespace()
labels: #@ labels()
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: NodePort
selector:
app: #@ data.values.app_name
selector: #@ deploymentPodLabel()
ports:
#@ if data.values.service_http_nodeport_port:
- name: http
@@ -45,9 +47,12 @@ metadata:
name: #@ defaultResourceNameWithSuffix("clusterip")
namespace: #@ namespace()
labels: #@ labels()
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: ClusterIP
selector: #@ defaultLabel()
selector: #@ deploymentPodLabel()
ports:
#@ if data.values.service_http_clusterip_port:
- name: http
@@ -71,9 +76,12 @@ metadata:
name: #@ defaultResourceNameWithSuffix("loadbalancer")
namespace: #@ namespace()
labels: #@ labels()
#! prevent kapp from altering the selector of our services to match kubectl behavior
annotations:
kapp.k14s.io/disable-default-label-scoping-rules: ""
spec:
type: LoadBalancer
selector: #@ defaultLabel()
selector: #@ deploymentPodLabel()
#@ if data.values.service_loadbalancer_ip:
loadBalancerIP: #@ data.values.service_loadbalancer_ip
#@ end

View File

@@ -65,3 +65,11 @@ run_as_group: 1001 #! run_as_group specifies the group ID that will own the proc
#! authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then
#! Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
api_group_suffix: pinniped.dev
#! Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers.
#! These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS,
#! e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider.
#! The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
#! Optional.
https_proxy: #! e.g. http://proxy.example.com
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local" #! do not proxy Kubernetes endpoints

View File

@@ -22,3 +22,21 @@ metadata:
name: #@ pinnipedDevAPIGroupWithPrefix("oidcidentityproviders.idp.supervisor")
spec:
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"ldapidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
---
metadata:
#@overlay/match missing_ok=True
labels: #@ labels()
name: #@ pinnipedDevAPIGroupWithPrefix("ldapidentityproviders.idp.supervisor")
spec:
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"activedirectoryidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
---
metadata:
#@overlay/match missing_ok=True
labels: #@ labels()
name: #@ pinnipedDevAPIGroupWithPrefix("activedirectoryidentityproviders.idp.supervisor")
spec:
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")

View File

@@ -220,7 +220,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped concierge configuration
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuer"]
==== CredentialIssuer
Describes the configuration status of a Pinniped credential issuer.
CredentialIssuer describes the configuration and status of the Pinniped Concierge credential issuer.
.Appears In:
****
@@ -232,7 +232,8 @@ Describes the configuration status of a Pinniped credential issuer.
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]__ | Status of the credential issuer.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerspec[$$CredentialIssuerSpec$$]__ | Spec describes the intended configuration of the Concierge.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]__ | CredentialIssuerStatus describes the status of the Concierge.
|===
@@ -275,10 +276,27 @@ Describes the configuration status of a Pinniped credential issuer.
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerspec"]
==== CredentialIssuerSpec
CredentialIssuerSpec describes the intended configuration of the Concierge.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuer[$$CredentialIssuer$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`impersonationProxy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]__ | ImpersonationProxy describes the intended configuration of the Concierge impersonation proxy.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerstatus"]
==== CredentialIssuerStatus
Status of a credential issuer.
CredentialIssuerStatus describes the status of the Concierge.
.Appears In:
****
@@ -333,6 +351,70 @@ Status of a credential issuer.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxymode"]
==== ImpersonationProxyMode (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyservicespec"]
==== ImpersonationProxyServiceSpec
ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`type`* __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. This is not supported on all cloud providers.
| *`annotations`* __object (keys:string, values:string)__ | Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyservicetype"]
==== ImpersonationProxyServiceType (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyspec"]
==== ImpersonationProxySpec
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-credentialissuerspec[$$CredentialIssuerSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`mode`* __ImpersonationProxyMode__ | Mode configures whether the impersonation proxy should be started: - "disabled" explicitly disables the impersonation proxy. This is the default. - "enabled" explicitly enables the impersonation proxy. - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
| *`service`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]__ | Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will be served using the external name of the LoadBalancer service or the cluster service DNS name.
This field must be non-empty when spec.impersonationProxy.service.type is "None".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-concierge-config-v1alpha1-tokencredentialrequestapiinfo"]
==== TokenCredentialRequestAPIInfo
@@ -666,13 +748,166 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition"]
==== Condition
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"]
==== ActiveDirectoryIdentityProvider
Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API version we can switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"]
==== ActiveDirectoryIdentityProviderBind
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"]
==== ActiveDirectoryIdentityProviderGroupSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". Optional, when not specified it will be based on the result of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse). The default behavior searches your entire domain for groups. It may make sense to specify a subtree as a search base if you wish to exclude some groups for security reasons or to make searches faster.
| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})". This searches nested groups by default. Note that nested group search can be slow for some Active Directory servers. To disable it, you can set the filter to "(&(objectClass=group)(member={})"
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"]
==== ActiveDirectoryIdentityProviderGroupSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, this defaults to a custom field that looks like "sAMAccountName@domain", where domain is constructed from the domain components of the group DN.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"]
==== ActiveDirectoryIdentityProviderSpec
Spec for configuring an ActiveDirectory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host.
| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory.
| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"]
==== ActiveDirectoryIdentityProviderStatus
Status of an Active Directory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"]
==== ActiveDirectoryIdentityProviderUserSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be based on the result of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse). The default behavior searches your entire domain for users. It may make sense to specify a subtree as a search base if you wish to exclude some users or to make searches faster.
| *`filter`* __string__ | Filter is the search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))' This means that the user is a person, is not a computer, the sAMAccountType is for a normal user account, and is not shown in advanced view only (which would likely mean its a system created service account with advanced permissions). Also, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"]
==== ActiveDirectoryIdentityProviderUserSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`username`* __string__ | Username specifies the name of the attribute in Active Directory entry whose value shall become the username of the user after a successful authentication. Optional, when empty this defaults to "userPrincipalName".
| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition"]
==== Condition
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$]
****
@@ -688,6 +923,169 @@ Condition status of a resource (mirrored from the metav1.Condition type added in
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-conditionstatus"]
==== ConditionStatus (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovider"]
==== LDAPIdentityProvider
LDAPIdentityProvider describes the configuration of an upstream Lightweight Directory Access Protocol (LDAP) identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderlist[$$LDAPIdentityProviderList$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]__ | Spec for configuring the identity provider.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$]__ | Status of the identity provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderbind"]
==== LDAPIdentityProviderBind
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an LDAP bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch"]
==== LDAPIdentityProviderGroupSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the LDAP provider. Also, when not specified, the values of Filter and Attributes are ignored.
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}".
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes[$$LDAPIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each LDAP entry which was found as the result of the group search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes"]
==== LDAPIdentityProviderGroupSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch[$$LDAPIdentityProviderGroupSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`groupName`* __string__ | GroupName specifies the name of the attribute in the LDAP entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name).
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec"]
==== LDAPIdentityProviderSpec
Spec for configuring an LDAP identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovider[$$LDAPIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`host`* __string__ | Host is the hostname of this LDAP identity provider, i.e., where to connect. For example: ldap.example.com:636.
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host.
| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderbind[$$LDAPIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the LDAP server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch[$$LDAPIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in the LDAP provider.
| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch[$$LDAPIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in the LDAP provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus"]
==== LDAPIdentityProviderStatus
Status of an LDAP identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityprovider[$$LDAPIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`phase`* __LDAPIdentityProviderPhase__ | Phase summarizes the overall status of the LDAPIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch"]
==== LDAPIdentityProviderUserSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work.
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearchattributes[$$LDAPIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the LDAP entry which was found as the result of the user search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearchattributes"]
==== LDAPIdentityProviderUserSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch[$$LDAPIdentityProviderUserSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`username`* __string__ | Username specifies the name of the attribute in the LDAP entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in the user search filter, although it can be different. E.g. "mail" or "uid" or "userPrincipalName". The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. Distinguished names can be used by specifying lower-case "dn". When this field is set to "dn" then the LDAPIdentityProviderUserSearch's Filter field cannot be blank, since the default value of "dn={}" would not work.
| *`uid`* __string__ | UID specifies the name of the attribute in the LDAP entry which whose value shall be used to uniquely identify the user within this LDAP provider after a successful authentication. E.g. "uidNumber" or "objectGUID". The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. Distinguished names can be used by specifying lower-case "dn".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-oidcauthorizationconfig"]
==== OIDCAuthorizationConfig
@@ -701,7 +1099,8 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`additionalScopes`* __string array__ | AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization request flow with an OIDC identity provider. By default only the "openid" scope will be requested.
| *`additionalScopes`* __string array__ | AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization request flow with an OIDC identity provider. In the case of a Resource Owner Password Credentials Grant flow, AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the token request (see also the allowPasswordGrant field). By default, only the "openid" scope will be requested.
| *`allowPasswordGrant`* __boolean__ | AllowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. AllowPasswordGrant defaults to false.
|===
@@ -797,7 +1196,7 @@ Status of an OIDC identity provider.
|===
| Field | Description
| *`phase`* __OIDCIdentityProviderPhase__ | Phase summarizes the overall status of the OIDCIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$]__ | Represents the observations of an identity provider's current state.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
@@ -808,6 +1207,8 @@ Status of an OIDC identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$]
****

View File

@@ -3,17 +3,23 @@
package v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// StrategyType enumerates a type of "strategy" used to implement credential access on a cluster.
// +kubebuilder:validation:Enum=KubeClusterSigningCertificate;ImpersonationProxy
type StrategyType string
// FrontendType enumerates a type of "frontend" used to provide access to users of a cluster.
// +kubebuilder:validation:Enum=TokenCredentialRequestAPI;ImpersonationProxy
type FrontendType string
// StrategyStatus enumerates whether a strategy is working on a cluster.
// +kubebuilder:validation:Enum=Success;Error
type StrategyStatus string
// StrategyReason enumerates the detailed reason why a strategy is in a particular status.
// +kubebuilder:validation:Enum=Listening;Pending;Disabled;ErrorDuringSetup;CouldNotFetchKey;CouldNotGetClusterInfo;FetchedKey
type StrategyReason string
@@ -36,7 +42,91 @@ const (
FetchedKeyStrategyReason = StrategyReason("FetchedKey")
)
// Status of a credential issuer.
// CredentialIssuerSpec describes the intended configuration of the Concierge.
type CredentialIssuerSpec struct {
// ImpersonationProxy describes the intended configuration of the Concierge impersonation proxy.
ImpersonationProxy *ImpersonationProxySpec `json:"impersonationProxy"`
}
// ImpersonationProxyMode enumerates the configuration modes for the impersonation proxy.
//
// +kubebuilder:validation:Enum=auto;enabled;disabled
type ImpersonationProxyMode string
const (
// ImpersonationProxyModeDisabled explicitly disables the impersonation proxy.
ImpersonationProxyModeDisabled = ImpersonationProxyMode("disabled")
// ImpersonationProxyModeEnabled explicitly enables the impersonation proxy.
ImpersonationProxyModeEnabled = ImpersonationProxyMode("enabled")
// ImpersonationProxyModeAuto enables or disables the impersonation proxy based upon the cluster in which it is running.
ImpersonationProxyModeAuto = ImpersonationProxyMode("auto")
)
// ImpersonationProxyServiceType enumerates the types of service that can be provisioned for the impersonation proxy.
//
// +kubebuilder:validation:Enum=LoadBalancer;ClusterIP;None
type ImpersonationProxyServiceType string
const (
// ImpersonationProxyServiceTypeLoadBalancer provisions a service of type LoadBalancer.
ImpersonationProxyServiceTypeLoadBalancer = ImpersonationProxyServiceType("LoadBalancer")
// ImpersonationProxyServiceTypeClusterIP provisions a service of type ClusterIP.
ImpersonationProxyServiceTypeClusterIP = ImpersonationProxyServiceType("ClusterIP")
// ImpersonationProxyServiceTypeNone does not automatically provision any service.
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
)
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
type ImpersonationProxySpec struct {
// Mode configures whether the impersonation proxy should be started:
// - "disabled" explicitly disables the impersonation proxy. This is the default.
// - "enabled" explicitly enables the impersonation proxy.
// - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
Mode ImpersonationProxyMode `json:"mode"`
// Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
//
// +kubebuilder:default:={"type": "LoadBalancer"}
Service ImpersonationProxyServiceSpec `json:"service"`
// 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".
//
// +optional
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
}
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
type ImpersonationProxyServiceSpec struct {
// 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.
//
// +kubebuilder:default:="LoadBalancer"
Type ImpersonationProxyServiceType `json:"type,omitempty"`
// LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service.
// This is not supported on all cloud providers.
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=255
// +optional
LoadBalancerIP string `json:"loadBalancerIP,omitempty"`
// Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
//
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}
// CredentialIssuerStatus describes the status of the Concierge.
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
@@ -47,7 +137,8 @@ type CredentialIssuerStatus struct {
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// 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
@@ -59,7 +150,7 @@ type CredentialIssuerKubeConfigInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Status of an integration strategy that was attempted by Pinniped.
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
type CredentialIssuerStrategy struct {
// Type of integration attempted.
Type StrategyType `json:"type"`
@@ -81,6 +172,7 @@ type CredentialIssuerStrategy struct {
Frontend *CredentialIssuerFrontend `json:"frontend,omitempty"`
}
// CredentialIssuerFrontend describes how to connect using a particular integration strategy.
type CredentialIssuerFrontend struct {
// Type describes which frontend mechanism clients can use with a strategy.
Type FrontendType `json:"type"`
@@ -118,7 +210,7 @@ type ImpersonationProxyInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Describes the configuration status of a Pinniped credential issuer.
// CredentialIssuer describes the configuration and status of the Pinniped Concierge credential issuer.
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -128,12 +220,18 @@ type CredentialIssuer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Status of the credential issuer.
// Spec describes the intended configuration of the Concierge.
//
// +optional
Spec CredentialIssuerSpec `json:"spec"`
// CredentialIssuerStatus describes the status of the Concierge.
//
// +optional
Status CredentialIssuerStatus `json:"status"`
}
// List of CredentialIssuer objects.
// CredentialIssuerList is a list of CredentialIssuer objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type CredentialIssuerList struct {
metav1.TypeMeta `json:",inline"`

View File

@@ -16,6 +16,7 @@ func (in *CredentialIssuer) DeepCopyInto(out *CredentialIssuer) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
@@ -113,6 +114,27 @@ func (in *CredentialIssuerList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerSpec) DeepCopyInto(out *CredentialIssuerSpec) {
*out = *in
if in.ImpersonationProxy != nil {
in, out := &in.ImpersonationProxy, &out.ImpersonationProxy
*out = new(ImpersonationProxySpec)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerSpec.
func (in *CredentialIssuerSpec) DeepCopy() *CredentialIssuerSpec {
if in == nil {
return nil
}
out := new(CredentialIssuerSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
*out = *in
@@ -179,6 +201,46 @@ func (in *ImpersonationProxyInfo) DeepCopy() *ImpersonationProxyInfo {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImpersonationProxyServiceSpec) DeepCopyInto(out *ImpersonationProxyServiceSpec) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxyServiceSpec.
func (in *ImpersonationProxyServiceSpec) DeepCopy() *ImpersonationProxyServiceSpec {
if in == nil {
return nil
}
out := new(ImpersonationProxyServiceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImpersonationProxySpec) DeepCopyInto(out *ImpersonationProxySpec) {
*out = *in
in.Service.DeepCopyInto(&out.Service)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxySpec.
func (in *ImpersonationProxySpec) DeepCopy() *ImpersonationProxySpec {
if in == nil {
return nil
}
out := new(ImpersonationProxySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TokenCredentialRequestAPIInfo) DeepCopyInto(out *TokenCredentialRequestAPIInfo) {
*out = *in

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -32,6 +32,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&OIDCIdentityProvider{},
&OIDCIdentityProviderList{},
&LDAPIdentityProvider{},
&LDAPIdentityProviderList{},
&ActiveDirectoryIdentityProvider{},
&ActiveDirectoryIdentityProviderList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@@ -0,0 +1,182 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ActiveDirectoryIdentityProviderPhase string
const (
// ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources.
ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending"
// ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state.
ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready"
// ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state.
ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error"
)
// Status of an Active Directory identity provider.
type ActiveDirectoryIdentityProviderStatus struct {
// Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type ActiveDirectoryIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type ActiveDirectoryIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in Active Directory entry whose value shall become the username
// of the user after a successful authentication.
// Optional, when empty this defaults to "userPrincipalName".
// +optional
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely
// identify the user within this ActiveDirectory provider after a successful authentication.
// Optional, when empty this defaults to "objectGUID".
// +optional
UID string `json:"uid,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, this defaults to a custom field that looks like "sAMAccountName@domain",
// where domain is constructed from the domain components of the group DN.
// +optional
GroupName string `json:"groupName,omitempty"`
}
type ActiveDirectoryIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for users.
// It may make sense to specify a subtree as a search base if you wish to exclude some users
// or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will be
// '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
// This means that the user is a person, is not a computer, the sAMAccountType is for a normal user account,
// and is not shown in advanced view only
// (which would likely mean its a system created service account with advanced permissions).
// Also, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as
// the result of the user search.
// +optional
Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for groups.
// It may make sense to specify a subtree as a search base if you wish to exclude some groups
// for security reasons or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the filter were specified as
// "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
// This searches nested groups by default.
// Note that nested group search can be slow for some Active Directory servers. To disable it,
// you can set the filter to
// "(&(objectClass=group)(member={})"
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
// the result of the group search.
// +optional
Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an ActiveDirectory identity provider.
type ActiveDirectoryIdentityProviderSpec struct {
// Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in Active Directory.
UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.
GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type ActiveDirectoryIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec ActiveDirectoryIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"`
}
// List of ActiveDirectoryIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ActiveDirectoryIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ActiveDirectoryIdentityProvider `json:"items"`
}

View File

@@ -0,0 +1,171 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type LDAPIdentityProviderPhase string
const (
// LDAPPhasePending is the default phase for newly-created LDAPIdentityProvider resources.
LDAPPhasePending LDAPIdentityProviderPhase = "Pending"
// LDAPPhaseReady is the phase for an LDAPIdentityProvider resource in a healthy state.
LDAPPhaseReady LDAPIdentityProviderPhase = "Ready"
// LDAPPhaseError is the phase for an LDAPIdentityProvider in an unhealthy state.
LDAPPhaseError LDAPIdentityProviderPhase = "Error"
)
// Status of an LDAP identity provider.
type LDAPIdentityProviderStatus struct {
// Phase summarizes the overall status of the LDAPIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase LDAPIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type LDAPIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an LDAP bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type LDAPIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in the LDAP entry whose value shall become the username
// of the user after a successful authentication. This would typically be the same attribute name used in
// the user search filter, although it can be different. E.g. "mail" or "uid" or "userPrincipalName".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn". When this field
// is set to "dn" then the LDAPIdentityProviderUserSearch's Filter field cannot be blank, since the default
// value of "dn={}" would not work.
// +kubebuilder:validation:MinLength=1
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the LDAP entry which whose value shall be used to uniquely
// identify the user within this LDAP provider after a successful authentication. E.g. "uidNumber" or "objectGUID".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn".
// +kubebuilder:validation:MinLength=1
UID string `json:"uid,omitempty"`
}
type LDAPIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the LDAP entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name).
// +optional
GroupName string `json:"groupName,omitempty"`
}
type LDAPIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// +kubebuilder:validation:MinLength=1
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as the value from
// Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be
// explicitly specified, since the default value of "dn={}" would not work.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the LDAP entry which was found as
// the result of the user search.
// +optional
Attributes LDAPIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type LDAPIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and
// authenticated users will not belong to any groups from the LDAP provider. Also, when not specified,
// the values of Filter and Attributes are ignored.
// +optional
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as "member={}".
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
// the result of the group search.
// +optional
Attributes LDAPIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an LDAP identity provider.
type LDAPIdentityProviderSpec struct {
// Host is the hostname of this LDAP identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the LDAP server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind LDAPIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in the LDAP provider.
UserSearch LDAPIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in the LDAP provider.
GroupSearch LDAPIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// LDAPIdentityProvider describes the configuration of an upstream Lightweight Directory Access
// Protocol (LDAP) identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type LDAPIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec LDAPIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status LDAPIdentityProviderStatus `json:"status,omitempty"`
}
// List of LDAPIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type LDAPIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []LDAPIdentityProvider `json:"items"`
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -39,9 +39,31 @@ type OIDCIdentityProviderStatus struct {
// request parameters.
type OIDCAuthorizationConfig struct {
// AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization
// request flow with an OIDC identity provider. By default only the "openid" scope will be requested.
// request flow with an OIDC identity provider.
// In the case of a Resource Owner Password Credentials Grant flow, AdditionalScopes are the scopes
// in addition to "openid" that will be requested as part of the token request (see also the allowPasswordGrant field).
// By default, only the "openid" scope will be requested.
// +optional
AdditionalScopes []string `json:"additionalScopes,omitempty"`
// AllowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant
// (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a
// username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow.
// The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be
// supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password
// Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose
// to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the
// cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be
// convenient for users, especially for identities from your OIDC provider which are not intended to represent a human
// actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it,
// you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this
// OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password
// Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords
// (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other
// web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins.
// AllowPasswordGrant defaults to false.
// +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
}
// OIDCClaims provides a mapping from upstream claims into identities.

View File

@@ -11,6 +11,196 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider.
func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProvider)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind.
func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderBind)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch.
func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderGroupSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes.
func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ActiveDirectoryIdentityProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList.
func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) {
*out = *in
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSSpec)
**out = **in
}
out.Bind = in.Bind
out.UserSearch = in.UserSearch
out.GroupSearch = in.GroupSearch
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec.
func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus.
func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch.
func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderUserSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes.
func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderUserSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Condition) DeepCopyInto(out *Condition) {
*out = *in
@@ -28,6 +218,196 @@ func (in *Condition) DeepCopy() *Condition {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProvider) DeepCopyInto(out *LDAPIdentityProvider) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProvider.
func (in *LDAPIdentityProvider) DeepCopy() *LDAPIdentityProvider {
if in == nil {
return nil
}
out := new(LDAPIdentityProvider)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LDAPIdentityProvider) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderBind) DeepCopyInto(out *LDAPIdentityProviderBind) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderBind.
func (in *LDAPIdentityProviderBind) DeepCopy() *LDAPIdentityProviderBind {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderBind)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderGroupSearch) DeepCopyInto(out *LDAPIdentityProviderGroupSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderGroupSearch.
func (in *LDAPIdentityProviderGroupSearch) DeepCopy() *LDAPIdentityProviderGroupSearch {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderGroupSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderGroupSearchAttributes) DeepCopyInto(out *LDAPIdentityProviderGroupSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderGroupSearchAttributes.
func (in *LDAPIdentityProviderGroupSearchAttributes) DeepCopy() *LDAPIdentityProviderGroupSearchAttributes {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderGroupSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderList) DeepCopyInto(out *LDAPIdentityProviderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]LDAPIdentityProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderList.
func (in *LDAPIdentityProviderList) DeepCopy() *LDAPIdentityProviderList {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LDAPIdentityProviderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderSpec) DeepCopyInto(out *LDAPIdentityProviderSpec) {
*out = *in
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSSpec)
**out = **in
}
out.Bind = in.Bind
out.UserSearch = in.UserSearch
out.GroupSearch = in.GroupSearch
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderSpec.
func (in *LDAPIdentityProviderSpec) DeepCopy() *LDAPIdentityProviderSpec {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderStatus) DeepCopyInto(out *LDAPIdentityProviderStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderStatus.
func (in *LDAPIdentityProviderStatus) DeepCopy() *LDAPIdentityProviderStatus {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderUserSearch) DeepCopyInto(out *LDAPIdentityProviderUserSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderUserSearch.
func (in *LDAPIdentityProviderUserSearch) DeepCopy() *LDAPIdentityProviderUserSearch {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderUserSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderUserSearchAttributes) DeepCopyInto(out *LDAPIdentityProviderUserSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderUserSearchAttributes.
func (in *LDAPIdentityProviderUserSearchAttributes) DeepCopy() *LDAPIdentityProviderUserSearchAttributes {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderUserSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OIDCAuthorizationConfig) DeepCopyInto(out *OIDCAuthorizationConfig) {
*out = *in

View File

@@ -0,0 +1,66 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// IDPType are the strings that can be returned by the Supervisor identity provider discovery endpoint
// as the "type" of each returned identity provider.
type IDPType string
// IDPFlow are the strings that can be returned by the Supervisor identity provider discovery endpoint
// in the array of allowed client "flows" for each returned identity provider.
type IDPFlow string
const (
IDPTypeOIDC IDPType = "oidc"
IDPTypeLDAP IDPType = "ldap"
IDPTypeActiveDirectory IDPType = "activedirectory"
IDPFlowCLIPassword IDPFlow = "cli_password"
IDPFlowBrowserAuthcode IDPFlow = "browser_authcode"
)
// Equals is a convenience function for comparing an IDPType to a string.
func (r IDPType) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPType to a string.
func (r IDPType) String() string {
return string(r)
}
// Equals is a convenience function for comparing an IDPFlow to a string.
func (r IDPFlow) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPFlow to a string.
func (r IDPFlow) String() string {
return string(r)
}
// OIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type OIDCDiscoveryResponse struct {
SupervisorDiscovery OIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// OIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type OIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// IDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type IDPDiscoveryResponse struct {
PinnipedIDPs []PinnipedIDP `json:"pinniped_identity_providers"`
}
// PinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type PinnipedIDP struct {
Name string `json:"name"`
Type IDPType `json:"type"`
Flows []IDPFlow `json:"flows,omitempty"`
}

View File

@@ -0,0 +1,25 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package oidc
// Constants related to the Supervisor FederationDomain's authorization and token endpoints.
const (
// AuthorizeUsernameHeaderName is the name of the HTTP header which can be used to transmit a username
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizeUsernameHeaderName = "Pinniped-Username"
// AuthorizePasswordHeaderName is the name of the HTTP header which can be used to transmit a password
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizePasswordHeaderName = "Pinniped-Password" //nolint:gosec // this is not a credential
// AuthorizeUpstreamIDPNameParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the name of the desired identity provider.
AuthorizeUpstreamIDPNameParamName = "pinniped_idp_name"
// AuthorizeUpstreamIDPTypeParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the type of the desired identity provider.
AuthorizeUpstreamIDPTypeParamName = "pinniped_idp_type"
)

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,9 @@ module go.pinniped.dev/generated/1.17/client
go 1.13
require (
github.com/go-openapi/spec v0.19.9
go.pinniped.dev/generated/1.17/apis v0.0.0-00010101000000-000000000000
k8s.io/apimachinery v0.17.11
k8s.io/client-go v0.17.11
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
)
replace go.pinniped.dev/generated/1.17/apis => ../apis

View File

@@ -11,11 +11,7 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -23,7 +19,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b h1:vCplRbYcTTeBVLjIU0KvipEeVBSxl6sakUBRmeLBTkw=
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
@@ -32,17 +27,9 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc=
github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -89,9 +76,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -137,7 +121,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -159,9 +142,8 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -191,7 +173,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -0,0 +1,178 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"time"
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
scheme "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface.
// A group's client should implement this interface.
type ActiveDirectoryIdentityProvidersGetter interface {
ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface
}
// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources.
type ActiveDirectoryIdentityProviderInterface interface {
Create(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
Update(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
UpdateStatus(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
List(opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error)
ActiveDirectoryIdentityProviderExpansion
}
// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface
type activeDirectoryIdentityProviders struct {
client rest.Interface
ns string
}
// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders
func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders {
return &activeDirectoryIdentityProviders{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any.
func (c *activeDirectoryIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors.
func (c *activeDirectoryIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.ActiveDirectoryIdentityProviderList{}
err = c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders.
func (c *activeDirectoryIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *activeDirectoryIdentityProviders) Create(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Post().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Body(activeDirectoryIdentityProvider).
Do().
Into(result)
return
}
// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *activeDirectoryIdentityProviders) Update(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(activeDirectoryIdentityProvider.Name).
Body(activeDirectoryIdentityProvider).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *activeDirectoryIdentityProviders) UpdateStatus(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(activeDirectoryIdentityProvider.Name).
SubResource("status").
Body(activeDirectoryIdentityProvider).
Do().
Into(result)
return
}
// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs.
func (c *activeDirectoryIdentityProviders) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *activeDirectoryIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched activeDirectoryIdentityProvider.
func (c *activeDirectoryIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -0,0 +1,127 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface
type FakeActiveDirectoryIdentityProviders struct {
Fake *FakeIDPV1alpha1
ns string
}
var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"}
var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"}
// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors.
func (c *FakeActiveDirectoryIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta}
for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders.
func (c *FakeActiveDirectoryIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts))
}
// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Create(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Update(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs.
func (c *FakeActiveDirectoryIdentityProviders) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{})
return err
}
// Patch applies the patch and returns the patched activeDirectoryIdentityProvider.
func (c *FakeActiveDirectoryIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}

View File

@@ -15,6 +15,14 @@ type FakeIDPV1alpha1 struct {
*testing.Fake
}
func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface {
return &FakeActiveDirectoryIdentityProviders{c, namespace}
}
func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface {
return &FakeLDAPIdentityProviders{c, namespace}
}
func (c *FakeIDPV1alpha1) OIDCIdentityProviders(namespace string) v1alpha1.OIDCIdentityProviderInterface {
return &FakeOIDCIdentityProviders{c, namespace}
}

View File

@@ -0,0 +1,127 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeLDAPIdentityProviders implements LDAPIdentityProviderInterface
type FakeLDAPIdentityProviders struct {
Fake *FakeIDPV1alpha1
ns string
}
var ldapidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "ldapidentityproviders"}
var ldapidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "LDAPIdentityProvider"}
// Get takes name of the lDAPIdentityProvider, and returns the corresponding lDAPIdentityProvider object, and an error if there is any.
func (c *FakeLDAPIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(ldapidentityprovidersResource, c.ns, name), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// List takes label and field selectors, and returns the list of LDAPIdentityProviders that match those selectors.
func (c *FakeLDAPIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.LDAPIdentityProviderList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(ldapidentityprovidersResource, ldapidentityprovidersKind, c.ns, opts), &v1alpha1.LDAPIdentityProviderList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.LDAPIdentityProviderList{ListMeta: obj.(*v1alpha1.LDAPIdentityProviderList).ListMeta}
for _, item := range obj.(*v1alpha1.LDAPIdentityProviderList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested lDAPIdentityProviders.
func (c *FakeLDAPIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(ldapidentityprovidersResource, c.ns, opts))
}
// Create takes the representation of a lDAPIdentityProvider and creates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *FakeLDAPIdentityProviders) Create(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(ldapidentityprovidersResource, c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// Update takes the representation of a lDAPIdentityProvider and updates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *FakeLDAPIdentityProviders) Update(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(ldapidentityprovidersResource, c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeLDAPIdentityProviders) UpdateStatus(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (*v1alpha1.LDAPIdentityProvider, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(ldapidentityprovidersResource, "status", c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// Delete takes name of the lDAPIdentityProvider and deletes it. Returns an error if one occurs.
func (c *FakeLDAPIdentityProviders) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(ldapidentityprovidersResource, c.ns, name), &v1alpha1.LDAPIdentityProvider{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeLDAPIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(ldapidentityprovidersResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha1.LDAPIdentityProviderList{})
return err
}
// Patch applies the patch and returns the patched lDAPIdentityProvider.
func (c *FakeLDAPIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(ldapidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}

View File

@@ -5,4 +5,8 @@
package v1alpha1
type ActiveDirectoryIdentityProviderExpansion interface{}
type LDAPIdentityProviderExpansion interface{}
type OIDCIdentityProviderExpansion interface{}

View File

@@ -13,6 +13,8 @@ import (
type IDPV1alpha1Interface interface {
RESTClient() rest.Interface
ActiveDirectoryIdentityProvidersGetter
LDAPIdentityProvidersGetter
OIDCIdentityProvidersGetter
}
@@ -21,6 +23,14 @@ type IDPV1alpha1Client struct {
restClient rest.Interface
}
func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface {
return newActiveDirectoryIdentityProviders(c, namespace)
}
func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface {
return newLDAPIdentityProviders(c, namespace)
}
func (c *IDPV1alpha1Client) OIDCIdentityProviders(namespace string) OIDCIdentityProviderInterface {
return newOIDCIdentityProviders(c, namespace)
}

View File

@@ -0,0 +1,178 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"time"
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
scheme "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// LDAPIdentityProvidersGetter has a method to return a LDAPIdentityProviderInterface.
// A group's client should implement this interface.
type LDAPIdentityProvidersGetter interface {
LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface
}
// LDAPIdentityProviderInterface has methods to work with LDAPIdentityProvider resources.
type LDAPIdentityProviderInterface interface {
Create(*v1alpha1.LDAPIdentityProvider) (*v1alpha1.LDAPIdentityProvider, error)
Update(*v1alpha1.LDAPIdentityProvider) (*v1alpha1.LDAPIdentityProvider, error)
UpdateStatus(*v1alpha1.LDAPIdentityProvider) (*v1alpha1.LDAPIdentityProvider, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.LDAPIdentityProvider, error)
List(opts v1.ListOptions) (*v1alpha1.LDAPIdentityProviderList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error)
LDAPIdentityProviderExpansion
}
// lDAPIdentityProviders implements LDAPIdentityProviderInterface
type lDAPIdentityProviders struct {
client rest.Interface
ns string
}
// newLDAPIdentityProviders returns a LDAPIdentityProviders
func newLDAPIdentityProviders(c *IDPV1alpha1Client, namespace string) *lDAPIdentityProviders {
return &lDAPIdentityProviders{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the lDAPIdentityProvider, and returns the corresponding lDAPIdentityProvider object, and an error if there is any.
func (c *lDAPIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of LDAPIdentityProviders that match those selectors.
func (c *lDAPIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.LDAPIdentityProviderList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.LDAPIdentityProviderList{}
err = c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested lDAPIdentityProviders.
func (c *lDAPIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a lDAPIdentityProvider and creates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *lDAPIdentityProviders) Create(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Post().
Namespace(c.ns).
Resource("ldapidentityproviders").
Body(lDAPIdentityProvider).
Do().
Into(result)
return
}
// Update takes the representation of a lDAPIdentityProvider and updates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *lDAPIdentityProviders) Update(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(lDAPIdentityProvider.Name).
Body(lDAPIdentityProvider).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *lDAPIdentityProviders) UpdateStatus(lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(lDAPIdentityProvider.Name).
SubResource("status").
Body(lDAPIdentityProvider).
Do().
Into(result)
return
}
// Delete takes name of the lDAPIdentityProvider and deletes it. Returns an error if one occurs.
func (c *lDAPIdentityProviders) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *lDAPIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched lDAPIdentityProvider.
func (c *lDAPIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("ldapidentityproviders").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -45,6 +45,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil
// Group=idp.supervisor.pinniped.dev, Version=v1alpha1
case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil
case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil
case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().OIDCIdentityProviders().Informer()}, nil

View File

@@ -0,0 +1,76 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
time "time"
idpv1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
versioned "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned"
internalinterfaces "go.pinniped.dev/generated/1.17/client/supervisor/informers/externalversions/internalinterfaces"
v1alpha1 "go.pinniped.dev/generated/1.17/client/supervisor/listers/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for
// ActiveDirectoryIdentityProviders.
type ActiveDirectoryIdentityProviderInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.ActiveDirectoryIdentityProviderLister
}
type activeDirectoryIdentityProviderInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(options)
},
},
&idpv1alpha1.ActiveDirectoryIdentityProvider{},
resyncPeriod,
indexers,
)
}
func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer)
}
func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister {
return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer())
}

View File

@@ -11,6 +11,10 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer.
ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer
// LDAPIdentityProviders returns a LDAPIdentityProviderInformer.
LDAPIdentityProviders() LDAPIdentityProviderInformer
// OIDCIdentityProviders returns a OIDCIdentityProviderInformer.
OIDCIdentityProviders() OIDCIdentityProviderInformer
}
@@ -26,6 +30,16 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer.
func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer {
return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// LDAPIdentityProviders returns a LDAPIdentityProviderInformer.
func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer {
return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// OIDCIdentityProviders returns a OIDCIdentityProviderInformer.
func (v *version) OIDCIdentityProviders() OIDCIdentityProviderInformer {
return &oIDCIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}

View File

@@ -0,0 +1,76 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
time "time"
idpv1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
versioned "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned"
internalinterfaces "go.pinniped.dev/generated/1.17/client/supervisor/informers/externalversions/internalinterfaces"
v1alpha1 "go.pinniped.dev/generated/1.17/client/supervisor/listers/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// LDAPIdentityProviderInformer provides access to a shared informer and lister for
// LDAPIdentityProviders.
type LDAPIdentityProviderInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.LDAPIdentityProviderLister
}
type lDAPIdentityProviderInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewLDAPIdentityProviderInformer constructs a new informer for LDAPIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewLDAPIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredLDAPIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredLDAPIdentityProviderInformer constructs a new informer for LDAPIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredLDAPIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().LDAPIdentityProviders(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().LDAPIdentityProviders(namespace).Watch(options)
},
},
&idpv1alpha1.LDAPIdentityProvider{},
resyncPeriod,
indexers,
)
}
func (f *lDAPIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredLDAPIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *lDAPIdentityProviderInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&idpv1alpha1.LDAPIdentityProvider{}, f.defaultInformer)
}
func (f *lDAPIdentityProviderInformer) Lister() v1alpha1.LDAPIdentityProviderLister {
return v1alpha1.NewLDAPIdentityProviderLister(f.Informer().GetIndexer())
}

View File

@@ -0,0 +1,81 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
import (
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders.
type ActiveDirectoryIdentityProviderLister interface {
// List lists all ActiveDirectoryIdentityProviders in the indexer.
List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error)
// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders.
ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister
ActiveDirectoryIdentityProviderListerExpansion
}
// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface.
type activeDirectoryIdentityProviderLister struct {
indexer cache.Indexer
}
// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister.
func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister {
return &activeDirectoryIdentityProviderLister{indexer: indexer}
}
// List lists all ActiveDirectoryIdentityProviders in the indexer.
func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider))
})
return ret, err
}
// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders.
func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister {
return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders.
type ActiveDirectoryIdentityProviderNamespaceLister interface {
// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error)
// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name.
Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
ActiveDirectoryIdentityProviderNamespaceListerExpansion
}
// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister
// interface.
type activeDirectoryIdentityProviderNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace.
func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider))
})
return ret, err
}
// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name.
func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name)
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil
}

View File

@@ -5,6 +5,22 @@
package v1alpha1
// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to
// ActiveDirectoryIdentityProviderLister.
type ActiveDirectoryIdentityProviderListerExpansion interface{}
// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to
// ActiveDirectoryIdentityProviderNamespaceLister.
type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{}
// LDAPIdentityProviderListerExpansion allows custom methods to be added to
// LDAPIdentityProviderLister.
type LDAPIdentityProviderListerExpansion interface{}
// LDAPIdentityProviderNamespaceListerExpansion allows custom methods to be added to
// LDAPIdentityProviderNamespaceLister.
type LDAPIdentityProviderNamespaceListerExpansion interface{}
// OIDCIdentityProviderListerExpansion allows custom methods to be added to
// OIDCIdentityProviderLister.
type OIDCIdentityProviderListerExpansion interface{}

View File

@@ -0,0 +1,81 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
import (
v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// LDAPIdentityProviderLister helps list LDAPIdentityProviders.
type LDAPIdentityProviderLister interface {
// List lists all LDAPIdentityProviders in the indexer.
List(selector labels.Selector) (ret []*v1alpha1.LDAPIdentityProvider, err error)
// LDAPIdentityProviders returns an object that can list and get LDAPIdentityProviders.
LDAPIdentityProviders(namespace string) LDAPIdentityProviderNamespaceLister
LDAPIdentityProviderListerExpansion
}
// lDAPIdentityProviderLister implements the LDAPIdentityProviderLister interface.
type lDAPIdentityProviderLister struct {
indexer cache.Indexer
}
// NewLDAPIdentityProviderLister returns a new LDAPIdentityProviderLister.
func NewLDAPIdentityProviderLister(indexer cache.Indexer) LDAPIdentityProviderLister {
return &lDAPIdentityProviderLister{indexer: indexer}
}
// List lists all LDAPIdentityProviders in the indexer.
func (s *lDAPIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.LDAPIdentityProvider, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.LDAPIdentityProvider))
})
return ret, err
}
// LDAPIdentityProviders returns an object that can list and get LDAPIdentityProviders.
func (s *lDAPIdentityProviderLister) LDAPIdentityProviders(namespace string) LDAPIdentityProviderNamespaceLister {
return lDAPIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// LDAPIdentityProviderNamespaceLister helps list and get LDAPIdentityProviders.
type LDAPIdentityProviderNamespaceLister interface {
// List lists all LDAPIdentityProviders in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha1.LDAPIdentityProvider, err error)
// Get retrieves the LDAPIdentityProvider from the indexer for a given namespace and name.
Get(name string) (*v1alpha1.LDAPIdentityProvider, error)
LDAPIdentityProviderNamespaceListerExpansion
}
// lDAPIdentityProviderNamespaceLister implements the LDAPIdentityProviderNamespaceLister
// interface.
type lDAPIdentityProviderNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all LDAPIdentityProviders in the indexer for a given namespace.
func (s lDAPIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.LDAPIdentityProvider, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.LDAPIdentityProvider))
})
return ret, err
}
// Get retrieves the LDAPIdentityProvider from the indexer for a given namespace and name.
func (s lDAPIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.LDAPIdentityProvider, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha1.Resource("ldapidentityprovider"), name)
}
return obj.(*v1alpha1.LDAPIdentityProvider), nil
}

View File

@@ -21,7 +21,8 @@ spec:
- name: v1alpha1
schema:
openAPIV3Schema:
description: Describes the configuration status of a Pinniped credential issuer.
description: CredentialIssuer describes the configuration and status of the
Pinniped Concierge credential issuer.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@@ -35,8 +36,73 @@ spec:
type: string
metadata:
type: object
spec:
description: Spec describes the intended configuration of the Concierge.
properties:
impersonationProxy:
description: ImpersonationProxy describes the intended configuration
of the Concierge impersonation proxy.
properties:
externalEndpoint:
description: "ExternalEndpoint describes the HTTPS endpoint where
the proxy will be exposed. If not set, the proxy will be served
using the external name of the LoadBalancer service or the cluster
service DNS name. \n This field must be non-empty when spec.impersonationProxy.service.type
is \"None\"."
type: string
mode:
description: 'Mode configures whether the impersonation proxy
should be started: - "disabled" explicitly disables the impersonation
proxy. This is the default. - "enabled" explicitly enables the
impersonation proxy. - "auto" enables or disables the impersonation
proxy based upon the cluster in which it is running.'
enum:
- auto
- enabled
- disabled
type: string
service:
default:
type: LoadBalancer
description: Service describes the configuration of the Service
provisioned to expose the impersonation proxy to clients.
properties:
annotations:
additionalProperties:
type: string
description: Annotations specifies zero or more key/value
pairs to set as annotations on the provisioned Service.
type: object
loadBalancerIP:
description: LoadBalancerIP specifies the IP address to set
in the spec.loadBalancerIP field of the provisioned Service.
This is not supported on all cloud providers.
maxLength: 255
minLength: 1
type: string
type:
default: LoadBalancer
description: "Type specifies the type of Service to provision
for the impersonation proxy. \n If the type is \"None\",
then the \"spec.impersonationProxy.externalEndpoint\" field
must be set to a non-empty value so that the Concierge can
properly advertise the endpoint in the CredentialIssuer's
status."
enum:
- LoadBalancer
- ClusterIP
- None
type: string
type: object
required:
- mode
- service
type: object
required:
- impersonationProxy
type: object
status:
description: Status of the credential issuer.
description: CredentialIssuerStatus describes the status of the Concierge.
properties:
kubeConfigInfo:
description: Information needed to form a valid Pinniped-based kubeconfig
@@ -60,8 +126,8 @@ spec:
description: List of integration strategies that were attempted by
Pinniped.
items:
description: Status of an integration strategy that was attempted
by Pinniped.
description: CredentialIssuerStrategy describes the status of an
integration strategy that was attempted by Pinniped.
properties:
frontend:
description: Frontend describes how clients can connect using

View File

@@ -0,0 +1,281 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.0
creationTimestamp: null
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
spec:
group: idp.supervisor.pinniped.dev
names:
categories:
- pinniped
- pinniped-idp
- pinniped-idps
kind: ActiveDirectoryIdentityProvider
listKind: ActiveDirectoryIdentityProviderList
plural: activedirectoryidentityproviders
singular: activedirectoryidentityprovider
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.host
name: Host
type: string
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ActiveDirectoryIdentityProvider describes the configuration of
an upstream Microsoft Active Directory identity provider.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec for configuring the identity provider.
properties:
bind:
description: Bind contains the configuration for how to provide access
credentials during an initial bind to the ActiveDirectory server
to be allowed to perform searches and binds to validate a user's
credentials during a user's authentication attempt.
properties:
secretName:
description: SecretName contains the name of a namespace-local
Secret object that provides the username and password for an
Active Directory bind user. This account will be used to perform
LDAP searches. The Secret should be of type "kubernetes.io/basic-auth"
which includes "username" and "password" keys. The username
value should be the full dn (distinguished name) of your bind
account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
The password must be non-empty.
minLength: 1
type: string
required:
- secretName
type: object
groupSearch:
description: GroupSearch contains the configuration for searching
for a user's group membership in ActiveDirectory.
properties:
attributes:
description: Attributes specifies how the group's information
should be read from each ActiveDirectory entry which was found
as the result of the group search.
properties:
groupName:
description: GroupName specifies the name of the attribute
in the Active Directory entries whose value shall become
a group name in the user's list of groups after a successful
authentication. The value of this field is case-sensitive
and must match the case of the attribute name returned by
the ActiveDirectory server in the user's entry. E.g. "cn"
for common name. Distinguished names can be used by specifying
lower-case "dn". Optional. When not specified, this defaults
to a custom field that looks like "sAMAccountName@domain",
where domain is constructed from the domain components of
the group DN.
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
Optional, when not specified it will be based on the result
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
The default behavior searches your entire domain for groups.
It may make sense to specify a subtree as a search base if you
wish to exclude some groups for security reasons or to make
searches faster.
type: string
filter:
description: Filter is the ActiveDirectory search filter which
should be applied when searching for groups for a user. The
pattern "{}" must occur in the filter at least once and will
be dynamically replaced by the dn (distinguished name) of the
user entry found as a result of the user search. E.g. "member={}"
or "&(objectClass=groupOfNames)(member={})". For more information
about ActiveDirectory filters, see https://ldap.com/ldap-filters.
Note that the dn (distinguished name) is not an attribute of
an entry, so "dn={}" cannot be used. Optional. When not specified,
the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
This searches nested groups by default. Note that nested group
search can be slow for some Active Directory servers. To disable
it, you can set the filter to "(&(objectClass=group)(member={})"
type: string
type: object
host:
description: 'Host is the hostname of this Active Directory identity
provider, i.e., where to connect. For example: ldap.example.com:636.'
minLength: 1
type: string
tls:
description: TLS contains the connection settings for how to establish
the connection to the Host.
properties:
certificateAuthorityData:
description: X.509 Certificate Authority (base64-encoded PEM bundle).
If omitted, a default set of system roots will be trusted.
type: string
type: object
userSearch:
description: UserSearch contains the configuration for searching for
a user by name in Active Directory.
properties:
attributes:
description: Attributes specifies how the user's information should
be read from the ActiveDirectory entry which was found as the
result of the user search.
properties:
uid:
description: UID specifies the name of the attribute in the
ActiveDirectory entry which whose value shall be used to
uniquely identify the user within this ActiveDirectory provider
after a successful authentication. Optional, when empty
this defaults to "objectGUID".
type: string
username:
description: Username specifies the name of the attribute
in Active Directory entry whose value shall become the username
of the user after a successful authentication. Optional,
when empty this defaults to "userPrincipalName".
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
Optional, when not specified it will be based on the result
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
The default behavior searches your entire domain for users.
It may make sense to specify a subtree as a search base if you
wish to exclude some users or to make searches faster.
type: string
filter:
description: Filter is the search filter which should be applied
when searching for users. The pattern "{}" must occur in the
filter at least once and will be dynamically replaced by the
username for which the search is being run. E.g. "mail={}" or
"&(objectClass=person)(uid={})". For more information about
LDAP filters, see https://ldap.com/ldap-filters. Note that the
dn (distinguished name) is not an attribute of an entry, so
"dn={}" cannot be used. Optional. When not specified, the default
will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
This means that the user is a person, is not a computer, the
sAMAccountType is for a normal user account, and is not shown
in advanced view only (which would likely mean its a system
created service account with advanced permissions). Also, either
the sAMAccountName, the userPrincipalName, or the mail attribute
matches the input username.
type: string
type: object
required:
- host
type: object
status:
description: Status of the identity provider.
properties:
conditions:
description: Represents the observations of an identity provider's
current state.
items:
description: Condition status of a resource (mirrored from the metav1.Condition
type added in Kubernetes 1.19). In a future API version we can
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
phase:
default: Pending
description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
enum:
- Pending
- Ready
- Error
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -0,0 +1,278 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.0
creationTimestamp: null
name: ldapidentityproviders.idp.supervisor.pinniped.dev
spec:
group: idp.supervisor.pinniped.dev
names:
categories:
- pinniped
- pinniped-idp
- pinniped-idps
kind: LDAPIdentityProvider
listKind: LDAPIdentityProviderList
plural: ldapidentityproviders
singular: ldapidentityprovider
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.host
name: Host
type: string
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: LDAPIdentityProvider describes the configuration of an upstream
Lightweight Directory Access Protocol (LDAP) identity provider.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec for configuring the identity provider.
properties:
bind:
description: Bind contains the configuration for how to provide access
credentials during an initial bind to the LDAP server to be allowed
to perform searches and binds to validate a user's credentials during
a user's authentication attempt.
properties:
secretName:
description: SecretName contains the name of a namespace-local
Secret object that provides the username and password for an
LDAP bind user. This account will be used to perform LDAP searches.
The Secret should be of type "kubernetes.io/basic-auth" which
includes "username" and "password" keys. The username value
should be the full dn (distinguished name) of your bind account,
e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password
must be non-empty.
minLength: 1
type: string
required:
- secretName
type: object
groupSearch:
description: GroupSearch contains the configuration for searching
for a user's group membership in the LDAP provider.
properties:
attributes:
description: Attributes specifies how the group's information
should be read from each LDAP entry which was found as the result
of the group search.
properties:
groupName:
description: GroupName specifies the name of the attribute
in the LDAP entries whose value shall become a group name
in the user's list of groups after a successful authentication.
The value of this field is case-sensitive and must match
the case of the attribute name returned by the LDAP server
in the user's entry. E.g. "cn" for common name. Distinguished
names can be used by specifying lower-case "dn". Optional.
When not specified, the default will act as if the GroupName
were specified as "dn" (distinguished name).
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
When not specified, no group search will be performed and authenticated
users will not belong to any groups from the LDAP provider.
Also, when not specified, the values of Filter and Attributes
are ignored.
type: string
filter:
description: Filter is the LDAP search filter which should be
applied when searching for groups for a user. The pattern "{}"
must occur in the filter at least once and will be dynamically
replaced by the dn (distinguished name) of the user entry found
as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
For more information about LDAP filters, see https://ldap.com/ldap-filters.
Note that the dn (distinguished name) is not an attribute of
an entry, so "dn={}" cannot be used. Optional. When not specified,
the default will act as if the Filter were specified as "member={}".
type: string
type: object
host:
description: 'Host is the hostname of this LDAP identity provider,
i.e., where to connect. For example: ldap.example.com:636.'
minLength: 1
type: string
tls:
description: TLS contains the connection settings for how to establish
the connection to the Host.
properties:
certificateAuthorityData:
description: X.509 Certificate Authority (base64-encoded PEM bundle).
If omitted, a default set of system roots will be trusted.
type: string
type: object
userSearch:
description: UserSearch contains the configuration for searching for
a user by name in the LDAP provider.
properties:
attributes:
description: Attributes specifies how the user's information should
be read from the LDAP entry which was found as the result of
the user search.
properties:
uid:
description: UID specifies the name of the attribute in the
LDAP entry which whose value shall be used to uniquely identify
the user within this LDAP provider after a successful authentication.
E.g. "uidNumber" or "objectGUID". The value of this field
is case-sensitive and must match the case of the attribute
name returned by the LDAP server in the user's entry. Distinguished
names can be used by specifying lower-case "dn".
minLength: 1
type: string
username:
description: Username specifies the name of the attribute
in the LDAP entry whose value shall become the username
of the user after a successful authentication. This would
typically be the same attribute name used in the user search
filter, although it can be different. E.g. "mail" or "uid"
or "userPrincipalName". The value of this field is case-sensitive
and must match the case of the attribute name returned by
the LDAP server in the user's entry. Distinguished names
can be used by specifying lower-case "dn". When this field
is set to "dn" then the LDAPIdentityProviderUserSearch's
Filter field cannot be blank, since the default value of
"dn={}" would not work.
minLength: 1
type: string
type: object
base:
description: Base is the dn (distinguished name) that should be
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
minLength: 1
type: string
filter:
description: Filter is the LDAP search filter which should be
applied when searching for users. The pattern "{}" must occur
in the filter at least once and will be dynamically replaced
by the username for which the search is being run. E.g. "mail={}"
or "&(objectClass=person)(uid={})". For more information about
LDAP filters, see https://ldap.com/ldap-filters. Note that the
dn (distinguished name) is not an attribute of an entry, so
"dn={}" cannot be used. Optional. When not specified, the default
will act as if the Filter were specified as the value from Attributes.Username
appended by "={}". When the Attributes.Username is set to "dn"
then the Filter must be explicitly specified, since the default
value of "dn={}" would not work.
type: string
type: object
required:
- host
type: object
status:
description: Status of the identity provider.
properties:
conditions:
description: Represents the observations of an identity provider's
current state.
items:
description: Condition status of a resource (mirrored from the metav1.Condition
type added in Kubernetes 1.19). In a future API version we can
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
phase:
default: Pending
description: Phase summarizes the overall status of the LDAPIdentityProvider.
enum:
- Pending
- Ready
- Error
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -59,11 +59,44 @@ spec:
additionalScopes:
description: AdditionalScopes are the scopes in addition to "openid"
that will be requested as part of the authorization request
flow with an OIDC identity provider. By default only the "openid"
scope will be requested.
flow with an OIDC identity provider. In the case of a Resource
Owner Password Credentials Grant flow, AdditionalScopes are
the scopes in addition to "openid" that will be requested as
part of the token request (see also the allowPasswordGrant field).
By default, only the "openid" scope will be requested.
items:
type: string
type: array
allowPasswordGrant:
description: AllowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see
https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to
authenticate to the OIDC provider using a username and password
without a web browser, in addition to the usual browser-based
OIDC Authorization Code Flow. The Resource Owner Password Credentials
Grant is not officially part of the OIDC specification, so it
may not be supported by your OIDC provider. If your OIDC provider
supports returning ID tokens from a Resource Owner Password
Credentials Grant token request, then you can choose to set
this field to true. This will allow end users to choose to present
their username and password to the kubectl CLI (using the Pinniped
plugin) to authenticate to the cluster, without using a web
browser to log in as is customary in OIDC Authorization Code
Flow. This may be convenient for users, especially for identities
from your OIDC provider which are not intended to represent
a human actor, such as service accounts performing actions in
a CI/CD environment. Even if your OIDC provider supports it,
you may wish to disable this behavior by setting this field
to false when you prefer to only allow users of this OIDCIdentityProvider
to log in via the browser-based OIDC Authorization Code Flow.
Using the Resource Owner Password Credentials Grant means that
the Pinniped CLI and Pinniped Supervisor will directly handle
your end users' passwords (similar to LDAPIdentityProvider),
and you will not be able to require multi-factor authentication
or use the other web-based login features of your OIDC provider
during Resource Owner Password Credentials Grant logins. AllowPasswordGrant
defaults to false.
type: boolean
type: object
claims:
description: Claims provides the names of token claims that will be

View File

@@ -220,7 +220,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped concierge configuration
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuer"]
==== CredentialIssuer
Describes the configuration status of a Pinniped credential issuer.
CredentialIssuer describes the configuration and status of the Pinniped Concierge credential issuer.
.Appears In:
****
@@ -232,7 +232,8 @@ Describes the configuration status of a Pinniped credential issuer.
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]__ | Status of the credential issuer.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerspec[$$CredentialIssuerSpec$$]__ | Spec describes the intended configuration of the Concierge.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$]__ | CredentialIssuerStatus describes the status of the Concierge.
|===
@@ -275,10 +276,27 @@ Describes the configuration status of a Pinniped credential issuer.
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerspec"]
==== CredentialIssuerSpec
CredentialIssuerSpec describes the intended configuration of the Concierge.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuer[$$CredentialIssuer$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`impersonationProxy`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]__ | ImpersonationProxy describes the intended configuration of the Concierge impersonation proxy.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerstatus"]
==== CredentialIssuerStatus
Status of a credential issuer.
CredentialIssuerStatus describes the status of the Concierge.
.Appears In:
****
@@ -333,6 +351,70 @@ Status of a credential issuer.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxymode"]
==== ImpersonationProxyMode (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyservicespec"]
==== ImpersonationProxyServiceSpec
ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyspec[$$ImpersonationProxySpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`type`* __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. This is not supported on all cloud providers.
| *`annotations`* __object (keys:string, values:string)__ | Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyservicetype"]
==== ImpersonationProxyServiceType (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyspec"]
==== ImpersonationProxySpec
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-credentialissuerspec[$$CredentialIssuerSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`mode`* __ImpersonationProxyMode__ | Mode configures whether the impersonation proxy should be started: - "disabled" explicitly disables the impersonation proxy. This is the default. - "enabled" explicitly enables the impersonation proxy. - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
| *`service`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-impersonationproxyservicespec[$$ImpersonationProxyServiceSpec$$]__ | Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
| *`externalEndpoint`* __string__ | ExternalEndpoint describes the HTTPS endpoint where the proxy will be exposed. If not set, the proxy will be served using the external name of the LoadBalancer service or the cluster service DNS name.
This field must be non-empty when spec.impersonationProxy.service.type is "None".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-concierge-config-v1alpha1-tokencredentialrequestapiinfo"]
==== TokenCredentialRequestAPIInfo
@@ -666,13 +748,166 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition"]
==== Condition
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"]
==== ActiveDirectoryIdentityProvider
Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API version we can switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"]
==== ActiveDirectoryIdentityProviderBind
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"]
==== ActiveDirectoryIdentityProviderGroupSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". Optional, when not specified it will be based on the result of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse). The default behavior searches your entire domain for groups. It may make sense to specify a subtree as a search base if you wish to exclude some groups for security reasons or to make searches faster.
| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})". This searches nested groups by default. Note that nested group search can be slow for some Active Directory servers. To disable it, you can set the filter to "(&(objectClass=group)(member={})"
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"]
==== ActiveDirectoryIdentityProviderGroupSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, this defaults to a custom field that looks like "sAMAccountName@domain", where domain is constructed from the domain components of the group DN.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"]
==== ActiveDirectoryIdentityProviderSpec
Spec for configuring an ActiveDirectory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host.
| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory.
| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"]
==== ActiveDirectoryIdentityProviderStatus
Status of an Active Directory identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"]
==== ActiveDirectoryIdentityProviderUserSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be based on the result of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse). The default behavior searches your entire domain for users. It may make sense to specify a subtree as a search base if you wish to exclude some users or to make searches faster.
| *`filter`* __string__ | Filter is the search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))' This means that the user is a person, is not a computer, the sAMAccountType is for a normal user account, and is not shown in advanced view only (which would likely mean its a system created service account with advanced permissions). Also, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"]
==== ActiveDirectoryIdentityProviderUserSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`username`* __string__ | Username specifies the name of the attribute in Active Directory entry whose value shall become the username of the user after a successful authentication. Optional, when empty this defaults to "userPrincipalName".
| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition"]
==== Condition
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$]
****
@@ -688,6 +923,169 @@ Condition status of a resource (mirrored from the metav1.Condition type added in
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-conditionstatus"]
==== ConditionStatus (string)
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$]
****
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovider"]
==== LDAPIdentityProvider
LDAPIdentityProvider describes the configuration of an upstream Lightweight Directory Access Protocol (LDAP) identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderlist[$$LDAPIdentityProviderList$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`.
| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]__ | Spec for configuring the identity provider.
| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$]__ | Status of the identity provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderbind"]
==== LDAPIdentityProviderBind
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an LDAP bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch"]
==== LDAPIdentityProviderGroupSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the LDAP provider. Also, when not specified, the values of Filter and Attributes are ignored.
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}".
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes[$$LDAPIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each LDAP entry which was found as the result of the group search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearchattributes"]
==== LDAPIdentityProviderGroupSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch[$$LDAPIdentityProviderGroupSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`groupName`* __string__ | GroupName specifies the name of the attribute in the LDAP entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name).
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec"]
==== LDAPIdentityProviderSpec
Spec for configuring an LDAP identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovider[$$LDAPIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`host`* __string__ | Host is the hostname of this LDAP identity provider, i.e., where to connect. For example: ldap.example.com:636.
| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host.
| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderbind[$$LDAPIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the LDAP server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch[$$LDAPIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in the LDAP provider.
| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovidergroupsearch[$$LDAPIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in the LDAP provider.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus"]
==== LDAPIdentityProviderStatus
Status of an LDAP identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityprovider[$$LDAPIdentityProvider$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`phase`* __LDAPIdentityProviderPhase__ | Phase summarizes the overall status of the LDAPIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch"]
==== LDAPIdentityProviderUserSearch
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
| *`filter`* __string__ | Filter is the LDAP search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work.
| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearchattributes[$$LDAPIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the LDAP entry which was found as the result of the user search.
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearchattributes"]
==== LDAPIdentityProviderUserSearchAttributes
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderusersearch[$$LDAPIdentityProviderUserSearch$$]
****
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`username`* __string__ | Username specifies the name of the attribute in the LDAP entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in the user search filter, although it can be different. E.g. "mail" or "uid" or "userPrincipalName". The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. Distinguished names can be used by specifying lower-case "dn". When this field is set to "dn" then the LDAPIdentityProviderUserSearch's Filter field cannot be blank, since the default value of "dn={}" would not work.
| *`uid`* __string__ | UID specifies the name of the attribute in the LDAP entry which whose value shall be used to uniquely identify the user within this LDAP provider after a successful authentication. E.g. "uidNumber" or "objectGUID". The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP server in the user's entry. Distinguished names can be used by specifying lower-case "dn".
|===
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-oidcauthorizationconfig"]
==== OIDCAuthorizationConfig
@@ -701,7 +1099,8 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
[cols="25a,75a", options="header"]
|===
| Field | Description
| *`additionalScopes`* __string array__ | AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization request flow with an OIDC identity provider. By default only the "openid" scope will be requested.
| *`additionalScopes`* __string array__ | AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization request flow with an OIDC identity provider. In the case of a Resource Owner Password Credentials Grant flow, AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the token request (see also the allowPasswordGrant field). By default, only the "openid" scope will be requested.
| *`allowPasswordGrant`* __boolean__ | AllowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. AllowPasswordGrant defaults to false.
|===
@@ -797,7 +1196,7 @@ Status of an OIDC identity provider.
|===
| Field | Description
| *`phase`* __OIDCIdentityProviderPhase__ | Phase summarizes the overall status of the OIDCIdentityProvider.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$]__ | Represents the observations of an identity provider's current state.
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state.
|===
@@ -808,6 +1207,8 @@ Status of an OIDC identity provider.
.Appears In:
****
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$]
- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$]
****

View File

@@ -3,17 +3,23 @@
package v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// StrategyType enumerates a type of "strategy" used to implement credential access on a cluster.
// +kubebuilder:validation:Enum=KubeClusterSigningCertificate;ImpersonationProxy
type StrategyType string
// FrontendType enumerates a type of "frontend" used to provide access to users of a cluster.
// +kubebuilder:validation:Enum=TokenCredentialRequestAPI;ImpersonationProxy
type FrontendType string
// StrategyStatus enumerates whether a strategy is working on a cluster.
// +kubebuilder:validation:Enum=Success;Error
type StrategyStatus string
// StrategyReason enumerates the detailed reason why a strategy is in a particular status.
// +kubebuilder:validation:Enum=Listening;Pending;Disabled;ErrorDuringSetup;CouldNotFetchKey;CouldNotGetClusterInfo;FetchedKey
type StrategyReason string
@@ -36,7 +42,91 @@ const (
FetchedKeyStrategyReason = StrategyReason("FetchedKey")
)
// Status of a credential issuer.
// CredentialIssuerSpec describes the intended configuration of the Concierge.
type CredentialIssuerSpec struct {
// ImpersonationProxy describes the intended configuration of the Concierge impersonation proxy.
ImpersonationProxy *ImpersonationProxySpec `json:"impersonationProxy"`
}
// ImpersonationProxyMode enumerates the configuration modes for the impersonation proxy.
//
// +kubebuilder:validation:Enum=auto;enabled;disabled
type ImpersonationProxyMode string
const (
// ImpersonationProxyModeDisabled explicitly disables the impersonation proxy.
ImpersonationProxyModeDisabled = ImpersonationProxyMode("disabled")
// ImpersonationProxyModeEnabled explicitly enables the impersonation proxy.
ImpersonationProxyModeEnabled = ImpersonationProxyMode("enabled")
// ImpersonationProxyModeAuto enables or disables the impersonation proxy based upon the cluster in which it is running.
ImpersonationProxyModeAuto = ImpersonationProxyMode("auto")
)
// ImpersonationProxyServiceType enumerates the types of service that can be provisioned for the impersonation proxy.
//
// +kubebuilder:validation:Enum=LoadBalancer;ClusterIP;None
type ImpersonationProxyServiceType string
const (
// ImpersonationProxyServiceTypeLoadBalancer provisions a service of type LoadBalancer.
ImpersonationProxyServiceTypeLoadBalancer = ImpersonationProxyServiceType("LoadBalancer")
// ImpersonationProxyServiceTypeClusterIP provisions a service of type ClusterIP.
ImpersonationProxyServiceTypeClusterIP = ImpersonationProxyServiceType("ClusterIP")
// ImpersonationProxyServiceTypeNone does not automatically provision any service.
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
)
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
type ImpersonationProxySpec struct {
// Mode configures whether the impersonation proxy should be started:
// - "disabled" explicitly disables the impersonation proxy. This is the default.
// - "enabled" explicitly enables the impersonation proxy.
// - "auto" enables or disables the impersonation proxy based upon the cluster in which it is running.
Mode ImpersonationProxyMode `json:"mode"`
// Service describes the configuration of the Service provisioned to expose the impersonation proxy to clients.
//
// +kubebuilder:default:={"type": "LoadBalancer"}
Service ImpersonationProxyServiceSpec `json:"service"`
// 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".
//
// +optional
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
}
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
type ImpersonationProxyServiceSpec struct {
// 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.
//
// +kubebuilder:default:="LoadBalancer"
Type ImpersonationProxyServiceType `json:"type,omitempty"`
// LoadBalancerIP specifies the IP address to set in the spec.loadBalancerIP field of the provisioned Service.
// This is not supported on all cloud providers.
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=255
// +optional
LoadBalancerIP string `json:"loadBalancerIP,omitempty"`
// Annotations specifies zero or more key/value pairs to set as annotations on the provisioned Service.
//
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}
// CredentialIssuerStatus describes the status of the Concierge.
type CredentialIssuerStatus struct {
// List of integration strategies that were attempted by Pinniped.
Strategies []CredentialIssuerStrategy `json:"strategies"`
@@ -47,7 +137,8 @@ type CredentialIssuerStatus struct {
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
}
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
// 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
@@ -59,7 +150,7 @@ type CredentialIssuerKubeConfigInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Status of an integration strategy that was attempted by Pinniped.
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
type CredentialIssuerStrategy struct {
// Type of integration attempted.
Type StrategyType `json:"type"`
@@ -81,6 +172,7 @@ type CredentialIssuerStrategy struct {
Frontend *CredentialIssuerFrontend `json:"frontend,omitempty"`
}
// CredentialIssuerFrontend describes how to connect using a particular integration strategy.
type CredentialIssuerFrontend struct {
// Type describes which frontend mechanism clients can use with a strategy.
Type FrontendType `json:"type"`
@@ -118,7 +210,7 @@ type ImpersonationProxyInfo struct {
CertificateAuthorityData string `json:"certificateAuthorityData"`
}
// Describes the configuration status of a Pinniped credential issuer.
// CredentialIssuer describes the configuration and status of the Pinniped Concierge credential issuer.
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -128,12 +220,18 @@ type CredentialIssuer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Status of the credential issuer.
// Spec describes the intended configuration of the Concierge.
//
// +optional
Spec CredentialIssuerSpec `json:"spec"`
// CredentialIssuerStatus describes the status of the Concierge.
//
// +optional
Status CredentialIssuerStatus `json:"status"`
}
// List of CredentialIssuer objects.
// CredentialIssuerList is a list of CredentialIssuer objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type CredentialIssuerList struct {
metav1.TypeMeta `json:",inline"`

View File

@@ -16,6 +16,7 @@ func (in *CredentialIssuer) DeepCopyInto(out *CredentialIssuer) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
@@ -113,6 +114,27 @@ func (in *CredentialIssuerList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerSpec) DeepCopyInto(out *CredentialIssuerSpec) {
*out = *in
if in.ImpersonationProxy != nil {
in, out := &in.ImpersonationProxy, &out.ImpersonationProxy
*out = new(ImpersonationProxySpec)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerSpec.
func (in *CredentialIssuerSpec) DeepCopy() *CredentialIssuerSpec {
if in == nil {
return nil
}
out := new(CredentialIssuerSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) {
*out = *in
@@ -179,6 +201,46 @@ func (in *ImpersonationProxyInfo) DeepCopy() *ImpersonationProxyInfo {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImpersonationProxyServiceSpec) DeepCopyInto(out *ImpersonationProxyServiceSpec) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxyServiceSpec.
func (in *ImpersonationProxyServiceSpec) DeepCopy() *ImpersonationProxyServiceSpec {
if in == nil {
return nil
}
out := new(ImpersonationProxyServiceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImpersonationProxySpec) DeepCopyInto(out *ImpersonationProxySpec) {
*out = *in
in.Service.DeepCopyInto(&out.Service)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxySpec.
func (in *ImpersonationProxySpec) DeepCopy() *ImpersonationProxySpec {
if in == nil {
return nil
}
out := new(ImpersonationProxySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TokenCredentialRequestAPIInfo) DeepCopyInto(out *TokenCredentialRequestAPIInfo) {
*out = *in

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -32,6 +32,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&OIDCIdentityProvider{},
&OIDCIdentityProviderList{},
&LDAPIdentityProvider{},
&LDAPIdentityProviderList{},
&ActiveDirectoryIdentityProvider{},
&ActiveDirectoryIdentityProviderList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@@ -0,0 +1,182 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ActiveDirectoryIdentityProviderPhase string
const (
// ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources.
ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending"
// ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state.
ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready"
// ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state.
ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error"
)
// Status of an Active Directory identity provider.
type ActiveDirectoryIdentityProviderStatus struct {
// Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type ActiveDirectoryIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type ActiveDirectoryIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in Active Directory entry whose value shall become the username
// of the user after a successful authentication.
// Optional, when empty this defaults to "userPrincipalName".
// +optional
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely
// identify the user within this ActiveDirectory provider after a successful authentication.
// Optional, when empty this defaults to "objectGUID".
// +optional
UID string `json:"uid,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, this defaults to a custom field that looks like "sAMAccountName@domain",
// where domain is constructed from the domain components of the group DN.
// +optional
GroupName string `json:"groupName,omitempty"`
}
type ActiveDirectoryIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for users.
// It may make sense to specify a subtree as a search base if you wish to exclude some users
// or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will be
// '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
// This means that the user is a person, is not a computer, the sAMAccountType is for a normal user account,
// and is not shown in advanced view only
// (which would likely mean its a system created service account with advanced permissions).
// Also, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as
// the result of the user search.
// +optional
Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type ActiveDirectoryIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com".
// Optional, when not specified it will be based on the result of a query for the defaultNamingContext
// (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
// The default behavior searches your entire domain for groups.
// It may make sense to specify a subtree as a search base if you wish to exclude some groups
// for security reasons or to make searches faster.
// +optional
Base string `json:"base,omitempty"`
// Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the filter were specified as
// "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
// This searches nested groups by default.
// Note that nested group search can be slow for some Active Directory servers. To disable it,
// you can set the filter to
// "(&(objectClass=group)(member={})"
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
// the result of the group search.
// +optional
Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an ActiveDirectory identity provider.
type ActiveDirectoryIdentityProviderSpec struct {
// Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in Active Directory.
UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.
GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type ActiveDirectoryIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec ActiveDirectoryIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"`
}
// List of ActiveDirectoryIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ActiveDirectoryIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ActiveDirectoryIdentityProvider `json:"items"`
}

View File

@@ -0,0 +1,171 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type LDAPIdentityProviderPhase string
const (
// LDAPPhasePending is the default phase for newly-created LDAPIdentityProvider resources.
LDAPPhasePending LDAPIdentityProviderPhase = "Pending"
// LDAPPhaseReady is the phase for an LDAPIdentityProvider resource in a healthy state.
LDAPPhaseReady LDAPIdentityProviderPhase = "Ready"
// LDAPPhaseError is the phase for an LDAPIdentityProvider in an unhealthy state.
LDAPPhaseError LDAPIdentityProviderPhase = "Error"
)
// Status of an LDAP identity provider.
type LDAPIdentityProviderStatus struct {
// Phase summarizes the overall status of the LDAPIdentityProvider.
// +kubebuilder:default=Pending
// +kubebuilder:validation:Enum=Pending;Ready;Error
Phase LDAPIdentityProviderPhase `json:"phase,omitempty"`
// Represents the observations of an identity provider's current state.
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
type LDAPIdentityProviderBind struct {
// SecretName contains the name of a namespace-local Secret object that provides the username and
// password for an LDAP bind user. This account will be used to perform LDAP searches. The Secret should be
// of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value
// should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
// The password must be non-empty.
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
}
type LDAPIdentityProviderUserSearchAttributes struct {
// Username specifies the name of the attribute in the LDAP entry whose value shall become the username
// of the user after a successful authentication. This would typically be the same attribute name used in
// the user search filter, although it can be different. E.g. "mail" or "uid" or "userPrincipalName".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn". When this field
// is set to "dn" then the LDAPIdentityProviderUserSearch's Filter field cannot be blank, since the default
// value of "dn={}" would not work.
// +kubebuilder:validation:MinLength=1
Username string `json:"username,omitempty"`
// UID specifies the name of the attribute in the LDAP entry which whose value shall be used to uniquely
// identify the user within this LDAP provider after a successful authentication. E.g. "uidNumber" or "objectGUID".
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. Distinguished names can be used by specifying lower-case "dn".
// +kubebuilder:validation:MinLength=1
UID string `json:"uid,omitempty"`
}
type LDAPIdentityProviderGroupSearchAttributes struct {
// GroupName specifies the name of the attribute in the LDAP entries whose value shall become a group name
// in the user's list of groups after a successful authentication.
// The value of this field is case-sensitive and must match the case of the attribute name returned by the LDAP
// server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn".
// Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name).
// +optional
GroupName string `json:"groupName,omitempty"`
}
type LDAPIdentityProviderUserSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for users.
// E.g. "ou=users,dc=example,dc=com".
// +kubebuilder:validation:MinLength=1
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for users. The pattern "{}" must occur
// in the filter at least once and will be dynamically replaced by the username for which the search is being run.
// E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as the value from
// Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be
// explicitly specified, since the default value of "dn={}" would not work.
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the user's information should be read from the LDAP entry which was found as
// the result of the user search.
// +optional
Attributes LDAPIdentityProviderUserSearchAttributes `json:"attributes,omitempty"`
}
type LDAPIdentityProviderGroupSearch struct {
// Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
// "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and
// authenticated users will not belong to any groups from the LDAP provider. Also, when not specified,
// the values of Filter and Attributes are ignored.
// +optional
Base string `json:"base,omitempty"`
// Filter is the LDAP search filter which should be applied when searching for groups for a user.
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
// dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or
// "&(objectClass=groupOfNames)(member={})". For more information about LDAP filters, see
// https://ldap.com/ldap-filters.
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
// Optional. When not specified, the default will act as if the Filter were specified as "member={}".
// +optional
Filter string `json:"filter,omitempty"`
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
// the result of the group search.
// +optional
Attributes LDAPIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"`
}
// Spec for configuring an LDAP identity provider.
type LDAPIdentityProviderSpec struct {
// Host is the hostname of this LDAP identity provider, i.e., where to connect. For example: ldap.example.com:636.
// +kubebuilder:validation:MinLength=1
Host string `json:"host"`
// TLS contains the connection settings for how to establish the connection to the Host.
TLS *TLSSpec `json:"tls,omitempty"`
// Bind contains the configuration for how to provide access credentials during an initial bind to the LDAP server
// to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.
Bind LDAPIdentityProviderBind `json:"bind,omitempty"`
// UserSearch contains the configuration for searching for a user by name in the LDAP provider.
UserSearch LDAPIdentityProviderUserSearch `json:"userSearch,omitempty"`
// GroupSearch contains the configuration for searching for a user's group membership in the LDAP provider.
GroupSearch LDAPIdentityProviderGroupSearch `json:"groupSearch,omitempty"`
}
// LDAPIdentityProvider describes the configuration of an upstream Lightweight Directory Access
// Protocol (LDAP) identity provider.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:subresource:status
type LDAPIdentityProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec for configuring the identity provider.
Spec LDAPIdentityProviderSpec `json:"spec"`
// Status of the identity provider.
Status LDAPIdentityProviderStatus `json:"status,omitempty"`
}
// List of LDAPIdentityProvider objects.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type LDAPIdentityProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []LDAPIdentityProvider `json:"items"`
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1

View File

@@ -1,4 +1,4 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
@@ -39,9 +39,31 @@ type OIDCIdentityProviderStatus struct {
// request parameters.
type OIDCAuthorizationConfig struct {
// AdditionalScopes are the scopes in addition to "openid" that will be requested as part of the authorization
// request flow with an OIDC identity provider. By default only the "openid" scope will be requested.
// request flow with an OIDC identity provider.
// In the case of a Resource Owner Password Credentials Grant flow, AdditionalScopes are the scopes
// in addition to "openid" that will be requested as part of the token request (see also the allowPasswordGrant field).
// By default, only the "openid" scope will be requested.
// +optional
AdditionalScopes []string `json:"additionalScopes,omitempty"`
// AllowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant
// (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a
// username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow.
// The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be
// supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password
// Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose
// to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the
// cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be
// convenient for users, especially for identities from your OIDC provider which are not intended to represent a human
// actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it,
// you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this
// OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password
// Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords
// (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other
// web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins.
// AllowPasswordGrant defaults to false.
// +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
}
// OIDCClaims provides a mapping from upstream claims into identities.

View File

@@ -11,6 +11,196 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider.
func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProvider)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind.
func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderBind)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch.
func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderGroupSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes.
func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ActiveDirectoryIdentityProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList.
func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) {
*out = *in
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSSpec)
**out = **in
}
out.Bind = in.Bind
out.UserSearch = in.UserSearch
out.GroupSearch = in.GroupSearch
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec.
func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus.
func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch.
func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderUserSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes.
func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes {
if in == nil {
return nil
}
out := new(ActiveDirectoryIdentityProviderUserSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Condition) DeepCopyInto(out *Condition) {
*out = *in
@@ -28,6 +218,196 @@ func (in *Condition) DeepCopy() *Condition {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProvider) DeepCopyInto(out *LDAPIdentityProvider) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProvider.
func (in *LDAPIdentityProvider) DeepCopy() *LDAPIdentityProvider {
if in == nil {
return nil
}
out := new(LDAPIdentityProvider)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LDAPIdentityProvider) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderBind) DeepCopyInto(out *LDAPIdentityProviderBind) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderBind.
func (in *LDAPIdentityProviderBind) DeepCopy() *LDAPIdentityProviderBind {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderBind)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderGroupSearch) DeepCopyInto(out *LDAPIdentityProviderGroupSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderGroupSearch.
func (in *LDAPIdentityProviderGroupSearch) DeepCopy() *LDAPIdentityProviderGroupSearch {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderGroupSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderGroupSearchAttributes) DeepCopyInto(out *LDAPIdentityProviderGroupSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderGroupSearchAttributes.
func (in *LDAPIdentityProviderGroupSearchAttributes) DeepCopy() *LDAPIdentityProviderGroupSearchAttributes {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderGroupSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderList) DeepCopyInto(out *LDAPIdentityProviderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]LDAPIdentityProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderList.
func (in *LDAPIdentityProviderList) DeepCopy() *LDAPIdentityProviderList {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LDAPIdentityProviderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderSpec) DeepCopyInto(out *LDAPIdentityProviderSpec) {
*out = *in
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSSpec)
**out = **in
}
out.Bind = in.Bind
out.UserSearch = in.UserSearch
out.GroupSearch = in.GroupSearch
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderSpec.
func (in *LDAPIdentityProviderSpec) DeepCopy() *LDAPIdentityProviderSpec {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderStatus) DeepCopyInto(out *LDAPIdentityProviderStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderStatus.
func (in *LDAPIdentityProviderStatus) DeepCopy() *LDAPIdentityProviderStatus {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderUserSearch) DeepCopyInto(out *LDAPIdentityProviderUserSearch) {
*out = *in
out.Attributes = in.Attributes
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderUserSearch.
func (in *LDAPIdentityProviderUserSearch) DeepCopy() *LDAPIdentityProviderUserSearch {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderUserSearch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LDAPIdentityProviderUserSearchAttributes) DeepCopyInto(out *LDAPIdentityProviderUserSearchAttributes) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPIdentityProviderUserSearchAttributes.
func (in *LDAPIdentityProviderUserSearchAttributes) DeepCopy() *LDAPIdentityProviderUserSearchAttributes {
if in == nil {
return nil
}
out := new(LDAPIdentityProviderUserSearchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OIDCAuthorizationConfig) DeepCopyInto(out *OIDCAuthorizationConfig) {
*out = *in

View File

@@ -0,0 +1,66 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// IDPType are the strings that can be returned by the Supervisor identity provider discovery endpoint
// as the "type" of each returned identity provider.
type IDPType string
// IDPFlow are the strings that can be returned by the Supervisor identity provider discovery endpoint
// in the array of allowed client "flows" for each returned identity provider.
type IDPFlow string
const (
IDPTypeOIDC IDPType = "oidc"
IDPTypeLDAP IDPType = "ldap"
IDPTypeActiveDirectory IDPType = "activedirectory"
IDPFlowCLIPassword IDPFlow = "cli_password"
IDPFlowBrowserAuthcode IDPFlow = "browser_authcode"
)
// Equals is a convenience function for comparing an IDPType to a string.
func (r IDPType) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPType to a string.
func (r IDPType) String() string {
return string(r)
}
// Equals is a convenience function for comparing an IDPFlow to a string.
func (r IDPFlow) Equals(s string) bool {
return string(r) == s
}
// String is a convenience function to convert an IDPFlow to a string.
func (r IDPFlow) String() string {
return string(r)
}
// OIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type OIDCDiscoveryResponse struct {
SupervisorDiscovery OIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// OIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type OIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// IDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type IDPDiscoveryResponse struct {
PinnipedIDPs []PinnipedIDP `json:"pinniped_identity_providers"`
}
// PinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type PinnipedIDP struct {
Name string `json:"name"`
Type IDPType `json:"type"`
Flows []IDPFlow `json:"flows,omitempty"`
}

View File

@@ -0,0 +1,25 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package oidc
// Constants related to the Supervisor FederationDomain's authorization and token endpoints.
const (
// AuthorizeUsernameHeaderName is the name of the HTTP header which can be used to transmit a username
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizeUsernameHeaderName = "Pinniped-Username"
// AuthorizePasswordHeaderName is the name of the HTTP header which can be used to transmit a password
// to the authorize endpoint when using a password flow, for example an OIDCIdentityProvider with a password grant
// or an LDAPIdentityProvider.
AuthorizePasswordHeaderName = "Pinniped-Password" //nolint:gosec // this is not a credential
// AuthorizeUpstreamIDPNameParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the name of the desired identity provider.
AuthorizeUpstreamIDPNameParamName = "pinniped_idp_name"
// AuthorizeUpstreamIDPTypeParamName is the name of the HTTP request parameter which can be used to help select which
// identity provider should be used for authentication by sending the type of the desired identity provider.
AuthorizeUpstreamIDPTypeParamName = "pinniped_idp_type"
)

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,9 @@ module go.pinniped.dev/generated/1.18/client
go 1.13
require (
github.com/go-openapi/spec v0.19.9
go.pinniped.dev/generated/1.18/apis v0.0.0-00010101000000-000000000000
k8s.io/apimachinery v0.18.2
k8s.io/client-go v0.18.2
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
)
replace go.pinniped.dev/generated/1.18/apis => ../apis

View File

@@ -11,11 +11,7 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -23,7 +19,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -32,17 +27,9 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc=
github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -90,9 +77,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -136,7 +120,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -158,9 +141,8 @@ golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -190,7 +172,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -0,0 +1,182 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1"
scheme "go.pinniped.dev/generated/1.18/client/supervisor/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface.
// A group's client should implement this interface.
type ActiveDirectoryIdentityProvidersGetter interface {
ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface
}
// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources.
type ActiveDirectoryIdentityProviderInterface interface {
Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error)
ActiveDirectoryIdentityProviderExpansion
}
// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface
type activeDirectoryIdentityProviders struct {
client rest.Interface
ns string
}
// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders
func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders {
return &activeDirectoryIdentityProviders{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any.
func (c *activeDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors.
func (c *activeDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.ActiveDirectoryIdentityProviderList{}
err = c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders.
func (c *activeDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *activeDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Post().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Body(activeDirectoryIdentityProvider).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *activeDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(activeDirectoryIdentityProvider.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(activeDirectoryIdentityProvider).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *activeDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(activeDirectoryIdentityProvider.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(activeDirectoryIdentityProvider).
Do(ctx).
Into(result)
return
}
// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs.
func (c *activeDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *activeDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched activeDirectoryIdentityProvider.
func (c *activeDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
result = &v1alpha1.ActiveDirectoryIdentityProvider{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("activedirectoryidentityproviders").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -0,0 +1,129 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface
type FakeActiveDirectoryIdentityProviders struct {
Fake *FakeIDPV1alpha1
ns string
}
var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"}
var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"}
// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors.
func (c *FakeActiveDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta}
for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders.
func (c *FakeActiveDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts))
}
// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any.
func (c *FakeActiveDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}
// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs.
func (c *FakeActiveDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{})
return err
}
// Patch applies the patch and returns the patched activeDirectoryIdentityProvider.
func (c *FakeActiveDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err
}

View File

@@ -15,6 +15,14 @@ type FakeIDPV1alpha1 struct {
*testing.Fake
}
func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface {
return &FakeActiveDirectoryIdentityProviders{c, namespace}
}
func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface {
return &FakeLDAPIdentityProviders{c, namespace}
}
func (c *FakeIDPV1alpha1) OIDCIdentityProviders(namespace string) v1alpha1.OIDCIdentityProviderInterface {
return &FakeOIDCIdentityProviders{c, namespace}
}

View File

@@ -0,0 +1,129 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeLDAPIdentityProviders implements LDAPIdentityProviderInterface
type FakeLDAPIdentityProviders struct {
Fake *FakeIDPV1alpha1
ns string
}
var ldapidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "ldapidentityproviders"}
var ldapidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "LDAPIdentityProvider"}
// Get takes name of the lDAPIdentityProvider, and returns the corresponding lDAPIdentityProvider object, and an error if there is any.
func (c *FakeLDAPIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(ldapidentityprovidersResource, c.ns, name), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// List takes label and field selectors, and returns the list of LDAPIdentityProviders that match those selectors.
func (c *FakeLDAPIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.LDAPIdentityProviderList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(ldapidentityprovidersResource, ldapidentityprovidersKind, c.ns, opts), &v1alpha1.LDAPIdentityProviderList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.LDAPIdentityProviderList{ListMeta: obj.(*v1alpha1.LDAPIdentityProviderList).ListMeta}
for _, item := range obj.(*v1alpha1.LDAPIdentityProviderList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested lDAPIdentityProviders.
func (c *FakeLDAPIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(ldapidentityprovidersResource, c.ns, opts))
}
// Create takes the representation of a lDAPIdentityProvider and creates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *FakeLDAPIdentityProviders) Create(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(ldapidentityprovidersResource, c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// Update takes the representation of a lDAPIdentityProvider and updates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *FakeLDAPIdentityProviders) Update(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(ldapidentityprovidersResource, c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeLDAPIdentityProviders) UpdateStatus(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.LDAPIdentityProvider, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(ldapidentityprovidersResource, "status", c.ns, lDAPIdentityProvider), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}
// Delete takes name of the lDAPIdentityProvider and deletes it. Returns an error if one occurs.
func (c *FakeLDAPIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(ldapidentityprovidersResource, c.ns, name), &v1alpha1.LDAPIdentityProvider{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeLDAPIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(ldapidentityprovidersResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.LDAPIdentityProviderList{})
return err
}
// Patch applies the patch and returns the patched lDAPIdentityProvider.
func (c *FakeLDAPIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(ldapidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.LDAPIdentityProvider{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.LDAPIdentityProvider), err
}

View File

@@ -5,4 +5,8 @@
package v1alpha1
type ActiveDirectoryIdentityProviderExpansion interface{}
type LDAPIdentityProviderExpansion interface{}
type OIDCIdentityProviderExpansion interface{}

View File

@@ -13,6 +13,8 @@ import (
type IDPV1alpha1Interface interface {
RESTClient() rest.Interface
ActiveDirectoryIdentityProvidersGetter
LDAPIdentityProvidersGetter
OIDCIdentityProvidersGetter
}
@@ -21,6 +23,14 @@ type IDPV1alpha1Client struct {
restClient rest.Interface
}
func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface {
return newActiveDirectoryIdentityProviders(c, namespace)
}
func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface {
return newLDAPIdentityProviders(c, namespace)
}
func (c *IDPV1alpha1Client) OIDCIdentityProviders(namespace string) OIDCIdentityProviderInterface {
return newOIDCIdentityProviders(c, namespace)
}

View File

@@ -0,0 +1,182 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1"
scheme "go.pinniped.dev/generated/1.18/client/supervisor/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// LDAPIdentityProvidersGetter has a method to return a LDAPIdentityProviderInterface.
// A group's client should implement this interface.
type LDAPIdentityProvidersGetter interface {
LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface
}
// LDAPIdentityProviderInterface has methods to work with LDAPIdentityProvider resources.
type LDAPIdentityProviderInterface interface {
Create(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.CreateOptions) (*v1alpha1.LDAPIdentityProvider, error)
Update(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.LDAPIdentityProvider, error)
UpdateStatus(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.LDAPIdentityProvider, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.LDAPIdentityProvider, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.LDAPIdentityProviderList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error)
LDAPIdentityProviderExpansion
}
// lDAPIdentityProviders implements LDAPIdentityProviderInterface
type lDAPIdentityProviders struct {
client rest.Interface
ns string
}
// newLDAPIdentityProviders returns a LDAPIdentityProviders
func newLDAPIdentityProviders(c *IDPV1alpha1Client, namespace string) *lDAPIdentityProviders {
return &lDAPIdentityProviders{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the lDAPIdentityProvider, and returns the corresponding lDAPIdentityProvider object, and an error if there is any.
func (c *lDAPIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of LDAPIdentityProviders that match those selectors.
func (c *lDAPIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.LDAPIdentityProviderList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.LDAPIdentityProviderList{}
err = c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested lDAPIdentityProviders.
func (c *lDAPIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a lDAPIdentityProvider and creates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *lDAPIdentityProviders) Create(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Post().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&opts, scheme.ParameterCodec).
Body(lDAPIdentityProvider).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a lDAPIdentityProvider and updates it. Returns the server's representation of the lDAPIdentityProvider, and an error, if there is any.
func (c *lDAPIdentityProviders) Update(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(lDAPIdentityProvider.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(lDAPIdentityProvider).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *lDAPIdentityProviders) UpdateStatus(ctx context.Context, lDAPIdentityProvider *v1alpha1.LDAPIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Put().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(lDAPIdentityProvider.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(lDAPIdentityProvider).
Do(ctx).
Into(result)
return
}
// Delete takes name of the lDAPIdentityProvider and deletes it. Returns an error if one occurs.
func (c *lDAPIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *lDAPIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("ldapidentityproviders").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched lDAPIdentityProvider.
func (c *lDAPIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.LDAPIdentityProvider, err error) {
result = &v1alpha1.LDAPIdentityProvider{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("ldapidentityproviders").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -45,6 +45,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil
// Group=idp.supervisor.pinniped.dev, Version=v1alpha1
case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil
case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil
case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().OIDCIdentityProviders().Informer()}, nil

View File

@@ -0,0 +1,77 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
idpv1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1"
versioned "go.pinniped.dev/generated/1.18/client/supervisor/clientset/versioned"
internalinterfaces "go.pinniped.dev/generated/1.18/client/supervisor/informers/externalversions/internalinterfaces"
v1alpha1 "go.pinniped.dev/generated/1.18/client/supervisor/listers/idp/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for
// ActiveDirectoryIdentityProviders.
type ActiveDirectoryIdentityProviderInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.ActiveDirectoryIdentityProviderLister
}
type activeDirectoryIdentityProviderInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(context.TODO(), options)
},
},
&idpv1alpha1.ActiveDirectoryIdentityProvider{},
resyncPeriod,
indexers,
)
}
func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer)
}
func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister {
return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer())
}

Some files were not shown because too many files have changed in this diff Show More