mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-25 23:22:16 +00:00
Compare commits
755 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca6a60b534 | ||
|
|
99755624e8 | ||
|
|
bc5eb3cf57 | ||
|
|
c86a615713 | ||
|
|
c494add2ce | ||
|
|
f94b1e70fc | ||
|
|
42ed11a5cb | ||
|
|
a7c6c43112 | ||
|
|
17d6def081 | ||
|
|
73e7aeca6e | ||
|
|
305f3f6abe | ||
|
|
e4d6a72087 | ||
|
|
85e5970d6e | ||
|
|
424e7406af | ||
|
|
3e148b629d | ||
|
|
545df755b8 | ||
|
|
e6cb439d9c | ||
|
|
879b840ee2 | ||
|
|
773fad9701 | ||
|
|
fbc3334e8c | ||
|
|
0baae51425 | ||
|
|
ad7df9f7d1 | ||
|
|
460fbbacc7 | ||
|
|
d67238d46f | ||
|
|
5ec1ee086d | ||
|
|
c0f1e408da | ||
|
|
0a63dd104d | ||
|
|
070819754f | ||
|
|
56d7dee25d | ||
|
|
9d21bcacb6 | ||
|
|
d0781c42dc | ||
|
|
1f2d2bff71 | ||
|
|
3bdb380a1a | ||
|
|
1ac2215724 | ||
|
|
9d92f21638 | ||
|
|
9838a7cb6d | ||
|
|
51b1dbd2af | ||
|
|
9a8df262d9 | ||
|
|
9c2df74e54 | ||
|
|
581f671643 | ||
|
|
b99da0c805 | ||
|
|
57a07a498f | ||
|
|
136bc7ac09 | ||
|
|
a1efcefdce | ||
|
|
5dbf05c31d | ||
|
|
af9612e98e | ||
|
|
b31a893caf | ||
|
|
c8bc192e0b | ||
|
|
def2b35e6e | ||
|
|
5fe94c4e2b | ||
|
|
1d8310ed44 | ||
|
|
c79f8c89d7 | ||
|
|
7c0c3211d1 | ||
|
|
0ef98f0558 | ||
|
|
94bee9e882 | ||
|
|
da135d9958 | ||
|
|
206a16f9e3 | ||
|
|
e048859afd | ||
|
|
8c081c50d4 | ||
|
|
59fef0c1b2 | ||
|
|
23d8a279c4 | ||
|
|
f50ab87b53 | ||
|
|
df9a06ddfe | ||
|
|
55aaf33d94 | ||
|
|
8ea339139e | ||
|
|
e950e7e001 | ||
|
|
68339f3acb | ||
|
|
f4660f0250 | ||
|
|
bf3cda54ba | ||
|
|
1b4194373b | ||
|
|
241093bb96 | ||
|
|
722f00e485 | ||
|
|
67c328f4d0 | ||
|
|
146e61ed03 | ||
|
|
6718a32fe4 | ||
|
|
7387f675e2 | ||
|
|
f0a43e0402 | ||
|
|
c6b0820438 | ||
|
|
f86c46e160 | ||
|
|
eed0c9d5b0 | ||
|
|
e38a27d93d | ||
|
|
b0904c2e99 | ||
|
|
bec5fe85cc | ||
|
|
5bc4e678bf | ||
|
|
90e7343fb5 | ||
|
|
5c0d67dc50 | ||
|
|
b6512bcbb6 | ||
|
|
097e6d5340 | ||
|
|
a45a537cdb | ||
|
|
0467e5c1d5 | ||
|
|
5c1fa6d52c | ||
|
|
337459feb0 | ||
|
|
590e2d18f7 | ||
|
|
ef36b454ba | ||
|
|
4465810ff8 | ||
|
|
d301bc60b7 | ||
|
|
6307a3212b | ||
|
|
92a082b0f7 | ||
|
|
15627e7803 | ||
|
|
a70ce9cef7 | ||
|
|
eab6f0d713 | ||
|
|
cc96f85ec7 | ||
|
|
6557197bae | ||
|
|
ed351938d4 | ||
|
|
718cf234b8 | ||
|
|
159b2d50eb | ||
|
|
bc8aebeffe | ||
|
|
135eab037e | ||
|
|
714aa59a34 | ||
|
|
33fe2bcff4 | ||
|
|
665b921d63 | ||
|
|
b99634764f | ||
|
|
4a8cd180f8 | ||
|
|
6c7d3e62dd | ||
|
|
c4b5476088 | ||
|
|
61835e9f08 | ||
|
|
d49b011d65 | ||
|
|
f881bbb137 | ||
|
|
f55d56bf4a | ||
|
|
ffc49d96b3 | ||
|
|
8a40dda3ab | ||
|
|
ab0682917a | ||
|
|
ed15927d90 | ||
|
|
e43cf81c38 | ||
|
|
eb08a9f91f | ||
|
|
9423ff5e48 | ||
|
|
df580fcb39 | ||
|
|
ca58911cc2 | ||
|
|
6afc48849a | ||
|
|
5569b114ba | ||
|
|
c8bfe780c7 | ||
|
|
b79a2ccf7c | ||
|
|
27d0c58319 | ||
|
|
ffadca7f68 | ||
|
|
62c086a725 | ||
|
|
99781443b0 | ||
|
|
f498cb3918 | ||
|
|
e8482ab9e9 | ||
|
|
868ff9ed2b | ||
|
|
42acf8dcce | ||
|
|
1c7e7048a8 | ||
|
|
73e4d3144b | ||
|
|
1a633adde6 | ||
|
|
09bd51f481 | ||
|
|
084c3114f4 | ||
|
|
47639340ec | ||
|
|
fd14a5794e | ||
|
|
a4447fa606 | ||
|
|
f18d7310a8 | ||
|
|
28251f8b92 | ||
|
|
50b54580de | ||
|
|
d88883328a | ||
|
|
ca6687d428 | ||
|
|
848d83c496 | ||
|
|
5bd73fc10d | ||
|
|
40e548ebf0 | ||
|
|
64b0e69430 | ||
|
|
daec673b81 | ||
|
|
01d6bdb497 | ||
|
|
216fce70aa | ||
|
|
5939ce8cc6 | ||
|
|
9471ed2d09 | ||
|
|
0d31e955ae | ||
|
|
5697bb2915 | ||
|
|
ca7b27de3f | ||
|
|
867468ee66 | ||
|
|
4b4a4ad592 | ||
|
|
b341e52214 | ||
|
|
1e8e7b948e | ||
|
|
1bc13e94f7 | ||
|
|
9db87132b1 | ||
|
|
9992855cb8 | ||
|
|
23dce42a94 | ||
|
|
edf92303ae | ||
|
|
719cd75f64 | ||
|
|
ceb9973657 | ||
|
|
cf82cf996e | ||
|
|
5c702738cf | ||
|
|
485b2271f0 | ||
|
|
dce9409ccc | ||
|
|
d5ce48bd4b | ||
|
|
492dfa84d8 | ||
|
|
e4fddc3596 | ||
|
|
ad9d9ce1a5 | ||
|
|
904a60f04a | ||
|
|
bf3b4bfca7 | ||
|
|
560ee45b50 | ||
|
|
d2794114f4 | ||
|
|
e303a45dd1 | ||
|
|
c47bc74ad0 | ||
|
|
a728822993 | ||
|
|
5cd4d47f9e | ||
|
|
2832e7c45e | ||
|
|
04bb45947d | ||
|
|
f2c9b67854 | ||
|
|
e05ae08b77 | ||
|
|
1ab1fd4c50 | ||
|
|
d17dd65d0f | ||
|
|
a832bb641b | ||
|
|
18da164130 | ||
|
|
07b1a144b3 | ||
|
|
4c3f304ba5 | ||
|
|
c7445def21 | ||
|
|
d23f6690af | ||
|
|
0a8264c9c8 | ||
|
|
8c7cda84e1 | ||
|
|
6767a07a8d | ||
|
|
6908c2ab65 | ||
|
|
80b65619bf | ||
|
|
2aa87dd069 | ||
|
|
bb99d269eb | ||
|
|
84a1f2a771 | ||
|
|
e67838932d | ||
|
|
50e4d6db6c | ||
|
|
bcf070cb73 | ||
|
|
4ce96634c6 | ||
|
|
c356754aaa | ||
|
|
75a130bafd | ||
|
|
1d6e51d14a | ||
|
|
da9432b5b2 | ||
|
|
d4971ef2da | ||
|
|
bdb7f80571 | ||
|
|
c7299f4daf | ||
|
|
659224a207 | ||
|
|
2c5214724b | ||
|
|
b2e3f84156 | ||
|
|
a58649faa6 | ||
|
|
a4883507b5 | ||
|
|
461e272d79 | ||
|
|
981004eec4 | ||
|
|
0332362598 | ||
|
|
f519b271d2 | ||
|
|
be7a4f781f | ||
|
|
0e3c815e9b | ||
|
|
3b4147f90e | ||
|
|
3b10cc3097 | ||
|
|
d8ec87d0e1 | ||
|
|
cdd38dd55e | ||
|
|
236a7cf3fb | ||
|
|
3e74b38a95 | ||
|
|
a05acadf80 | ||
|
|
c5d1f380d2 | ||
|
|
9883b4e236 | ||
|
|
348187d2f4 | ||
|
|
86ee66d21d | ||
|
|
2198b4820a | ||
|
|
4b7b9e4362 | ||
|
|
70f2bbf4f8 | ||
|
|
7a3efb9981 | ||
|
|
e1954b1df9 | ||
|
|
37c2ce53d7 | ||
|
|
9d3773e58a | ||
|
|
aa651973fc | ||
|
|
745852ef2e | ||
|
|
ca5ad85bbd | ||
|
|
8296093beb | ||
|
|
6d79fe5f4c | ||
|
|
ef6369d71e | ||
|
|
7616799adb | ||
|
|
dea3513125 | ||
|
|
5f4645d505 | ||
|
|
c439cc03a2 | ||
|
|
2603bbfcd6 | ||
|
|
dc1d563549 | ||
|
|
416a66f68a | ||
|
|
8f2da915aa | ||
|
|
aad74158ba | ||
|
|
98dde187bb | ||
|
|
ab71450c69 | ||
|
|
a4789e2b2c | ||
|
|
1c2829a326 | ||
|
|
9be8cd40d2 | ||
|
|
90a3538806 | ||
|
|
b68e7f3e9e | ||
|
|
4f15fc2123 | ||
|
|
2bc6c15d25 | ||
|
|
a740fb34c5 | ||
|
|
be1416b7b5 | ||
|
|
aad8dc50e7 | ||
|
|
47f6de58c3 | ||
|
|
61c630caf0 | ||
|
|
2985d55edf | ||
|
|
4f794571a2 | ||
|
|
d5ae3da893 | ||
|
|
80d5f42b57 | ||
|
|
d5aa682cbc | ||
|
|
b61557d3c3 | ||
|
|
d4e2622ea8 | ||
|
|
88a97033fb | ||
|
|
c4f9869e7c | ||
|
|
c455a17abe | ||
|
|
9a632134ae | ||
|
|
1b540181a7 | ||
|
|
1f8aa6c262 | ||
|
|
46bea27cb7 | ||
|
|
98bd12241d | ||
|
|
c3410c4b14 | ||
|
|
1e9f9181a1 | ||
|
|
07e9c5bd93 | ||
|
|
e10d21d678 | ||
|
|
e3d9eb7d82 | ||
|
|
97f6e8a07b | ||
|
|
865ef8d447 | ||
|
|
0a342a803c | ||
|
|
120b35a617 | ||
|
|
3f92a546df | ||
|
|
132e39c8fd | ||
|
|
634654578f | ||
|
|
18f95d3d1e | ||
|
|
b38723ece2 | ||
|
|
bf1366412a | ||
|
|
a6f7e05d3d | ||
|
|
660b155eaa | ||
|
|
29e939db7f | ||
|
|
3c2d921300 | ||
|
|
d1e5a9aff3 | ||
|
|
54d4879c69 | ||
|
|
78aa45a970 | ||
|
|
3c33c59aa9 | ||
|
|
b9b4d31c6b | ||
|
|
0501159ac0 | ||
|
|
779b084b53 | ||
|
|
f90f2334ba | ||
|
|
a8c35c6f7e | ||
|
|
ced08aeaf7 | ||
|
|
9c5bc763ac | ||
|
|
dd0039e94c | ||
|
|
9d836c789f | ||
|
|
ef291bb790 | ||
|
|
d4e3cf51b7 | ||
|
|
247123965e | ||
|
|
097a1ac3d3 | ||
|
|
ec532f622f | ||
|
|
d73acd6896 | ||
|
|
0c4e3aa5f1 | ||
|
|
cbd892a4b2 | ||
|
|
e46acbee43 | ||
|
|
c1995c1eea | ||
|
|
423e2932aa | ||
|
|
c0ac0fa183 | ||
|
|
521dec2e04 | ||
|
|
0a47aa59fc | ||
|
|
3a21c9a35b | ||
|
|
6ee1e35329 | ||
|
|
a077972ce5 | ||
|
|
9d89a8dea4 | ||
|
|
d965b65b0a | ||
|
|
bc1593e833 | ||
|
|
de5026b90f | ||
|
|
13f0b5e782 | ||
|
|
6310dde4f5 | ||
|
|
bbf4412ff3 | ||
|
|
1409f236da | ||
|
|
0cca3a12e6 | ||
|
|
5852a9e0ab | ||
|
|
8c4c99bbaf | ||
|
|
69e3627946 | ||
|
|
a27a355071 | ||
|
|
826d8236d9 | ||
|
|
776e436e35 | ||
|
|
af7d3092a5 | ||
|
|
62c597eb3b | ||
|
|
78cb86215b | ||
|
|
8a7f7b8842 | ||
|
|
172db05d8d | ||
|
|
113bebfb4d | ||
|
|
af7a1a1f58 | ||
|
|
0ab6311cf5 | ||
|
|
24069b56dc | ||
|
|
87b7ea14d5 | ||
|
|
7513092432 | ||
|
|
192553aed9 | ||
|
|
d44882fddc | ||
|
|
cede6403e1 | ||
|
|
e25ecea684 | ||
|
|
ac9887afdc | ||
|
|
58c5146592 | ||
|
|
5e06c6d5ad | ||
|
|
ca6c29e463 | ||
|
|
1ac8691199 | ||
|
|
4bb596e2cd | ||
|
|
78a7d4deea | ||
|
|
bed9a74b58 | ||
|
|
5af01bba4e | ||
|
|
9fe9753cbc | ||
|
|
cef5745d2d | ||
|
|
cd1e4bacf8 | ||
|
|
7de8f82295 | ||
|
|
62887a9cc8 | ||
|
|
c0e7a6ecbf | ||
|
|
465a0c3d80 | ||
|
|
4b4cc93ae7 | ||
|
|
4a89a9fa16 | ||
|
|
eb7a9f89e2 | ||
|
|
162041c794 | ||
|
|
0e7ef1637d | ||
|
|
91d5159743 | ||
|
|
efb53d3190 | ||
|
|
c97bb58e3c | ||
|
|
3cecb62705 | ||
|
|
52db01d8ef | ||
|
|
1d500ded67 | ||
|
|
edc5f3fc15 | ||
|
|
54fb03153a | ||
|
|
06d456fc87 | ||
|
|
5573c629b5 | ||
|
|
2cecc17ef0 | ||
|
|
c52ed93bf8 | ||
|
|
84498d5a55 | ||
|
|
8faf3b0e26 | ||
|
|
a7bd494ec3 | ||
|
|
b6f0dc3ba7 | ||
|
|
e2bdab9e2d | ||
|
|
28210ab14d | ||
|
|
593d55ec09 | ||
|
|
5ad7e9a8ca | ||
|
|
7f70fcf679 | ||
|
|
f653942065 | ||
|
|
d4611b829d | ||
|
|
b2656b9cb1 | ||
|
|
2eb82cc1d7 | ||
|
|
0a21cb6d08 | ||
|
|
519aece8a5 | ||
|
|
e6c78facfc | ||
|
|
01ab7758d8 | ||
|
|
957892b677 | ||
|
|
c701a4a344 | ||
|
|
92bf826ec5 | ||
|
|
446384a7f5 | ||
|
|
6d82a11645 | ||
|
|
bd5cabf0ff | ||
|
|
51742366fe | ||
|
|
5341322071 | ||
|
|
23ed2856ce | ||
|
|
84041e0c55 | ||
|
|
4b75ced52c | ||
|
|
61bb01b31d | ||
|
|
64f41d0d0c | ||
|
|
e42e3ca421 | ||
|
|
b89e6d9d93 | ||
|
|
c771328bb1 | ||
|
|
52925a2a46 | ||
|
|
013030041a | ||
|
|
be973bc87e | ||
|
|
617f57e1c9 | ||
|
|
0aacedf943 | ||
|
|
b05e8a5e24 | ||
|
|
8e169f9702 | ||
|
|
32063db46e | ||
|
|
31d67a1af3 | ||
|
|
a9f2f672c7 | ||
|
|
76709892bc | ||
|
|
a38fb16295 | ||
|
|
e334ad6f7e | ||
|
|
40dcc8a7f1 | ||
|
|
97a374c00b | ||
|
|
fe9364c58b | ||
|
|
e9fb4242d5 | ||
|
|
48e44e13c6 | ||
|
|
5e2f98af65 | ||
|
|
3521e129cd | ||
|
|
0b408f4fc0 | ||
|
|
022fdb9cfd | ||
|
|
e4f43683d4 | ||
|
|
514f9964c1 | ||
|
|
2c4927debe | ||
|
|
0f23931fe4 | ||
|
|
98ee9f0979 | ||
|
|
048f05d39c | ||
|
|
b71e5964aa | ||
|
|
9d792352bf | ||
|
|
86c791b8a6 | ||
|
|
3160b5bad1 | ||
|
|
610f886fd8 | ||
|
|
770f8af62b | ||
|
|
6ef9cf273e | ||
|
|
793d1c6a5d | ||
|
|
8f6a12eae4 | ||
|
|
5c0425fb71 | ||
|
|
96098841dd | ||
|
|
b7627208ea | ||
|
|
32aa015d5b | ||
|
|
7af75dfe3c | ||
|
|
1a53b4daea | ||
|
|
5385fb38db | ||
|
|
be11966a64 | ||
|
|
fee737b267 | ||
|
|
64f1bff13f | ||
|
|
96fcfe4d53 | ||
|
|
ce567c481b | ||
|
|
33311714e5 | ||
|
|
1bab4ccdb7 | ||
|
|
d91ebc1049 | ||
|
|
4e48388693 | ||
|
|
8df2d3cc58 | ||
|
|
f6cbc879ef | ||
|
|
46c773aba6 | ||
|
|
cd91edf26c | ||
|
|
8fd55a1d81 | ||
|
|
3908097c54 | ||
|
|
12f18cbed8 | ||
|
|
05a1187e2e | ||
|
|
5effb1a89b | ||
|
|
b14e86bb91 | ||
|
|
c3445a747d | ||
|
|
a5c481cf61 | ||
|
|
fd1936c45f | ||
|
|
fbeb45a1a0 | ||
|
|
23bd3e7cc9 | ||
|
|
7cda8f4123 | ||
|
|
a42e3edf56 | ||
|
|
76933f69b9 | ||
|
|
5c9d26baeb | ||
|
|
9248db971a | ||
|
|
2dcc149fee | ||
|
|
38230fc518 | ||
|
|
8edecffcc0 | ||
|
|
ca05969f8d | ||
|
|
1b504b6fbd | ||
|
|
dfd3d5075d | ||
|
|
c51722a121 | ||
|
|
23ec91dee0 | ||
|
|
ccba159639 | ||
|
|
20cfa0a207 | ||
|
|
835b8a5333 | ||
|
|
decd40bc26 | ||
|
|
2891da25f5 | ||
|
|
c54933bf33 | ||
|
|
820c565d21 | ||
|
|
e5e8c13f23 | ||
|
|
b81206c15d | ||
|
|
31c144261f | ||
|
|
4d0da0a5b2 | ||
|
|
8c96616b51 | ||
|
|
c7b49d9b93 | ||
|
|
7f0d04dba6 | ||
|
|
1707995378 | ||
|
|
f24f82b25b | ||
|
|
391c38057d | ||
|
|
e2e9819c58 | ||
|
|
dc61d132cf | ||
|
|
959f18b67b | ||
|
|
ee75a63057 | ||
|
|
bd035a180e | ||
|
|
8df9033bfc | ||
|
|
3e57716f0e | ||
|
|
c78db66665 | ||
|
|
8dec84b3b2 | ||
|
|
fcf707b1ce | ||
|
|
563ac77b2f | ||
|
|
e091cd6180 | ||
|
|
a71f1f88d9 | ||
|
|
bb670249cf | ||
|
|
f632698568 | ||
|
|
0c81cdf309 | ||
|
|
fbb5296f68 | ||
|
|
14c353993b | ||
|
|
2cdd7c9577 | ||
|
|
4512eeca9a | ||
|
|
2c27db0c85 | ||
|
|
ed3217459d | ||
|
|
411bc5cf1c | ||
|
|
82b39190ba | ||
|
|
fd54caeb55 | ||
|
|
c4f221d778 | ||
|
|
057304e9aa | ||
|
|
63b5f921e1 | ||
|
|
eb87739060 | ||
|
|
122f819ed9 | ||
|
|
850b4f8510 | ||
|
|
6bb4e89fe2 | ||
|
|
743cb2d250 | ||
|
|
01393aff7e | ||
|
|
89b7007694 | ||
|
|
947f8e2ed4 | ||
|
|
6c329ba56f | ||
|
|
39912060f7 | ||
|
|
c142c52258 | ||
|
|
741ccfd2ce | ||
|
|
183c771d4e | ||
|
|
3d7eb55fc2 | ||
|
|
5004925444 | ||
|
|
10c3e482b4 | ||
|
|
8d8e1f3abd | ||
|
|
f8ce2af08c | ||
|
|
52b0cf43ca | ||
|
|
f6c2d40141 | ||
|
|
38c281331a | ||
|
|
26686d6b94 | ||
|
|
8648cdf8e4 | ||
|
|
7e5ce4b4f3 | ||
|
|
6c65fd910e | ||
|
|
95fdfba06d | ||
|
|
0f613d1823 | ||
|
|
6db9c79fe0 | ||
|
|
ab227a7c71 | ||
|
|
314ec48f46 | ||
|
|
67cd5e70c2 | ||
|
|
dbbaf9b969 | ||
|
|
1ac36cfcf8 | ||
|
|
95dd5aabc2 | ||
|
|
8a755676fa | ||
|
|
c3dccbb23d | ||
|
|
914861c5da | ||
|
|
9a87a7f14f | ||
|
|
533c41f143 | ||
|
|
4f3c081401 | ||
|
|
d4b20b3899 | ||
|
|
86e360dc14 | ||
|
|
c9d54de91a | ||
|
|
d30d76b7ac | ||
|
|
5fa2992bc5 | ||
|
|
020e04baf8 | ||
|
|
1bdb491376 | ||
|
|
b6b11a6d0c | ||
|
|
a78c677ca1 | ||
|
|
d0048595da | ||
|
|
46178e91ee | ||
|
|
33cc973b43 | ||
|
|
d4710cb16e | ||
|
|
600d002a35 | ||
|
|
0a1f966886 | ||
|
|
552eceabdb | ||
|
|
e3b7ba3677 | ||
|
|
6cbfde95ec | ||
|
|
6bd34fa6ea | ||
|
|
c187474499 | ||
|
|
bad5e60a8e | ||
|
|
e4dc810bff | ||
|
|
749a208773 | ||
|
|
cb7732083d | ||
|
|
e9d343d80d | ||
|
|
3871e75140 | ||
|
|
b93ac16cee | ||
|
|
bd95f33f5e | ||
|
|
e717748a3c | ||
|
|
2d2cbef8de | ||
|
|
187ee80ee3 | ||
|
|
484f134a98 | ||
|
|
1e6e9e0c0e | ||
|
|
bc9afc4554 | ||
|
|
8c3395481b | ||
|
|
b40366d1f6 | ||
|
|
a1a99b9eeb | ||
|
|
4756df08cb | ||
|
|
cf11f8ee7e | ||
|
|
6b86d91cd7 | ||
|
|
49af96b2b1 | ||
|
|
c08ebc622c | ||
|
|
7bd09ff21d | ||
|
|
6801238e3e | ||
|
|
6cac3d583f | ||
|
|
e13794cf73 | ||
|
|
5690ed7acd | ||
|
|
6b1dc9f3ce | ||
|
|
ff89148a93 | ||
|
|
93f51c1a1d | ||
|
|
e66406ffe2 | ||
|
|
03a2d603d3 | ||
|
|
a7b4e65521 | ||
|
|
b4f5be1332 | ||
|
|
eb4254b1c2 | ||
|
|
19b60fe563 | ||
|
|
985260dcea | ||
|
|
7cd16b179c | ||
|
|
64263fdb0a | ||
|
|
a04129548f | ||
|
|
f7fac330f5 | ||
|
|
6ae3c0a9c3 | ||
|
|
84e2f27249 | ||
|
|
f99ca61bba | ||
|
|
7d394658cc | ||
|
|
d659b90e19 | ||
|
|
bd56eebb8a | ||
|
|
2ba378904d | ||
|
|
1ebc8e8b2e | ||
|
|
1699a9995e | ||
|
|
255f51f75b | ||
|
|
5928e05d9e | ||
|
|
fc0f9d959a | ||
|
|
6ee05611a1 | ||
|
|
a783a5d6b2 | ||
|
|
72d537f8b4 | ||
|
|
1c8ab72f4f | ||
|
|
241a3a6cfb | ||
|
|
daf4be03ce | ||
|
|
7d48fad385 | ||
|
|
0aa4892353 | ||
|
|
947b4fd579 | ||
|
|
205559b4f3 | ||
|
|
2bd24f674a | ||
|
|
8b8af49651 | ||
|
|
60d12d88ac | ||
|
|
77041760cc | ||
|
|
b9c8e359ab | ||
|
|
24cf7c5bcd | ||
|
|
0d4a4fd2bf | ||
|
|
d0784eaed2 | ||
|
|
2d3e53e6ac | ||
|
|
7a74ca9f57 | ||
|
|
d9e79eac9d | ||
|
|
adcfedff68 | ||
|
|
6d39b81b8f | ||
|
|
efeb9a9de0 | ||
|
|
d2afdfaf9a | ||
|
|
bd9d6fab27 | ||
|
|
5756c56497 | ||
|
|
c6e4133c5e | ||
|
|
5005f94ebb | ||
|
|
15d700a41c | ||
|
|
044cbd0325 | ||
|
|
e6a18978d1 | ||
|
|
14858a6db3 | ||
|
|
8cad5ea3c9 | ||
|
|
0ffd01d993 | ||
|
|
23f6dd44a0 | ||
|
|
7ff3b3d9cb | ||
|
|
a430f4b730 | ||
|
|
585adc96d8 | ||
|
|
3b46547efc | ||
|
|
53f56f328b | ||
|
|
9aafff78f1 | ||
|
|
a49e48c6f7 | ||
|
|
6926c1ab64 | ||
|
|
f9e2212882 | ||
|
|
95d35a174d | ||
|
|
2f9b8b105d | ||
|
|
3d20fa79a7 | ||
|
|
74c3156059 | ||
|
|
6156fdf175 | ||
|
|
f494c61790 | ||
|
|
2633d72ce2 | ||
|
|
a94bbe70c7 | ||
|
|
9acc456fd7 | ||
|
|
8ff6ef32e9 | ||
|
|
f4c9202f49 | ||
|
|
bc7ffd37a6 | ||
|
|
f691baec74 | ||
|
|
39a95e1198 | ||
|
|
6d3ed73eee | ||
|
|
e3a963b73f | ||
|
|
30818cb66d | ||
|
|
976035115e | ||
|
|
85b67f254c | ||
|
|
e1a0367b03 | ||
|
|
a9aac69c65 | ||
|
|
d88895c4a5 | ||
|
|
d35306aa85 | ||
|
|
3548362ce4 | ||
|
|
4951cbe5d4 | ||
|
|
66f4ee8a1b | ||
|
|
09b9075abb | ||
|
|
99c635c38d | ||
|
|
265c63fa54 | ||
|
|
2995e6a48c |
@@ -21,3 +21,6 @@
|
||||
|
||||
# MacOS Desktop Services Store
|
||||
.DS_Store
|
||||
|
||||
# Hugo temp file
|
||||
.hugo_build.lock
|
||||
|
||||
30
.github/dependabot.yml
vendored
30
.github/dependabot.yml
vendored
@@ -2,18 +2,28 @@
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
open-pull-requests-limit: 100
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 2
|
||||
directory: "/hack/update-go-mod"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Our own CI job is responsible for updating this go.mod file now.
|
||||
# - package-ecosystem: "gomod"
|
||||
# open-pull-requests-limit: 100
|
||||
# directory: "/"
|
||||
# schedule:
|
||||
# interval: "daily"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/hack" # this should keep the FIPS dockerfile updated per https://github.com/dependabot/feedback/issues/145#issuecomment-414738498
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Our own CI job is responsible for updating this Docker file now.
|
||||
# - package-ecosystem: "docker"
|
||||
# directory: "/"
|
||||
# schedule:
|
||||
# interval: "daily"
|
||||
|
||||
# Our own CI job is responsible for updating this Docker file now.
|
||||
# - package-ecosystem: "docker"
|
||||
# directory: "/hack" # this should keep the FIPS dockerfile updated per https://github.com/dependabot/feedback/issues/145#issuecomment-414738498
|
||||
# schedule:
|
||||
# interval: "daily"
|
||||
|
||||
47
.github/workflows/codeql-analysis.yml
vendored
47
.github/workflows/codeql-analysis.yml
vendored
@@ -1,18 +1,23 @@
|
||||
# See https://codeql.github.com and https://github.com/github/codeql-action
|
||||
# This action runs GitHub's industry-leading semantic code analysis engine, CodeQL, against a
|
||||
# repository's source code to find security vulnerabilities. It then automatically uploads the
|
||||
# results to GitHub so they can be displayed in the repository's security tab.
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, release*, dynamic_clients ]
|
||||
branches: [ "main", release* ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main, release*, dynamic_clients ]
|
||||
branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '39 13 * * 2'
|
||||
- cron: '24 3 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -24,34 +29,44 @@ jobs:
|
||||
language: [ 'go', 'javascript' ]
|
||||
|
||||
steps:
|
||||
# Checkout our repository.
|
||||
# See https://github.com/actions/checkout for documentation.
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# Install Go.
|
||||
# See https://github.com/actions/setup-go?tab=readme-ov-file#getting-go-version-from-the-gomod-file.
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
55
.github/workflows/scorecards.yml
vendored
55
.github/workflows/scorecards.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '29 11 * * 3'
|
||||
push:
|
||||
branches: [ main, release* ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@c1aec4ac820532bab364f02a81873c555a0ba3a1 # v1.0.4
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# Read-only PAT token. To create it,
|
||||
# follow the steps in https://github.com/ossf/scorecard-action#pat-token-creation.
|
||||
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||
# Publish the results to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`,
|
||||
# regardless of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional).
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -19,3 +19,6 @@
|
||||
|
||||
# MacOS Desktop Services Store
|
||||
.DS_Store
|
||||
|
||||
# Hugo temp file
|
||||
.hugo_build.lock
|
||||
|
||||
@@ -7,52 +7,52 @@ run:
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
# default linters
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
# default linters
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
|
||||
# additional linters for this project (we should disable these if they get annoying).
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- depguard
|
||||
- dogsled
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- goheader
|
||||
- goimports
|
||||
- revive
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- rowserrcheck
|
||||
- exportloopref
|
||||
- sqlclosecheck
|
||||
- unconvert
|
||||
- whitespace
|
||||
# additional linters for this project (we should disable these if they get annoying).
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
# - depguard
|
||||
- dogsled
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- goheader
|
||||
- goimports
|
||||
- revive
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- rowserrcheck
|
||||
- exportloopref
|
||||
- sqlclosecheck
|
||||
- unconvert
|
||||
- whitespace
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# exclude tests from some rules for things that are useful in a testing context.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
|
||||
linters-settings:
|
||||
funlen:
|
||||
@@ -64,7 +64,15 @@ linters-settings:
|
||||
# YYYY or YYYY-YYYY
|
||||
YEARS: \d\d\d\d(-\d\d\d\d)?
|
||||
template: |-
|
||||
Copyright {{YEARS}} the Pinniped contributors. All Rights Reserved.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
Copyright {{YEARS}} the Pinniped contributors. All Rights Reserved.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
goimports:
|
||||
local-prefixes: go.pinniped.dev
|
||||
revive:
|
||||
max-open-files: 2048
|
||||
rules:
|
||||
- name: unused-parameter
|
||||
arguments:
|
||||
# Allow unused params that start with underscore. It can be nice to keep unused param names when implementing
|
||||
# an interface sometimes, to help readers understand why it is unused in that particular implementation.
|
||||
- allowRegex: "^_"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exclude: '^(site|generated)/'
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
# TODO: find a version of this to validate ytt templates?
|
||||
# - id: check-yaml
|
||||
|
||||
@@ -114,7 +114,6 @@ go build -o pinniped ./cmd/pinniped
|
||||
|
||||
1. Install dependencies:
|
||||
|
||||
- [`chromedriver`](https://chromedriver.chromium.org/) (and [Chrome](https://www.google.com/chrome/))
|
||||
- [`docker`](https://www.docker.com/)
|
||||
- `htpasswd` (installed by default on MacOS, usually found in `apache2-utils` package for linux)
|
||||
- [`kapp`](https://carvel.dev/#getting-started)
|
||||
@@ -122,11 +121,13 @@ go build -o pinniped ./cmd/pinniped
|
||||
- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||
- [`ytt`](https://carvel.dev/#getting-started)
|
||||
- [`nmap`](https://nmap.org/download.html)
|
||||
- [`openssl`](https://www.openssl.org) (installed by default on MacOS)
|
||||
- [Chrome](https://www.google.com/chrome/)
|
||||
|
||||
On macOS, these tools can be installed with [Homebrew](https://brew.sh/) (assuming you have Chrome installed already):
|
||||
|
||||
```bash
|
||||
brew install kind vmware-tanzu/carvel/ytt vmware-tanzu/carvel/kapp kubectl chromedriver nmap && brew cask install docker
|
||||
brew install kind vmware-tanzu/carvel/ytt vmware-tanzu/carvel/kapp kubectl nmap && brew cask install docker
|
||||
```
|
||||
|
||||
1. Create a kind cluster, compile, create container images, and install Pinniped and supporting test dependencies using:
|
||||
@@ -151,9 +152,32 @@ go build -o pinniped ./cmd/pinniped
|
||||
|
||||
To destroy the local Kubernetes cluster, run `./hack/kind-down.sh`.
|
||||
|
||||
#### Using GoLand to Run an Integration Test
|
||||
|
||||
It can sometimes be convenient to use GoLand to run an integration test. For example, this allows using the
|
||||
GoLand debugger to debug the test itself (not the server, since that it running in-cluster).
|
||||
|
||||
Note that the output of `hack/prepare-for-integration-tests.sh` says:
|
||||
|
||||
```bash
|
||||
# Using GoLand? Paste the result of this command into GoLand's run configuration "Environment".
|
||||
# hack/integration-test-env-goland.sh | pbcopy
|
||||
```
|
||||
|
||||
After using `hack/prepare-for-integration-tests.sh`, run `hack/integration-test-env-goland.sh | pbcopy` as instructed. Then:
|
||||
|
||||
1. Select and run an integration test within GoLand. It will fail complaining about missing env vars.
|
||||
1. Pull down the menu that shows the name of the test which you just ran in the previous step, and choose "Edit Configurations...".
|
||||
1. In the "Environment" text box for the run configuration of the integration test that you just ran,
|
||||
paste the results of `hack/integration-test-env-goland.sh | pbcopy`.
|
||||
1. Apply, and then run the integration test again. This time the test will use the environment variables provided.
|
||||
|
||||
Note that if you run `hack/prepare-for-integration-tests.sh` again, then you may need to repeat these steps.
|
||||
Each run of `hack/prepare-for-integration-tests.sh` can result in different values for some of the env vars.
|
||||
|
||||
### Observing Tests on the Continuous Integration Environment
|
||||
|
||||
[CI](https://hush-house.pivotal.io/teams/tanzu-user-auth/pipelines/pinniped-pull-requests)
|
||||
[CI](https://ci.pinniped.dev/teams/main/pipelines/pull-requests)
|
||||
will not be triggered on a pull request until the pull request is reviewed and
|
||||
approved for CI by a project [maintainer](MAINTAINERS.md). Once CI is triggered,
|
||||
the progress and results will appear on the Github page for that
|
||||
|
||||
33
Dockerfile
33
Dockerfile
@@ -1,22 +1,34 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.19.1 as build-env
|
||||
ARG BUILD_IMAGE=golang:1.22.3@sha256:b1e05e2c918f52c59d39ce7d5844f73b2f4511f7734add8bb98c9ecdd4443365
|
||||
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:e9ac71e2b8e279a8372741b7a0293afda17650d926900233ec3a7b2b7c22a246
|
||||
|
||||
# Prepare to cross-compile by always running the build stage in the build platform, not the target platform.
|
||||
FROM --platform=$BUILDPLATFORM $BUILD_IMAGE as build-env
|
||||
|
||||
WORKDIR /work
|
||||
COPY . .
|
||||
|
||||
ARG GOPROXY
|
||||
|
||||
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
||||
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
||||
# can be re-used between image builds.
|
||||
ARG KUBE_GIT_VERSION
|
||||
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
||||
|
||||
# These will be set by buildkit automatically, e.g. TARGETOS set to "linux" and TARGETARCH set to "amd64" or "arm64".
|
||||
# Useful for building multi-arch container images.
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
# Build the statically linked (CGO_ENABLED=0) binary.
|
||||
# Mount source, build cache, and module cache for performance reasons.
|
||||
# See https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
|
||||
RUN \
|
||||
--mount=target=. \
|
||||
--mount=type=cache,target=/cache/gocache \
|
||||
--mount=type=cache,target=/cache/gomodcache \
|
||||
mkdir out && \
|
||||
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=linux GOARCH=amd64 && \
|
||||
export GOCACHE=/cache/gocache GOMODCACHE=/cache/gomodcache CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH && \
|
||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-concierge-kube-cert-agent ./cmd/pinniped-concierge-kube-cert-agent/... && \
|
||||
go build -v -trimpath -ldflags "$(hack/get-ldflags.sh) -w -s" -o /usr/local/bin/pinniped-server ./cmd/pinniped-server/... && \
|
||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/pinniped-concierge && \
|
||||
@@ -24,7 +36,10 @@ RUN \
|
||||
ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator
|
||||
|
||||
# Use a distroless runtime image with CA certificates, timezone data, and not much else.
|
||||
FROM gcr.io/distroless/static:nonroot@sha256:2a9e2b4fa771d31fe3346a873be845bfc2159695b9f90ca08e950497006ccc2e
|
||||
# Note that we are not using --platform here, so it will choose the base image for the target platform, not the build platform.
|
||||
# By using "distroless/static" instead of "distroless/static-debianXX" we can float on the latest stable version of debian.
|
||||
# See https://github.com/GoogleContainerTools/distroless#base-operating-system
|
||||
FROM $BASE_IMAGE
|
||||
|
||||
# Copy the server binary from the build-env stage.
|
||||
COPY --from=build-env /usr/local/bin /usr/local/bin
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
# Pinniped Maintainers
|
||||
# Current Pinniped Maintainers
|
||||
|
||||
This is the current list of maintainers for the Pinniped project.
|
||||
|
||||
| Maintainer | GitHub ID | Affiliation |
|
||||
| --------------- | --------- | ----------- |
|
||||
| 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/) |
|
||||
| Ben Petersen | [benjaminapetersen](https://github.com/benjaminapetersen) | [VMware](https://www.github.com/vmware/) |
|
||||
| Maintainer | GitHub ID | Affiliation |
|
||||
|-----------------|-----------------------------------------------------------|------------------------------------------|
|
||||
| Ben Petersen | [benjaminapetersen](https://github.com/benjaminapetersen) | [VMware](https://www.github.com/vmware/) |
|
||||
| Ryan Richard | [cfryanr](https://github.com/cfryanr) | [VMware](https://www.github.com/vmware/) |
|
||||
| Joshua T. Casey | [joshuatcasey](https://github.com/joshuatcasey) | [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)
|
||||
* Margo Crawford, [margocrawf](https://github.com/margocrawf)
|
||||
* Mo Khan, [enj](https://github.com/enj)
|
||||
|
||||
## Pinniped Contributors & Stakeholders
|
||||
|
||||
| Feature Area | Lead |
|
||||
| ----------------------------- | :---------------------: |
|
||||
| Technical Lead | Ryan Richard (cfryanr) |
|
||||
| Product Management | Anjali Telang (anjaltelang) |
|
||||
| Community Management | Nigel Brown (pnbrown) |
|
||||
| Maintainer | GitHub ID |
|
||||
|-------------------|---------------------------------------------------------|
|
||||
| Andrew Keesler | [ankeesler](https://github.com/ankeesler) |
|
||||
| Anjali Telang | [anjaltelang](https://github.com/anjaltelang) |
|
||||
| Margo Crawford | [margocrawf](https://github.com/margocrawf) |
|
||||
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) |
|
||||
| Mo Khan | [enj](https://github.com/enj) |
|
||||
| Pablo Schuhmacher | [pabloschuhmacher](https://github.com/pabloschuhmacher) |
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=authentication.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped concierge authentication API.
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
type JWTAuthenticatorPhase string
|
||||
|
||||
const (
|
||||
// JWTAuthenticatorPhasePending is the default phase for newly-created JWTAuthenticator resources.
|
||||
JWTAuthenticatorPhasePending JWTAuthenticatorPhase = "Pending"
|
||||
|
||||
// JWTAuthenticatorPhaseReady is the phase for an JWTAuthenticator resource in a healthy state.
|
||||
JWTAuthenticatorPhaseReady JWTAuthenticatorPhase = "Ready"
|
||||
|
||||
// JWTAuthenticatorPhaseError is the phase for an JWTAuthenticator in an unhealthy state.
|
||||
JWTAuthenticatorPhaseError JWTAuthenticatorPhase = "Error"
|
||||
)
|
||||
|
||||
// Status of a JWT authenticator.
|
||||
type JWTAuthenticatorStatus struct {
|
||||
// Represents the observations of the authenticator's current state.
|
||||
@@ -12,7 +25,11 @@ type JWTAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
// Phase summarizes the overall status of the JWTAuthenticator.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase JWTAuthenticatorPhase `json:"phase,omitempty"`
|
||||
}
|
||||
|
||||
// Spec for configuring a JWT authenticator.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,10 +1,23 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
type WebhookAuthenticatorPhase string
|
||||
|
||||
const (
|
||||
// WebhookAuthenticatorPhasePending is the default phase for newly-created WebhookAuthenticator resources.
|
||||
WebhookAuthenticatorPhasePending WebhookAuthenticatorPhase = "Pending"
|
||||
|
||||
// WebhookAuthenticatorPhaseReady is the phase for an WebhookAuthenticator resource in a healthy state.
|
||||
WebhookAuthenticatorPhaseReady WebhookAuthenticatorPhase = "Ready"
|
||||
|
||||
// WebhookAuthenticatorPhaseError is the phase for an WebhookAuthenticator in an unhealthy state.
|
||||
WebhookAuthenticatorPhaseError WebhookAuthenticatorPhase = "Error"
|
||||
)
|
||||
|
||||
// Status of a webhook authenticator.
|
||||
type WebhookAuthenticatorStatus struct {
|
||||
// Represents the observations of the authenticator's current state.
|
||||
@@ -12,7 +25,11 @@ type WebhookAuthenticatorStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
// Phase summarizes the overall status of the WebhookAuthenticator.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase WebhookAuthenticatorPhase `json:"phase,omitempty"`
|
||||
}
|
||||
|
||||
// Spec for configuring a webhook authenticator.
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=config.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped concierge configuration API.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -80,6 +80,28 @@ const (
|
||||
ImpersonationProxyServiceTypeNone = ImpersonationProxyServiceType("None")
|
||||
)
|
||||
|
||||
// ImpersonationProxyTLSSpec contains information about how the Concierge impersonation proxy should
|
||||
// serve TLS.
|
||||
//
|
||||
// If CertificateAuthorityData is not provided, the Concierge impersonation proxy will check the secret
|
||||
// for a field called "ca.crt", which will be used as the CertificateAuthorityData.
|
||||
//
|
||||
// If neither CertificateAuthorityData nor ca.crt is provided, no CA bundle will be advertised for
|
||||
// the impersonation proxy endpoint.
|
||||
type ImpersonationProxyTLSSpec struct {
|
||||
// X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
// Used to advertise the CA bundle for the impersonation proxy endpoint.
|
||||
//
|
||||
// +optional
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData,omitempty"`
|
||||
|
||||
// SecretName is the name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains
|
||||
// the TLS serving certificate for the Concierge impersonation proxy endpoint.
|
||||
//
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxySpec describes the intended configuration of the Concierge impersonation proxy.
|
||||
type ImpersonationProxySpec struct {
|
||||
// Mode configures whether the impersonation proxy should be started:
|
||||
@@ -100,6 +122,13 @@ type ImpersonationProxySpec struct {
|
||||
//
|
||||
// +optional
|
||||
ExternalEndpoint string `json:"externalEndpoint,omitempty"`
|
||||
|
||||
// TLS contains information about how the Concierge impersonation proxy should serve TLS.
|
||||
//
|
||||
// If this field is empty, the impersonation proxy will generate its own TLS certificate.
|
||||
//
|
||||
// +optional
|
||||
TLS *ImpersonationProxyTLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// ImpersonationProxyServiceSpec describes how the Concierge should provision a Service to expose the impersonation proxy.
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/GENERATED_PKG/apis/supervisor/config
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=config.supervisor.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor configuration API.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -8,14 +8,17 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||
type FederationDomainStatusCondition string
|
||||
type FederationDomainPhase string
|
||||
|
||||
const (
|
||||
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||
// FederationDomainPhasePending is the default phase for newly-created FederationDomain resources.
|
||||
FederationDomainPhasePending FederationDomainPhase = "Pending"
|
||||
|
||||
// FederationDomainPhaseReady is the phase for an FederationDomain resource in a healthy state.
|
||||
FederationDomainPhaseReady FederationDomainPhase = "Ready"
|
||||
|
||||
// FederationDomainPhaseError is the phase for an FederationDomain in an unhealthy state.
|
||||
FederationDomainPhaseError FederationDomainPhase = "Error"
|
||||
)
|
||||
|
||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||
@@ -42,6 +45,157 @@ type FederationDomainTLSSpec struct {
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainTransformsConstant defines a constant variable and its value which will be made available to
|
||||
// the transform expressions. This is a union type, and Type is the discriminator field.
|
||||
type FederationDomainTransformsConstant struct {
|
||||
// Name determines the name of the constant. It must be a valid identifier name.
|
||||
// +kubebuilder:validation:Pattern=`^[a-zA-Z][_a-zA-Z0-9]*$`
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:MaxLength=64
|
||||
Name string `json:"name"`
|
||||
|
||||
// Type determines the type of the constant, and indicates which other field should be non-empty.
|
||||
// +kubebuilder:validation:Enum=string;stringList
|
||||
Type string `json:"type"`
|
||||
|
||||
// StringValue should hold the value when Type is "string", and is otherwise ignored.
|
||||
// +optional
|
||||
StringValue string `json:"stringValue,omitempty"`
|
||||
|
||||
// StringListValue should hold the value when Type is "stringList", and is otherwise ignored.
|
||||
// +optional
|
||||
StringListValue []string `json:"stringListValue,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainTransformsExpression defines a transform expression.
|
||||
type FederationDomainTransformsExpression struct {
|
||||
// Type determines the type of the expression. It must be one of the supported types.
|
||||
// +kubebuilder:validation:Enum=policy/v1;username/v1;groups/v1
|
||||
Type string `json:"type"`
|
||||
|
||||
// Expression is a CEL expression that will be evaluated based on the Type during an authentication.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Expression string `json:"expression"`
|
||||
|
||||
// Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects
|
||||
// an authentication attempt. When empty, a default message will be used.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainTransformsExample defines a transform example.
|
||||
type FederationDomainTransformsExample struct {
|
||||
// Username is the input username.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Username string `json:"username"`
|
||||
|
||||
// Groups is the input list of group names.
|
||||
// +optional
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
|
||||
// Expects is the expected output of the entire sequence of transforms when they are run against the
|
||||
// input Username and Groups.
|
||||
Expects FederationDomainTransformsExampleExpects `json:"expects"`
|
||||
}
|
||||
|
||||
// FederationDomainTransformsExampleExpects defines the expected result for a transforms example.
|
||||
type FederationDomainTransformsExampleExpects struct {
|
||||
// Username is the expected username after the transformations have been applied.
|
||||
// +optional
|
||||
Username string `json:"username,omitempty"`
|
||||
|
||||
// Groups is the expected list of group names after the transformations have been applied.
|
||||
// +optional
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
|
||||
// Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression
|
||||
// after the transformations have been applied. True means that it is expected that the authentication would be
|
||||
// rejected. The default value of false means that it is expected that the authentication would not be rejected
|
||||
// by any policy expression.
|
||||
// +optional
|
||||
Rejected bool `json:"rejected,omitempty"`
|
||||
|
||||
// Message is the expected error message of the transforms. When Rejected is true, then Message is the expected
|
||||
// message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank,
|
||||
// then Message will be treated as the default error message for authentication attempts which are rejected by a
|
||||
// policy. When Rejected is false, then Message is the expected error message for some other non-policy
|
||||
// transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainTransforms defines identity transformations for an identity provider's usage on a FederationDomain.
|
||||
type FederationDomainTransforms struct {
|
||||
// Constants defines constant variables and their values which will be made available to the transform expressions.
|
||||
// +patchMergeKey=name
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=name
|
||||
// +optional
|
||||
Constants []FederationDomainTransformsConstant `json:"constants,omitempty"`
|
||||
|
||||
// Expressions are an optional list of transforms and policies to be executed in the order given during every
|
||||
// authentication attempt, including during every session refresh.
|
||||
// Each is a CEL expression. It may use the basic CEL language as defined in
|
||||
// https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in
|
||||
// https://github.com/google/cel-go/tree/master/ext#strings.
|
||||
//
|
||||
// The username and groups extracted from the identity provider, and the constants defined in this CR, are
|
||||
// available as variables in all expressions. The username is provided via a variable called `username` and
|
||||
// the list of group names is provided via a variable called `groups` (which may be an empty list).
|
||||
// Each user-provided constants is provided via a variable named `strConst.varName` for string constants
|
||||
// and `strListConst.varName` for string list constants.
|
||||
//
|
||||
// The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1.
|
||||
// Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated
|
||||
// and the authentication attempt is rejected.
|
||||
// Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the
|
||||
// username or group names.
|
||||
// Each username/v1 transform must return the new username (a string), which can be the same as the old username.
|
||||
// Transformations of type username/v1 do not return group names, and therefore cannot change the group names.
|
||||
// Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old
|
||||
// groups list.
|
||||
// Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames.
|
||||
// After each expression, the new (potentially changed) username or groups get passed to the following expression.
|
||||
//
|
||||
// Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain.
|
||||
// During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the
|
||||
// authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username
|
||||
// and group names have been decided for that authentication attempt.
|
||||
//
|
||||
// +optional
|
||||
Expressions []FederationDomainTransformsExpression `json:"expressions,omitempty"`
|
||||
|
||||
// Examples can optionally be used to ensure that the sequence of transformation expressions are working as
|
||||
// expected. Examples define sample input identities which are then run through the expression list, and the
|
||||
// results are compared to the expected results. If any example in this list fails, then this
|
||||
// identity provider will not be available for use within this FederationDomain, and the error(s) will be
|
||||
// added to the FederationDomain status. This can be used to help guard against programming mistakes in the
|
||||
// expressions, and also act as living documentation for other administrators to better understand the expressions.
|
||||
// +optional
|
||||
Examples []FederationDomainTransformsExample `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainIdentityProvider describes how an identity provider is made available in this FederationDomain.
|
||||
type FederationDomainIdentityProvider struct {
|
||||
// DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the
|
||||
// kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a
|
||||
// disruptive change for those users.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
DisplayName string `json:"displayName"`
|
||||
|
||||
// ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required.
|
||||
// If the reference cannot be resolved then the identity provider will not be made available.
|
||||
// Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider,
|
||||
// LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
||||
ObjectRef corev1.TypedLocalObjectReference `json:"objectRef"`
|
||||
|
||||
// Transforms is an optional way to specify transformations to be applied during user authentication and
|
||||
// session refresh.
|
||||
// +optional
|
||||
Transforms FederationDomainTransforms `json:"transforms,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||
type FederationDomainSpec struct {
|
||||
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||
@@ -55,9 +209,35 @@ type FederationDomainSpec struct {
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||
// TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain.
|
||||
// +optional
|
||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||
|
||||
// IdentityProviders is the list of identity providers available for use by this FederationDomain.
|
||||
//
|
||||
// An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server,
|
||||
// how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to
|
||||
// extract a normalized user identity. Normalized user identities include a username and a list of group names.
|
||||
// In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which
|
||||
// belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations
|
||||
// on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid
|
||||
// accidental conflicts when multiple identity providers have different users with the same username (e.g.
|
||||
// "idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication
|
||||
// rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow
|
||||
// the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could
|
||||
// disallow the authentication unless the user belongs to a specific group in the identity provider.
|
||||
//
|
||||
// For backwards compatibility with versions of Pinniped which predate support for multiple identity providers,
|
||||
// an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which
|
||||
// exist in the same namespace, but also to reject all authentication requests when there is more than one identity
|
||||
// provider currently defined. In this backwards compatibility mode, the name of the identity provider resource
|
||||
// (e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this
|
||||
// FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of
|
||||
// relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead
|
||||
// explicitly list the identity provider using this IdentityProviders field.
|
||||
//
|
||||
// +optional
|
||||
IdentityProviders []FederationDomainIdentityProvider `json:"identityProviders,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||
@@ -86,20 +266,17 @@ type FederationDomainSecrets struct {
|
||||
|
||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||
type FederationDomainStatus struct {
|
||||
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||
// represent success or failure.
|
||||
// +optional
|
||||
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||
// Phase summarizes the overall status of the FederationDomain.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase FederationDomainPhase `json:"phase,omitempty"`
|
||||
|
||||
// Message provides human-readable details about the Status.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get
|
||||
// around some undesirable behavior with respect to the empty metav1.Time value (see
|
||||
// https://github.com/kubernetes/kubernetes/issues/86811).
|
||||
// +optional
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
// Conditions represent the observations of an FederationDomain's current state.
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
|
||||
// Secrets contains information about this OIDC Provider's secrets.
|
||||
// +optional
|
||||
@@ -111,7 +288,7 @@ type FederationDomainStatus struct {
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped
|
||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type FederationDomain struct {
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2022-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -8,14 +8,14 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
type OIDCClientPhase string
|
||||
|
||||
const (
|
||||
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||
PhasePending OIDCClientPhase = "Pending"
|
||||
// OIDCClientPhasePending is the default phase for newly-created OIDCClient resources.
|
||||
OIDCClientPhasePending OIDCClientPhase = "Pending"
|
||||
|
||||
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
PhaseReady OIDCClientPhase = "Ready"
|
||||
// OIDCClientPhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
OIDCClientPhaseReady OIDCClientPhase = "Ready"
|
||||
|
||||
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
PhaseError OIDCClientPhase = "Error"
|
||||
// OIDCClientPhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
OIDCClientPhaseError OIDCClientPhase = "Error"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||
@@ -71,6 +71,28 @@ type OIDCClientSpec struct {
|
||||
// +listType=set
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
AllowedScopes []Scope `json:"allowedScopes"`
|
||||
|
||||
// tokenLifetimes are the optional overrides of token lifetimes for an OIDCClient.
|
||||
// +optional
|
||||
TokenLifetimes OIDCClientTokenLifetimes `json:"tokenLifetimes,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCClientTokenLifetimes describes the optional overrides of token lifetimes for an OIDCClient.
|
||||
type OIDCClientTokenLifetimes struct {
|
||||
// idTokenSeconds is the lifetime of ID tokens issued to this client, in seconds. This will choose the lifetime of
|
||||
// ID tokens returned by the authorization flow and the refresh grant. It will not influence the lifetime of the ID
|
||||
// tokens returned by RFC8693 token exchange. When null, a short-lived default value will be used.
|
||||
// This value must be between 120 and 1,800 seconds (30 minutes), inclusive. It is recommended to make these tokens
|
||||
// short-lived to force the client to perform the refresh grant often, because the refresh grant will check with the
|
||||
// external identity provider to decide if it is acceptable for the end user to continue their session, and will
|
||||
// update the end user's group memberships from the external identity provider. Giving these tokens a long life is
|
||||
// will allow the end user to continue to use a token while avoiding these updates from the external identity
|
||||
// provider. However, some web applications may have reasons specific to the design of that application to prefer
|
||||
// longer lifetimes.
|
||||
// +kubebuilder:validation:Minimum=120
|
||||
// +kubebuilder:validation:Maximum=1800
|
||||
// +optional
|
||||
IDTokenSeconds *int32 `json:"idTokenSeconds,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||
@@ -85,7 +107,7 @@ type OIDCClientStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
|
||||
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||
// +optional
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=idp.supervisor.pinniped.dev
|
||||
// +groupGoName=IDP
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -32,7 +32,7 @@ type ActiveDirectoryIdentityProviderStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
type ActiveDirectoryIdentityProviderBind struct {
|
||||
@@ -114,9 +114,10 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
||||
|
||||
// Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
|
||||
// The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
|
||||
// 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.
|
||||
// value of an attribute of the user entry found as a result of the user search. Which attribute's
|
||||
// value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||
// E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||
// For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
||||
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
|
||||
// Optional. When not specified, the default will act as if the filter were specified as
|
||||
// "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
|
||||
@@ -127,6 +128,17 @@ type ActiveDirectoryIdentityProviderGroupSearch struct {
|
||||
// +optional
|
||||
Filter string `json:"filter,omitempty"`
|
||||
|
||||
// UserAttributeForFilter specifies which attribute's value from the user entry found as a result of
|
||||
// the user search will be used to replace the "{}" placeholder(s) in the group search Filter.
|
||||
// For example, specifying "uid" as the UserAttributeForFilter while specifying
|
||||
// "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing
|
||||
// the "{}" placeholder in the Filter with the value of the user's "uid" attribute.
|
||||
// Optional. When not specified, the default will act as if "dn" were specified. For example, leaving
|
||||
// UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter
|
||||
// would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||
// +optional
|
||||
UserAttributeForFilter string `json:"userAttributeForFilter,omitempty"`
|
||||
|
||||
// Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as
|
||||
// the result of the group search.
|
||||
// +optional
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -32,7 +32,7 @@ type LDAPIdentityProviderStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
type LDAPIdentityProviderBind struct {
|
||||
@@ -101,20 +101,31 @@ 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.
|
||||
// the values of Filter, UserAttributeForFilter, Attributes, and SkipGroupRefresh 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.
|
||||
// value of an attribute of the user entry found as a result of the user search. Which attribute's
|
||||
// value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||
// For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
||||
// Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
|
||||
// Optional. When not specified, the default will act as if the Filter were specified as "member={}".
|
||||
// +optional
|
||||
Filter string `json:"filter,omitempty"`
|
||||
|
||||
// UserAttributeForFilter specifies which attribute's value from the user entry found as a result of
|
||||
// the user search will be used to replace the "{}" placeholder(s) in the group search Filter.
|
||||
// For example, specifying "uid" as the UserAttributeForFilter while specifying
|
||||
// "&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing
|
||||
// the "{}" placeholder in the Filter with the value of the user's "uid" attribute.
|
||||
// Optional. When not specified, the default will act as if "dn" were specified. For example, leaving
|
||||
// UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter
|
||||
// would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||
// +optional
|
||||
UserAttributeForFilter string `json:"userAttributeForFilter,omitempty"`
|
||||
|
||||
// Attributes specifies how the group's information should be read from each LDAP entry which was found as
|
||||
// the result of the group search.
|
||||
// +optional
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
@@ -32,7 +32,7 @@ type OIDCIdentityProviderStatus struct {
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
||||
@@ -138,6 +138,17 @@ type OIDCClaims struct {
|
||||
// the ID token.
|
||||
// +optional
|
||||
Username string `json:"username"`
|
||||
|
||||
// AdditionalClaimMappings allows for additional arbitrary upstream claim values to be mapped into the
|
||||
// "additionalClaims" claim of the ID tokens generated by the Supervisor. This should be specified as a map of
|
||||
// new claim names as the keys, and upstream claim names as the values. These new claim names will be nested
|
||||
// under the top-level "additionalClaims" claim in ID tokens generated by the Supervisor when this
|
||||
// OIDCIdentityProvider was used for user authentication. These claims will be made available to all clients.
|
||||
// This feature is not required to use the Supervisor to provide authentication for Kubernetes clusters, but can be
|
||||
// used when using the Supervisor for other authentication purposes. When this map is empty or the upstream claims
|
||||
// are not available, the "additionalClaims" claim will be excluded from the ID tokens generated by the Supervisor.
|
||||
// +optional
|
||||
AdditionalClaimMappings map[string]string `json:"additionalClaimMappings,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCClient contains information about an OIDC client (e.g., client ID and client
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
@@ -29,6 +29,10 @@ const (
|
||||
// IDTokenClaimSubject is name of the subject claim defined by the OIDC spec.
|
||||
IDTokenClaimSubject = "sub"
|
||||
|
||||
// IDTokenSubClaimIDPNameQueryParam is the name of the query param used in the values of the "sub" claim
|
||||
// in Supervisor-issued ID tokens to identify with which external identity provider the user authenticated.
|
||||
IDTokenSubClaimIDPNameQueryParam = "idpName"
|
||||
|
||||
// IDTokenClaimAuthorizedParty is name of the authorized party claim defined by the OIDC spec.
|
||||
IDTokenClaimAuthorizedParty = "azp"
|
||||
|
||||
@@ -40,6 +44,10 @@ const (
|
||||
// group names which were mapped from the upstream identity provider.
|
||||
IDTokenClaimGroups = "groups"
|
||||
|
||||
// IDTokenClaimAdditionalClaims is the top level claim used to hold additional claims in the downstream ID
|
||||
// token, if any claims are present.
|
||||
IDTokenClaimAdditionalClaims = "additionalClaims"
|
||||
|
||||
// GrantTypeAuthorizationCode is the name of the grant type for authorization code flows defined by the OIDC spec.
|
||||
GrantTypeAuthorizationCode = "authorization_code"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 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.
|
||||
@@ -13,8 +13,23 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
||||
_ "go.pinniped.dev/internal/crypto/ptls"
|
||||
// This side effect import ensures that we use fipsonly crypto during TLS in fips_strict mode.
|
||||
//
|
||||
// Commenting this out because it causes the runtime memory consumption of this binary to increase
|
||||
// from ~1 MB to ~8 MB (as measured when running the sleep subcommand). This binary does not use TLS,
|
||||
// so it should not be needed. If this binary is ever changed to make use of TLS client and/or server
|
||||
// code, then we should bring this import back to support the use of the ptls library for client and
|
||||
// server code, and we should also increase the memory limits on the kube cert agent deployment (as
|
||||
// decided by the kube cert agent controller in the Concierge).
|
||||
//
|
||||
//nolint:godot // This is not sentence, it is a commented out line of import code.
|
||||
// _ "go.pinniped.dev/internal/crypto/ptls"
|
||||
|
||||
// This side effect imports cgo so that runtime/cgo gets linked, when in fips_strict mode.
|
||||
// Without this line, the binary will exit 133 upon startup in fips_strict mode.
|
||||
// It also enables fipsonly tls mode, just to be absolutely sure that the fips code is enabled,
|
||||
// even though it shouldn't be used currently by this binary.
|
||||
_ "go.pinniped.dev/internal/crypto/fips"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // these are swapped during unit tests.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main is the combined entrypoint for all Pinniped server components.
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
||||
concierge "go.pinniped.dev/internal/concierge/server"
|
||||
// this side effect import ensures that we use fipsonly crypto in fips_strict mode.
|
||||
_ "go.pinniped.dev/internal/crypto/ptls"
|
||||
lua "go.pinniped.dev/internal/localuserauthenticator"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var alphaCmd = &cobra.Command{
|
||||
Use: "alpha",
|
||||
Short: "alpha",
|
||||
Long: "alpha subcommands (syntax or flags are still subject to change)",
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
rootCmd.AddCommand(alphaCmd)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
||||
func TestConciergeModeFlag(t *testing.T) {
|
||||
@@ -52,7 +51,7 @@ func TestConciergeModeFlag(t *testing.T) {
|
||||
func TestCABundleFlag(t *testing.T) {
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := testutil.TempDir(t)
|
||||
tmpdir := t.TempDir()
|
||||
emptyFilePath := filepath.Join(tmpdir, "empty")
|
||||
require.NoError(t, os.WriteFile(emptyFilePath, []byte{}, 0600))
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -24,7 +24,7 @@ func generateMarkdownHelpCommand() *cobra.Command {
|
||||
Args: cobra.NoArgs,
|
||||
Use: "generate-markdown-help",
|
||||
Short: "Generate markdown help for the current set of non-hidden CLI commands",
|
||||
SilenceUsage: true,
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
Hidden: true,
|
||||
RunE: runGenerateMarkdownHelp,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -8,7 +8,11 @@ import (
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var getCmd = &cobra.Command{Use: "get", Short: "get"}
|
||||
var getCmd = &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Gets one of [kubeconfig]",
|
||||
SilenceUsage: true, // Do not print usage message when commands fail.
|
||||
}
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
@@ -95,6 +96,12 @@ type getKubeconfigParams struct {
|
||||
credentialCachePath string
|
||||
credentialCachePathSet bool
|
||||
installHint string
|
||||
pinnipedCliPath string
|
||||
}
|
||||
|
||||
type discoveryResponseScopesSupported struct {
|
||||
// Same as ScopesSupported in the Supervisor's discovery handler's struct.
|
||||
ScopesSupported []string `json:"scopes_supported"`
|
||||
}
|
||||
|
||||
func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||
@@ -103,7 +110,7 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||
Args: cobra.NoArgs,
|
||||
Use: "kubeconfig",
|
||||
Short: "Generate a Pinniped-based kubeconfig for a cluster",
|
||||
SilenceUsage: true,
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
flags getKubeconfigParams
|
||||
namespace string // unused now
|
||||
@@ -145,14 +152,16 @@ func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
|
||||
f.StringVarP(&flags.outputPath, "output", "o", "", "Output file path (default: stdout)")
|
||||
f.StringVar(&flags.generatedNameSuffix, "generated-name-suffix", "-pinniped", "Suffix to append to generated cluster, context, user kubeconfig entries")
|
||||
f.StringVar(&flags.credentialCachePath, "credential-cache", "", "Path to cluster-specific credentials cache")
|
||||
f.StringVar(&flags.pinnipedCliPath, "pinniped-cli-path", "", "Full path or executable name for the Pinniped CLI binary to be embedded in the resulting kubeconfig output (e.g. 'pinniped') (default: full path of the binary used to execute this command)")
|
||||
f.StringVar(&flags.installHint, "install-hint", "The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli for more details", "This text is shown to the user when the pinniped CLI is not installed.")
|
||||
mustMarkHidden(cmd, "oidc-debug-session-cache")
|
||||
|
||||
// --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")
|
||||
mustMarkHidden(cmd,
|
||||
"oidc-debug-session-cache",
|
||||
"oidc-skip-listen", // --oidc-skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
|
||||
"concierge-namespace",
|
||||
)
|
||||
|
||||
mustMarkDeprecated(cmd, "concierge-namespace", "not needed anymore")
|
||||
mustMarkHidden(cmd, "concierge-namespace")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
if flags.outputPath != "" {
|
||||
@@ -232,11 +241,9 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
||||
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, deps.log); err != nil {
|
||||
if len(flags.oidc.issuer) > 0 {
|
||||
err = pinnipedSupervisorDiscovery(ctx, &flags, deps.log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -264,7 +271,12 @@ func newExecConfig(deps kubeconfigDeps, flags getKubeconfigParams) (*clientcmdap
|
||||
|
||||
execConfig.InstallHint = flags.installHint
|
||||
var err error
|
||||
execConfig.Command, err = deps.getPathToSelf()
|
||||
execConfig.Command, err = func() (string, error) {
|
||||
if flags.pinnipedCliPath != "" {
|
||||
return flags.pinnipedCliPath, nil
|
||||
}
|
||||
return deps.getPathToSelf()
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine the Pinniped executable path: %w", err)
|
||||
}
|
||||
@@ -720,6 +732,7 @@ func validateKubeconfig(ctx context.Context, flags getKubeconfigParams, kubeconf
|
||||
func countCACerts(pemData []byte) int {
|
||||
pool := x509.NewCertPool()
|
||||
pool.AppendCertsFromPEM(pemData)
|
||||
//nolint:staticcheck // since we're not using .Subjects() to access the system pool
|
||||
return len(pool.Subjects())
|
||||
}
|
||||
|
||||
@@ -732,21 +745,75 @@ func hasPendingStrategy(credentialIssuer *configv1alpha1.CredentialIssuer) bool
|
||||
return false
|
||||
}
|
||||
|
||||
func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||
func pinnipedSupervisorDiscovery(ctx context.Context, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
// Make a client suitable for calling the provider, which may or may not be a Pinniped Supervisor.
|
||||
oidcProviderHTTPClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(ctx, flags.oidc.issuer, httpClient)
|
||||
// Call the provider's discovery endpoint, but don't parse the results yet.
|
||||
discoveredProvider, err := discoverOIDCProvider(ctx, flags.oidc.issuer, oidcProviderHTTPClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse the discovery response to find the Supervisor IDP discovery endpoint.
|
||||
pinnipedIDPsEndpoint, err := discoverIDPsDiscoveryEndpointURL(discoveredProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pinnipedIDPsEndpoint == "" {
|
||||
// The issuer is not advertising itself as a Pinniped Supervisor which supports upstream IDP discovery.
|
||||
// Since this field is not present, then assume that the provider is not a Pinniped Supervisor. This field
|
||||
// was added to the discovery response in v0.9.0, which is so long ago that we can assume there are no such
|
||||
// old Supervisors in the wild which need to work with this CLI command anymore. Since the issuer is not a
|
||||
// Supervisor, then there is no need to do the rest of the Supervisor-specific business logic below related
|
||||
// to username/groups scopes or IDP types/names/flows.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now that we know that the provider is a Supervisor, perform an additional check based on its response.
|
||||
// The username and groups scopes were added to the Supervisor in v0.20.0, and were also added to the
|
||||
// "scopes_supported" field in the discovery response in that same version. If this CLI command is talking
|
||||
// to an older Supervisor, then remove the username and groups scopes from the list of requested scopes
|
||||
// since they will certainly cause an error from the old Supervisor during authentication.
|
||||
supervisorSupportsBothUsernameAndGroupsScopes, err := discoverScopesSupportedIncludesBothUsernameAndGroups(discoveredProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !supervisorSupportsBothUsernameAndGroupsScopes {
|
||||
flags.oidc.scopes = slices.Filter(nil, flags.oidc.scopes, func(scope string) bool {
|
||||
if scope == oidcapi.ScopeUsername || scope == oidcapi.ScopeGroups {
|
||||
log.Info("removed scope from --oidc-scopes list because it is not supported by this Supervisor", "scope", scope)
|
||||
return false // Remove username and groups scopes if there were present in the flags.
|
||||
}
|
||||
return true // Keep any other scopes in the flag list.
|
||||
})
|
||||
}
|
||||
|
||||
// If any upstream IDP flags are not already set, then try to discover Supervisor upstream IDP details.
|
||||
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input.
|
||||
// Maybe they know something that we can't know, like the name of an IDP that they are going to define in the
|
||||
// future.
|
||||
if flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "" {
|
||||
if err := discoverSupervisorUpstreamIDP(ctx, pinnipedIDPsEndpoint, oidcProviderHTTPClient, flags, log); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func discoverOIDCProvider(ctx context.Context, issuer string, httpClient *http.Client) (*coreosoidc.Provider, error) {
|
||||
discoveredProvider, err := coreosoidc.NewProvider(coreosoidc.ClientContext(ctx, httpClient), issuer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
return discoveredProvider, nil
|
||||
}
|
||||
|
||||
func discoverSupervisorUpstreamIDP(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client, flags *getKubeconfigParams, log plog.MinLogger) error {
|
||||
discoveredUpstreamIDPs, err := discoverAllAvailableSupervisorUpstreamIDPs(ctx, pinnipedIDPsEndpoint, httpClient)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -786,21 +853,24 @@ func newDiscoveryHTTPClient(caBundleFlag caBundleFlag) (*http.Client, error) {
|
||||
return phttp.Default(rootCAs), nil
|
||||
}
|
||||
|
||||
func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpClient *http.Client) (string, error) {
|
||||
discoveredProvider, err := coreosoidc.NewProvider(coreosoidc.ClientContext(ctx, httpClient), issuer)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
|
||||
func discoverIDPsDiscoveryEndpointURL(discoveredProvider *coreosoidc.Provider) (string, error) {
|
||||
var body idpdiscoveryv1alpha1.OIDCDiscoveryResponse
|
||||
err = discoveredProvider.Claims(&body)
|
||||
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 discoverScopesSupportedIncludesBothUsernameAndGroups(discoveredProvider *coreosoidc.Provider) (bool, error) {
|
||||
var body discoveryResponseScopesSupported
|
||||
err := discoveredProvider.Claims(&body)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
|
||||
}
|
||||
return slices.Contains(body.ScopesSupported, oidcapi.ScopeUsername) && slices.Contains(body.ScopesSupported, oidcapi.ScopeGroups), nil
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -7,15 +7,27 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
"k8s.io/client-go/tools/auth/exec"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var loginCmd = &cobra.Command{
|
||||
Use: "login",
|
||||
Short: "login",
|
||||
Long: "Login to a Pinniped server",
|
||||
Use: "login",
|
||||
Short: "Authenticates with one of [oidc, static]",
|
||||
Long: here.Doc(
|
||||
`Authenticates with one of [oidc, static]
|
||||
|
||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which will include
|
||||
one of these login subcommands in its configuration. The oidc and static
|
||||
subcommands are not meant to be invoked directly by a user.
|
||||
|
||||
The oidc and static subcommands are Kubernetes client-go credential plugins
|
||||
which are meant to be configured inside a kubeconfig file. (See the Kubernetes
|
||||
authentication documentation for more information about client-go credential
|
||||
plugins.)`,
|
||||
),
|
||||
SilenceUsage: true, // Do not print usage message when commands fail.
|
||||
Hidden: true, // These commands are not really meant to be used directly by users, so it's confusing to have them discoverable.
|
||||
}
|
||||
|
||||
//nolint:gochecknoinits
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
|
||||
"go.pinniped.dev/internal/execcredcache"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/net/phttp"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/pkg/conciergeclient"
|
||||
@@ -38,6 +39,18 @@ const (
|
||||
// which specifies "cli_password" when using an IDE plugin where there is no interactive CLI available. This allows
|
||||
// the user to use one kubeconfig file for both flows.
|
||||
upstreamIdentityProviderFlowEnvVarName = "PINNIPED_UPSTREAM_IDENTITY_PROVIDER_FLOW"
|
||||
|
||||
// When using a browser-based login flow, the user may skip printing the login URL to the screen in the case
|
||||
// where the browser was launched with the login URL. This can be useful, for example, when using a console-based
|
||||
// UI like k9s, to avoid having any output to stderr which may confuse the UI. Set this env var to "true" to
|
||||
// skip printing the URL.
|
||||
skipPrintLoginURLEnvVarName = "PINNIPED_SKIP_PRINT_LOGIN_URL"
|
||||
|
||||
// Set this env var to "true" to cause debug logs to be printed to stderr.
|
||||
debugEnvVarName = "PINNIPED_DEBUG"
|
||||
|
||||
// The value to use for true/false env vars to enable the behavior caused by the env var.
|
||||
envVarTruthyValue = "true"
|
||||
)
|
||||
|
||||
//nolint:gochecknoinits
|
||||
@@ -88,10 +101,21 @@ type oidcLoginFlags struct {
|
||||
func oidcLoginCommand(deps oidcLoginCommandDeps) *cobra.Command {
|
||||
var (
|
||||
cmd = &cobra.Command{
|
||||
Args: cobra.NoArgs,
|
||||
Use: "oidc --issuer ISSUER",
|
||||
Short: "Login using an OpenID Connect provider",
|
||||
SilenceUsage: true,
|
||||
Args: cobra.NoArgs,
|
||||
Use: "oidc --issuer ISSUER",
|
||||
Short: "Login using an OpenID Connect provider",
|
||||
Long: here.Doc(
|
||||
`Login using an OpenID Connect provider
|
||||
|
||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
||||
login command in its configuration. This login command is not meant to be
|
||||
invoked directly by a user.
|
||||
|
||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
||||
documentation for more information about client-go credential plugins.)`,
|
||||
),
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
flags oidcLoginFlags
|
||||
conciergeNamespace string // unused now
|
||||
@@ -152,11 +176,16 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
||||
// Initialize the login handler.
|
||||
opts := []oidcclient.Option{
|
||||
oidcclient.WithContext(cmd.Context()),
|
||||
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
||||
oidcclient.WithLogger(plog.Logr()), //nolint:staticcheck // old code with lots of log statements
|
||||
oidcclient.WithScopes(flags.scopes),
|
||||
oidcclient.WithSessionCache(sessionCache),
|
||||
}
|
||||
|
||||
skipPrintLoginURL, _ := deps.lookupEnv(skipPrintLoginURLEnvVarName)
|
||||
if skipPrintLoginURL == envVarTruthyValue {
|
||||
opts = append(opts, oidcclient.WithSkipPrintLoginURL())
|
||||
}
|
||||
|
||||
if flags.listenPort != 0 {
|
||||
opts = append(opts, oidcclient.WithListenPort(flags.listenPort))
|
||||
}
|
||||
@@ -229,12 +258,12 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
||||
}
|
||||
|
||||
pLogger.Debug("Performing OIDC login", "issuer", flags.issuer, "client id", flags.clientID)
|
||||
// Do the basic login to get an OIDC token.
|
||||
// Do the basic login to get an OIDC token. Although this can return several tokens, we only need the ID token here.
|
||||
token, err := deps.login(flags.issuer, flags.clientID, opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not complete Pinniped login: %w", err)
|
||||
}
|
||||
cred := tokenCredential(token)
|
||||
cred := tokenCredential(token.IDToken)
|
||||
|
||||
// If the concierge was configured, exchange the credential for a separate short-lived, cluster-specific credential.
|
||||
if concierge != nil {
|
||||
@@ -332,25 +361,25 @@ func makeClient(caBundlePaths []string, caBundleData []string) (*http.Client, er
|
||||
return phttp.Default(pool), nil
|
||||
}
|
||||
|
||||
func tokenCredential(token *oidctypes.Token) *clientauthv1beta1.ExecCredential {
|
||||
func tokenCredential(idToken *oidctypes.IDToken) *clientauthv1beta1.ExecCredential {
|
||||
cred := clientauthv1beta1.ExecCredential{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "ExecCredential",
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
Status: &clientauthv1beta1.ExecCredentialStatus{
|
||||
Token: token.IDToken.Token,
|
||||
Token: idToken.Token,
|
||||
},
|
||||
}
|
||||
if !token.IDToken.Expiry.IsZero() {
|
||||
cred.Status.ExpirationTimestamp = &token.IDToken.Expiry
|
||||
if !idToken.Expiry.IsZero() {
|
||||
cred.Status.ExpirationTimestamp = &idToken.Expiry
|
||||
}
|
||||
return &cred
|
||||
}
|
||||
|
||||
func SetLogLevel(ctx context.Context, lookupEnv func(string) (string, bool)) (plog.Logger, error) {
|
||||
debug, _ := lookupEnv("PINNIPED_DEBUG")
|
||||
if debug == "true" {
|
||||
debug, _ := lookupEnv(debugEnvVarName)
|
||||
if debug == envVarTruthyValue {
|
||||
err := plog.ValidateAndSetLogLevelAndFormatGlobally(ctx, plog.LogSpec{Level: plog.LevelDebug, Format: plog.FormatCLI})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -10,12 +10,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
@@ -34,7 +32,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := testutil.TempDir(t)
|
||||
tmpdir := t.TempDir()
|
||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||
|
||||
@@ -62,6 +60,14 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantStdout: here.Doc(`
|
||||
Login using an OpenID Connect provider
|
||||
|
||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
||||
login command in its configuration. This login command is not meant to be
|
||||
invoked directly by a user.
|
||||
|
||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
||||
documentation for more information about client-go credential plugins.)
|
||||
|
||||
Usage:
|
||||
oidc --issuer ISSUER [flags]
|
||||
|
||||
@@ -181,6 +187,18 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantOptionsCount: 4,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||
},
|
||||
{
|
||||
name: "PINNIPED_SKIP_PRINT_LOGIN_URL adds an option",
|
||||
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
|
||||
},
|
||||
env: map[string]string{"PINNIPED_SKIP_PRINT_LOGIN_URL": "true"},
|
||||
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 CLI flow is allowed",
|
||||
args: []string{
|
||||
@@ -483,8 +501,8 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantOptionsCount: 4,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||
wantLogs: []string{
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:231 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:251 No concierge configured, skipping token credential exchange`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:260 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:280 No concierge configured, skipping token credential exchange`,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -505,18 +523,18 @@ 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", // must specify --credential-cache or else the cache file on disk causes test pollution
|
||||
"--credential-cache", t.TempDir() + "/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: 11,
|
||||
env: map[string]string{"PINNIPED_DEBUG": "true", "PINNIPED_SKIP_PRINT_LOGIN_URL": "true"},
|
||||
wantOptionsCount: 12,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
|
||||
wantLogs: []string{
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:231 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:241 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:249 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:256 caching cluster credential for future use.`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:260 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:270 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:278 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` pinniped-login cmd/login_oidc.go:285 caching cluster credential for future use.`,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -524,12 +542,9 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
fakeClock := clocktesting.NewFakeClock(now)
|
||||
ctx := plog.TestZapOverrides(context.Background(), t, &buf, nil, zap.WithClock(plog.ZapClock(fakeClock)))
|
||||
ctx := plog.AddZapOverridesToContext(context.Background(), t, &buf, nil, clocktesting.NewFakeClock(now))
|
||||
|
||||
var (
|
||||
gotOptions []oidcclient.Option
|
||||
)
|
||||
var gotOptions []oidcclient.Option
|
||||
cmd := oidcLoginCommand(oidcLoginCommandDeps{
|
||||
lookupEnv: func(s string) (string, bool) {
|
||||
v, ok := tt.env[s]
|
||||
@@ -581,15 +596,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
require.Equal(t, tt.wantStderr, stderr.String(), "unexpected stderr")
|
||||
require.Len(t, gotOptions, tt.wantOptionsCount)
|
||||
|
||||
require.Equal(t, tt.wantLogs, logLines(buf.String()))
|
||||
require.Equal(t, tt.wantLogs, testutil.SplitByNewline(buf.String()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func logLines(logs string) []string {
|
||||
if len(logs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return strings.Split(strings.TrimSpace(logs), "\n")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/execcredcache"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/pkg/conciergeclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
@@ -55,10 +56,21 @@ type staticLoginParams struct {
|
||||
func staticLoginCommand(deps staticLoginDeps) *cobra.Command {
|
||||
var (
|
||||
cmd = &cobra.Command{
|
||||
Args: cobra.NoArgs,
|
||||
Use: "static [--token TOKEN] [--token-env TOKEN_NAME]",
|
||||
Short: "Login using a static token",
|
||||
SilenceUsage: true,
|
||||
Args: cobra.NoArgs,
|
||||
Use: "static [--token TOKEN] [--token-env TOKEN_NAME]",
|
||||
Short: "Login using a static token",
|
||||
Long: here.Doc(
|
||||
`Login using a static token
|
||||
|
||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
||||
login command in its configuration. This login command is not meant to be
|
||||
invoked directly by a user.
|
||||
|
||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
||||
documentation for more information about client-go credential plugins.)`,
|
||||
),
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
flags staticLoginParams
|
||||
conciergeNamespace string // unused now
|
||||
@@ -121,7 +133,7 @@ func runStaticLogin(cmd *cobra.Command, deps staticLoginDeps, flags staticLoginP
|
||||
return fmt.Errorf("--token-env variable %q is empty", flags.staticTokenEnvName)
|
||||
}
|
||||
}
|
||||
cred := tokenCredential(&oidctypes.Token{IDToken: &oidctypes.IDToken{Token: token}})
|
||||
cred := tokenCredential(&oidctypes.IDToken{Token: token})
|
||||
|
||||
// Look up cached credentials based on a hash of all the CLI arguments, the current token value, and the cluster info.
|
||||
cacheKey := struct {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
@@ -30,7 +29,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
|
||||
testCA, err := certauthority.New("Test CA", 1*time.Hour)
|
||||
require.NoError(t, err)
|
||||
tmpdir := testutil.TempDir(t)
|
||||
tmpdir := t.TempDir()
|
||||
testCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||
require.NoError(t, os.WriteFile(testCABundlePath, testCA.Bundle(), 0600))
|
||||
|
||||
@@ -56,6 +55,14 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
wantStdout: here.Doc(`
|
||||
Login using a static token
|
||||
|
||||
Use "pinniped get kubeconfig" to generate a kubeconfig file which includes this
|
||||
login command in its configuration. This login command is not meant to be
|
||||
invoked directly by a user.
|
||||
|
||||
This login command is a Kubernetes client-go credential plugin which is meant to
|
||||
be configured inside a kubeconfig file. (See the Kubernetes authentication
|
||||
documentation for more information about client-go credential plugins.)
|
||||
|
||||
Usage:
|
||||
static [--token TOKEN] [--token-env TOKEN_NAME] [flags]
|
||||
|
||||
@@ -140,7 +147,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
Error: could not complete Concierge credential exchange: some concierge error
|
||||
`),
|
||||
wantLogs: []string{
|
||||
nowStr + ` pinniped-login cmd/login_static.go:147 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` pinniped-login cmd/login_static.go:159 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -171,8 +178,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
fakeClock := clocktesting.NewFakeClock(now)
|
||||
ctx := plog.TestZapOverrides(context.Background(), t, &buf, nil, zap.WithClock(plog.ZapClock(fakeClock)))
|
||||
ctx := plog.AddZapOverridesToContext(context.Background(), t, &buf, nil, clocktesting.NewFakeClock(now))
|
||||
|
||||
cmd := staticLoginCommand(staticLoginDeps{
|
||||
lookupEnv: func(s string) (string, bool) {
|
||||
@@ -210,7 +216,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
require.Equal(t, tt.wantStdout, stdout.String(), "unexpected stdout")
|
||||
require.Equal(t, tt.wantStderr, stderr.String(), "unexpected stderr")
|
||||
|
||||
require.Equal(t, tt.wantLogs, logLines(buf.String()))
|
||||
require.Equal(t, tt.wantLogs, testutil.SplitByNewline(buf.String()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -8,14 +8,18 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "pinniped",
|
||||
Short: "pinniped",
|
||||
Long: "pinniped is the client-side binary for use with Pinniped-enabled Kubernetes clusters.",
|
||||
Use: "pinniped",
|
||||
Long: here.Doc(
|
||||
`The Pinniped CLI is the client-side binary for use with Pinniped-enabled Kubernetes clusters
|
||||
|
||||
Find more information at: https://pinniped.dev`,
|
||||
),
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/component-base/version"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"go.pinniped.dev/internal/pversion"
|
||||
)
|
||||
|
||||
//nolint:gochecknoinits
|
||||
@@ -15,14 +18,44 @@ func init() {
|
||||
rootCmd.AddCommand(newVersionCommand())
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var (
|
||||
output = new(string)
|
||||
// getBuildInfo can be overwritten by tests.
|
||||
getBuildInfo = pversion.Get
|
||||
)
|
||||
|
||||
func newVersionCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%#v\n", version.Get())
|
||||
return nil
|
||||
},
|
||||
c := &cobra.Command{
|
||||
RunE: runner,
|
||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||
Use: "version",
|
||||
Short: "Print the version of this Pinniped CLI",
|
||||
}
|
||||
c.Flags().StringVarP(output, "output", "o", "", "one of 'yaml' or 'json'")
|
||||
return c
|
||||
}
|
||||
|
||||
func runner(cmd *cobra.Command, _ []string) error {
|
||||
buildVersion := getBuildInfo()
|
||||
|
||||
switch {
|
||||
case output == nil || *output == "":
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", buildVersion.GitVersion)
|
||||
case *output == "json":
|
||||
bytes, err := json.MarshalIndent(buildVersion, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", bytes)
|
||||
case *output == "yaml":
|
||||
bytes, err := yaml.Marshal(buildVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprint(cmd.OutOrStdout(), string(bytes))
|
||||
default:
|
||||
return fmt.Errorf("'%s' is not a valid option for output", *output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/pversion"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -19,8 +21,8 @@ var (
|
||||
version \[flags\]
|
||||
|
||||
Flags:
|
||||
-h, --help help for version
|
||||
|
||||
-h, --help help for version
|
||||
-o, --output string one of 'yaml' or 'json'
|
||||
`)
|
||||
|
||||
knownGoodHelpRegexpForVersion = here.Doc(`
|
||||
@@ -30,24 +32,55 @@ var (
|
||||
version \[flags\]
|
||||
|
||||
Flags:
|
||||
-h, --help help for version
|
||||
-h, --help help for version
|
||||
-o, --output string one of 'yaml' or 'json'
|
||||
`)
|
||||
|
||||
emptyVersionRegexp = `version.Info{Major:"", Minor:"", GitVersion:".*", GitCommit:".*", GitTreeState:"", BuildDate:".*", GoVersion:".*", Compiler:".*", Platform:".*/.*"}`
|
||||
jsonRegexp = here.Doc(`{
|
||||
"major": "\d*",
|
||||
"minor": "\d*",
|
||||
"gitVersion": "i am a version for json output",
|
||||
"gitCommit": ".*",
|
||||
"gitTreeState": ".*",
|
||||
"buildDate": ".*",
|
||||
"goVersion": ".*",
|
||||
"compiler": ".*",
|
||||
"platform": ".*/.*"
|
||||
}`)
|
||||
|
||||
yamlRegexp = here.Doc(`buildDate: ".*"
|
||||
compiler: .*
|
||||
gitCommit: .*
|
||||
gitTreeState: .*
|
||||
gitVersion: i am a version for yaml output
|
||||
goVersion: .*
|
||||
major: "\d*"
|
||||
minor: "\d*"
|
||||
platform: .*/.*
|
||||
`)
|
||||
)
|
||||
|
||||
func TestNewVersionCmd(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
getBuildInfo = pversion.Get
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
vars string
|
||||
getBuildInfo func() apimachineryversion.Info
|
||||
wantError bool
|
||||
wantStdoutRegexp string
|
||||
wantStderrRegexp string
|
||||
}{
|
||||
{
|
||||
name: "no flags",
|
||||
args: []string{},
|
||||
wantStdoutRegexp: emptyVersionRegexp + "\n",
|
||||
name: "no flags",
|
||||
args: []string{},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{GitVersion: "v55.66.44"}
|
||||
},
|
||||
wantStdoutRegexp: "v55.66.44\n",
|
||||
},
|
||||
{
|
||||
name: "help flag passed",
|
||||
@@ -61,10 +94,44 @@ func TestNewVersionCmd(t *testing.T) {
|
||||
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||
},
|
||||
{
|
||||
name: "json output",
|
||||
args: []string{"--output", "json"},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{
|
||||
GitVersion: "i am a version for json output",
|
||||
Platform: "a/b",
|
||||
}
|
||||
},
|
||||
wantStdoutRegexp: jsonRegexp,
|
||||
},
|
||||
{
|
||||
name: "yaml output",
|
||||
args: []string{"--output", "yaml"},
|
||||
getBuildInfo: func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{
|
||||
GitVersion: "i am a version for yaml output",
|
||||
Platform: "c/d",
|
||||
}
|
||||
},
|
||||
wantStdoutRegexp: yamlRegexp,
|
||||
},
|
||||
{
|
||||
name: "incorrect output",
|
||||
args: []string{"--output", "foo"},
|
||||
wantError: true,
|
||||
wantStderrRegexp: `Error: 'foo' is not a valid option for output`,
|
||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.getBuildInfo != nil {
|
||||
getBuildInfo = tt.getBuildInfo
|
||||
}
|
||||
|
||||
cmd := newVersionCommand()
|
||||
require.NotNil(t, cmd)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -31,6 +31,7 @@ func init() {
|
||||
|
||||
type whoamiFlags struct {
|
||||
outputFormat string // e.g., yaml, json, text
|
||||
timeout time.Duration
|
||||
|
||||
kubeconfigPath string
|
||||
kubeconfigContextOverride string
|
||||
@@ -48,7 +49,7 @@ func newWhoamiCommand(getClientset getConciergeClientsetFunc) *cobra.Command {
|
||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||
Use: "whoami",
|
||||
Short: "Print information about the current user",
|
||||
SilenceUsage: true,
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
flags := &whoamiFlags{}
|
||||
|
||||
@@ -58,6 +59,7 @@ func newWhoamiCommand(getClientset getConciergeClientsetFunc) *cobra.Command {
|
||||
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.StringVar(&flags.apiGroupSuffix, "api-group-suffix", groupsuffix.PinnipedDefaultSuffix, "Concierge API group suffix")
|
||||
f.DurationVar(&flags.timeout, "timeout", 0, "Timeout for the WhoAmI API request (default: 0, meaning no timeout)")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, _ []string) error {
|
||||
return runWhoami(cmd.OutOrStdout(), getClientset, flags)
|
||||
@@ -78,8 +80,22 @@ func runWhoami(output io.Writer, getClientset getConciergeClientsetFunc, flags *
|
||||
return fmt.Errorf("could not get current cluster info: %w", err)
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancelFunc()
|
||||
// Making the WhoAmI request may cause client-go to invoke the credential plugin, which may
|
||||
// ask the user to interactively authenticate. The time that the user takes to authenticate
|
||||
// is included in the timeout time, but their authentication is not cancelled by exceeding
|
||||
// this timeout. Only the subsequent whoami API request is cancelled. Using a short timeout
|
||||
// causes the odd behavior of a successful login immediately followed by a whoami request failure
|
||||
// due to timeout. For comparison, kubectl uses an infinite timeout by default on API requests
|
||||
// but also allows the user to adjust this timeout with the `--request-timeout` CLI option,
|
||||
// so we will take a similar approach. Note that kubectl has the same behavior when a client-go
|
||||
// credential plugin is invoked and the user takes longer then the timeout to authenticate.
|
||||
ctx := context.Background()
|
||||
if flags.timeout > 0 {
|
||||
var cancelFunc context.CancelFunc
|
||||
ctx, cancelFunc = context.WithTimeout(ctx, flags.timeout)
|
||||
defer cancelFunc()
|
||||
}
|
||||
|
||||
whoAmI, err := clientset.IdentityV1alpha1().WhoAmIRequests().Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
hint := ""
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2023 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
@@ -45,6 +45,7 @@ func TestWhoami(t *testing.T) {
|
||||
--kubeconfig string Path to kubeconfig file
|
||||
--kubeconfig-context string Kubeconfig context name (default: current active context)
|
||||
-o, --output string Output format (e.g., 'yaml', 'json', 'text') (default "text")
|
||||
--timeout duration Timeout for the WhoAmI API request (default: 0, meaning no timeout)
|
||||
`),
|
||||
},
|
||||
{
|
||||
@@ -312,7 +313,12 @@ func TestWhoami(t *testing.T) {
|
||||
stdout, stderr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
|
||||
cmd.SetOut(stdout)
|
||||
cmd.SetErr(stderr)
|
||||
cmd.SetArgs(test.args)
|
||||
if test.args == nil {
|
||||
// cobra uses os.Args[1:] when SetArgs is called with nil, so avoid using nil for tests.
|
||||
cmd.SetArgs([]string{})
|
||||
} else {
|
||||
cmd.SetArgs(test.args)
|
||||
}
|
||||
|
||||
err := cmd.Execute()
|
||||
if test.wantError {
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
@@ -32,20 +31,27 @@ spec:
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: "JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
\n Upon receiving a signed JWT, a JWTAuthenticator will performs some validation
|
||||
on it (e.g., valid signature, existence of claims, etc.) and extract the
|
||||
username and groups from the token."
|
||||
description: |-
|
||||
JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
|
||||
|
||||
Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
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'
|
||||
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'
|
||||
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
|
||||
@@ -57,24 +63,25 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
claims:
|
||||
description: Claims allows customization of the claims that will be
|
||||
mapped to user identity for Kubernetes access.
|
||||
description: |-
|
||||
Claims allows customization of the claims that will be mapped to user identity
|
||||
for Kubernetes access.
|
||||
properties:
|
||||
groups:
|
||||
description: Groups is the name of the claim which should be read
|
||||
to extract the user's group membership from the JWT token. When
|
||||
not specified, it will default to "groups".
|
||||
description: |-
|
||||
Groups is the name of the claim which should be read to extract the user's
|
||||
group membership from the JWT token. When not specified, it will default to "groups".
|
||||
type: string
|
||||
username:
|
||||
description: Username is the name of the claim which should be
|
||||
read to extract the username from the JWT token. When not specified,
|
||||
it will default to "username".
|
||||
description: |-
|
||||
Username is the name of the claim which should be read to extract the
|
||||
username from the JWT token. When not specified, it will default to "username".
|
||||
type: string
|
||||
type: object
|
||||
issuer:
|
||||
description: Issuer is the OIDC issuer URL that will be used to discover
|
||||
public signing keys. Issuer is also used to validate the "iss" JWT
|
||||
claim.
|
||||
description: |-
|
||||
Issuer is the OIDC issuer URL that will be used to discover public signing keys. Issuer is
|
||||
also used to validate the "iss" JWT claim.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
@@ -97,37 +104,43 @@ spec:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -141,11 +154,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -160,6 +174,14 @@ spec:
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the JWTAuthenticator.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
@@ -168,9 +190,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
@@ -33,14 +32,19 @@ spec:
|
||||
authenticator.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
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'
|
||||
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
|
||||
@@ -70,37 +74,43 @@ spec:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -114,11 +124,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -133,6 +144,14 @@ spec:
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the WebhookAuthenticator.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
@@ -141,9 +160,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
@@ -34,14 +33,19 @@ spec:
|
||||
Pinniped Concierge credential issuer.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
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'
|
||||
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
|
||||
@@ -53,18 +57,19 @@ spec:
|
||||
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\"."
|
||||
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.
|
||||
|
||||
|
||||
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.'
|
||||
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
|
||||
@@ -83,26 +88,45 @@ spec:
|
||||
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.
|
||||
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."
|
||||
description: |-
|
||||
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.
|
||||
enum:
|
||||
- LoadBalancer
|
||||
- ClusterIP
|
||||
- None
|
||||
type: string
|
||||
type: object
|
||||
tls:
|
||||
description: |-
|
||||
TLS contains information about how the Concierge impersonation proxy should serve TLS.
|
||||
|
||||
|
||||
If this field is empty, the impersonation proxy will generate its own TLS certificate.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: |-
|
||||
X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
Used to advertise the CA bundle for the impersonation proxy endpoint.
|
||||
type: string
|
||||
secretName:
|
||||
description: |-
|
||||
SecretName is the name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains
|
||||
the TLS serving certificate for the Concierge impersonation proxy endpoint.
|
||||
minLength: 1
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- mode
|
||||
- service
|
||||
@@ -114,9 +138,9 @@ spec:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: Information needed to form a valid Pinniped-based kubeconfig
|
||||
using this credential issuer. This field is deprecated and will
|
||||
be removed in a future version.
|
||||
description: |-
|
||||
Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
This field is deprecated and will be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
@@ -143,9 +167,9 @@ spec:
|
||||
this strategy.
|
||||
properties:
|
||||
impersonationProxyInfo:
|
||||
description: ImpersonationProxyInfo describes the parameters
|
||||
for the impersonation proxy on this Concierge. This field
|
||||
is only set when Type is "ImpersonationProxy".
|
||||
description: |-
|
||||
ImpersonationProxyInfo describes the parameters for the impersonation proxy on this Concierge.
|
||||
This field is only set when Type is "ImpersonationProxy".
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: CertificateAuthorityData is the base64-encoded
|
||||
@@ -163,9 +187,9 @@ spec:
|
||||
- endpoint
|
||||
type: object
|
||||
tokenCredentialRequestInfo:
|
||||
description: TokenCredentialRequestAPIInfo describes the
|
||||
parameters for the TokenCredentialRequest API on this
|
||||
Concierge. This field is only set when Type is "TokenCredentialRequestAPI".
|
||||
description: |-
|
||||
TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRequest API on this Concierge.
|
||||
This field is only set when Type is "TokenCredentialRequestAPI".
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: CertificateAuthorityData is the base64-encoded
|
||||
@@ -238,9 +262,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -45,8 +45,9 @@ metadata:
|
||||
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")
|
||||
kubernetes.io/enforce-mountable-secrets: "true"
|
||||
secrets: [] #! make sure the token controller does not create any secrets
|
||||
automountServiceAccountToken: false
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
@@ -77,6 +78,8 @@ data:
|
||||
impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @)
|
||||
impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @)
|
||||
agentServiceAccount: (@= defaultResourceNameWithSuffix("kube-cert-agent") @)
|
||||
impersonationProxyServiceAccount: (@= defaultResourceNameWithSuffix("impersonation-proxy") @)
|
||||
impersonationProxyLegacySecret: (@= defaultResourceNameWithSuffix("impersonation-proxy") @)
|
||||
labels: (@= json.encode(labels()).rstrip() @)
|
||||
kubeCertAgent:
|
||||
namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @)
|
||||
@@ -93,14 +96,9 @@ data:
|
||||
imagePullSecrets:
|
||||
- image-pull-secret
|
||||
(@ end @)
|
||||
(@ if data.values.log_level or data.values.deprecated_log_format: @)
|
||||
(@ if data.values.log_level: @)
|
||||
log:
|
||||
(@ if data.values.log_level: @)
|
||||
level: (@= getAndValidateLogLevel() @)
|
||||
(@ end @)
|
||||
(@ if data.values.deprecated_log_format: @)
|
||||
format: (@= data.values.deprecated_log_format @)
|
||||
(@ end @)
|
||||
(@ end @)
|
||||
---
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
@@ -134,8 +132,6 @@ spec:
|
||||
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
||||
_: #@ template.replace(deploymentPodLabel())
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: #@ data.values.run_as_user
|
||||
@@ -184,9 +180,6 @@ spec:
|
||||
- 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
|
||||
@@ -222,12 +215,6 @@ spec:
|
||||
- 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:
|
||||
@@ -247,9 +234,14 @@ spec:
|
||||
effect: NoSchedule
|
||||
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||
effect: NoSchedule
|
||||
#! "system-cluster-critical" cannot be used outside the kube-system namespace until Kubernetes >= 1.17,
|
||||
#! so we skip setting this for now (see https://github.com/kubernetes/kubernetes/issues/60596).
|
||||
#!priorityClassName: system-cluster-critical
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: amd64 #! Allow running on amd64 nodes.
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: arm64 #! Also allow running on arm64 nodes.
|
||||
#! This will help make sure our multiple pods run on different nodes, making
|
||||
#! our deployment "more" "HA".
|
||||
affinity:
|
||||
@@ -344,17 +336,9 @@ spec:
|
||||
#@ if data.values.impersonation_proxy_spec.service.load_balancer_ip:
|
||||
loadBalancerIP: #@ data.values.impersonation_proxy_spec.service.load_balancer_ip
|
||||
#@ end
|
||||
#@ if data.values.impersonation_proxy_spec.service.annotations == None:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "4000"
|
||||
#@ else:
|
||||
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
|
||||
#@ end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -19,7 +19,7 @@ rules:
|
||||
resources: [ apiservices ]
|
||||
verbs: [ get, list, patch, update, watch ]
|
||||
- apiGroups: [ admissionregistration.k8s.io ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations, validatingadmissionpolicies, validatingadmissionpolicybindings ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||
@@ -43,6 +43,10 @@ rules:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||
resources: [ jwtauthenticators, webhookauthenticators ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||
resources: [ jwtauthenticators/status, webhookauthenticators/status ]
|
||||
verbs: [ get, list, watch, update ]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
@@ -156,6 +160,13 @@ rules:
|
||||
- apiGroups: [ coordination.k8s.io ]
|
||||
resources: [ leases ]
|
||||
verbs: [ create, get, update ]
|
||||
#! We need to be able to get service accounts and create serviceaccounts/tokens so that we can create short-lived tokens for the impersonation proxy
|
||||
- apiGroups: [""]
|
||||
resources: [ serviceaccounts ]
|
||||
verbs: [ get ]
|
||||
- apiGroups: [""]
|
||||
resources: [ serviceaccounts/token ]
|
||||
verbs: [ create ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
||||
@@ -1,107 +1,216 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@data/values
|
||||
---
|
||||
#@ def validate_strings_map(obj):
|
||||
#@ # Returns True if obj is an associative data structure string→string, and False otherwise.
|
||||
#@ for key in obj:
|
||||
#@ if type(key) != "string" or type(obj[key]) != "string":
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ end
|
||||
#@ return True
|
||||
#@ end
|
||||
|
||||
#@data/values-schema
|
||||
---
|
||||
#@schema/title "App name"
|
||||
#@schema/desc "Used to help determine the names of various resources and labels."
|
||||
#@schema/validation min_len=1
|
||||
app_name: pinniped-concierge
|
||||
|
||||
#! Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
#@schema/title "Namespace"
|
||||
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||
#@schema/validation min_len=1
|
||||
namespace: pinniped-concierge
|
||||
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||
into_namespace: #! e.g. my-preexisting-namespace
|
||||
|
||||
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||
#! The app can be uninstalled either by:
|
||||
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||
#! resources that were dynamically created by controllers at runtime
|
||||
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||
#@schema/title "Into namespace"
|
||||
#@ into_namespace_desc = "If specified, assumes that a namespace of the given name already exists and installs the app into that namespace. \
|
||||
#@ If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used."
|
||||
#@schema/desc into_namespace_desc
|
||||
#@schema/examples ("The name of an existing namespace", "my-preexisting-namespace")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
into_namespace: ""
|
||||
|
||||
#! Specify how many replicas of the Pinniped server to run.
|
||||
#@schema/title "Custom labels"
|
||||
#@ custom_labels_desc = "All resources created statically by yaml at install-time and all resources created dynamically \
|
||||
#@ by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here. The value of \
|
||||
#@ `custom_labels` must be a map of string keys to string values. The app can be uninstalled either by: 1.) deleting the \
|
||||
#@ static install-time yaml resources including the static namespace, which will cascade and also delete \
|
||||
#@ resources that were dynamically created by controllers at runtime, or 2.) deleting all resources by label, which does \
|
||||
#@ not assume that there was a static install-time yaml namespace."
|
||||
#@schema/desc custom_labels_desc
|
||||
#@schema/examples ("Example set of labels", {"myCustomLabelName": "myCustomLabelValue", "otherCustomLabelName": "otherCustomLabelValue"})
|
||||
#@schema/type any=True
|
||||
#@schema/validation ("a map of string keys and string values", validate_strings_map)
|
||||
custom_labels: { }
|
||||
|
||||
#@schema/title "Replicas"
|
||||
#@schema/desc "Specify how many replicas of the Pinniped server to run."
|
||||
replicas: 2
|
||||
|
||||
#! Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest: #! e.g. sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||
#@schema/title "Image repo"
|
||||
#@schema/desc "The repository for the Concierge container image."
|
||||
#@schema/validation min_len=1
|
||||
image_repo: ghcr.io/vmware-tanzu/pinniped/pinniped-server
|
||||
|
||||
#@schema/title "Image digest"
|
||||
#@schema/desc "The image digest for the Concierge container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Providing a digest", "sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_tag"] == None
|
||||
image_digest: ""
|
||||
|
||||
#@schema/title "Image tag"
|
||||
#@schema/desc "The image tag for the Concierge container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Providing a tag", "v0.25.0")
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_digest"] == None
|
||||
image_tag: latest
|
||||
|
||||
#! Optionally specify a different image for the "kube-cert-agent" pod which is scheduled
|
||||
#! on the control plane. This image needs only to include `sleep` and `cat` binaries.
|
||||
#! By default, the same image specified for image_repo/image_digest/image_tag will be re-used.
|
||||
kube_cert_agent_image:
|
||||
#@schema/title "Kube Cert Agent image"
|
||||
#@ kube_cert_agent_image = "Optionally specify a different image for the 'kube-cert-agent' pod which is scheduled \
|
||||
#@ on the control plane. This image needs only to include `sleep` and `cat` binaries. \
|
||||
#@ By default, the same image specified for image_repo/image_digest/image_tag will be re-used."
|
||||
#@schema/desc kube_cert_agent_image
|
||||
#@schema/examples ("Image including tag or digest", "ghcr.io/vmware-tanzu/pinniped/pinniped-server:latest")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
kube_cert_agent_image: ""
|
||||
|
||||
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||
#! Can be used when the above image_repo is a private registry.
|
||||
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||
#! Optional.
|
||||
image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||
#@schema/title "Image pull dockerconfigjson"
|
||||
#@ image_pull_dockerconfigjson_desc = "A base64 encoded secret to be used when pulling the `image_repo` container image. \
|
||||
#@ Can be used when the image_repo is a private registry. Typically, the value would be the output of: \
|
||||
#@ kubectl create secret docker-registry x --docker-server=https://example.io --docker-username='USERNAME' --docker-password='PASSWORD' --dry-run=client -o json | jq -r '.data[\".dockerconfigjson\"]'"
|
||||
#@schema/desc image_pull_dockerconfigjson_desc
|
||||
#@ example_desc = 'base64 encoding of: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}'
|
||||
#@ example_value = "eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUuaW8iOnsidXNlcm5hbWUiOiJVU0VSTkFNRSIsInBhc3N3b3JkIjoiUEFTU1dPUkQiLCJhdXRoIjoiVlZORlVrNUJUVVU2VUVGVFUxZFBVa1E9In19fQ=="
|
||||
#@schema/examples (example_desc, example_value)
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
image_pull_dockerconfigjson: ""
|
||||
|
||||
#! Pinniped will try to guess the right K8s API URL for sharing that information with potential clients.
|
||||
#! This setting allows the guess to be overridden.
|
||||
#! Optional.
|
||||
discovery_url: #! e.g., https://example.com
|
||||
#@schema/title "Discovery URL"
|
||||
#@schema/desc "Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden."
|
||||
#@schema/examples ("Kubernetes API URL","https://example.com")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
discovery_url: ""
|
||||
|
||||
#! Specify the duration and renewal interval for the API serving certificate.
|
||||
#! The defaults are set to expire the cert about every 30 days, and to rotate it
|
||||
#! about every 25 days.
|
||||
#@schema/title "API serving certificate duration seconds"
|
||||
#@ api_serving_certificate_duration_seconds_desc = "Specify the duration for the API serving certificate. \
|
||||
#@ The default is set to expire the cert about every 30 days. \
|
||||
#@ Specify this as an integer or as a string which contains an integer value."
|
||||
#@schema/desc api_serving_certificate_duration_seconds_desc
|
||||
#@schema/type any=True
|
||||
#@schema/validation ("an int or string which contains an integer value", lambda v: type(v) in ["int", "string"])
|
||||
api_serving_certificate_duration_seconds: 2592000
|
||||
|
||||
#@schema/title "API serving certificate renew before seconds"
|
||||
#@ api_serving_certificate_renew_before_seconds_desc = "Specify the renewal interval for the API serving certificate. \
|
||||
#@ The default is set to rotate it about every 25 days. \
|
||||
#@ Specify this as an integer or as a string which contains an integer value."
|
||||
#@schema/desc api_serving_certificate_renew_before_seconds_desc
|
||||
#@schema/type any=True
|
||||
#@schema/validation ("an int or string which contains an integer value", lambda v: type(v) in ["int", "string"])
|
||||
api_serving_certificate_renew_before_seconds: 2160000
|
||||
|
||||
#! Specify the verbosity of logging: info ("nice to know" information), debug (developer
|
||||
#! information), trace (timing information), all (kitchen sink).
|
||||
log_level: #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||
#! Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs).
|
||||
#! By default, when this value is left unset, logs are formatted in json.
|
||||
#! This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.
|
||||
deprecated_log_format:
|
||||
#@schema/title "Log level"
|
||||
#@ log_level_desc = "Specify the verbosity of logging: info (\"nice to know\" information), debug (developer information), trace (timing information), \
|
||||
#@ or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged. \
|
||||
#@ When this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs."
|
||||
#@schema/desc log_level_desc
|
||||
#@schema/examples ("Developer logging information","debug")
|
||||
#@schema/nullable
|
||||
#@schema/validation one_of=["info", "debug", "trace", "all"]
|
||||
log_level: ""
|
||||
|
||||
run_as_user: 65532 #! run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
run_as_group: 65532 #! run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
#@schema/title "Run as user"
|
||||
#@schema/desc "The user ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_user: 65532
|
||||
|
||||
#! Specify the API group suffix for all Pinniped API groups. By default, this is set to
|
||||
#! pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev,
|
||||
#! authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then
|
||||
#! Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
#@schema/title "Run as group"
|
||||
#@schema/desc "The group ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_group: 65532
|
||||
|
||||
#@schema/title "API group suffix"
|
||||
#@ api_group_suffix_desc = "Specify the API group suffix for all Pinniped API groups. By default, this is set to \
|
||||
#@ pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, \
|
||||
#@ authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then \
|
||||
#@ Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc."
|
||||
#@schema/desc api_group_suffix_desc
|
||||
#@schema/validation min_len=1
|
||||
api_group_suffix: pinniped.dev
|
||||
|
||||
#! Customize CredentialIssuer.spec.impersonationProxy to change how the concierge
|
||||
#! handles impersonation.
|
||||
#@schema/title "Impersonation proxy spec"
|
||||
#@schema/desc "Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation."
|
||||
impersonation_proxy_spec:
|
||||
#! options are "auto", "disabled" or "enabled".
|
||||
#! If auto, the impersonation proxy will run only if the cluster signing key is not available
|
||||
#! and the other strategy does not work.
|
||||
#! If disabled, the impersonation proxy will never run, which could mean that the concierge
|
||||
#! doesn't work at all.
|
||||
#! If enabled, the impersonation proxy will always run regardless of other strategies available.
|
||||
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
|
||||
#@schema/title "Mode"
|
||||
#@ impersonation_mode_desc = "Enables or disables the impersonation proxy. 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 enabled, the impersonation proxy will always run regardless of other strategies available. \
|
||||
#@ If disabled, the impersonation proxy will never run, which could mean \
|
||||
#@ that the concierge doesn't work at all."
|
||||
#@schema/desc impersonation_mode_desc
|
||||
#@schema/validation one_of=["auto", "disabled", "enabled"]
|
||||
mode: auto
|
||||
|
||||
#@schema/title "External endpoint"
|
||||
#@ external_endpoint_desc = "The endpoint which the client should use to connect to the impersonation proxy. \
|
||||
#@ If left unset, the client will default to connecting based on the ClusterIP or LoadBalancer endpoint."
|
||||
#@schema/desc external_endpoint_desc
|
||||
#@schema/examples ("Specified impersonation proxy endpoint", "https://1.2.3.4:5678")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
external_endpoint: ""
|
||||
|
||||
#@schema/title "Service"
|
||||
#@schema/desc "The impersonation proxy service configuration"
|
||||
service:
|
||||
|
||||
#@schema/title "Type"
|
||||
#@ impersonation_service_type_desc = "Service backing the impersonation proxy. Options are 'LoadBalancer', 'ClusterIP' \
|
||||
#@ and 'None'. LoadBalancer automatically provisions a Service of type LoadBalancer pointing at the impersonation \
|
||||
#@ proxy. Some cloud providers will allocate a public IP address by default even on private clusters. ClusterIP \
|
||||
#@ automatically provisions a Service of type ClusterIP pointing at the impersonation proxy. None does not provision \
|
||||
#@ either and assumes that you have set the external_endpoint and set up your own ingress to connect to the impersonation proxy."
|
||||
#@schema/desc impersonation_service_type_desc
|
||||
#@schema/validation one_of=["LoadBalancer", "ClusterIP", "None"]
|
||||
type: LoadBalancer
|
||||
|
||||
#@schema/title "Annotations"
|
||||
#@ annotations_desc = "The annotations that should be set on the ClusterIP or LoadBalancer Service. The default includes \
|
||||
#@ a value for the AWS-specific service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout annotation, which will \
|
||||
#@ be ignored except when using AWS to provide load balancer Services."
|
||||
#@schema/desc annotations_desc
|
||||
#@schema/nullable
|
||||
#@schema/type any=True
|
||||
#@schema/validation ("a map of string keys and string values", validate_strings_map)
|
||||
annotations:
|
||||
|
||||
#@schema/title "Load balancer IP"
|
||||
#@schema/desc "When mode LoadBalancer is set, this will set the LoadBalancer Service's spec.loadBalancerIP."
|
||||
#@schema/examples ("Specifying an IP", "1.2.3.4")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
load_balancer_ip: ""
|
||||
|
||||
#@schema/title "HTTPS proxy"
|
||||
#@ https_proxy_desc = "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. \
|
||||
#@ These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, \
|
||||
#@ e.g. when the Concierge fetches discovery documents and JWKS keys for JWTAuthenticators and POSTs to webhooks for WebhookAuthenticators. \
|
||||
#@ The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||
#@schema/desc https_proxy_desc
|
||||
#@schema/examples ("Providing a proxy endpoint","http://proxy.example.com")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
https_proxy: ""
|
||||
|
||||
#@schema/title "No proxy"
|
||||
#@ no_proxy_desc = "Endpoints that should not be proxied. Defaults to not proxying internal Kubernetes endpoints, \
|
||||
#@ localhost endpoints, and the known instance metadata IP address for public cloud providers."
|
||||
#@schema/desc no_proxy_desc
|
||||
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -76,6 +76,15 @@ spec:
|
||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||
seccompProfile:
|
||||
type: "RuntimeDefault"
|
||||
tolerations:
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: amd64 #! Allow running on amd64 nodes.
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: arm64 #! Also allow running on arm64 nodes.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
|
||||
@@ -1,19 +1,44 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@data/values
|
||||
#@data/values-schema
|
||||
---
|
||||
#@schema/title "Image repo"
|
||||
#@schema/desc "The repository for the local-user-authenticator container image."
|
||||
#@schema/validation min_len=1
|
||||
image_repo: ghcr.io/vmware-tanzu/pinniped/pinniped-server
|
||||
|
||||
#! Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest: #! e.g. sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||
#@schema/title "Image digest"
|
||||
#@schema/desc "The image digest for the local-user-authenticator container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Providing a digest", "sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_tag"] == None
|
||||
image_digest: ""
|
||||
|
||||
#@schema/title "Image tag"
|
||||
#@schema/desc "The image tag for the local-user-authenticator container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Providing a tag", "v0.25.0")
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_digest"] == None
|
||||
image_tag: latest
|
||||
|
||||
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||
#! Can be used when the above image_repo is a private registry.
|
||||
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||
#! Optional.
|
||||
image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||
#@schema/title "Image pull dockerconfigjson"
|
||||
#@ image_pull_dockerconfigjson_desc = "A base64 encoded secret to be used when pulling the `image_repo` container image. \
|
||||
#@ Can be used when the image_repo is a private registry. Typically, the value would be the output of: \
|
||||
#@ kubectl create secret docker-registry x --docker-server=https://example.io --docker-username='USERNAME' --docker-password='PASSWORD' --dry-run=client -o json | jq -r '.data[\".dockerconfigjson\"]'"
|
||||
#@schema/desc image_pull_dockerconfigjson_desc
|
||||
#@ example_desc = 'base64 encoding of: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}'
|
||||
#@ example_value = "eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUuaW8iOnsidXNlcm5hbWUiOiJVU0VSTkFNRSIsInBhc3N3b3JkIjoiUEFTU1dPUkQiLCJhdXRoIjoiVlZORlVrNUJUVVU2VUVGVFUxZFBVa1E9In19fQ=="
|
||||
#@schema/examples (example_desc, example_value)
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
image_pull_dockerconfigjson: ""
|
||||
|
||||
run_as_user: 65532 #! run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
run_as_group: 65532 #! run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
#@schema/title "Run as user"
|
||||
#@schema/desc "The user ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_user: 65532
|
||||
|
||||
#@schema/title "Run as group"
|
||||
#@schema/desc "The group ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_group: 65532
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -21,7 +20,7 @@ spec:
|
||||
- jsonPath: .spec.issuer
|
||||
name: Issuer
|
||||
type: string
|
||||
- jsonPath: .status.status
|
||||
- jsonPath: .status.phase
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
@@ -33,56 +32,294 @@ spec:
|
||||
description: FederationDomain describes the configuration of an OIDC provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
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'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec of the OIDC provider.
|
||||
properties:
|
||||
identityProviders:
|
||||
description: |-
|
||||
IdentityProviders is the list of identity providers available for use by this FederationDomain.
|
||||
|
||||
|
||||
An identity provider CR (e.g. OIDCIdentityProvider or LDAPIdentityProvider) describes how to connect to a server,
|
||||
how to talk in a specific protocol for authentication, and how to use the schema of that server/protocol to
|
||||
extract a normalized user identity. Normalized user identities include a username and a list of group names.
|
||||
In contrast, IdentityProviders describes how to use that normalized identity in those Kubernetes clusters which
|
||||
belong to this FederationDomain. Each entry in IdentityProviders can be configured with arbitrary transformations
|
||||
on that normalized identity. For example, a transformation can add a prefix to all usernames to help avoid
|
||||
accidental conflicts when multiple identity providers have different users with the same username (e.g.
|
||||
"idp1:ryan" versus "idp2:ryan"). Each entry in IdentityProviders can also implement arbitrary authentication
|
||||
rejection policies. Even though a user was able to authenticate with the identity provider, a policy can disallow
|
||||
the authentication to the Kubernetes clusters that belong to this FederationDomain. For example, a policy could
|
||||
disallow the authentication unless the user belongs to a specific group in the identity provider.
|
||||
|
||||
|
||||
For backwards compatibility with versions of Pinniped which predate support for multiple identity providers,
|
||||
an empty IdentityProviders list will cause the FederationDomain to use all available identity providers which
|
||||
exist in the same namespace, but also to reject all authentication requests when there is more than one identity
|
||||
provider currently defined. In this backwards compatibility mode, the name of the identity provider resource
|
||||
(e.g. the Name of an OIDCIdentityProvider resource) will be used as the name of the identity provider in this
|
||||
FederationDomain. This mode is provided to make upgrading from older versions easier. However, instead of
|
||||
relying on this backwards compatibility mode, please consider this mode to be deprecated and please instead
|
||||
explicitly list the identity provider using this IdentityProviders field.
|
||||
items:
|
||||
description: FederationDomainIdentityProvider describes how an identity
|
||||
provider is made available in this FederationDomain.
|
||||
properties:
|
||||
displayName:
|
||||
description: |-
|
||||
DisplayName is the name of this identity provider as it will appear to clients. This name ends up in the
|
||||
kubeconfig of end users, so changing the name of an identity provider that is in use by end users will be a
|
||||
disruptive change for those users.
|
||||
minLength: 1
|
||||
type: string
|
||||
objectRef:
|
||||
description: |-
|
||||
ObjectRef is a reference to a Pinniped identity provider resource. A valid reference is required.
|
||||
If the reference cannot be resolved then the identity provider will not be made available.
|
||||
Must refer to a resource of one of the Pinniped identity provider types, e.g. OIDCIdentityProvider,
|
||||
LDAPIdentityProvider, ActiveDirectoryIdentityProvider.
|
||||
properties:
|
||||
apiGroup:
|
||||
description: |-
|
||||
APIGroup is the group for the resource being referenced.
|
||||
If APIGroup is not specified, the specified Kind must be in the core API group.
|
||||
For any other third-party types, APIGroup is required.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind is the type of resource being referenced
|
||||
type: string
|
||||
name:
|
||||
description: Name is the name of resource being referenced
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
transforms:
|
||||
description: |-
|
||||
Transforms is an optional way to specify transformations to be applied during user authentication and
|
||||
session refresh.
|
||||
properties:
|
||||
constants:
|
||||
description: Constants defines constant variables and their
|
||||
values which will be made available to the transform expressions.
|
||||
items:
|
||||
description: |-
|
||||
FederationDomainTransformsConstant defines a constant variable and its value which will be made available to
|
||||
the transform expressions. This is a union type, and Type is the discriminator field.
|
||||
properties:
|
||||
name:
|
||||
description: Name determines the name of the constant.
|
||||
It must be a valid identifier name.
|
||||
maxLength: 64
|
||||
minLength: 1
|
||||
pattern: ^[a-zA-Z][_a-zA-Z0-9]*$
|
||||
type: string
|
||||
stringListValue:
|
||||
description: StringListValue should hold the value
|
||||
when Type is "stringList", and is otherwise ignored.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
stringValue:
|
||||
description: StringValue should hold the value when
|
||||
Type is "string", and is otherwise ignored.
|
||||
type: string
|
||||
type:
|
||||
description: Type determines the type of the constant,
|
||||
and indicates which other field should be non-empty.
|
||||
enum:
|
||||
- string
|
||||
- stringList
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- name
|
||||
x-kubernetes-list-type: map
|
||||
examples:
|
||||
description: |-
|
||||
Examples can optionally be used to ensure that the sequence of transformation expressions are working as
|
||||
expected. Examples define sample input identities which are then run through the expression list, and the
|
||||
results are compared to the expected results. If any example in this list fails, then this
|
||||
identity provider will not be available for use within this FederationDomain, and the error(s) will be
|
||||
added to the FederationDomain status. This can be used to help guard against programming mistakes in the
|
||||
expressions, and also act as living documentation for other administrators to better understand the expressions.
|
||||
items:
|
||||
description: FederationDomainTransformsExample defines
|
||||
a transform example.
|
||||
properties:
|
||||
expects:
|
||||
description: |-
|
||||
Expects is the expected output of the entire sequence of transforms when they are run against the
|
||||
input Username and Groups.
|
||||
properties:
|
||||
groups:
|
||||
description: Groups is the expected list of group
|
||||
names after the transformations have been applied.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
message:
|
||||
description: |-
|
||||
Message is the expected error message of the transforms. When Rejected is true, then Message is the expected
|
||||
message for the policy which rejected the authentication attempt. When Rejected is true and Message is blank,
|
||||
then Message will be treated as the default error message for authentication attempts which are rejected by a
|
||||
policy. When Rejected is false, then Message is the expected error message for some other non-policy
|
||||
transformation error, such as a runtime error. When Rejected is false, there is no default expected Message.
|
||||
type: string
|
||||
rejected:
|
||||
description: |-
|
||||
Rejected is a boolean that indicates whether authentication is expected to be rejected by a policy expression
|
||||
after the transformations have been applied. True means that it is expected that the authentication would be
|
||||
rejected. The default value of false means that it is expected that the authentication would not be rejected
|
||||
by any policy expression.
|
||||
type: boolean
|
||||
username:
|
||||
description: Username is the expected username
|
||||
after the transformations have been applied.
|
||||
type: string
|
||||
type: object
|
||||
groups:
|
||||
description: Groups is the input list of group names.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
username:
|
||||
description: Username is the input username.
|
||||
minLength: 1
|
||||
type: string
|
||||
required:
|
||||
- expects
|
||||
- username
|
||||
type: object
|
||||
type: array
|
||||
expressions:
|
||||
description: |-
|
||||
Expressions are an optional list of transforms and policies to be executed in the order given during every
|
||||
authentication attempt, including during every session refresh.
|
||||
Each is a CEL expression. It may use the basic CEL language as defined in
|
||||
https://github.com/google/cel-spec/blob/master/doc/langdef.md plus the CEL string extensions defined in
|
||||
https://github.com/google/cel-go/tree/master/ext#strings.
|
||||
|
||||
|
||||
The username and groups extracted from the identity provider, and the constants defined in this CR, are
|
||||
available as variables in all expressions. The username is provided via a variable called `username` and
|
||||
the list of group names is provided via a variable called `groups` (which may be an empty list).
|
||||
Each user-provided constants is provided via a variable named `strConst.varName` for string constants
|
||||
and `strListConst.varName` for string list constants.
|
||||
|
||||
|
||||
The only allowed types for expressions are currently policy/v1, username/v1, and groups/v1.
|
||||
Each policy/v1 must return a boolean, and when it returns false, no more expressions from the list are evaluated
|
||||
and the authentication attempt is rejected.
|
||||
Transformations of type policy/v1 do not return usernames or group names, and therefore cannot change the
|
||||
username or group names.
|
||||
Each username/v1 transform must return the new username (a string), which can be the same as the old username.
|
||||
Transformations of type username/v1 do not return group names, and therefore cannot change the group names.
|
||||
Each groups/v1 transform must return the new groups list (list of strings), which can be the same as the old
|
||||
groups list.
|
||||
Transformations of type groups/v1 do not return usernames, and therefore cannot change the usernames.
|
||||
After each expression, the new (potentially changed) username or groups get passed to the following expression.
|
||||
|
||||
|
||||
Any compilation or static type-checking failure of any expression will cause an error status on the FederationDomain.
|
||||
During an authentication attempt, any unexpected runtime evaluation errors (e.g. division by zero) cause the
|
||||
authentication attempt to fail. When all expressions evaluate successfully, then the (potentially changed) username
|
||||
and group names have been decided for that authentication attempt.
|
||||
items:
|
||||
description: FederationDomainTransformsExpression defines
|
||||
a transform expression.
|
||||
properties:
|
||||
expression:
|
||||
description: Expression is a CEL expression that will
|
||||
be evaluated based on the Type during an authentication.
|
||||
minLength: 1
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
Message is only used when Type is policy/v1. It defines an error message to be used when the policy rejects
|
||||
an authentication attempt. When empty, a default message will be used.
|
||||
type: string
|
||||
type:
|
||||
description: Type determines the type of the expression.
|
||||
It must be one of the supported types.
|
||||
enum:
|
||||
- policy/v1
|
||||
- username/v1
|
||||
- groups/v1
|
||||
type: string
|
||||
required:
|
||||
- expression
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
required:
|
||||
- displayName
|
||||
- objectRef
|
||||
type: object
|
||||
type: array
|
||||
issuer:
|
||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||
Metadata document, as well as the identifier that it will use for
|
||||
the iss claim in issued JWTs. This field will also be used as the
|
||||
base URL for any endpoints used by the OIDC Provider (e.g., if your
|
||||
issuer is https://example.com/foo, then your authorization endpoint
|
||||
will look like https://example.com/foo/some/path/to/auth/endpoint).
|
||||
\n See https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3
|
||||
for more information."
|
||||
description: |-
|
||||
Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||
identifier that it will use for the iss claim in issued JWTs. This field will also be used as
|
||||
the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer is
|
||||
https://example.com/foo, then your authorization endpoint will look like
|
||||
https://example.com/foo/some/path/to/auth/endpoint).
|
||||
|
||||
|
||||
See
|
||||
https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
minLength: 1
|
||||
type: string
|
||||
tls:
|
||||
description: TLS configures how this FederationDomain is served over
|
||||
Transport Layer Security (TLS).
|
||||
description: TLS specifies a secret which will contain Transport Layer
|
||||
Security (TLS) configuration for the FederationDomain.
|
||||
properties:
|
||||
secretName:
|
||||
description: "SecretName is an optional name of a Secret in the
|
||||
same namespace, of type `kubernetes.io/tls`, which contains
|
||||
the TLS serving certificate for the HTTPS endpoints served by
|
||||
this FederationDomain. When provided, the TLS Secret named here
|
||||
must contain keys named `tls.crt` and `tls.key` that contain
|
||||
the certificate and private key to use for TLS. \n Server Name
|
||||
Indication (SNI) is an extension to the Transport Layer Security
|
||||
(TLS) supported by all major browsers. \n SecretName is required
|
||||
if you would like to use different TLS certificates for issuers
|
||||
of different hostnames. SNI requests do not include port numbers,
|
||||
so all issuers with the same DNS hostname must use the same
|
||||
SecretName value even if they have different port numbers. \n
|
||||
SecretName is not required when you would like to use only the
|
||||
HTTP endpoints (e.g. when the HTTP listener is configured to
|
||||
listen on loopback interfaces or UNIX domain sockets for traffic
|
||||
from a service mesh sidecar). It is also not required when you
|
||||
would like all requests to this OIDC Provider's HTTPS endpoints
|
||||
to use the default TLS certificate, which is configured elsewhere.
|
||||
\n When your Issuer URL's host is an IP address, then this field
|
||||
is ignored. SNI does not work for IP addresses."
|
||||
description: |-
|
||||
SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains
|
||||
the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret
|
||||
named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use
|
||||
for TLS.
|
||||
|
||||
|
||||
Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers.
|
||||
|
||||
|
||||
SecretName is required if you would like to use different TLS certificates for issuers of different hostnames.
|
||||
SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same
|
||||
SecretName value even if they have different port numbers.
|
||||
|
||||
|
||||
SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is
|
||||
configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar).
|
||||
It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to
|
||||
use the default TLS certificate, which is configured elsewhere.
|
||||
|
||||
|
||||
When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
@@ -91,69 +328,146 @@ spec:
|
||||
status:
|
||||
description: Status of the OIDC provider.
|
||||
properties:
|
||||
lastUpdateTime:
|
||||
description: LastUpdateTime holds the time at which the Status was
|
||||
last updated. It is a pointer to get around some undesirable behavior
|
||||
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message provides human-readable details about the Status.
|
||||
conditions:
|
||||
description: Conditions represent the observations of an FederationDomain's
|
||||
current state.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
---
|
||||
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the FederationDomain.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
secrets:
|
||||
description: Secrets contains information about this OIDC Provider's
|
||||
secrets.
|
||||
properties:
|
||||
jwks:
|
||||
description: JWKS holds the name of the corev1.Secret in which
|
||||
this OIDC Provider's signing/verification keys are stored. If
|
||||
it is empty, then the signing/verification keys are either unknown
|
||||
or they don't exist.
|
||||
description: |-
|
||||
JWKS holds the name of the corev1.Secret in which this OIDC Provider's signing/verification keys are
|
||||
stored. If it is empty, then the signing/verification keys are either unknown or they don't
|
||||
exist.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
stateEncryptionKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for encrypting state parameters
|
||||
is stored.
|
||||
description: |-
|
||||
StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
encrypting state parameters is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
stateSigningKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for signing state parameters
|
||||
is stored.
|
||||
description: |-
|
||||
StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
signing state parameters is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
tokenSigningKey:
|
||||
description: TokenSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for signing tokens is stored.
|
||||
description: |-
|
||||
TokenSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
signing tokens is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
type: object
|
||||
status:
|
||||
description: Status holds an enum that describes the state of this
|
||||
OIDC Provider. Note that this Status can represent success or failure.
|
||||
enum:
|
||||
- Success
|
||||
- Duplicate
|
||||
- Invalid
|
||||
- SameIssuerHostMustUseSameSecret
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
@@ -162,9 +476,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
@@ -36,14 +35,19 @@ spec:
|
||||
description: OIDCClient describes the configuration of an OIDC client.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
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'
|
||||
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
|
||||
@@ -51,17 +55,19 @@ spec:
|
||||
description: Spec of the OIDC client.
|
||||
properties:
|
||||
allowedGrantTypes:
|
||||
description: "allowedGrantTypes is a list of the allowed grant_type
|
||||
param values that should be accepted during OIDC flows with this
|
||||
client. \n Must only contain the following values: - authorization_code:
|
||||
allows the client to perform the authorization code grant flow,
|
||||
i.e. allows the webapp to authenticate users. This grant must always
|
||||
be listed. - refresh_token: allows the client to perform refresh
|
||||
grants for the user to extend the user's session. This grant must
|
||||
be listed if allowedScopes lists offline_access. - urn:ietf:params:oauth:grant-type:token-exchange:
|
||||
allows the client to perform RFC8693 token exchange, which is a
|
||||
step in the process to be able to get a cluster credential for the
|
||||
user. This grant must be listed if allowedScopes lists pinniped:request-audience."
|
||||
description: |-
|
||||
allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this
|
||||
client.
|
||||
|
||||
|
||||
Must only contain the following values:
|
||||
- authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to
|
||||
authenticate users. This grant must always be listed.
|
||||
- refresh_token: allows the client to perform refresh grants for the user to extend the user's session.
|
||||
This grant must be listed if allowedScopes lists offline_access.
|
||||
- urn:ietf:params:oauth:grant-type:token-exchange: allows the client to perform RFC8693 token exchange,
|
||||
which is a step in the process to be able to get a cluster credential for the user.
|
||||
This grant must be listed if allowedScopes lists pinniped:request-audience.
|
||||
items:
|
||||
enum:
|
||||
- authorization_code
|
||||
@@ -72,12 +78,11 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
allowedRedirectURIs:
|
||||
description: allowedRedirectURIs is a list of the allowed redirect_uri
|
||||
param values that should be accepted during OIDC flows with this
|
||||
client. Any other uris will be rejected. Must be a URI with the
|
||||
https scheme, unless the hostname is 127.0.0.1 or ::1 which may
|
||||
use the http scheme. Port numbers are not required for 127.0.0.1
|
||||
or ::1 and are ignored when checking for a matching redirect_uri.
|
||||
description: |-
|
||||
allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||
client. Any other uris will be rejected.
|
||||
Must be a URI with the https scheme, unless the hostname is 127.0.0.1 or ::1 which may use the http scheme.
|
||||
Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking for a matching redirect_uri.
|
||||
items:
|
||||
pattern: ^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/
|
||||
type: string
|
||||
@@ -85,27 +90,24 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
allowedScopes:
|
||||
description: "allowedScopes is a list of the allowed scopes param
|
||||
values that should be accepted during OIDC flows with this client.
|
||||
\n Must only contain the following values: - openid: The client
|
||||
is allowed to request ID tokens. ID tokens only include the required
|
||||
claims by default (iss, sub, aud, exp, iat). This scope must always
|
||||
be listed. - offline_access: The client is allowed to request an
|
||||
initial refresh token during the authorization code grant flow.
|
||||
This scope must be listed if allowedGrantTypes lists refresh_token.
|
||||
- pinniped:request-audience: The client is allowed to request a
|
||||
new audience value during a RFC8693 token exchange, which is a step
|
||||
in the process to be able to get a cluster credential for the user.
|
||||
openid, username and groups scopes must be listed when this scope
|
||||
is present. This scope must be listed if allowedGrantTypes lists
|
||||
urn:ietf:params:oauth:grant-type:token-exchange. - username: The
|
||||
client is allowed to request that ID tokens contain the user's username.
|
||||
Without the username scope being requested and allowed, the ID token
|
||||
will not contain the user's username. - groups: The client is allowed
|
||||
to request that ID tokens contain the user's group membership, if
|
||||
their group membership is discoverable by the Supervisor. Without
|
||||
the groups scope being requested and allowed, the ID token will
|
||||
not contain groups."
|
||||
description: |-
|
||||
allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client.
|
||||
|
||||
|
||||
Must only contain the following values:
|
||||
- openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat).
|
||||
This scope must always be listed.
|
||||
- offline_access: The client is allowed to request an initial refresh token during the authorization code grant flow.
|
||||
This scope must be listed if allowedGrantTypes lists refresh_token.
|
||||
- pinniped:request-audience: The client is allowed to request a new audience value during a RFC8693 token exchange,
|
||||
which is a step in the process to be able to get a cluster credential for the user.
|
||||
openid, username and groups scopes must be listed when this scope is present.
|
||||
This scope must be listed if allowedGrantTypes lists urn:ietf:params:oauth:grant-type:token-exchange.
|
||||
- username: The client is allowed to request that ID tokens contain the user's username.
|
||||
Without the username scope being requested and allowed, the ID token will not contain the user's username.
|
||||
- groups: The client is allowed to request that ID tokens contain the user's group membership,
|
||||
if their group membership is discoverable by the Supervisor.
|
||||
Without the groups scope being requested and allowed, the ID token will not contain groups.
|
||||
items:
|
||||
enum:
|
||||
- openid
|
||||
@@ -117,6 +119,27 @@ spec:
|
||||
minItems: 1
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
tokenLifetimes:
|
||||
description: tokenLifetimes are the optional overrides of token lifetimes
|
||||
for an OIDCClient.
|
||||
properties:
|
||||
idTokenSeconds:
|
||||
description: |-
|
||||
idTokenSeconds is the lifetime of ID tokens issued to this client, in seconds. This will choose the lifetime of
|
||||
ID tokens returned by the authorization flow and the refresh grant. It will not influence the lifetime of the ID
|
||||
tokens returned by RFC8693 token exchange. When null, a short-lived default value will be used.
|
||||
This value must be between 120 and 1,800 seconds (30 minutes), inclusive. It is recommended to make these tokens
|
||||
short-lived to force the client to perform the refresh grant often, because the refresh grant will check with the
|
||||
external identity provider to decide if it is acceptable for the end user to continue their session, and will
|
||||
update the end user's group memberships from the external identity provider. Giving these tokens a long life is
|
||||
will allow the end user to continue to use a token while avoiding these updates from the external identity
|
||||
provider. However, some web applications may have reasons specific to the design of that application to prefer
|
||||
longer lifetimes.
|
||||
format: int32
|
||||
maximum: 1800
|
||||
minimum: 120
|
||||
type: integer
|
||||
type: object
|
||||
required:
|
||||
- allowedGrantTypes
|
||||
- allowedRedirectURIs
|
||||
@@ -129,37 +152,43 @@ spec:
|
||||
description: conditions represent the observations of an OIDCClient's
|
||||
current state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -173,11 +202,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -213,9 +243,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -190,6 +190,15 @@ spec:
|
||||
- name: socket
|
||||
emptyDir: {}
|
||||
#@ end
|
||||
tolerations:
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: amd64 #! Allow running on amd64 nodes.
|
||||
- key: kubernetes.io/arch
|
||||
effect: NoSchedule
|
||||
operator: Equal
|
||||
value: arm64 #! Also allow running on arm64 nodes.
|
||||
#! This will help make sure our multiple pods run on different nodes, making
|
||||
#! our deployment "more" "HA".
|
||||
affinity:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -53,17 +53,11 @@ _: #@ template.replace(data.values.custom_labels)
|
||||
#@ "apiService": defaultResourceNameWithSuffix("api"),
|
||||
#@ },
|
||||
#@ "labels": labels(),
|
||||
#@ "insecureAcceptExternalUnencryptedHttpRequests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests
|
||||
#@ }
|
||||
#@ if data.values.log_level or data.values.deprecated_log_format:
|
||||
#@ config["log"] = {}
|
||||
#@ end
|
||||
#@ if data.values.log_level:
|
||||
#@ config["log"] = {}
|
||||
#@ config["log"]["level"] = getAndValidateLogLevel()
|
||||
#@ end
|
||||
#@ if data.values.deprecated_log_format:
|
||||
#@ config["log"]["format"] = data.values.deprecated_log_format
|
||||
#@ end
|
||||
#@ if data.values.endpoints:
|
||||
#@ config["endpoints"] = data.values.endpoints
|
||||
#@ end
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@@ -36,14 +35,19 @@ spec:
|
||||
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'
|
||||
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'
|
||||
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
|
||||
@@ -51,19 +55,16 @@ 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.
|
||||
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".
|
||||
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
|
||||
@@ -75,73 +76,86 @@ spec:
|
||||
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.
|
||||
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.
|
||||
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).
|
||||
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.
|
||||
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={})"
|
||||
description: |-
|
||||
Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.
|
||||
The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
|
||||
value of an attribute of the user entry found as a result of the user search. Which attribute's
|
||||
value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||
E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||
For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
||||
Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
|
||||
Optional. When not specified, the default will act as if the filter were specified as
|
||||
"(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
|
||||
This searches nested groups by default.
|
||||
Note that nested group search can be slow for some Active Directory servers. To disable it,
|
||||
you can set the filter to
|
||||
"(&(objectClass=group)(member={})"
|
||||
type: string
|
||||
skipGroupRefresh:
|
||||
description: "The user's group membership is refreshed as they
|
||||
interact with the supervisor to obtain new credentials (as their
|
||||
old credentials expire). This allows group membership changes
|
||||
to be quickly reflected into Kubernetes clusters. Since group
|
||||
membership is often used to bind authorization policies, it
|
||||
is important to keep the groups observed in Kubernetes clusters
|
||||
in-sync with the identity provider. \n In some environments,
|
||||
frequent group membership queries may result in a significant
|
||||
performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak
|
||||
the group query to be more performant, for example by disabling
|
||||
nested group search or by using a more targeted group search
|
||||
base. \n If the group search query cannot be made performant
|
||||
and you are willing to have group memberships remain static
|
||||
for approximately a day, then set skipGroupRefresh to true.
|
||||
\ This is an insecure configuration as authorization policies
|
||||
that are bound to group membership will not notice if a user
|
||||
has been removed from a particular group until their next login.
|
||||
\n This is an experimental feature that may be removed or significantly
|
||||
altered in the future. Consumers of this configuration should
|
||||
carefully read all release notes before upgrading to ensure
|
||||
that the meaning of this field has not changed."
|
||||
description: |-
|
||||
The user's group membership is refreshed as they interact with the supervisor
|
||||
to obtain new credentials (as their old credentials expire). This allows group
|
||||
membership changes to be quickly reflected into Kubernetes clusters. Since
|
||||
group membership is often used to bind authorization policies, it is important
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity
|
||||
provider.
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a
|
||||
significant performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak the group query
|
||||
to be more performant, for example by disabling nested group search or by
|
||||
using a more targeted group search base.
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to
|
||||
have group memberships remain static for approximately a day, then set
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization
|
||||
policies that are bound to group membership will not notice if a user has
|
||||
been removed from a particular group until their next login.
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered
|
||||
in the future. Consumers of this configuration should carefully read all
|
||||
release notes before upgrading to ensure that the meaning of this field has
|
||||
not changed.
|
||||
type: boolean
|
||||
userAttributeForFilter:
|
||||
description: |-
|
||||
UserAttributeForFilter specifies which attribute's value from the user entry found as a result of
|
||||
the user search will be used to replace the "{}" placeholder(s) in the group search Filter.
|
||||
For example, specifying "uid" as the UserAttributeForFilter while specifying
|
||||
"&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing
|
||||
the "{}" placeholder in the Filter with the value of the user's "uid" attribute.
|
||||
Optional. When not specified, the default will act as if "dn" were specified. For example, leaving
|
||||
UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter
|
||||
would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||
type: string
|
||||
type: object
|
||||
host:
|
||||
description: 'Host is the hostname of this Active Directory identity
|
||||
@@ -162,49 +176,46 @@ spec:
|
||||
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.
|
||||
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".
|
||||
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".
|
||||
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).
|
||||
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.
|
||||
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.
|
||||
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:
|
||||
@@ -217,37 +228,43 @@ spec:
|
||||
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.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -261,11 +278,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -296,9 +314,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@@ -32,18 +31,24 @@ spec:
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: LDAPIdentityProvider describes the configuration of an upstream
|
||||
Lightweight Directory Access Protocol (LDAP) identity provider.
|
||||
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'
|
||||
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'
|
||||
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
|
||||
@@ -51,20 +56,17 @@ 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.
|
||||
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.
|
||||
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:
|
||||
@@ -75,65 +77,76 @@ spec:
|
||||
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.
|
||||
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
|
||||
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).
|
||||
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.
|
||||
description: |-
|
||||
Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.
|
||||
"ou=groups,dc=example,dc=com". When not specified, no group search will be performed and
|
||||
authenticated users will not belong to any groups from the LDAP provider. Also, when not specified,
|
||||
the values of Filter, UserAttributeForFilter, Attributes, and SkipGroupRefresh are ignored.
|
||||
type: string
|
||||
filter:
|
||||
description: Filter is the LDAP search filter which should be
|
||||
applied when searching for groups for a user. The pattern "{}"
|
||||
must occur in the filter at least once and will be dynamically
|
||||
replaced by the dn (distinguished name) of the user entry found
|
||||
as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||
description: |-
|
||||
Filter is the LDAP search filter which should be applied when searching for groups for a user.
|
||||
The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the
|
||||
value of an attribute of the user entry found as a result of the user search. Which attribute's
|
||||
value is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||
For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
||||
Note that the dn (distinguished name) is not an attribute of
|
||||
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
||||
the default will act as if the Filter were specified as "member={}".
|
||||
Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used.
|
||||
Optional. When not specified, the default will act as if the Filter were specified as "member={}".
|
||||
type: string
|
||||
skipGroupRefresh:
|
||||
description: "The user's group membership is refreshed as they
|
||||
interact with the supervisor to obtain new credentials (as their
|
||||
old credentials expire). This allows group membership changes
|
||||
to be quickly reflected into Kubernetes clusters. Since group
|
||||
membership is often used to bind authorization policies, it
|
||||
is important to keep the groups observed in Kubernetes clusters
|
||||
in-sync with the identity provider. \n In some environments,
|
||||
frequent group membership queries may result in a significant
|
||||
performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak
|
||||
the group query to be more performant, for example by disabling
|
||||
nested group search or by using a more targeted group search
|
||||
base. \n If the group search query cannot be made performant
|
||||
and you are willing to have group memberships remain static
|
||||
for approximately a day, then set skipGroupRefresh to true.
|
||||
\ This is an insecure configuration as authorization policies
|
||||
that are bound to group membership will not notice if a user
|
||||
has been removed from a particular group until their next login.
|
||||
\n This is an experimental feature that may be removed or significantly
|
||||
altered in the future. Consumers of this configuration should
|
||||
carefully read all release notes before upgrading to ensure
|
||||
that the meaning of this field has not changed."
|
||||
description: |-
|
||||
The user's group membership is refreshed as they interact with the supervisor
|
||||
to obtain new credentials (as their old credentials expire). This allows group
|
||||
membership changes to be quickly reflected into Kubernetes clusters. Since
|
||||
group membership is often used to bind authorization policies, it is important
|
||||
to keep the groups observed in Kubernetes clusters in-sync with the identity
|
||||
provider.
|
||||
|
||||
|
||||
In some environments, frequent group membership queries may result in a
|
||||
significant performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak the group query
|
||||
to be more performant, for example by disabling nested group search or by
|
||||
using a more targeted group search base.
|
||||
|
||||
|
||||
If the group search query cannot be made performant and you are willing to
|
||||
have group memberships remain static for approximately a day, then set
|
||||
skipGroupRefresh to true. This is an insecure configuration as authorization
|
||||
policies that are bound to group membership will not notice if a user has
|
||||
been removed from a particular group until their next login.
|
||||
|
||||
|
||||
This is an experimental feature that may be removed or significantly altered
|
||||
in the future. Consumers of this configuration should carefully read all
|
||||
release notes before upgrading to ensure that the meaning of this field has
|
||||
not changed.
|
||||
type: boolean
|
||||
userAttributeForFilter:
|
||||
description: |-
|
||||
UserAttributeForFilter specifies which attribute's value from the user entry found as a result of
|
||||
the user search will be used to replace the "{}" placeholder(s) in the group search Filter.
|
||||
For example, specifying "uid" as the UserAttributeForFilter while specifying
|
||||
"&(objectClass=posixGroup)(memberUid={})" as the Filter would search for groups by replacing
|
||||
the "{}" placeholder in the Filter with the value of the user's "uid" attribute.
|
||||
Optional. When not specified, the default will act as if "dn" were specified. For example, leaving
|
||||
UserAttributeForFilter unspecified while specifying "&(objectClass=groupOfNames)(member={})" as the Filter
|
||||
would search for groups by replacing the "{}" placeholder(s) with the dn (distinguished name) of the user.
|
||||
type: string
|
||||
type: object
|
||||
host:
|
||||
description: 'Host is the hostname of this LDAP identity provider,
|
||||
@@ -154,54 +167,46 @@ spec:
|
||||
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.
|
||||
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".
|
||||
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.
|
||||
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".
|
||||
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.
|
||||
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:
|
||||
@@ -214,37 +219,43 @@ spec:
|
||||
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.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -258,11 +269,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -293,9 +305,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
@@ -36,14 +35,19 @@ spec:
|
||||
OpenID Connect identity provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
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'
|
||||
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
|
||||
@@ -51,39 +55,29 @@ spec:
|
||||
description: Spec for configuring the identity provider.
|
||||
properties:
|
||||
authorizationConfig:
|
||||
description: AuthorizationConfig holds information about how to form
|
||||
the OAuth2 authorization request parameters to be used with this
|
||||
OIDC identity provider.
|
||||
description: |-
|
||||
AuthorizationConfig holds information about how to form the OAuth2 authorization request
|
||||
parameters to be used with this OIDC identity provider.
|
||||
properties:
|
||||
additionalAuthorizeParameters:
|
||||
description: additionalAuthorizeParameters are extra query parameters
|
||||
that should be included in the authorize request to your OIDC
|
||||
provider in the authorization request during an OIDC Authorization
|
||||
Code Flow. By default, no extra parameters are sent. The standard
|
||||
parameters that will be sent are "response_type", "scope", "client_id",
|
||||
"state", "nonce", "code_challenge", "code_challenge_method",
|
||||
and "redirect_uri". These parameters cannot be included in this
|
||||
setting. Additionally, the "hd" parameter cannot be included
|
||||
in this setting at this time. The "hd" parameter is used by
|
||||
Google's OIDC provider to provide a hint as to which "hosted
|
||||
domain" the user should use during login. However, Pinniped
|
||||
does not yet support validating the hosted domain in the resulting
|
||||
ID token, so it is not yet safe to use this feature of Google's
|
||||
OIDC provider with Pinniped. This setting does not influence
|
||||
the parameters sent to the token endpoint in the Resource Owner
|
||||
Password Credentials Grant. The Pinniped Supervisor requires
|
||||
that your OIDC provider returns refresh tokens to the Supervisor
|
||||
from the authorization flows. Some OIDC providers may require
|
||||
a certain value for the "prompt" parameter in order to properly
|
||||
request refresh tokens. See the documentation of your OIDC provider's
|
||||
authorization endpoint for its requirements for what to include
|
||||
in the request in order to receive a refresh token in the response,
|
||||
if anything. If your provider requires the prompt parameter
|
||||
to request a refresh token, then include it here. Also note
|
||||
that most providers also require a certain scope to be requested
|
||||
in order to receive refresh tokens. See the additionalScopes
|
||||
setting for more information about using scopes to request refresh
|
||||
tokens.
|
||||
description: |-
|
||||
additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your
|
||||
OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra
|
||||
parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id",
|
||||
"state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be
|
||||
included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time.
|
||||
The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user
|
||||
should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting
|
||||
ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped.
|
||||
This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password
|
||||
Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the
|
||||
Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt"
|
||||
parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's
|
||||
authorization endpoint for its requirements for what to include in the request in order to receive a refresh
|
||||
token in the response, if anything. If your provider requires the prompt parameter to request a refresh token,
|
||||
then include it here. Also note that most providers also require a certain scope to be requested in order to
|
||||
receive refresh tokens. See the additionalScopes setting for more information about using scopes to request
|
||||
refresh tokens.
|
||||
items:
|
||||
description: Parameter is a key/value pair which represents
|
||||
a parameter in an HTTP request.
|
||||
@@ -103,121 +97,109 @@ spec:
|
||||
- name
|
||||
x-kubernetes-list-type: map
|
||||
additionalScopes:
|
||||
description: 'additionalScopes are the additional scopes that
|
||||
will be requested from your OIDC provider in the authorization
|
||||
request during an OIDC Authorization Code Flow and in the token
|
||||
request during a Resource Owner Password Credentials Grant.
|
||||
Note that the "openid" scope will always be requested regardless
|
||||
of the value in this setting, since it is always required according
|
||||
to the OIDC spec. By default, when this field is not set, the
|
||||
Supervisor will request the following scopes: "openid", "offline_access",
|
||||
"email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
|
||||
for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
||||
for a description of the "offline_access" scope. This default
|
||||
value may change in future versions of Pinniped as the standard
|
||||
evolves, or as common patterns used by providers who implement
|
||||
the standard in the ecosystem evolve. By setting this list to
|
||||
anything other than an empty list, you are overriding the default
|
||||
value, so you may wish to include some of "offline_access",
|
||||
"email", and "profile" in your override list. If you do not
|
||||
want any of these scopes to be requested, you may set this list
|
||||
to contain only "openid". Some OIDC providers may also require
|
||||
a scope to get access to the user''s group membership, in which
|
||||
case you may wish to include it in this list. Sometimes the
|
||||
scope to request the user''s group membership is called "groups",
|
||||
but unfortunately this is not specified in the OIDC standard.
|
||||
Generally speaking, you should include any scopes required to
|
||||
cause the appropriate claims to be the returned by your OIDC
|
||||
provider in the ID token or userinfo endpoint results for those
|
||||
claims which you would like to use in the oidcClaims settings
|
||||
to determine the usernames and group memberships of your Kubernetes
|
||||
users. See your OIDC provider''s documentation for more information
|
||||
about what scopes are available to request claims. Additionally,
|
||||
the Pinniped Supervisor requires that your OIDC provider returns
|
||||
refresh tokens to the Supervisor from these authorization flows.
|
||||
For most OIDC providers, the scope required to receive refresh
|
||||
tokens will be "offline_access". See the documentation of your
|
||||
OIDC provider''s authorization and token endpoints for its requirements
|
||||
for what to include in the request in order to receive a refresh
|
||||
token in the response, if anything. Note that it may be safe
|
||||
to send "offline_access" even to providers which do not require
|
||||
it, since the provider may ignore scopes that it does not understand
|
||||
or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3).
|
||||
In the unusual case that you must avoid sending the "offline_access"
|
||||
scope, then you must override the default value of this setting.
|
||||
This is required if your OIDC provider will reject the request
|
||||
when it includes "offline_access" (e.g. GitLab''s OIDC provider).'
|
||||
description: |-
|
||||
additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization
|
||||
request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials
|
||||
Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is
|
||||
always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request
|
||||
the following scopes: "openid", "offline_access", "email", and "profile". See
|
||||
https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email"
|
||||
scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the
|
||||
"offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves,
|
||||
or as common patterns used by providers who implement the standard in the ecosystem evolve.
|
||||
By setting this list to anything other than an empty list, you are overriding the
|
||||
default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list.
|
||||
If you do not want any of these scopes to be requested, you may set this list to contain only "openid".
|
||||
Some OIDC providers may also require a scope to get access to the user's group membership, in which case you
|
||||
may wish to include it in this list. Sometimes the scope to request the user's group membership is called
|
||||
"groups", but unfortunately this is not specified in the OIDC standard.
|
||||
Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by
|
||||
your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in
|
||||
the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See
|
||||
your OIDC provider's documentation for more information about what scopes are available to request claims.
|
||||
Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor
|
||||
from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be
|
||||
"offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its
|
||||
requirements for what to include in the request in order to receive a refresh token in the response, if anything.
|
||||
Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider
|
||||
may ignore scopes that it does not understand or require (see
|
||||
https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the
|
||||
"offline_access" scope, then you must override the default value of this setting. This is required if your OIDC
|
||||
provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
allowPasswordGrant:
|
||||
description: allowPasswordGrant, when true, will allow the use
|
||||
of OAuth 2.0's Resource Owner Password Credentials Grant (see
|
||||
https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to
|
||||
authenticate to the OIDC provider using a username and password
|
||||
without a web browser, in addition to the usual browser-based
|
||||
OIDC Authorization Code Flow. The Resource Owner Password Credentials
|
||||
Grant is not officially part of the OIDC specification, so it
|
||||
may not be supported by your OIDC provider. If your OIDC provider
|
||||
supports returning ID tokens from a Resource Owner Password
|
||||
Credentials Grant token request, then you can choose to set
|
||||
this field to true. This will allow end users to choose to present
|
||||
their username and password to the kubectl CLI (using the Pinniped
|
||||
plugin) to authenticate to the cluster, without using a web
|
||||
browser to log in as is customary in OIDC Authorization Code
|
||||
Flow. This may be convenient for users, especially for identities
|
||||
from your OIDC provider which are not intended to represent
|
||||
a human actor, such as service accounts performing actions in
|
||||
a CI/CD environment. Even if your OIDC provider supports it,
|
||||
you may wish to disable this behavior by setting this field
|
||||
to false when you prefer to only allow users of this OIDCIdentityProvider
|
||||
to log in via the browser-based OIDC Authorization Code Flow.
|
||||
Using the Resource Owner Password Credentials Grant means that
|
||||
the Pinniped CLI and Pinniped Supervisor will directly handle
|
||||
your end users' passwords (similar to LDAPIdentityProvider),
|
||||
and you will not be able to require multi-factor authentication
|
||||
or use the other web-based login features of your OIDC provider
|
||||
during Resource Owner Password Credentials Grant logins. allowPasswordGrant
|
||||
defaults to false.
|
||||
description: |-
|
||||
allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant
|
||||
(see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a
|
||||
username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow.
|
||||
The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be
|
||||
supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password
|
||||
Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose
|
||||
to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the
|
||||
cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be
|
||||
convenient for users, especially for identities from your OIDC provider which are not intended to represent a human
|
||||
actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it,
|
||||
you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this
|
||||
OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password
|
||||
Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords
|
||||
(similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other
|
||||
web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins.
|
||||
allowPasswordGrant defaults to false.
|
||||
type: boolean
|
||||
type: object
|
||||
claims:
|
||||
description: Claims provides the names of token claims that will be
|
||||
used when inspecting an identity from this OIDC identity provider.
|
||||
description: |-
|
||||
Claims provides the names of token claims that will be used when inspecting an identity from
|
||||
this OIDC identity provider.
|
||||
properties:
|
||||
additionalClaimMappings:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
AdditionalClaimMappings allows for additional arbitrary upstream claim values to be mapped into the
|
||||
"additionalClaims" claim of the ID tokens generated by the Supervisor. This should be specified as a map of
|
||||
new claim names as the keys, and upstream claim names as the values. These new claim names will be nested
|
||||
under the top-level "additionalClaims" claim in ID tokens generated by the Supervisor when this
|
||||
OIDCIdentityProvider was used for user authentication. These claims will be made available to all clients.
|
||||
This feature is not required to use the Supervisor to provide authentication for Kubernetes clusters, but can be
|
||||
used when using the Supervisor for other authentication purposes. When this map is empty or the upstream claims
|
||||
are not available, the "additionalClaims" claim will be excluded from the ID tokens generated by the Supervisor.
|
||||
type: object
|
||||
groups:
|
||||
description: Groups provides the name of the ID token claim or
|
||||
userinfo endpoint response claim that will be used to ascertain
|
||||
the groups to which an identity belongs. By default, the identities
|
||||
will not include any group memberships when this setting is
|
||||
not configured.
|
||||
description: |-
|
||||
Groups provides the name of the ID token claim or userinfo endpoint response claim that will be used to ascertain
|
||||
the groups to which an identity belongs. By default, the identities will not include any group memberships when
|
||||
this setting is not configured.
|
||||
type: string
|
||||
username:
|
||||
description: Username provides the name of the ID token claim
|
||||
or userinfo endpoint response claim that will be used to ascertain
|
||||
an identity's username. When not set, the username will be an
|
||||
automatically constructed unique string which will include the
|
||||
issuer URL of your OIDC provider along with the value of the
|
||||
"sub" (subject) claim from the ID token.
|
||||
description: |-
|
||||
Username provides the name of the ID token claim or userinfo endpoint response claim that will be used to
|
||||
ascertain an identity's username. When not set, the username will be an automatically constructed unique string
|
||||
which will include the issuer URL of your OIDC provider along with the value of the "sub" (subject) claim from
|
||||
the ID token.
|
||||
type: string
|
||||
type: object
|
||||
client:
|
||||
description: OIDCClient contains OIDC client information to be used
|
||||
used with this OIDC identity provider.
|
||||
description: |-
|
||||
OIDCClient contains OIDC client information to be used used with this OIDC identity
|
||||
provider.
|
||||
properties:
|
||||
secretName:
|
||||
description: SecretName contains the name of a namespace-local
|
||||
Secret object that provides the clientID and clientSecret for
|
||||
an OIDC client. If only the SecretName is specified in an OIDCClient
|
||||
struct, then it is expected that the Secret is of type "secrets.pinniped.dev/oidc-client"
|
||||
with keys "clientID" and "clientSecret".
|
||||
description: |-
|
||||
SecretName contains the name of a namespace-local Secret object that provides the clientID and
|
||||
clientSecret for an OIDC client. If only the SecretName is specified in an OIDCClient
|
||||
struct, then it is expected that the Secret is of type "secrets.pinniped.dev/oidc-client" with keys
|
||||
"clientID" and "clientSecret".
|
||||
type: string
|
||||
required:
|
||||
- secretName
|
||||
type: object
|
||||
issuer:
|
||||
description: Issuer is the issuer URL of this OIDC identity provider,
|
||||
i.e., where to fetch /.well-known/openid-configuration.
|
||||
description: |-
|
||||
Issuer is the issuer URL of this OIDC identity provider, i.e., where to fetch
|
||||
/.well-known/openid-configuration.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
@@ -241,37 +223,43 @@ spec:
|
||||
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.
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
@@ -285,11 +273,12 @@ spec:
|
||||
- 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)
|
||||
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
|
||||
@@ -320,9 +309,3 @@ spec:
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
@@ -131,7 +131,7 @@ rules:
|
||||
resources: [ apiservices ]
|
||||
verbs: [ get, list, patch, update, watch ]
|
||||
- apiGroups: [ admissionregistration.k8s.io ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations, validatingadmissionpolicies, validatingadmissionpolicybindings ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:assert", "assert")
|
||||
#@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix")
|
||||
|
||||
#@ if hasattr(data.values, "service_http_nodeport_port"):
|
||||
#@ assert.fail('value "service_http_nodeport_port" has been renamed to "deprecated_service_http_nodeport_port" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_nodeport_nodeport"):
|
||||
#@ assert.fail('value "service_http_nodeport_nodeport" has been renamed to "deprecated_service_http_nodeport_nodeport" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_loadbalancer_port"):
|
||||
#@ assert.fail('value "service_http_loadbalancer_port" has been renamed to "deprecated_service_http_loadbalancer_port" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_clusterip_port"):
|
||||
#@ assert.fail('value "service_http_clusterip_port" has been renamed to "deprecated_service_http_clusterip_port" and will be removed in a future release')
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_nodeport_port or data.values.service_https_nodeport_port:
|
||||
#@ if data.values.service_https_nodeport_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -33,15 +19,6 @@ spec:
|
||||
type: NodePort
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_nodeport_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_nodeport_port
|
||||
targetPort: 8080
|
||||
#@ if data.values.deprecated_service_http_nodeport_nodeport:
|
||||
nodePort: #@ data.values.deprecated_service_http_nodeport_nodeport
|
||||
#@ end
|
||||
#@ end
|
||||
#@ if data.values.service_https_nodeport_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
@@ -53,7 +30,7 @@ spec:
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_clusterip_port or data.values.service_https_clusterip_port:
|
||||
#@ if data.values.service_https_clusterip_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -68,12 +45,6 @@ spec:
|
||||
type: ClusterIP
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_clusterip_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_clusterip_port
|
||||
targetPort: 8080
|
||||
#@ end
|
||||
#@ if data.values.service_https_clusterip_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
@@ -82,7 +53,7 @@ spec:
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_loadbalancer_port or data.values.service_https_loadbalancer_port:
|
||||
#@ if data.values.service_https_loadbalancer_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -100,12 +71,6 @@ spec:
|
||||
loadBalancerIP: #@ data.values.service_loadbalancer_ip
|
||||
#@ end
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_loadbalancer_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_loadbalancer_port
|
||||
targetPort: 8080
|
||||
#@ end
|
||||
#@ if data.values.service_https_loadbalancer_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
|
||||
@@ -1,133 +1,205 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@data/values
|
||||
---
|
||||
#@ def validate_strings_map(obj):
|
||||
#@ # Returns True if obj is an associative data structure string→string, and False otherwise.
|
||||
#@ for key in obj:
|
||||
#@ if type(key) != "string" or type(obj[key]) != "string":
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ end
|
||||
#@ return True
|
||||
#@ end
|
||||
|
||||
#@data/values-schema
|
||||
---
|
||||
#@schema/title "App name"
|
||||
#@schema/desc "Used to help determine the names of various resources and labels."
|
||||
#@schema/validation min_len=1
|
||||
app_name: pinniped-supervisor
|
||||
|
||||
#! Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
#@schema/title "Namespace"
|
||||
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||
#@schema/validation min_len=1
|
||||
namespace: pinniped-supervisor
|
||||
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||
into_namespace: #! e.g. my-preexisting-namespace
|
||||
|
||||
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||
#! The app can be uninstalled either by:
|
||||
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||
#! resources that were dynamically created by controllers at runtime
|
||||
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||
#@schema/title "Into namespace"
|
||||
#@ into_namespace_desc = "If specified, assumes that a namespace of the given name already exists and installs the app into that namespace. \
|
||||
#@ If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used."
|
||||
#@schema/desc into_namespace_desc
|
||||
#@schema/examples ("The name of an existing namespace", "my-preexisting-namespace")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
into_namespace: ""
|
||||
|
||||
#! Specify how many replicas of the Pinniped server to run.
|
||||
#@schema/title "Custom labels"
|
||||
#@ custom_labels_desc = "All resources created statically by yaml at install-time and all resources created dynamically \
|
||||
#@ by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here. The value of \
|
||||
#@ `custom_labels` must be a map of string keys to string values. The app can be uninstalled either by: 1.) deleting the \
|
||||
#@ static install-time yaml resources including the static namespace, which will cascade and also delete \
|
||||
#@ resources that were dynamically created by controllers at runtime, or 2.) deleting all resources by label, which does \
|
||||
#@ not assume that there was a static install-time yaml namespace."
|
||||
#@schema/desc custom_labels_desc
|
||||
#@schema/examples ("Example set of labels", {"myCustomLabelName": "myCustomLabelValue", "otherCustomLabelName": "otherCustomLabelValue"})
|
||||
#@schema/type any=True
|
||||
#@schema/validation ("a map of keys and values", validate_strings_map)
|
||||
custom_labels: { }
|
||||
|
||||
#@schema/title "Replicas"
|
||||
#@schema/desc "Specify how many replicas of the Pinniped server to run."
|
||||
replicas: 2
|
||||
|
||||
#! Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest: #! e.g. sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||
#@schema/title "Image repo"
|
||||
#@schema/desc "The repository for the Supervisor container image."
|
||||
#@schema/validation min_len=1
|
||||
image_repo: ghcr.io/vmware-tanzu/pinniped/pinniped-server
|
||||
|
||||
#@schema/title "Image digest"
|
||||
#@schema/desc "The image digest for the Supervisor container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Digest", "sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_tag"] == None
|
||||
image_digest: ""
|
||||
|
||||
#@schema/title "Image tag"
|
||||
#@schema/desc "The image tag for the Supervisor container image. If both image_digest or an image_tag are given, only image_digest will be used."
|
||||
#@schema/examples ("Tag", "v0.25.0")
|
||||
#@schema/validation min_len=1, when=lambda _, ctx: ctx.parent["image_digest"] == None
|
||||
image_tag: latest
|
||||
|
||||
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||
#! Can be used when the above image_repo is a private registry.
|
||||
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||
#! Optional.
|
||||
image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||
#@schema/title "Image pull dockerconfigjson"
|
||||
#@ image_pull_dockerconfigjson_desc = "A base64 encoded secret to be used when pulling the `image_repo` container image. \
|
||||
#@ Can be used when the image_repo is a private registry. Typically, the value would be the output of: \
|
||||
#@ kubectl create secret docker-registry x --docker-server=https://example.io --docker-username='USERNAME' --docker-password='PASSWORD' --dry-run=client -o json | jq -r '.data[\".dockerconfigjson\"]'"
|
||||
#@schema/desc image_pull_dockerconfigjson_desc
|
||||
#@ example_desc = 'base64 encoding of: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}'
|
||||
#@ example_value = "eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUuaW8iOnsidXNlcm5hbWUiOiJVU0VSTkFNRSIsInBhc3N3b3JkIjoiUEFTU1dPUkQiLCJhdXRoIjoiVlZORlVrNUJUVVU2VUVGVFUxZFBVa1E9In19fQ=="
|
||||
#@schema/examples (example_desc, example_value)
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
image_pull_dockerconfigjson: ""
|
||||
|
||||
#! Specify how to expose the Supervisor app's HTTPS port as a Service.
|
||||
#! Typically, you would set a value for only one of the following service types.
|
||||
#! Setting any of these values means that a Service of that type will be created. They are all optional.
|
||||
#! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`.
|
||||
#! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to
|
||||
#! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated.
|
||||
deprecated_service_http_nodeport_port: #! will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234
|
||||
deprecated_service_http_nodeport_nodeport: #! will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234
|
||||
deprecated_service_http_loadbalancer_port: #! will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
deprecated_service_http_clusterip_port: #! will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
service_https_nodeport_port: #! when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243
|
||||
service_https_nodeport_nodeport: #! the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243
|
||||
service_https_loadbalancer_port: #! when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
service_https_clusterip_port: #! when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
#! The `loadBalancerIP` value of the LoadBalancer Service.
|
||||
#! Ignored unless service_https_loadbalancer_port is provided.
|
||||
#! Optional.
|
||||
service_loadbalancer_ip: #! e.g. 1.2.3.4
|
||||
#@schema/title "Service https nodeport port"
|
||||
#@schema/desc "When specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`"
|
||||
#@schema/examples ("Specify port",31243)
|
||||
#@schema/nullable
|
||||
service_https_nodeport_port: 0
|
||||
|
||||
#! Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information),
|
||||
#! or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.
|
||||
log_level: #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||
#! Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs).
|
||||
#! By default, when this value is left unset, logs are formatted in json.
|
||||
#! This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.
|
||||
deprecated_log_format:
|
||||
#@schema/title "Service https nodeport nodeport"
|
||||
#@schema/desc "The `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified"
|
||||
#@schema/examples ("Specify port",31243)
|
||||
#@schema/nullable
|
||||
service_https_nodeport_nodeport: 0
|
||||
|
||||
run_as_user: 65532 #! run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
run_as_group: 65532 #! run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
#@schema/title "Service https loadbalancer port"
|
||||
#@schema/desc "When specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`"
|
||||
#@schema/examples ("Specify port",8443)
|
||||
#@schema/nullable
|
||||
service_https_loadbalancer_port: 0
|
||||
|
||||
#! Specify the API group suffix for all Pinniped API groups. By default, this is set to
|
||||
#! pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev,
|
||||
#! authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then
|
||||
#! Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
#@schema/title "Service https clusterip port"
|
||||
#@schema/desc "When specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`"
|
||||
#@schema/examples ("Specify port",8443)
|
||||
#@schema/nullable
|
||||
service_https_clusterip_port: 0
|
||||
|
||||
#@schema/title "Service loadbalancer ip"
|
||||
#@schema/desc "The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided."
|
||||
#@schema/examples ("Example IP address","1.2.3.4")
|
||||
#@schema/nullable
|
||||
service_loadbalancer_ip: ""
|
||||
|
||||
#@schema/title "Log level"
|
||||
#@ log_level_desc = "Specify the verbosity of logging: info (\"nice to know\" information), debug (developer information), trace (timing information), \
|
||||
#@ or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged. \
|
||||
#@ When this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs."
|
||||
#@schema/desc log_level_desc
|
||||
#@schema/examples ("Developer logging information","debug")
|
||||
#@schema/nullable
|
||||
#@schema/validation one_of=["info", "debug", "trace", "all"]
|
||||
log_level: ""
|
||||
|
||||
#@schema/title "Run as user"
|
||||
#@schema/desc "The user ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_user: 65532
|
||||
|
||||
#@schema/title "Run as group"
|
||||
#@schema/desc "The group ID that will own the process."
|
||||
#! See the Dockerfile for the reasoning behind this default value.
|
||||
run_as_group: 65532
|
||||
|
||||
#@schema/title "API group suffix"
|
||||
#@ api_group_suffix_desc = "Specify the API group suffix for all Pinniped API groups. By default, this is set to \
|
||||
#@ pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, \
|
||||
#@ config.supervisor.pinniped.dev, etc. As an example, if this is set to tuna.io, then \
|
||||
#@ Pinniped API groups will look like foo.tuna.io. config.supervisor.tuna.io, etc."
|
||||
#@schema/desc api_group_suffix_desc
|
||||
#@schema/validation min_len=1
|
||||
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
|
||||
#@schema/title "HTTPS proxy"
|
||||
#@ https_proxy_desc = "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. \
|
||||
#@ These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, \
|
||||
#@ e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. \
|
||||
#@ The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||
#@schema/desc https_proxy_desc
|
||||
#@schema/examples ("Providing a proxy endpoint","http://proxy.example.com")
|
||||
#@schema/nullable
|
||||
#@schema/validation min_len=1
|
||||
https_proxy: ""
|
||||
|
||||
#! Control the HTTP and HTTPS listeners of the Supervisor.
|
||||
#!
|
||||
#! The schema of this config is as follows:
|
||||
#!
|
||||
#! endpoints:
|
||||
#! https:
|
||||
#! network: tcp | unix | disabled
|
||||
#! address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||
#! http:
|
||||
#! network: same as above
|
||||
#! address: same as above, except that when network=tcp then the address is only allowed to bind to loopback interfaces
|
||||
#!
|
||||
#! Setting network to disabled turns off that particular listener.
|
||||
#! See https://pkg.go.dev/net#Listen and https://pkg.go.dev/net#Dial for a description of what can be
|
||||
#! specified in the address parameter based on the given network parameter. To aid in the use of unix
|
||||
#! domain sockets, a writable empty dir volume is mounted at /pinniped_socket when network is set to "unix."
|
||||
#!
|
||||
#! The current defaults are:
|
||||
#!
|
||||
#! endpoints:
|
||||
#! https:
|
||||
#! network: tcp
|
||||
#! address: :8443
|
||||
#! http:
|
||||
#! network: disabled
|
||||
#!
|
||||
#! These defaults mean: For HTTPS listening, bind to all interfaces using TCP on port 8443.
|
||||
#! Disable HTTP listening by default.
|
||||
#!
|
||||
#! The HTTP listener can only be bound to loopback interfaces. This allows the listener to accept
|
||||
#! traffic from within the pod, e.g. from a service mesh sidecar. The HTTP listener should not be
|
||||
#! used to accept traffic from outside the pod, since that would mean that the network traffic could be
|
||||
#! transmitted unencrypted. The HTTPS listener should be used instead to accept traffic from outside the pod.
|
||||
#! Ingresses and load balancers that terminate TLS connections should re-encrypt the data and route traffic
|
||||
#! to the HTTPS listener. Unix domain sockets may also be used for integrations with service meshes.
|
||||
#!
|
||||
#! Changing the HTTPS port number must be accompanied by matching changes to the service and deployment
|
||||
#! manifests. Changes to the HTTPS listener must be coordinated with the deployment health checks.
|
||||
#!
|
||||
#! Optional.
|
||||
endpoints:
|
||||
#@schema/title "No proxy"
|
||||
#@ no_proxy_desc = "Endpoints that should not be proxied. Defaults to not proxying internal Kubernetes endpoints, \
|
||||
#@ localhost endpoints, and the known instance metadata IP address for public cloud providers."
|
||||
#@schema/desc no_proxy_desc
|
||||
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
||||
|
||||
#! Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||
#! When deprecated_insecure_accept_external_unencrypted_http_requests is true, the HTTP listener is allowed to bind to any
|
||||
#! interface, including interfaces that are listening for traffic from outside the pod. This value is being introduced
|
||||
#! to ease the transition to the new loopback interface validation for the HTTP port for any users who need more time
|
||||
#! to change their ingress strategy to avoid using plain HTTP into the Supervisor pods.
|
||||
#! This value is immediately deprecated upon its introduction. It will be removed in some future release, at which time
|
||||
#! traffic from outside the pod will need to be sent to the HTTPS listener instead, with no simple workaround available.
|
||||
#! Allowed values are true (boolean), "true" (string), false (boolean), and "false" (string). The default is false.
|
||||
#! Optional.
|
||||
deprecated_insecure_accept_external_unencrypted_http_requests: false
|
||||
#@schema/title "Endpoints"
|
||||
#@ endpoints_desc = "Control the HTTP and HTTPS listeners of the Supervisor. The current defaults are: \
|
||||
#@ {\"https\":{\"network\":\"tcp\",\"address\":\":8443\"},\"http\":\"disabled\"}. \
|
||||
#@ These defaults mean: 1.) for HTTPS listening, bind to all interfaces using TCP on port 8443 and \
|
||||
#@ 2.) disable HTTP listening by default. \
|
||||
#@ The schema of this config is as follows: \
|
||||
#@ {\"https\":{\"network\":\"tcp | unix | disabled\",\"address\":\"host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix\"},\"http\":{\"network\":\"tcp | unix | disabled\",\"address\":\"same as https, except that when network=tcp then the address is only allowed to bind to loopback interfaces\"}} \
|
||||
#@ The HTTP listener can only be bound to loopback interfaces. This allows the listener to accept \
|
||||
#@ traffic from within the pod, e.g. from a service mesh sidecar. The HTTP listener should not be \
|
||||
#@ used to accept traffic from outside the pod, since that would mean that the network traffic could be \
|
||||
#@ transmitted unencrypted. The HTTPS listener should be used instead to accept traffic from outside the pod. \
|
||||
#@ Ingresses and load balancers that terminate TLS connections should re-encrypt the data and route traffic \
|
||||
#@ to the HTTPS listener. Unix domain sockets may also be used for integrations with service meshes. \
|
||||
#@ Changing the HTTPS port number must be accompanied by matching changes to the service and deployment \
|
||||
#@ manifests. Changes to the HTTPS listener must be coordinated with the deployment health checks."
|
||||
#@schema/desc endpoints_desc
|
||||
#@schema/examples ("Example matching default settings", '{"https":{"network":"tcp","address":":8443"},"http":"disabled"}')
|
||||
#@schema/type any=True
|
||||
#@ def validate_endpoint(endpoint):
|
||||
#@ if(type(endpoint) not in ["yamlfragment", "string"]):
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ if(type(endpoint) in ["string"]):
|
||||
#@ if (endpoint != "disabled"):
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ end
|
||||
#@ if(type(endpoint) in ["yamlfragment"]):
|
||||
#@ if (endpoint["network"] not in ["tcp", "unix", "disabled"]):
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ if (type(endpoint["address"]) not in ["string"]):
|
||||
#@ return False
|
||||
#@ end
|
||||
#@ end
|
||||
#@ return True
|
||||
#@ end
|
||||
#@ def validate_endpoints(endpoints):
|
||||
#@ """
|
||||
#@ Returns True if endpoints fulfill the expected structure
|
||||
#@ """
|
||||
#@ http_val = endpoints["http"]
|
||||
#@ https_val = endpoints["https"]
|
||||
#@ return validate_endpoint(http_val) and validate_endpoint(https_val)
|
||||
#@ end
|
||||
#@schema/nullable
|
||||
#@schema/validation ("a map with keys 'http' and 'https', whose values are either the string 'disabled' or a map having keys 'network' and 'address', and the value of 'network' must be one of the allowed values", validate_endpoints)
|
||||
endpoints: { }
|
||||
|
||||
1597
generated/1.17/README.adoc
generated
1597
generated/1.17/README.adoc
generated
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=authentication.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped concierge authentication API.
|
||||
package v1alpha1
|
||||
@@ -1,85 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// Status of a JWT authenticator.
|
||||
type JWTAuthenticatorStatus struct {
|
||||
// Represents the observations of the authenticator's current state.
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
// Spec for configuring a JWT authenticator.
|
||||
type JWTAuthenticatorSpec struct {
|
||||
// Issuer is the OIDC issuer URL that will be used to discover public signing keys. Issuer is
|
||||
// also used to validate the "iss" JWT claim.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://`
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// Audience is the required value of the "aud" JWT claim.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Audience string `json:"audience"`
|
||||
|
||||
// Claims allows customization of the claims that will be mapped to user identity
|
||||
// for Kubernetes access.
|
||||
// +optional
|
||||
Claims JWTTokenClaims `json:"claims"`
|
||||
|
||||
// TLS configuration for communicating with the OIDC provider.
|
||||
// +optional
|
||||
TLS *TLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// JWTTokenClaims allows customization of the claims that will be mapped to user identity
|
||||
// for Kubernetes access.
|
||||
type JWTTokenClaims struct {
|
||||
// Groups is the name of the claim which should be read to extract the user's
|
||||
// group membership from the JWT token. When not specified, it will default to "groups".
|
||||
// +optional
|
||||
Groups string `json:"groups"`
|
||||
|
||||
// Username is the name of the claim which should be read to extract the
|
||||
// username from the JWT token. When not specified, it will default to "username".
|
||||
// +optional
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
//
|
||||
// Upon receiving a signed JWT, a JWTAuthenticator will performs some validation on it (e.g., valid
|
||||
// signature, existence of claims, etc.) and extract the username and groups from the token.
|
||||
//
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped;pinniped-authenticator;pinniped-authenticators,scope=Cluster
|
||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||
// +kubebuilder:printcolumn:name="Audience",type=string,JSONPath=`.spec.audience`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type JWTAuthenticator struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec for configuring the authenticator.
|
||||
Spec JWTAuthenticatorSpec `json:"spec"`
|
||||
|
||||
// Status of the authenticator.
|
||||
Status JWTAuthenticatorStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// List of JWTAuthenticator objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type JWTAuthenticatorList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []JWTAuthenticator `json:"items"`
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// Status of a webhook authenticator.
|
||||
type WebhookAuthenticatorStatus struct {
|
||||
// Represents the observations of the authenticator's current state.
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
}
|
||||
|
||||
// Spec for configuring a webhook authenticator.
|
||||
type WebhookAuthenticatorSpec struct {
|
||||
// Webhook server endpoint URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://`
|
||||
Endpoint string `json:"endpoint"`
|
||||
|
||||
// TLS configuration.
|
||||
// +optional
|
||||
TLS *TLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookAuthenticator describes the configuration of a webhook authenticator.
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped;pinniped-authenticator;pinniped-authenticators,scope=Cluster
|
||||
// +kubebuilder:printcolumn:name="Endpoint",type=string,JSONPath=`.spec.endpoint`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type WebhookAuthenticator struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec for configuring the authenticator.
|
||||
Spec WebhookAuthenticatorSpec `json:"spec"`
|
||||
|
||||
// Status of the authenticator.
|
||||
Status WebhookAuthenticatorStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// List of WebhookAuthenticator objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type WebhookAuthenticatorList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []WebhookAuthenticator `json:"items"`
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 *Condition) DeepCopyInto(out *Condition) {
|
||||
*out = *in
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||
func (in *Condition) DeepCopy() *Condition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Condition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
|
||||
*out = *in
|
||||
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 JWTAuthenticator.
|
||||
func (in *JWTAuthenticator) DeepCopy() *JWTAuthenticator {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JWTAuthenticator)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *JWTAuthenticator) 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 *JWTAuthenticatorList) DeepCopyInto(out *JWTAuthenticatorList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]JWTAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTAuthenticatorList.
|
||||
func (in *JWTAuthenticatorList) DeepCopy() *JWTAuthenticatorList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JWTAuthenticatorList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *JWTAuthenticatorList) 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 *JWTAuthenticatorSpec) DeepCopyInto(out *JWTAuthenticatorSpec) {
|
||||
*out = *in
|
||||
out.Claims = in.Claims
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(TLSSpec)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTAuthenticatorSpec.
|
||||
func (in *JWTAuthenticatorSpec) DeepCopy() *JWTAuthenticatorSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JWTAuthenticatorSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JWTAuthenticatorStatus) DeepCopyInto(out *JWTAuthenticatorStatus) {
|
||||
*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 JWTAuthenticatorStatus.
|
||||
func (in *JWTAuthenticatorStatus) DeepCopy() *JWTAuthenticatorStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JWTAuthenticatorStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JWTTokenClaims) DeepCopyInto(out *JWTTokenClaims) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTTokenClaims.
|
||||
func (in *JWTTokenClaims) DeepCopy() *JWTTokenClaims {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JWTTokenClaims)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLSSpec) DeepCopyInto(out *TLSSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSpec.
|
||||
func (in *TLSSpec) DeepCopy() *TLSSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TLSSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WebhookAuthenticator) DeepCopyInto(out *WebhookAuthenticator) {
|
||||
*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 WebhookAuthenticator.
|
||||
func (in *WebhookAuthenticator) DeepCopy() *WebhookAuthenticator {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookAuthenticator)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WebhookAuthenticator) 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 *WebhookAuthenticatorList) DeepCopyInto(out *WebhookAuthenticatorList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]WebhookAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookAuthenticatorList.
|
||||
func (in *WebhookAuthenticatorList) DeepCopy() *WebhookAuthenticatorList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookAuthenticatorList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WebhookAuthenticatorList) 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 *WebhookAuthenticatorSpec) DeepCopyInto(out *WebhookAuthenticatorSpec) {
|
||||
*out = *in
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(TLSSpec)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookAuthenticatorSpec.
|
||||
func (in *WebhookAuthenticatorSpec) DeepCopy() *WebhookAuthenticatorSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookAuthenticatorSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WebhookAuthenticatorStatus) DeepCopyInto(out *WebhookAuthenticatorStatus) {
|
||||
*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 WebhookAuthenticatorStatus.
|
||||
func (in *WebhookAuthenticatorStatus) DeepCopy() *WebhookAuthenticatorStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookAuthenticatorStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
10
generated/1.17/apis/concierge/config/v1alpha1/doc.go
generated
10
generated/1.17/apis/concierge/config/v1alpha1/doc.go
generated
@@ -1,10 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=config.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped concierge configuration API.
|
||||
package v1alpha1
|
||||
@@ -1,244 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
const (
|
||||
KubeClusterSigningCertificateStrategyType = StrategyType("KubeClusterSigningCertificate")
|
||||
ImpersonationProxyStrategyType = StrategyType("ImpersonationProxy")
|
||||
|
||||
TokenCredentialRequestAPIFrontendType = FrontendType("TokenCredentialRequestAPI")
|
||||
ImpersonationProxyFrontendType = FrontendType("ImpersonationProxy")
|
||||
|
||||
SuccessStrategyStatus = StrategyStatus("Success")
|
||||
ErrorStrategyStatus = StrategyStatus("Error")
|
||||
|
||||
ListeningStrategyReason = StrategyReason("Listening")
|
||||
PendingStrategyReason = StrategyReason("Pending")
|
||||
DisabledStrategyReason = StrategyReason("Disabled")
|
||||
ErrorDuringSetupStrategyReason = StrategyReason("ErrorDuringSetup")
|
||||
CouldNotFetchKeyStrategyReason = StrategyReason("CouldNotFetchKey")
|
||||
CouldNotGetClusterInfoStrategyReason = StrategyReason("CouldNotGetClusterInfo")
|
||||
FetchedKeyStrategyReason = StrategyReason("FetchedKey")
|
||||
)
|
||||
|
||||
// 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"`
|
||||
|
||||
// Information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This field is deprecated and will be removed in a future version.
|
||||
// +optional
|
||||
KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer.
|
||||
// This type is deprecated and will be removed in a future version.
|
||||
type CredentialIssuerKubeConfigInfo struct {
|
||||
// The K8s API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// The K8s API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped.
|
||||
type CredentialIssuerStrategy struct {
|
||||
// Type of integration attempted.
|
||||
Type StrategyType `json:"type"`
|
||||
|
||||
// Status of the attempted integration strategy.
|
||||
Status StrategyStatus `json:"status"`
|
||||
|
||||
// Reason for the current status.
|
||||
Reason StrategyReason `json:"reason"`
|
||||
|
||||
// Human-readable description of the current status.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Message string `json:"message"`
|
||||
|
||||
// When the status was last checked.
|
||||
LastUpdateTime metav1.Time `json:"lastUpdateTime"`
|
||||
|
||||
// Frontend describes how clients can connect using this strategy.
|
||||
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"`
|
||||
|
||||
// TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRequest API on this Concierge.
|
||||
// This field is only set when Type is "TokenCredentialRequestAPI".
|
||||
TokenCredentialRequestAPIInfo *TokenCredentialRequestAPIInfo `json:"tokenCredentialRequestInfo,omitempty"`
|
||||
|
||||
// ImpersonationProxyInfo describes the parameters for the impersonation proxy on this Concierge.
|
||||
// This field is only set when Type is "ImpersonationProxy".
|
||||
ImpersonationProxyInfo *ImpersonationProxyInfo `json:"impersonationProxyInfo,omitempty"`
|
||||
}
|
||||
|
||||
// TokenCredentialRequestAPIInfo describes the parameters for the TokenCredentialRequest API on this Concierge.
|
||||
type TokenCredentialRequestAPIInfo struct {
|
||||
// Server is the Kubernetes API server URL.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://|^http://`
|
||||
Server string `json:"server"`
|
||||
|
||||
// CertificateAuthorityData is the base64-encoded Kubernetes API server CA bundle.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// ImpersonationProxyInfo describes the parameters for the impersonation proxy on this Concierge.
|
||||
type ImpersonationProxyInfo struct {
|
||||
// Endpoint is the HTTPS endpoint of the impersonation proxy.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://`
|
||||
Endpoint string `json:"endpoint"`
|
||||
|
||||
// CertificateAuthorityData is the base64-encoded PEM CA bundle of the impersonation proxy.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
CertificateAuthorityData string `json:"certificateAuthorityData"`
|
||||
}
|
||||
|
||||
// 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
|
||||
// +kubebuilder:resource:categories=pinniped,scope=Cluster
|
||||
// +kubebuilder:printcolumn:name="ProxyMode",type=string,JSONPath=`.spec.impersonationProxy.mode`
|
||||
// +kubebuilder:printcolumn:name="DefaultStrategy",type=string,JSONPath=`.status.strategies[?(@.status == "Success")].type`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type CredentialIssuer struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// CredentialIssuerList is a list of CredentialIssuer objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type CredentialIssuerList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []CredentialIssuer `json:"items"`
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 *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
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuer.
|
||||
func (in *CredentialIssuer) DeepCopy() *CredentialIssuer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CredentialIssuer) 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 *CredentialIssuerFrontend) DeepCopyInto(out *CredentialIssuerFrontend) {
|
||||
*out = *in
|
||||
if in.TokenCredentialRequestAPIInfo != nil {
|
||||
in, out := &in.TokenCredentialRequestAPIInfo, &out.TokenCredentialRequestAPIInfo
|
||||
*out = new(TokenCredentialRequestAPIInfo)
|
||||
**out = **in
|
||||
}
|
||||
if in.ImpersonationProxyInfo != nil {
|
||||
in, out := &in.ImpersonationProxyInfo, &out.ImpersonationProxyInfo
|
||||
*out = new(ImpersonationProxyInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerFrontend.
|
||||
func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerFrontend)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo.
|
||||
func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerKubeConfigInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CredentialIssuer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerList.
|
||||
func (in *CredentialIssuerList) DeepCopy() *CredentialIssuerList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CredentialIssuerList) 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 *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
|
||||
if in.Strategies != nil {
|
||||
in, out := &in.Strategies, &out.Strategies
|
||||
*out = make([]CredentialIssuerStrategy, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeConfigInfo != nil {
|
||||
in, out := &in.KubeConfigInfo, &out.KubeConfigInfo
|
||||
*out = new(CredentialIssuerKubeConfigInfo)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerStatus.
|
||||
func (in *CredentialIssuerStatus) DeepCopy() *CredentialIssuerStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CredentialIssuerStrategy) DeepCopyInto(out *CredentialIssuerStrategy) {
|
||||
*out = *in
|
||||
in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
|
||||
if in.Frontend != nil {
|
||||
in, out := &in.Frontend, &out.Frontend
|
||||
*out = new(CredentialIssuerFrontend)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerStrategy.
|
||||
func (in *CredentialIssuerStrategy) DeepCopy() *CredentialIssuerStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CredentialIssuerStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImpersonationProxyInfo) DeepCopyInto(out *ImpersonationProxyInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImpersonationProxyInfo.
|
||||
func (in *ImpersonationProxyInfo) DeepCopy() *ImpersonationProxyInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImpersonationProxyInfo)
|
||||
in.DeepCopyInto(out)
|
||||
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
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestAPIInfo.
|
||||
func (in *TokenCredentialRequestAPIInfo) DeepCopy() *TokenCredentialRequestAPIInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestAPIInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/concierge/identity
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=identity.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped identity API.
|
||||
package v1alpha1
|
||||
@@ -1,235 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
identity "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*KubernetesUserInfo)(nil), (*identity.KubernetesUserInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo(a.(*KubernetesUserInfo), b.(*identity.KubernetesUserInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.KubernetesUserInfo)(nil), (*KubernetesUserInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo(a.(*identity.KubernetesUserInfo), b.(*KubernetesUserInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UserInfo)(nil), (*identity.UserInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_UserInfo_To_identity_UserInfo(a.(*UserInfo), b.(*identity.UserInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.UserInfo)(nil), (*UserInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_UserInfo_To_v1alpha1_UserInfo(a.(*identity.UserInfo), b.(*UserInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*WhoAmIRequest)(nil), (*identity.WhoAmIRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_WhoAmIRequest_To_identity_WhoAmIRequest(a.(*WhoAmIRequest), b.(*identity.WhoAmIRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.WhoAmIRequest)(nil), (*WhoAmIRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_WhoAmIRequest_To_v1alpha1_WhoAmIRequest(a.(*identity.WhoAmIRequest), b.(*WhoAmIRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*WhoAmIRequestList)(nil), (*identity.WhoAmIRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_WhoAmIRequestList_To_identity_WhoAmIRequestList(a.(*WhoAmIRequestList), b.(*identity.WhoAmIRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.WhoAmIRequestList)(nil), (*WhoAmIRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_WhoAmIRequestList_To_v1alpha1_WhoAmIRequestList(a.(*identity.WhoAmIRequestList), b.(*WhoAmIRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*WhoAmIRequestSpec)(nil), (*identity.WhoAmIRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec(a.(*WhoAmIRequestSpec), b.(*identity.WhoAmIRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.WhoAmIRequestSpec)(nil), (*WhoAmIRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec(a.(*identity.WhoAmIRequestSpec), b.(*WhoAmIRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*WhoAmIRequestStatus)(nil), (*identity.WhoAmIRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus(a.(*WhoAmIRequestStatus), b.(*identity.WhoAmIRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*identity.WhoAmIRequestStatus)(nil), (*WhoAmIRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus(a.(*identity.WhoAmIRequestStatus), b.(*WhoAmIRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo(in *KubernetesUserInfo, out *identity.KubernetesUserInfo, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha1_UserInfo_To_identity_UserInfo(&in.User, &out.User, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo(in *KubernetesUserInfo, out *identity.KubernetesUserInfo, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo(in *identity.KubernetesUserInfo, out *KubernetesUserInfo, s conversion.Scope) error {
|
||||
if err := Convert_identity_UserInfo_To_v1alpha1_UserInfo(&in.User, &out.User, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo is an autogenerated conversion function.
|
||||
func Convert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo(in *identity.KubernetesUserInfo, out *KubernetesUserInfo, s conversion.Scope) error {
|
||||
return autoConvert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_UserInfo_To_identity_UserInfo(in *UserInfo, out *identity.UserInfo, s conversion.Scope) error {
|
||||
out.Username = in.Username
|
||||
out.UID = in.UID
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
out.Extra = *(*map[string]identity.ExtraValue)(unsafe.Pointer(&in.Extra))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_UserInfo_To_identity_UserInfo is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_UserInfo_To_identity_UserInfo(in *UserInfo, out *identity.UserInfo, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_UserInfo_To_identity_UserInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_UserInfo_To_v1alpha1_UserInfo(in *identity.UserInfo, out *UserInfo, s conversion.Scope) error {
|
||||
out.Username = in.Username
|
||||
out.UID = in.UID
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
out.Extra = *(*map[string]ExtraValue)(unsafe.Pointer(&in.Extra))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_UserInfo_To_v1alpha1_UserInfo is an autogenerated conversion function.
|
||||
func Convert_identity_UserInfo_To_v1alpha1_UserInfo(in *identity.UserInfo, out *UserInfo, s conversion.Scope) error {
|
||||
return autoConvert_identity_UserInfo_To_v1alpha1_UserInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_WhoAmIRequest_To_identity_WhoAmIRequest(in *WhoAmIRequest, out *identity.WhoAmIRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_WhoAmIRequest_To_identity_WhoAmIRequest is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_WhoAmIRequest_To_identity_WhoAmIRequest(in *WhoAmIRequest, out *identity.WhoAmIRequest, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_WhoAmIRequest_To_identity_WhoAmIRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_WhoAmIRequest_To_v1alpha1_WhoAmIRequest(in *identity.WhoAmIRequest, out *WhoAmIRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_WhoAmIRequest_To_v1alpha1_WhoAmIRequest is an autogenerated conversion function.
|
||||
func Convert_identity_WhoAmIRequest_To_v1alpha1_WhoAmIRequest(in *identity.WhoAmIRequest, out *WhoAmIRequest, s conversion.Scope) error {
|
||||
return autoConvert_identity_WhoAmIRequest_To_v1alpha1_WhoAmIRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_WhoAmIRequestList_To_identity_WhoAmIRequestList(in *WhoAmIRequestList, out *identity.WhoAmIRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]identity.WhoAmIRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_WhoAmIRequestList_To_identity_WhoAmIRequestList is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_WhoAmIRequestList_To_identity_WhoAmIRequestList(in *WhoAmIRequestList, out *identity.WhoAmIRequestList, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_WhoAmIRequestList_To_identity_WhoAmIRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_WhoAmIRequestList_To_v1alpha1_WhoAmIRequestList(in *identity.WhoAmIRequestList, out *WhoAmIRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]WhoAmIRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_WhoAmIRequestList_To_v1alpha1_WhoAmIRequestList is an autogenerated conversion function.
|
||||
func Convert_identity_WhoAmIRequestList_To_v1alpha1_WhoAmIRequestList(in *identity.WhoAmIRequestList, out *WhoAmIRequestList, s conversion.Scope) error {
|
||||
return autoConvert_identity_WhoAmIRequestList_To_v1alpha1_WhoAmIRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec(in *WhoAmIRequestSpec, out *identity.WhoAmIRequestSpec, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec(in *WhoAmIRequestSpec, out *identity.WhoAmIRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_WhoAmIRequestSpec_To_identity_WhoAmIRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec(in *identity.WhoAmIRequestSpec, out *WhoAmIRequestSpec, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec is an autogenerated conversion function.
|
||||
func Convert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec(in *identity.WhoAmIRequestSpec, out *WhoAmIRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_identity_WhoAmIRequestSpec_To_v1alpha1_WhoAmIRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus(in *WhoAmIRequestStatus, out *identity.WhoAmIRequestStatus, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha1_KubernetesUserInfo_To_identity_KubernetesUserInfo(&in.KubernetesUserInfo, &out.KubernetesUserInfo, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus(in *WhoAmIRequestStatus, out *identity.WhoAmIRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_WhoAmIRequestStatus_To_identity_WhoAmIRequestStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus(in *identity.WhoAmIRequestStatus, out *WhoAmIRequestStatus, s conversion.Scope) error {
|
||||
if err := Convert_identity_KubernetesUserInfo_To_v1alpha1_KubernetesUserInfo(&in.KubernetesUserInfo, &out.KubernetesUserInfo, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus is an autogenerated conversion function.
|
||||
func Convert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus(in *identity.WhoAmIRequestStatus, out *WhoAmIRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_identity_WhoAmIRequestStatus_To_v1alpha1_WhoAmIRequestStatus(in, out, s)
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 ExtraValue) DeepCopyInto(out *ExtraValue) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(ExtraValue, len(*in))
|
||||
copy(*out, *in)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraValue.
|
||||
func (in ExtraValue) DeepCopy() ExtraValue {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExtraValue)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesUserInfo) DeepCopyInto(out *KubernetesUserInfo) {
|
||||
*out = *in
|
||||
in.User.DeepCopyInto(&out.User)
|
||||
if in.Audiences != nil {
|
||||
in, out := &in.Audiences, &out.Audiences
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesUserInfo.
|
||||
func (in *KubernetesUserInfo) DeepCopy() *KubernetesUserInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesUserInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UserInfo) DeepCopyInto(out *UserInfo) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Extra != nil {
|
||||
in, out := &in.Extra, &out.Extra
|
||||
*out = make(map[string]ExtraValue, len(*in))
|
||||
for key, val := range *in {
|
||||
var outVal []string
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
in, out := &val, &outVal
|
||||
*out = make(ExtraValue, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfo.
|
||||
func (in *UserInfo) DeepCopy() *UserInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UserInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WhoAmIRequest) DeepCopyInto(out *WhoAmIRequest) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequest.
|
||||
func (in *WhoAmIRequest) DeepCopy() *WhoAmIRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WhoAmIRequest) 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 *WhoAmIRequestList) DeepCopyInto(out *WhoAmIRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]WhoAmIRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestList.
|
||||
func (in *WhoAmIRequestList) DeepCopy() *WhoAmIRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WhoAmIRequestList) 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 *WhoAmIRequestSpec) DeepCopyInto(out *WhoAmIRequestSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestSpec.
|
||||
func (in *WhoAmIRequestSpec) DeepCopy() *WhoAmIRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WhoAmIRequestStatus) DeepCopyInto(out *WhoAmIRequestStatus) {
|
||||
*out = *in
|
||||
in.KubernetesUserInfo.DeepCopyInto(&out.KubernetesUserInfo)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestStatus.
|
||||
func (in *WhoAmIRequestStatus) DeepCopy() *WhoAmIRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
identityapi "go.pinniped.dev/generated/1.17/apis/concierge/identity"
|
||||
)
|
||||
|
||||
func ValidateWhoAmIRequest(whoAmIRequest *identityapi.WhoAmIRequest) field.ErrorList {
|
||||
return nil // add validation for spec here if we expand it
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package identity
|
||||
|
||||
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 ExtraValue) DeepCopyInto(out *ExtraValue) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(ExtraValue, len(*in))
|
||||
copy(*out, *in)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraValue.
|
||||
func (in ExtraValue) DeepCopy() ExtraValue {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExtraValue)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesUserInfo) DeepCopyInto(out *KubernetesUserInfo) {
|
||||
*out = *in
|
||||
in.User.DeepCopyInto(&out.User)
|
||||
if in.Audiences != nil {
|
||||
in, out := &in.Audiences, &out.Audiences
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesUserInfo.
|
||||
func (in *KubernetesUserInfo) DeepCopy() *KubernetesUserInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesUserInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UserInfo) DeepCopyInto(out *UserInfo) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Extra != nil {
|
||||
in, out := &in.Extra, &out.Extra
|
||||
*out = make(map[string]ExtraValue, len(*in))
|
||||
for key, val := range *in {
|
||||
var outVal []string
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
in, out := &val, &outVal
|
||||
*out = make(ExtraValue, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfo.
|
||||
func (in *UserInfo) DeepCopy() *UserInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UserInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WhoAmIRequest) DeepCopyInto(out *WhoAmIRequest) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequest.
|
||||
func (in *WhoAmIRequest) DeepCopy() *WhoAmIRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WhoAmIRequest) 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 *WhoAmIRequestList) DeepCopyInto(out *WhoAmIRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]WhoAmIRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestList.
|
||||
func (in *WhoAmIRequestList) DeepCopy() *WhoAmIRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *WhoAmIRequestList) 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 *WhoAmIRequestSpec) DeepCopyInto(out *WhoAmIRequestSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestSpec.
|
||||
func (in *WhoAmIRequestSpec) DeepCopy() *WhoAmIRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WhoAmIRequestStatus) DeepCopyInto(out *WhoAmIRequestStatus) {
|
||||
*out = *in
|
||||
in.KubernetesUserInfo.DeepCopyInto(&out.KubernetesUserInfo)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhoAmIRequestStatus.
|
||||
func (in *WhoAmIRequestStatus) DeepCopy() *WhoAmIRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WhoAmIRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
11
generated/1.17/apis/concierge/login/v1alpha1/doc.go
generated
11
generated/1.17/apis/concierge/login/v1alpha1/doc.go
generated
@@ -1,11 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/concierge/login
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=login.concierge.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped login API.
|
||||
package v1alpha1
|
||||
@@ -1,201 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
login "go.pinniped.dev/generated/1.17/apis/concierge/login"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterCredential)(nil), (*login.ClusterCredential)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_ClusterCredential_To_login_ClusterCredential(a.(*ClusterCredential), b.(*login.ClusterCredential), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*login.ClusterCredential)(nil), (*ClusterCredential)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_login_ClusterCredential_To_v1alpha1_ClusterCredential(a.(*login.ClusterCredential), b.(*ClusterCredential), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*TokenCredentialRequest)(nil), (*login.TokenCredentialRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_TokenCredentialRequest_To_login_TokenCredentialRequest(a.(*TokenCredentialRequest), b.(*login.TokenCredentialRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*login.TokenCredentialRequest)(nil), (*TokenCredentialRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_login_TokenCredentialRequest_To_v1alpha1_TokenCredentialRequest(a.(*login.TokenCredentialRequest), b.(*TokenCredentialRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*TokenCredentialRequestList)(nil), (*login.TokenCredentialRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_TokenCredentialRequestList_To_login_TokenCredentialRequestList(a.(*TokenCredentialRequestList), b.(*login.TokenCredentialRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*login.TokenCredentialRequestList)(nil), (*TokenCredentialRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_login_TokenCredentialRequestList_To_v1alpha1_TokenCredentialRequestList(a.(*login.TokenCredentialRequestList), b.(*TokenCredentialRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*TokenCredentialRequestSpec)(nil), (*login.TokenCredentialRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec(a.(*TokenCredentialRequestSpec), b.(*login.TokenCredentialRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*login.TokenCredentialRequestSpec)(nil), (*TokenCredentialRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec(a.(*login.TokenCredentialRequestSpec), b.(*TokenCredentialRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*TokenCredentialRequestStatus)(nil), (*login.TokenCredentialRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus(a.(*TokenCredentialRequestStatus), b.(*login.TokenCredentialRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*login.TokenCredentialRequestStatus)(nil), (*TokenCredentialRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus(a.(*login.TokenCredentialRequestStatus), b.(*TokenCredentialRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterCredential_To_login_ClusterCredential(in *ClusterCredential, out *login.ClusterCredential, s conversion.Scope) error {
|
||||
out.ExpirationTimestamp = in.ExpirationTimestamp
|
||||
out.Token = in.Token
|
||||
out.ClientCertificateData = in.ClientCertificateData
|
||||
out.ClientKeyData = in.ClientKeyData
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_ClusterCredential_To_login_ClusterCredential is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_ClusterCredential_To_login_ClusterCredential(in *ClusterCredential, out *login.ClusterCredential, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterCredential_To_login_ClusterCredential(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_login_ClusterCredential_To_v1alpha1_ClusterCredential(in *login.ClusterCredential, out *ClusterCredential, s conversion.Scope) error {
|
||||
out.ExpirationTimestamp = in.ExpirationTimestamp
|
||||
out.Token = in.Token
|
||||
out.ClientCertificateData = in.ClientCertificateData
|
||||
out.ClientKeyData = in.ClientKeyData
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_login_ClusterCredential_To_v1alpha1_ClusterCredential is an autogenerated conversion function.
|
||||
func Convert_login_ClusterCredential_To_v1alpha1_ClusterCredential(in *login.ClusterCredential, out *ClusterCredential, s conversion.Scope) error {
|
||||
return autoConvert_login_ClusterCredential_To_v1alpha1_ClusterCredential(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_TokenCredentialRequest_To_login_TokenCredentialRequest(in *TokenCredentialRequest, out *login.TokenCredentialRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_TokenCredentialRequest_To_login_TokenCredentialRequest is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_TokenCredentialRequest_To_login_TokenCredentialRequest(in *TokenCredentialRequest, out *login.TokenCredentialRequest, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_TokenCredentialRequest_To_login_TokenCredentialRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_login_TokenCredentialRequest_To_v1alpha1_TokenCredentialRequest(in *login.TokenCredentialRequest, out *TokenCredentialRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_login_TokenCredentialRequest_To_v1alpha1_TokenCredentialRequest is an autogenerated conversion function.
|
||||
func Convert_login_TokenCredentialRequest_To_v1alpha1_TokenCredentialRequest(in *login.TokenCredentialRequest, out *TokenCredentialRequest, s conversion.Scope) error {
|
||||
return autoConvert_login_TokenCredentialRequest_To_v1alpha1_TokenCredentialRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_TokenCredentialRequestList_To_login_TokenCredentialRequestList(in *TokenCredentialRequestList, out *login.TokenCredentialRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]login.TokenCredentialRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_TokenCredentialRequestList_To_login_TokenCredentialRequestList is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_TokenCredentialRequestList_To_login_TokenCredentialRequestList(in *TokenCredentialRequestList, out *login.TokenCredentialRequestList, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_TokenCredentialRequestList_To_login_TokenCredentialRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_login_TokenCredentialRequestList_To_v1alpha1_TokenCredentialRequestList(in *login.TokenCredentialRequestList, out *TokenCredentialRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]TokenCredentialRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_login_TokenCredentialRequestList_To_v1alpha1_TokenCredentialRequestList is an autogenerated conversion function.
|
||||
func Convert_login_TokenCredentialRequestList_To_v1alpha1_TokenCredentialRequestList(in *login.TokenCredentialRequestList, out *TokenCredentialRequestList, s conversion.Scope) error {
|
||||
return autoConvert_login_TokenCredentialRequestList_To_v1alpha1_TokenCredentialRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec(in *TokenCredentialRequestSpec, out *login.TokenCredentialRequestSpec, s conversion.Scope) error {
|
||||
out.Token = in.Token
|
||||
out.Authenticator = in.Authenticator
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec(in *TokenCredentialRequestSpec, out *login.TokenCredentialRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_TokenCredentialRequestSpec_To_login_TokenCredentialRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec(in *login.TokenCredentialRequestSpec, out *TokenCredentialRequestSpec, s conversion.Scope) error {
|
||||
out.Token = in.Token
|
||||
out.Authenticator = in.Authenticator
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec is an autogenerated conversion function.
|
||||
func Convert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec(in *login.TokenCredentialRequestSpec, out *TokenCredentialRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_login_TokenCredentialRequestSpec_To_v1alpha1_TokenCredentialRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus(in *TokenCredentialRequestStatus, out *login.TokenCredentialRequestStatus, s conversion.Scope) error {
|
||||
out.Credential = (*login.ClusterCredential)(unsafe.Pointer(in.Credential))
|
||||
out.Message = (*string)(unsafe.Pointer(in.Message))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus(in *TokenCredentialRequestStatus, out *login.TokenCredentialRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_TokenCredentialRequestStatus_To_login_TokenCredentialRequestStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus(in *login.TokenCredentialRequestStatus, out *TokenCredentialRequestStatus, s conversion.Scope) error {
|
||||
out.Credential = (*ClusterCredential)(unsafe.Pointer(in.Credential))
|
||||
out.Message = (*string)(unsafe.Pointer(in.Message))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus is an autogenerated conversion function.
|
||||
func Convert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus(in *login.TokenCredentialRequestStatus, out *TokenCredentialRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_login_TokenCredentialRequestStatus_To_v1alpha1_TokenCredentialRequestStatus(in, out, s)
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 *ClusterCredential) DeepCopyInto(out *ClusterCredential) {
|
||||
*out = *in
|
||||
in.ExpirationTimestamp.DeepCopyInto(&out.ExpirationTimestamp)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCredential.
|
||||
func (in *ClusterCredential) DeepCopy() *ClusterCredential {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterCredential)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TokenCredentialRequest) DeepCopyInto(out *TokenCredentialRequest) {
|
||||
*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 TokenCredentialRequest.
|
||||
func (in *TokenCredentialRequest) DeepCopy() *TokenCredentialRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TokenCredentialRequest) 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 *TokenCredentialRequestList) DeepCopyInto(out *TokenCredentialRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]TokenCredentialRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestList.
|
||||
func (in *TokenCredentialRequestList) DeepCopy() *TokenCredentialRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TokenCredentialRequestList) 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 *TokenCredentialRequestSpec) DeepCopyInto(out *TokenCredentialRequestSpec) {
|
||||
*out = *in
|
||||
in.Authenticator.DeepCopyInto(&out.Authenticator)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestSpec.
|
||||
func (in *TokenCredentialRequestSpec) DeepCopy() *TokenCredentialRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TokenCredentialRequestStatus) DeepCopyInto(out *TokenCredentialRequestStatus) {
|
||||
*out = *in
|
||||
if in.Credential != nil {
|
||||
in, out := &in.Credential, &out.Credential
|
||||
*out = new(ClusterCredential)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Message != nil {
|
||||
in, out := &in.Message, &out.Message
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestStatus.
|
||||
func (in *TokenCredentialRequestStatus) DeepCopy() *TokenCredentialRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package login
|
||||
|
||||
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 *ClusterCredential) DeepCopyInto(out *ClusterCredential) {
|
||||
*out = *in
|
||||
in.ExpirationTimestamp.DeepCopyInto(&out.ExpirationTimestamp)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCredential.
|
||||
func (in *ClusterCredential) DeepCopy() *ClusterCredential {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterCredential)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TokenCredentialRequest) DeepCopyInto(out *TokenCredentialRequest) {
|
||||
*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 TokenCredentialRequest.
|
||||
func (in *TokenCredentialRequest) DeepCopy() *TokenCredentialRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TokenCredentialRequest) 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 *TokenCredentialRequestList) DeepCopyInto(out *TokenCredentialRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]TokenCredentialRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestList.
|
||||
func (in *TokenCredentialRequestList) DeepCopy() *TokenCredentialRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TokenCredentialRequestList) 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 *TokenCredentialRequestSpec) DeepCopyInto(out *TokenCredentialRequestSpec) {
|
||||
*out = *in
|
||||
in.Authenticator.DeepCopyInto(&out.Authenticator)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestSpec.
|
||||
func (in *TokenCredentialRequestSpec) DeepCopy() *TokenCredentialRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TokenCredentialRequestStatus) DeepCopyInto(out *TokenCredentialRequestStatus) {
|
||||
*out = *in
|
||||
if in.Credential != nil {
|
||||
in, out := &in.Credential, &out.Credential
|
||||
*out = new(ClusterCredential)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Message != nil {
|
||||
in, out := &in.Message, &out.Message
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenCredentialRequestStatus.
|
||||
func (in *TokenCredentialRequestStatus) DeepCopy() *TokenCredentialRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TokenCredentialRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
9
generated/1.17/apis/go.mod
generated
9
generated/1.17/apis/go.mod
generated
@@ -1,9 +0,0 @@
|
||||
// This go.mod file is generated by ./hack/codegen.sh.
|
||||
module go.pinniped.dev/generated/1.17/apis
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
k8s.io/api v0.17.17
|
||||
k8s.io/apimachinery v0.17.17
|
||||
)
|
||||
105
generated/1.17/apis/go.sum
generated
105
generated/1.17/apis/go.sum
generated
@@ -1,105 +0,0 @@
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
k8s.io/api v0.17.17 h1:S+Yv5pdfvy9OG1t148zMFk3/l/VYpF1N4j5Y/q8IMdg=
|
||||
k8s.io/api v0.17.17/go.mod h1:kk4nQM0EVx+BEY7o8CN5YL99CWmWEQ2a4NCak58yB6E=
|
||||
k8s.io/apimachinery v0.17.17 h1:HMpFl9yqNI5G2+2WllKOe2XYLkCyaWzfXvk7SosyVko=
|
||||
k8s.io/apimachinery v0.17.17/go.mod h1:T54ZSpncArE25c5r2PbUPsLeTpkPWY/ivafigSX6+xk=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU=
|
||||
sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/supervisor/clientsecret
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=clientsecret.supervisor.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped client secret API.
|
||||
package v1alpha1
|
||||
@@ -1,165 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
clientsecret "go.pinniped.dev/generated/1.17/apis/supervisor/clientsecret"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*OIDCClientSecretRequest)(nil), (*clientsecret.OIDCClientSecretRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_OIDCClientSecretRequest_To_clientsecret_OIDCClientSecretRequest(a.(*OIDCClientSecretRequest), b.(*clientsecret.OIDCClientSecretRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*clientsecret.OIDCClientSecretRequest)(nil), (*OIDCClientSecretRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_clientsecret_OIDCClientSecretRequest_To_v1alpha1_OIDCClientSecretRequest(a.(*clientsecret.OIDCClientSecretRequest), b.(*OIDCClientSecretRequest), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*OIDCClientSecretRequestList)(nil), (*clientsecret.OIDCClientSecretRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_OIDCClientSecretRequestList_To_clientsecret_OIDCClientSecretRequestList(a.(*OIDCClientSecretRequestList), b.(*clientsecret.OIDCClientSecretRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*clientsecret.OIDCClientSecretRequestList)(nil), (*OIDCClientSecretRequestList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_clientsecret_OIDCClientSecretRequestList_To_v1alpha1_OIDCClientSecretRequestList(a.(*clientsecret.OIDCClientSecretRequestList), b.(*OIDCClientSecretRequestList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*OIDCClientSecretRequestSpec)(nil), (*clientsecret.OIDCClientSecretRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec(a.(*OIDCClientSecretRequestSpec), b.(*clientsecret.OIDCClientSecretRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*clientsecret.OIDCClientSecretRequestSpec)(nil), (*OIDCClientSecretRequestSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec(a.(*clientsecret.OIDCClientSecretRequestSpec), b.(*OIDCClientSecretRequestSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*OIDCClientSecretRequestStatus)(nil), (*clientsecret.OIDCClientSecretRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus(a.(*OIDCClientSecretRequestStatus), b.(*clientsecret.OIDCClientSecretRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*clientsecret.OIDCClientSecretRequestStatus)(nil), (*OIDCClientSecretRequestStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus(a.(*clientsecret.OIDCClientSecretRequestStatus), b.(*OIDCClientSecretRequestStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_OIDCClientSecretRequest_To_clientsecret_OIDCClientSecretRequest(in *OIDCClientSecretRequest, out *clientsecret.OIDCClientSecretRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_OIDCClientSecretRequest_To_clientsecret_OIDCClientSecretRequest is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_OIDCClientSecretRequest_To_clientsecret_OIDCClientSecretRequest(in *OIDCClientSecretRequest, out *clientsecret.OIDCClientSecretRequest, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_OIDCClientSecretRequest_To_clientsecret_OIDCClientSecretRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientsecret_OIDCClientSecretRequest_To_v1alpha1_OIDCClientSecretRequest(in *clientsecret.OIDCClientSecretRequest, out *OIDCClientSecretRequest, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientsecret_OIDCClientSecretRequest_To_v1alpha1_OIDCClientSecretRequest is an autogenerated conversion function.
|
||||
func Convert_clientsecret_OIDCClientSecretRequest_To_v1alpha1_OIDCClientSecretRequest(in *clientsecret.OIDCClientSecretRequest, out *OIDCClientSecretRequest, s conversion.Scope) error {
|
||||
return autoConvert_clientsecret_OIDCClientSecretRequest_To_v1alpha1_OIDCClientSecretRequest(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_OIDCClientSecretRequestList_To_clientsecret_OIDCClientSecretRequestList(in *OIDCClientSecretRequestList, out *clientsecret.OIDCClientSecretRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]clientsecret.OIDCClientSecretRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_OIDCClientSecretRequestList_To_clientsecret_OIDCClientSecretRequestList is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_OIDCClientSecretRequestList_To_clientsecret_OIDCClientSecretRequestList(in *OIDCClientSecretRequestList, out *clientsecret.OIDCClientSecretRequestList, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_OIDCClientSecretRequestList_To_clientsecret_OIDCClientSecretRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientsecret_OIDCClientSecretRequestList_To_v1alpha1_OIDCClientSecretRequestList(in *clientsecret.OIDCClientSecretRequestList, out *OIDCClientSecretRequestList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]OIDCClientSecretRequest)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientsecret_OIDCClientSecretRequestList_To_v1alpha1_OIDCClientSecretRequestList is an autogenerated conversion function.
|
||||
func Convert_clientsecret_OIDCClientSecretRequestList_To_v1alpha1_OIDCClientSecretRequestList(in *clientsecret.OIDCClientSecretRequestList, out *OIDCClientSecretRequestList, s conversion.Scope) error {
|
||||
return autoConvert_clientsecret_OIDCClientSecretRequestList_To_v1alpha1_OIDCClientSecretRequestList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec(in *OIDCClientSecretRequestSpec, out *clientsecret.OIDCClientSecretRequestSpec, s conversion.Scope) error {
|
||||
out.GenerateNewSecret = in.GenerateNewSecret
|
||||
out.RevokeOldSecrets = in.RevokeOldSecrets
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec(in *OIDCClientSecretRequestSpec, out *clientsecret.OIDCClientSecretRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_OIDCClientSecretRequestSpec_To_clientsecret_OIDCClientSecretRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec(in *clientsecret.OIDCClientSecretRequestSpec, out *OIDCClientSecretRequestSpec, s conversion.Scope) error {
|
||||
out.GenerateNewSecret = in.GenerateNewSecret
|
||||
out.RevokeOldSecrets = in.RevokeOldSecrets
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec is an autogenerated conversion function.
|
||||
func Convert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec(in *clientsecret.OIDCClientSecretRequestSpec, out *OIDCClientSecretRequestSpec, s conversion.Scope) error {
|
||||
return autoConvert_clientsecret_OIDCClientSecretRequestSpec_To_v1alpha1_OIDCClientSecretRequestSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus(in *OIDCClientSecretRequestStatus, out *clientsecret.OIDCClientSecretRequestStatus, s conversion.Scope) error {
|
||||
out.GeneratedSecret = in.GeneratedSecret
|
||||
out.TotalClientSecrets = in.TotalClientSecrets
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus(in *OIDCClientSecretRequestStatus, out *clientsecret.OIDCClientSecretRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_OIDCClientSecretRequestStatus_To_clientsecret_OIDCClientSecretRequestStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus(in *clientsecret.OIDCClientSecretRequestStatus, out *OIDCClientSecretRequestStatus, s conversion.Scope) error {
|
||||
out.GeneratedSecret = in.GeneratedSecret
|
||||
out.TotalClientSecrets = in.TotalClientSecrets
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus is an autogenerated conversion function.
|
||||
func Convert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus(in *clientsecret.OIDCClientSecretRequestStatus, out *OIDCClientSecretRequestStatus, s conversion.Scope) error {
|
||||
return autoConvert_clientsecret_OIDCClientSecretRequestStatus_To_v1alpha1_OIDCClientSecretRequestStatus(in, out, s)
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 *OIDCClientSecretRequest) DeepCopyInto(out *OIDCClientSecretRequest) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
out.Status = in.Status
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequest.
|
||||
func (in *OIDCClientSecretRequest) DeepCopy() *OIDCClientSecretRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClientSecretRequest) 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 *OIDCClientSecretRequestList) DeepCopyInto(out *OIDCClientSecretRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OIDCClientSecretRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestList.
|
||||
func (in *OIDCClientSecretRequestList) DeepCopy() *OIDCClientSecretRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClientSecretRequestList) 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 *OIDCClientSecretRequestSpec) DeepCopyInto(out *OIDCClientSecretRequestSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestSpec.
|
||||
func (in *OIDCClientSecretRequestSpec) DeepCopy() *OIDCClientSecretRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClientSecretRequestStatus) DeepCopyInto(out *OIDCClientSecretRequestStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestStatus.
|
||||
func (in *OIDCClientSecretRequestStatus) DeepCopy() *OIDCClientSecretRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package clientsecret
|
||||
|
||||
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 *OIDCClientSecretRequest) DeepCopyInto(out *OIDCClientSecretRequest) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
out.Status = in.Status
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequest.
|
||||
func (in *OIDCClientSecretRequest) DeepCopy() *OIDCClientSecretRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClientSecretRequest) 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 *OIDCClientSecretRequestList) DeepCopyInto(out *OIDCClientSecretRequestList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OIDCClientSecretRequest, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestList.
|
||||
func (in *OIDCClientSecretRequestList) DeepCopy() *OIDCClientSecretRequestList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClientSecretRequestList) 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 *OIDCClientSecretRequestSpec) DeepCopyInto(out *OIDCClientSecretRequestSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestSpec.
|
||||
func (in *OIDCClientSecretRequestSpec) DeepCopy() *OIDCClientSecretRequestSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClientSecretRequestStatus) DeepCopyInto(out *OIDCClientSecretRequestStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSecretRequestStatus.
|
||||
func (in *OIDCClientSecretRequestStatus) DeepCopy() *OIDCClientSecretRequestStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSecretRequestStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=go.pinniped.dev/generated/1.17/apis/supervisor/config
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=config.supervisor.pinniped.dev
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor configuration API.
|
||||
package v1alpha1
|
||||
@@ -1,135 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=Success;Duplicate;Invalid;SameIssuerHostMustUseSameSecret
|
||||
type FederationDomainStatusCondition string
|
||||
|
||||
const (
|
||||
SuccessFederationDomainStatusCondition = FederationDomainStatusCondition("Success")
|
||||
DuplicateFederationDomainStatusCondition = FederationDomainStatusCondition("Duplicate")
|
||||
SameIssuerHostMustUseSameSecretFederationDomainStatusCondition = FederationDomainStatusCondition("SameIssuerHostMustUseSameSecret")
|
||||
InvalidFederationDomainStatusCondition = FederationDomainStatusCondition("Invalid")
|
||||
)
|
||||
|
||||
// FederationDomainTLSSpec is a struct that describes the TLS configuration for an OIDC Provider.
|
||||
type FederationDomainTLSSpec struct {
|
||||
// SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains
|
||||
// the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret
|
||||
// named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use
|
||||
// for TLS.
|
||||
//
|
||||
// Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers.
|
||||
//
|
||||
// SecretName is required if you would like to use different TLS certificates for issuers of different hostnames.
|
||||
// SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same
|
||||
// SecretName value even if they have different port numbers.
|
||||
//
|
||||
// SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is
|
||||
// configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar).
|
||||
// It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to
|
||||
// use the default TLS certificate, which is configured elsewhere.
|
||||
//
|
||||
// When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses.
|
||||
//
|
||||
// +optional
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSpec is a struct that describes an OIDC Provider.
|
||||
type FederationDomainSpec struct {
|
||||
// Issuer is the OIDC Provider's issuer, per the OIDC Discovery Metadata document, as well as the
|
||||
// identifier that it will use for the iss claim in issued JWTs. This field will also be used as
|
||||
// the base URL for any endpoints used by the OIDC Provider (e.g., if your issuer is
|
||||
// https://example.com/foo, then your authorization endpoint will look like
|
||||
// https://example.com/foo/some/path/to/auth/endpoint).
|
||||
//
|
||||
// See
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS configures how this FederationDomain is served over Transport Layer Security (TLS).
|
||||
// +optional
|
||||
TLS *FederationDomainTLSSpec `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainSecrets holds information about this OIDC Provider's secrets.
|
||||
type FederationDomainSecrets struct {
|
||||
// JWKS holds the name of the corev1.Secret in which this OIDC Provider's signing/verification keys are
|
||||
// stored. If it is empty, then the signing/verification keys are either unknown or they don't
|
||||
// exist.
|
||||
// +optional
|
||||
JWKS corev1.LocalObjectReference `json:"jwks,omitempty"`
|
||||
|
||||
// TokenSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// signing tokens is stored.
|
||||
// +optional
|
||||
TokenSigningKey corev1.LocalObjectReference `json:"tokenSigningKey,omitempty"`
|
||||
|
||||
// StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// signing state parameters is stored.
|
||||
// +optional
|
||||
StateSigningKey corev1.LocalObjectReference `json:"stateSigningKey,omitempty"`
|
||||
|
||||
// StateSigningKey holds the name of the corev1.Secret in which this OIDC Provider's key for
|
||||
// encrypting state parameters is stored.
|
||||
// +optional
|
||||
StateEncryptionKey corev1.LocalObjectReference `json:"stateEncryptionKey,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomainStatus is a struct that describes the actual state of an OIDC Provider.
|
||||
type FederationDomainStatus struct {
|
||||
// Status holds an enum that describes the state of this OIDC Provider. Note that this Status can
|
||||
// represent success or failure.
|
||||
// +optional
|
||||
Status FederationDomainStatusCondition `json:"status,omitempty"`
|
||||
|
||||
// Message provides human-readable details about the Status.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// LastUpdateTime holds the time at which the Status was last updated. It is a pointer to get
|
||||
// around some undesirable behavior with respect to the empty metav1.Time value (see
|
||||
// https://github.com/kubernetes/kubernetes/issues/86811).
|
||||
// +optional
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
|
||||
// Secrets contains information about this OIDC Provider's secrets.
|
||||
// +optional
|
||||
Secrets FederationDomainSecrets `json:"secrets,omitempty"`
|
||||
}
|
||||
|
||||
// FederationDomain describes the configuration of an OIDC provider.
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped
|
||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type FederationDomain struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec of the OIDC provider.
|
||||
Spec FederationDomainSpec `json:"spec"`
|
||||
|
||||
// Status of the OIDC provider.
|
||||
Status FederationDomainStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// List of FederationDomain objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type FederationDomainList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []FederationDomain `json:"items"`
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
type OIDCClientPhase string
|
||||
|
||||
const (
|
||||
// PhasePending is the default phase for newly-created OIDCClient resources.
|
||||
PhasePending OIDCClientPhase = "Pending"
|
||||
|
||||
// PhaseReady is the phase for an OIDCClient resource in a healthy state.
|
||||
PhaseReady OIDCClientPhase = "Ready"
|
||||
|
||||
// PhaseError is the phase for an OIDCClient in an unhealthy state.
|
||||
PhaseError OIDCClientPhase = "Error"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Pattern=`^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/`
|
||||
type RedirectURI string
|
||||
|
||||
// +kubebuilder:validation:Enum="authorization_code";"refresh_token";"urn:ietf:params:oauth:grant-type:token-exchange"
|
||||
type GrantType string
|
||||
|
||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||
type Scope string
|
||||
|
||||
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||
type OIDCClientSpec struct {
|
||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||
// client. Any other uris will be rejected.
|
||||
// Must be a URI with the https scheme, unless the hostname is 127.0.0.1 or ::1 which may use the http scheme.
|
||||
// Port numbers are not required for 127.0.0.1 or ::1 and are ignored when checking for a matching redirect_uri.
|
||||
// +listType=set
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
AllowedRedirectURIs []RedirectURI `json:"allowedRedirectURIs"`
|
||||
|
||||
// allowedGrantTypes is a list of the allowed grant_type param values that should be accepted during OIDC flows with this
|
||||
// client.
|
||||
//
|
||||
// Must only contain the following values:
|
||||
// - authorization_code: allows the client to perform the authorization code grant flow, i.e. allows the webapp to
|
||||
// authenticate users. This grant must always be listed.
|
||||
// - refresh_token: allows the client to perform refresh grants for the user to extend the user's session.
|
||||
// This grant must be listed if allowedScopes lists offline_access.
|
||||
// - urn:ietf:params:oauth:grant-type:token-exchange: allows the client to perform RFC8693 token exchange,
|
||||
// which is a step in the process to be able to get a cluster credential for the user.
|
||||
// This grant must be listed if allowedScopes lists pinniped:request-audience.
|
||||
// +listType=set
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
AllowedGrantTypes []GrantType `json:"allowedGrantTypes"`
|
||||
|
||||
// allowedScopes is a list of the allowed scopes param values that should be accepted during OIDC flows with this client.
|
||||
//
|
||||
// Must only contain the following values:
|
||||
// - openid: The client is allowed to request ID tokens. ID tokens only include the required claims by default (iss, sub, aud, exp, iat).
|
||||
// This scope must always be listed.
|
||||
// - offline_access: The client is allowed to request an initial refresh token during the authorization code grant flow.
|
||||
// This scope must be listed if allowedGrantTypes lists refresh_token.
|
||||
// - pinniped:request-audience: The client is allowed to request a new audience value during a RFC8693 token exchange,
|
||||
// which is a step in the process to be able to get a cluster credential for the user.
|
||||
// openid, username and groups scopes must be listed when this scope is present.
|
||||
// This scope must be listed if allowedGrantTypes lists urn:ietf:params:oauth:grant-type:token-exchange.
|
||||
// - username: The client is allowed to request that ID tokens contain the user's username.
|
||||
// Without the username scope being requested and allowed, the ID token will not contain the user's username.
|
||||
// - groups: The client is allowed to request that ID tokens contain the user's group membership,
|
||||
// if their group membership is discoverable by the Supervisor.
|
||||
// Without the groups scope being requested and allowed, the ID token will not contain groups.
|
||||
// +listType=set
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
AllowedScopes []Scope `json:"allowedScopes"`
|
||||
}
|
||||
|
||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||
type OIDCClientStatus struct {
|
||||
// phase summarizes the overall status of the OIDCClient.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||
|
||||
// conditions represent the observations of an OIDCClient's current state.
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
|
||||
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||
// +optional
|
||||
TotalClientSecrets int32 `json:"totalClientSecrets"` // do not omitempty to allow it to show in the printer column even when it is 0
|
||||
}
|
||||
|
||||
// OIDCClient describes the configuration of an OIDC client.
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped
|
||||
// +kubebuilder:printcolumn:name="Privileged Scopes",type=string,JSONPath=`.spec.allowedScopes[?(@ == "pinniped:request-audience")]`
|
||||
// +kubebuilder:printcolumn:name="Client Secrets",type=integer,JSONPath=`.status.totalClientSecrets`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type OIDCClient struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec of the OIDC client.
|
||||
Spec OIDCClientSpec `json:"spec"`
|
||||
|
||||
// Status of the OIDC client.
|
||||
Status OIDCClientStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// List of OIDCClient objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type OIDCClientList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []OIDCClient `json:"items"`
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 *Condition) DeepCopyInto(out *Condition) {
|
||||
*out = *in
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||
func (in *Condition) DeepCopy() *Condition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Condition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FederationDomain) DeepCopyInto(out *FederationDomain) {
|
||||
*out = *in
|
||||
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 FederationDomain.
|
||||
func (in *FederationDomain) DeepCopy() *FederationDomain {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomain)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *FederationDomain) 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 *FederationDomainList) DeepCopyInto(out *FederationDomainList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]FederationDomain, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainList.
|
||||
func (in *FederationDomainList) DeepCopy() *FederationDomainList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomainList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *FederationDomainList) 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 *FederationDomainSecrets) DeepCopyInto(out *FederationDomainSecrets) {
|
||||
*out = *in
|
||||
out.JWKS = in.JWKS
|
||||
out.TokenSigningKey = in.TokenSigningKey
|
||||
out.StateSigningKey = in.StateSigningKey
|
||||
out.StateEncryptionKey = in.StateEncryptionKey
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainSecrets.
|
||||
func (in *FederationDomainSecrets) DeepCopy() *FederationDomainSecrets {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomainSecrets)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FederationDomainSpec) DeepCopyInto(out *FederationDomainSpec) {
|
||||
*out = *in
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(FederationDomainTLSSpec)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainSpec.
|
||||
func (in *FederationDomainSpec) DeepCopy() *FederationDomainSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomainSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FederationDomainStatus) DeepCopyInto(out *FederationDomainStatus) {
|
||||
*out = *in
|
||||
if in.LastUpdateTime != nil {
|
||||
in, out := &in.LastUpdateTime, &out.LastUpdateTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
out.Secrets = in.Secrets
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainStatus.
|
||||
func (in *FederationDomainStatus) DeepCopy() *FederationDomainStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomainStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FederationDomainTLSSpec) DeepCopyInto(out *FederationDomainTLSSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederationDomainTLSSpec.
|
||||
func (in *FederationDomainTLSSpec) DeepCopy() *FederationDomainTLSSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FederationDomainTLSSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClient) DeepCopyInto(out *OIDCClient) {
|
||||
*out = *in
|
||||
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 OIDCClient.
|
||||
func (in *OIDCClient) DeepCopy() *OIDCClient {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClient)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClient) 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 *OIDCClientList) DeepCopyInto(out *OIDCClientList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OIDCClient, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientList.
|
||||
func (in *OIDCClientList) DeepCopy() *OIDCClientList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCClientList) 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 *OIDCClientSpec) DeepCopyInto(out *OIDCClientSpec) {
|
||||
*out = *in
|
||||
if in.AllowedRedirectURIs != nil {
|
||||
in, out := &in.AllowedRedirectURIs, &out.AllowedRedirectURIs
|
||||
*out = make([]RedirectURI, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AllowedGrantTypes != nil {
|
||||
in, out := &in.AllowedGrantTypes, &out.AllowedGrantTypes
|
||||
*out = make([]GrantType, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AllowedScopes != nil {
|
||||
in, out := &in.AllowedScopes, &out.AllowedScopes
|
||||
*out = make([]Scope, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClientSpec.
|
||||
func (in *OIDCClientSpec) DeepCopy() *OIDCClientSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClientStatus) DeepCopyInto(out *OIDCClientStatus) {
|
||||
*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 OIDCClientStatus.
|
||||
func (in *OIDCClientStatus) DeepCopy() *OIDCClientStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClientStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
11
generated/1.17/apis/supervisor/idp/v1alpha1/doc.go
generated
11
generated/1.17/apis/supervisor/idp/v1alpha1/doc.go
generated
@@ -1,11 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=idp.supervisor.pinniped.dev
|
||||
// +groupGoName=IDP
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity provider (IDP) API.
|
||||
package v1alpha1
|
||||
@@ -1,207 +0,0 @@
|
||||
// Copyright 2021-2022 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"`
|
||||
|
||||
// The user's group membership is refreshed as they interact with the supervisor
|
||||
// to obtain new credentials (as their old credentials expire). This allows group
|
||||
// membership changes to be quickly reflected into Kubernetes clusters. Since
|
||||
// group membership is often used to bind authorization policies, it is important
|
||||
// to keep the groups observed in Kubernetes clusters in-sync with the identity
|
||||
// provider.
|
||||
//
|
||||
// In some environments, frequent group membership queries may result in a
|
||||
// significant performance impact on the identity provider and/or the supervisor.
|
||||
// The best approach to handle performance impacts is to tweak the group query
|
||||
// to be more performant, for example by disabling nested group search or by
|
||||
// using a more targeted group search base.
|
||||
//
|
||||
// If the group search query cannot be made performant and you are willing to
|
||||
// have group memberships remain static for approximately a day, then set
|
||||
// skipGroupRefresh to true. This is an insecure configuration as authorization
|
||||
// policies that are bound to group membership will not notice if a user has
|
||||
// been removed from a particular group until their next login.
|
||||
//
|
||||
// This is an experimental feature that may be removed or significantly altered
|
||||
// in the future. Consumers of this configuration should carefully read all
|
||||
// release notes before upgrading to ensure that the meaning of this field has
|
||||
// not changed.
|
||||
SkipGroupRefresh bool `json:"skipGroupRefresh,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"`
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
// Copyright 2021-2022 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"`
|
||||
|
||||
// The user's group membership is refreshed as they interact with the supervisor
|
||||
// to obtain new credentials (as their old credentials expire). This allows group
|
||||
// membership changes to be quickly reflected into Kubernetes clusters. Since
|
||||
// group membership is often used to bind authorization policies, it is important
|
||||
// to keep the groups observed in Kubernetes clusters in-sync with the identity
|
||||
// provider.
|
||||
//
|
||||
// In some environments, frequent group membership queries may result in a
|
||||
// significant performance impact on the identity provider and/or the supervisor.
|
||||
// The best approach to handle performance impacts is to tweak the group query
|
||||
// to be more performant, for example by disabling nested group search or by
|
||||
// using a more targeted group search base.
|
||||
//
|
||||
// If the group search query cannot be made performant and you are willing to
|
||||
// have group memberships remain static for approximately a day, then set
|
||||
// skipGroupRefresh to true. This is an insecure configuration as authorization
|
||||
// policies that are bound to group membership will not notice if a user has
|
||||
// been removed from a particular group until their next login.
|
||||
//
|
||||
// This is an experimental feature that may be removed or significantly altered
|
||||
// in the future. Consumers of this configuration should carefully read all
|
||||
// release notes before upgrading to ensure that the meaning of this field has
|
||||
// not changed.
|
||||
SkipGroupRefresh bool `json:"skipGroupRefresh,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"`
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// ConditionStatus is effectively an enum type for Condition.Status.
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// Condition status of a resource (mirrored from the metav1.Condition type added in Kubernetes 1.19). In a future API
|
||||
// version we can switch to using the upstream type.
|
||||
// See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
type Condition struct {
|
||||
// type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
// ---
|
||||
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
// useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
|
||||
// +kubebuilder:validation:MaxLength=316
|
||||
Type string `json:"type"`
|
||||
|
||||
// status of the condition, one of True, False, Unknown.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Enum=True;False;Unknown
|
||||
Status ConditionStatus `json:"status"`
|
||||
|
||||
// observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
// with respect to the current state of the instance.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Format=date-time
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
|
||||
|
||||
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
// Producers of specific condition types may define expected values and meanings for this field,
|
||||
// and whether the values are considered a guaranteed API.
|
||||
// The value should be a CamelCase string.
|
||||
// This field may not be empty.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=1024
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
|
||||
Reason string `json:"reason"`
|
||||
|
||||
// message is a human readable message indicating details about the transition.
|
||||
// This may be an empty string.
|
||||
// +required
|
||||
// +kubebuilder:validation:Required
|
||||
// +kubebuilder:validation:MaxLength=32768
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type OIDCIdentityProviderPhase string
|
||||
|
||||
const (
|
||||
// PhasePending is the default phase for newly-created OIDCIdentityProvider resources.
|
||||
PhasePending OIDCIdentityProviderPhase = "Pending"
|
||||
|
||||
// PhaseReady is the phase for an OIDCIdentityProvider resource in a healthy state.
|
||||
PhaseReady OIDCIdentityProviderPhase = "Ready"
|
||||
|
||||
// PhaseError is the phase for an OIDCIdentityProvider in an unhealthy state.
|
||||
PhaseError OIDCIdentityProviderPhase = "Error"
|
||||
)
|
||||
|
||||
// OIDCIdentityProviderStatus is the status of an OIDC identity provider.
|
||||
type OIDCIdentityProviderStatus struct {
|
||||
// Phase summarizes the overall status of the OIDCIdentityProvider.
|
||||
// +kubebuilder:default=Pending
|
||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||
Phase OIDCIdentityProviderPhase `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"`
|
||||
}
|
||||
|
||||
// OIDCAuthorizationConfig provides information about how to form the OAuth2 authorization
|
||||
// request parameters.
|
||||
type OIDCAuthorizationConfig struct {
|
||||
// additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization
|
||||
// request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials
|
||||
// Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is
|
||||
// always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request
|
||||
// the following scopes: "openid", "offline_access", "email", and "profile". See
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email"
|
||||
// scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the
|
||||
// "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves,
|
||||
// or as common patterns used by providers who implement the standard in the ecosystem evolve.
|
||||
// By setting this list to anything other than an empty list, you are overriding the
|
||||
// default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list.
|
||||
// If you do not want any of these scopes to be requested, you may set this list to contain only "openid".
|
||||
// Some OIDC providers may also require a scope to get access to the user's group membership, in which case you
|
||||
// may wish to include it in this list. Sometimes the scope to request the user's group membership is called
|
||||
// "groups", but unfortunately this is not specified in the OIDC standard.
|
||||
// Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by
|
||||
// your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in
|
||||
// the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See
|
||||
// your OIDC provider's documentation for more information about what scopes are available to request claims.
|
||||
// Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor
|
||||
// from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be
|
||||
// "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its
|
||||
// requirements for what to include in the request in order to receive a refresh token in the response, if anything.
|
||||
// Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider
|
||||
// may ignore scopes that it does not understand or require (see
|
||||
// https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the
|
||||
// "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC
|
||||
// provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
|
||||
// +optional
|
||||
AdditionalScopes []string `json:"additionalScopes,omitempty"`
|
||||
|
||||
// additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your
|
||||
// OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra
|
||||
// parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id",
|
||||
// "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be
|
||||
// included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time.
|
||||
// The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user
|
||||
// should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting
|
||||
// ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped.
|
||||
// This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password
|
||||
// Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the
|
||||
// Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt"
|
||||
// parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's
|
||||
// authorization endpoint for its requirements for what to include in the request in order to receive a refresh
|
||||
// token in the response, if anything. If your provider requires the prompt parameter to request a refresh token,
|
||||
// then include it here. Also note that most providers also require a certain scope to be requested in order to
|
||||
// receive refresh tokens. See the additionalScopes setting for more information about using scopes to request
|
||||
// refresh tokens.
|
||||
// +optional
|
||||
// +patchMergeKey=name
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=name
|
||||
AdditionalAuthorizeParameters []Parameter `json:"additionalAuthorizeParameters,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"`
|
||||
}
|
||||
|
||||
// Parameter is a key/value pair which represents a parameter in an HTTP request.
|
||||
type Parameter struct {
|
||||
// The name of the parameter. Required.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Name string `json:"name"`
|
||||
|
||||
// The value of the parameter.
|
||||
// +optional
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCClaims provides a mapping from upstream claims into identities.
|
||||
type OIDCClaims struct {
|
||||
// Groups provides the name of the ID token claim or userinfo endpoint response claim that will be used to ascertain
|
||||
// the groups to which an identity belongs. By default, the identities will not include any group memberships when
|
||||
// this setting is not configured.
|
||||
// +optional
|
||||
Groups string `json:"groups"`
|
||||
|
||||
// Username provides the name of the ID token claim or userinfo endpoint response claim that will be used to
|
||||
// ascertain an identity's username. When not set, the username will be an automatically constructed unique string
|
||||
// which will include the issuer URL of your OIDC provider along with the value of the "sub" (subject) claim from
|
||||
// the ID token.
|
||||
// +optional
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// OIDCClient contains information about an OIDC client (e.g., client ID and client
|
||||
// secret).
|
||||
type OIDCClient struct {
|
||||
// SecretName contains the name of a namespace-local Secret object that provides the clientID and
|
||||
// clientSecret for an OIDC client. If only the SecretName is specified in an OIDCClient
|
||||
// struct, then it is expected that the Secret is of type "secrets.pinniped.dev/oidc-client" with keys
|
||||
// "clientID" and "clientSecret".
|
||||
SecretName string `json:"secretName"`
|
||||
}
|
||||
|
||||
// OIDCIdentityProviderSpec is the spec for configuring an OIDC identity provider.
|
||||
type OIDCIdentityProviderSpec struct {
|
||||
// Issuer is the issuer URL of this OIDC identity provider, i.e., where to fetch
|
||||
// /.well-known/openid-configuration.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Pattern=`^https://`
|
||||
Issuer string `json:"issuer"`
|
||||
|
||||
// TLS configuration for discovery/JWKS requests to the issuer.
|
||||
// +optional
|
||||
TLS *TLSSpec `json:"tls,omitempty"`
|
||||
|
||||
// AuthorizationConfig holds information about how to form the OAuth2 authorization request
|
||||
// parameters to be used with this OIDC identity provider.
|
||||
// +optional
|
||||
AuthorizationConfig OIDCAuthorizationConfig `json:"authorizationConfig,omitempty"`
|
||||
|
||||
// Claims provides the names of token claims that will be used when inspecting an identity from
|
||||
// this OIDC identity provider.
|
||||
// +optional
|
||||
Claims OIDCClaims `json:"claims"`
|
||||
|
||||
// OIDCClient contains OIDC client information to be used used with this OIDC identity
|
||||
// provider.
|
||||
Client OIDCClient `json:"client"`
|
||||
}
|
||||
|
||||
// OIDCIdentityProvider describes the configuration of an upstream OpenID Connect identity provider.
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps
|
||||
// +kubebuilder:printcolumn:name="Issuer",type=string,JSONPath=`.spec.issuer`
|
||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
// +kubebuilder:subresource:status
|
||||
type OIDCIdentityProvider struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec for configuring the identity provider.
|
||||
Spec OIDCIdentityProviderSpec `json:"spec"`
|
||||
|
||||
// Status of the identity provider.
|
||||
Status OIDCIdentityProviderStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCIdentityProviderList lists OIDCIdentityProvider objects.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type OIDCIdentityProviderList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []OIDCIdentityProvider `json:"items"`
|
||||
}
|
||||
@@ -1,608 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
|
||||
func (in *Condition) DeepCopy() *Condition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Condition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *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
|
||||
if in.AdditionalScopes != nil {
|
||||
in, out := &in.AdditionalScopes, &out.AdditionalScopes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AdditionalAuthorizeParameters != nil {
|
||||
in, out := &in.AdditionalAuthorizeParameters, &out.AdditionalAuthorizeParameters
|
||||
*out = make([]Parameter, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCAuthorizationConfig.
|
||||
func (in *OIDCAuthorizationConfig) DeepCopy() *OIDCAuthorizationConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCAuthorizationConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClaims) DeepCopyInto(out *OIDCClaims) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClaims.
|
||||
func (in *OIDCClaims) DeepCopy() *OIDCClaims {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClaims)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCClient) DeepCopyInto(out *OIDCClient) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCClient.
|
||||
func (in *OIDCClient) DeepCopy() *OIDCClient {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCClient)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCIdentityProvider) DeepCopyInto(out *OIDCIdentityProvider) {
|
||||
*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 OIDCIdentityProvider.
|
||||
func (in *OIDCIdentityProvider) DeepCopy() *OIDCIdentityProvider {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityProvider)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCIdentityProvider) 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 *OIDCIdentityProviderList) DeepCopyInto(out *OIDCIdentityProviderList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OIDCIdentityProvider, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCIdentityProviderList.
|
||||
func (in *OIDCIdentityProviderList) DeepCopy() *OIDCIdentityProviderList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityProviderList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OIDCIdentityProviderList) 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 *OIDCIdentityProviderSpec) DeepCopyInto(out *OIDCIdentityProviderSpec) {
|
||||
*out = *in
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(TLSSpec)
|
||||
**out = **in
|
||||
}
|
||||
in.AuthorizationConfig.DeepCopyInto(&out.AuthorizationConfig)
|
||||
out.Claims = in.Claims
|
||||
out.Client = in.Client
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCIdentityProviderSpec.
|
||||
func (in *OIDCIdentityProviderSpec) DeepCopy() *OIDCIdentityProviderSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityProviderSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCIdentityProviderStatus) DeepCopyInto(out *OIDCIdentityProviderStatus) {
|
||||
*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 OIDCIdentityProviderStatus.
|
||||
func (in *OIDCIdentityProviderStatus) DeepCopy() *OIDCIdentityProviderStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityProviderStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Parameter) DeepCopyInto(out *Parameter) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parameter.
|
||||
func (in *Parameter) DeepCopy() *Parameter {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Parameter)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLSSpec) DeepCopyInto(out *TLSSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSpec.
|
||||
func (in *TLSSpec) DeepCopy() *TLSSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TLSSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user