Compare commits

...

492 Commits

Author SHA1 Message Date
Kubernetes Publisher 6016cdfb88 Merge pull request #132803 from aramase/aramase/f/token_request_uid_check
Make kubelet token cache UID-aware to prevent stale tokens after service account recreation

Kubernetes-commit: 2bdcad7419c7a584da4174513e36f867e88424df
2025-07-11 09:20:03 +00:00
Kubernetes Publisher 6dc2a56d3a Merge pull request #132848 from serathius/etcd3-compactor
Expose compaction revision from compactor

Kubernetes-commit: 054750fc262a62dd311a52f31e1577d6096bcaa9
2025-07-10 21:20:36 +00:00
Marek Siarkowicz dda2fcb797 Expose compaction revision from compactor
Kubernetes-commit: 03e32bd260fbd77351e1b528f22a69a8eaece9ee
2025-07-09 16:22:19 +02:00
Marek Siarkowicz 34f5472b35 Add test for compactor
Kubernetes-commit: 5e3ea8e279c51a0b4fcc996d244d2c5593935816
2025-07-09 16:29:55 +02:00
Kubernetes Publisher 532260d25f Merge pull request #132813 from serathius/compact-test
Add testing compaction in storage List tests

Kubernetes-commit: da7058e92caf87208a15331020051c0523d71cfd
2025-07-09 21:30:45 +00:00
Kubernetes Publisher 0a000a99f6 Merge pull request #132715 from googs1025/fix/flaky_patch
fix: TestPatchResourceTimeout flaky test

Kubernetes-commit: 4142fb530ceb25d9965a3e6925be79a03d918cba
2025-07-08 17:28:12 +00:00
Kubernetes Publisher e824ccb0fa Merge pull request #132788 from ylink-lfs/chore/strptr_removal
chore: remove strPtr usage with ptr.To

Kubernetes-commit: 3d13f39f24e5533286278f04702c69fbed448c35
2025-07-08 09:20:06 +00:00
Marek Siarkowicz 2f077fcbca Add testing compaction in storage List tests
Kubernetes-commit: c53b41e98c2e9248916704f36443de87cbee64e0
2025-07-08 11:19:59 +02:00
Kubernetes Publisher d7827fc7e8 Merge pull request #132794 from PatrickLaabs/132749-boolptr
chore: replacement of boolPtr helper functions to ptr packge

Kubernetes-commit: 5f34f9233b2e2f9714b71dc1e1a0dbf24548866c
2025-07-08 05:20:18 +00:00
Kubernetes Publisher 32cbb819fe Merge pull request #132799 from BenTheElder/etcd-apiserver-panic
storage/etcd3: add back missing errcheck

Kubernetes-commit: 70e225397bb8e397d5219291f2dbfbb4aaaa999e
2025-07-08 05:20:16 +00:00
Benjamin Elder bf8c1a6d90 storage/etcd3: add back missing errcheck
lost in recent refactoring.

Kubernetes-commit: 838f3afc5219640725922266b689c7d24fbdf804
2025-07-07 17:37:36 -07:00
Anish Ramasekar c42cceba12 Add TokenRequestServiceAccountUIDValidation feature gate with UID validation
This change introduces the TokenRequestServiceAccountUIDValidation feature
gate and implements feature-gated service account UID validation for the
TokenRequest API. When enabled, the API validates that the service account
UID in token requests matches the actual service account UID, preventing
token requests for recreated service accounts with the same name but
different UIDs.

Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 45dfb46448a130482e9050664f9d7f7288c0b4b3
2025-07-07 16:51:41 -07:00
PatrickLaabs d972fefbb0 chore: replacement of helper functions to ptr packge
Kubernetes-commit: cfd65c5f74dbb5fa02e7b20c3b1039193567ba53
2025-07-07 21:28:54 +02:00
ylink-lfs 8cd1907cc9 chore: remove strPtr usage with ptr.To instead
Kubernetes-commit: 830a088d1bc7075bbb176b44d73a79adfa659d75
2025-07-07 20:12:31 +08:00
Kubernetes Publisher 5e1c1db1da Merge pull request #132752 from PatrickLaabs/132086-apiserver-2
chore: second depr. pointer pkg replacement for apiserver (2/2)

Kubernetes-commit: 116cfc0c5f38f37be05542d468943790cedde7c4
2025-07-07 01:28:13 +00:00
Kubernetes Publisher 03b538a8e8 Merge pull request #132751 from PatrickLaabs/132086-apiserver-1
chore: first depr. pointer pkg replacement for apiserver (1/2)

Kubernetes-commit: d7a06387fe7305df5d7b3ebbab998686fae84a63
2025-07-06 21:20:28 +00:00
PatrickLaabs d0ee71ec17 chore: second depr. pointer pkg replacement for apiserver
Kubernetes-commit: fe61e825e046d793d64fc0686110212dacf8231e
2025-07-06 11:09:16 +02:00
PatrickLaabs 9b1ef94042 chore: first depr. pointer pkg replacement for apiserver
Kubernetes-commit: 4a61b8170138998a1f1d49f01ad38e8e3aa88f20
2025-07-06 10:58:23 +02:00
googs1025 f482a77223 fix: TestPatchResourceTimeout flaky test
Signed-off-by: googs1025 <googs1025@gmail.com>

Kubernetes-commit: 83584d13c495d39392f02ac0ef5d753f7ef67a04
2025-07-04 11:34:06 +08:00
Kubernetes Publisher 7364e005dc Merge pull request #132314 from thockin/jp_nicer_api_errors
Nicer value rendering in API errors

Kubernetes-commit: 2a4b5f64761f1578409c3f69ef7aaab614cdd907
2025-07-03 09:20:11 +00:00
Kubernetes Publisher d2a696650a Merge pull request #131902 from liuxu623/fix-storage-objects-metrics
remove apiserver_storage_objects metrics after crd deleted

Kubernetes-commit: 2c2530c3dd31a31ae2a54cf5d19da94eb21a1eff
2025-07-03 01:33:26 -07:00
liuxu ab47d6f39c remove apiserver_storage_objects metrics after crd deleted
Kubernetes-commit: 8c6c7df736dff27903bc03a1b9a42c1e2c84c7ee
2025-07-03 09:57:15 +08:00
Kubernetes Publisher c93fe8d40f Merge pull request #132675 from dims/bump-sigs-k8s-io-json-no-code-changes
Bump sigs.k8s.io/json to latest - no code changes

Kubernetes-commit: e47ac3eb6faa97874658dc281c72b5623f994801
2025-07-03 01:30:47 +00:00
Kubernetes Publisher 2898f40277 Merge pull request #132677 from dims/update-github.com/emicklei/go-restful/v3-to-v3.12.2
Update github.com/emicklei/go-restful/v3 to v3.12.2

Kubernetes-commit: 305c0e06c99ff9df013edd804294217a04e4dd31
2025-07-02 21:26:27 +00:00
Kubernetes Publisher 3637a3a5aa Merge pull request #132049 from googs1025/fix/data_race_patch
fix: data race for patchResource func

Kubernetes-commit: 0a51ae22542b6e78fec51a573d95a922592f8273
2025-07-02 21:26:25 +00:00
Kubernetes Publisher 179348d538 Merge pull request #132676 from dims/bump-go.yaml.in/yaml/v3-to-v3.0.4
Bump go.yaml.in/yaml/v3 to v3.0.4

Kubernetes-commit: 01c03ae9cf7b1371c8bc2bdf12d9244e63e83750
2025-07-02 17:29:59 +00:00
Davanum Srinivas 6bc5ac2a1a Update github.com/emicklei/go-restful/v3 to v3.12.2
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: b44b0fbf1299c6821033076352b91914d2efef67
2025-07-02 08:00:43 -04:00
Davanum Srinivas b6975dfbe9 Bump go.yaml.in/yaml/v3 to v3.0.4
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 58e620cc4403d30f9fb6aab245cfb47db17957de
2025-07-02 07:37:06 -04:00
Davanum Srinivas 61137484d0 Bump sigs.k8s.io/json to latest - no code changes
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 00f8cbae6b8fd3799a1a044abcefdbb572d35b27
2025-07-02 07:32:24 -04:00
Kubernetes Publisher e26c3d7e23 Merge pull request #132654 from Jefftree/b-openapi
Bump kube-openapi

Kubernetes-commit: db49c25956df36c777213251c4a47d6d9ee1c5ea
2025-07-01 21:31:05 +00:00
Kubernetes Publisher 7710d9ff3e Merge pull request #132648 from serathius/kep-5116-ga
Graduate streaming list encoding feature gates

Kubernetes-commit: 20141c8a92a76900b0b207ca7c0fd4832bacaa55
2025-07-01 17:20:21 +00:00
Jefftree 08b1bbe4b9 Update vendor
Kubernetes-commit: d04ee27c98ba91680ac6c6a8ade9e33d7ee44569
2025-07-01 15:23:58 +00:00
Jefftree ff84ca3520 pin kube-openapi to v0.0.0-20250628140032-d90c4fd18f59
Kubernetes-commit: b41d375b8881f25ff5fe7775b4dedaba1eaa3f02
2025-07-01 15:21:22 +00:00
Marek Siarkowicz 2c9f20fd49 Graduate streaming list encoding feature gates
Kubernetes-commit: 799aa8b2a8cd4d6768d1c9cd4aa7df3a8f9d6113
2025-07-01 13:04:40 +02:00
Kubernetes Publisher 3565462805 Merge pull request #132472 from xiaoweim/validation-cleanup
Cleanup: Remove redundant detail messages in field.Required

Kubernetes-commit: eb1b603cda3b956e52bddf3b51748191e80a59a6
2025-07-01 09:41:38 +00:00
Kubernetes Publisher 09be259d76 Merge pull request #132625 from ylink-lfs/chore/rest_delete_utilpointer_removal
chore: remove utilpointer usage in package staging/src/k8s.io/apiserver/pkg/registry/rest/delete

Kubernetes-commit: ffa8eb89dab40c15b8393cbe3c67df0b91d490e0
2025-07-01 09:41:36 +00:00
Kubernetes Publisher ee98ed2094 Merge pull request #128767 from knrc/nested-filterlatency-tracing
Trace across start handler invocations, nesting spans

Kubernetes-commit: a87674895178ced3f6fc1987e3fc1ee76b05629c
2025-07-01 05:42:06 +00:00
ylink-lfs 6874062f41 chore: remove utilpointer usage in package staging/src/k8s.io/apiserver/pkg/registry/rest/delete
Kubernetes-commit: a0ea2569a760f114f62e40b494c376e90f2d9ede
2025-06-30 20:50:51 +08:00
Kubernetes Publisher 06b7bf2af7 Merge pull request #132438 from dims/golangci-plugin-for-sorting-feature-gates
golangci plugin for sorting feature gates

Kubernetes-commit: 2e02a0088574d126c6d4a82ea472c7cb6c3252f5
2025-06-27 21:50:21 +00:00
xiaoweim af5056a3db Cleanup: Remove redundant detail messages in field.Required
Kubernetes-commit: 8632257c9340aeae824c99642376a78f69b3ea5d
2025-06-26 19:41:17 +00:00
Davanum Srinivas 8c685320dc Ensure all the files have the updated sorting
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: d50e1a684cd53950210041b875ae3a41dac05c33
2025-06-25 08:21:01 -04:00
Kubernetes Publisher 895f2b3947 Merge pull request #132355 from serathius/apf_estimate_size
Estimate average size of objects in etcd and plug it into request cost estimator

Kubernetes-commit: 025636181393cc95bf78a48238fff5c8b05d6404
2025-06-26 13:41:20 +00:00
Kubernetes Publisher 2ca55b4189 Merge pull request #132150 from serathius/watchcache-consistent-list
Handle consistent LIST in watch cache to avoid incorrect semantics while setting ResourceVersion on options

Kubernetes-commit: 24d9d184c2002256ce1e88c8f818a7ed007cfe51
2025-06-26 04:46:35 -07:00
Marek Siarkowicz 67c4a8a9ee Add benchmark for SizeBasedListCostEstimate feature
Kubernetes-commit: 1639b090839b37ab08c1d90d62f2c7a4c44faba4
2025-06-25 15:50:34 +02:00
Marek Siarkowicz df850b5a51 Override getKeys when cacher is enabled
Kubernetes-commit: e2c6b7fdf97206cc60d6c5f0e1cb306652ec189a
2025-06-23 16:35:06 +02:00
Marek Siarkowicz b805c4d851 Run background cleanup goroutine
Kubernetes-commit: 7cb241799935745277125db033ae217fe64e322c
2025-06-18 17:24:17 +02:00
Tim Hockin 19608fe81a WIP: Fix tests
Notes:
* For types that define String() - should we prefer that or JSON?
* metav1.Time has a MarshalJSON() and inhereits a String() and they are
  different
* Since validation runs on internal types, we still get some GoNames
  instead of goNames.

Kubernetes-commit: 4ca91a03052ebf31d373a0de6e12891ae15966b9
2025-06-18 10:23:01 +09:00
Marek Siarkowicz cf27dab482 Estimate average size of objects in etcd and plug it into request cost estimator
Kubernetes-commit: ec78b8305ad392f6faf4e5247ea33ceabb484c3f
2025-06-13 16:34:42 +02:00
Marek Siarkowicz eaf6e48501 Handle consistent LIST in watch cache to avoid incorrect semantics while setting ResourceVersion on options
Kubernetes-commit: 292679a28ae472da29c5d860afdb5c2250637d31
2025-06-06 17:16:46 +02:00
Kubernetes Publisher 07ec5c5838 Merge pull request #132357 from dims/drop-usage-of-forked-copies-of-goyaml.v2-and-goyaml.v3
Drop usage of forked copies of goyaml.v2 and goyaml.v3

Kubernetes-commit: c1afec6a0b15ca1ed853c1321ac2c972488bf5b8
2025-06-25 17:49:28 +00:00
Kubernetes Publisher 662ba26adb Merge pull request #132504 from jpbetz/name-formats
Introduce OpenAPI format support for k8s-short-name and k8s-long-name

Kubernetes-commit: 1d932bd6cc951b9182d07d701946aebaf667df94
2025-06-25 17:49:26 +00:00
Lukasz Szaszkiewicz a77ab41bc0 client-go/reflector: stop exposing UseWatchList (#132453)
* client-go/reflector: stop exposing UseWatchList

* apiserver/cacher: stop setting reflector.UseWatchList

* test/integration/watchlist: fix TestReflectorWatchListFallback

Kubernetes-commit: b8b3984874e930c92057589fd1a7668dbdffc117
2025-06-25 13:45:59 +00:00
Kubernetes Publisher 1a56a2f375 Merge pull request #132374 from PatrickLaabs/132358
Fixed large resourceversion and limit for storages

Kubernetes-commit: 49bff137a7211ff300028bfdba3ce1929a5dfb2b
2025-06-25 13:45:54 +00:00
Davanum Srinivas 8ee91f3b4d switch to latest sigs.k8s.io/yaml v1.5.0 (run update-gofmt.sh as well)
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: c5b4b133ce3252ee19b7167eb69a99d88fdefda8
2025-06-25 08:03:06 -04:00
Kubernetes Publisher 942549e2f9 Merge pull request #132497 from p0lyn0mial/upstream-watchlist-etcd-cacher
apiserver/storage/cacher/listwatcher: error when the WatchList FG is disabled

Kubernetes-commit: 8eda367f27b79adf5b41f019ede7708abee9602d
2025-06-25 09:40:56 +00:00
Lukasz Szaszkiewicz 0d3a31d996 apiserver/storage/cacher/listwatcher: error when the WatchList FG is disabled
Kubernetes-commit: 7e0d71fc14bcbe1fae42ccc91f2d48fc9b99a049
2025-06-25 08:50:03 +02:00
Kubernetes Publisher 3f2a0b72ba Merge pull request #132499 from liggitt/unwanted-json-patch-v5
Add json-patch v4 compatibility test

Kubernetes-commit: 8d2a5a2c9c40e3c4e6aa2804cf167ea7fe169d55
2025-06-24 17:51:50 +00:00
Kubernetes Publisher 75e69719a1 Merge pull request #132470 from michaelasp/fixInvalidObj
fix: Improve error messaging on updating a deleted object

Kubernetes-commit: 80474f7b4ab495d5cbda4d58df57bededc7cf8bc
2025-06-24 17:51:49 +00:00
Kubernetes Publisher 389ff851fc Merge pull request #132479 from p0lyn0mial/upstream-watchlist-cacher-listwatcher
apiserver/cacher: properly wire listwatch options to the listwatcher

Kubernetes-commit: ae15bc5613ef3c0f90c940caad56467ff817c962
2025-06-24 13:41:08 +00:00
Joe Betz bab2fbdc6f Bump to latest kube-openapi
Kubernetes-commit: dc323756cea2d1ebe32d7acb5a14a1769c14486f
2025-06-24 09:24:27 -04:00
Jordan Liggitt 3d4aed0ded Add json-patch v4 compatibility test
Kubernetes-commit: d180fe28ad5154eae7930a518640a8860e5a96d8
2025-06-24 09:23:39 -04:00
Lukasz Szaszkiewicz 0e36545f56 apiserver/cacher: properly wire listwatch options to the listwatcher
Kubernetes-commit: dce69afadeaf3fc8c98d1dfd56394fb77d52225b
2025-06-24 10:55:06 +02:00
Michael Aspinwall a47cc30656 fix: Improve error messaging on updating a deleted object
Kubernetes-commit: 56d97283afb538b9758e23438fcf1074bc96c1f6
2025-06-23 21:37:00 +00:00
Kubernetes Publisher 0dd61ee79d Merge pull request #132454 from serathius/watchcache-close
Move UnsafeCorruptObjectDeletion outside of etcd3.New function

Kubernetes-commit: 314af2a00b2dd41576be316a92b3d1a1c05484c1
2025-06-23 06:00:53 -07:00
Marek Siarkowicz baef40d3ec Move UnsafeCorruptObjectDeletion outside of etcd3.New function
By returning *store instead of storage.Interface we can expose Close()
function so in the future we can register it to destroyFunc in
newETCD3Storage.

Kubernetes-commit: 72305f82f9a20315d7ff4904a840bfd56478d44a
2025-06-23 10:50:06 +02:00
Kubernetes Publisher d16c916aad Merge pull request #129438 from pacoxu/apiserver-probe-etcd
add etcd server overrides to etcd probe factory for healthz and readyz

Kubernetes-commit: b569406b792fef24bb5613f1263ea354755bbae0
2025-06-19 21:40:54 +00:00
PatrickLaabs fdccb8b2dc fixing large resourceversion and limit for storages
Kubernetes-commit: ccdef28acd3a286e8d62222ddf804ae4042764e5
2025-06-18 16:22:13 +02:00
Kubernetes Publisher 7a9026cb3a Merge pull request #132253 from serathius/watchcache-fallback-test
Validate requests sent to etcd in TestList "test List with limit" scenario

Kubernetes-commit: 46e2c3fc2d2db16d44a9a21e0c6f8be51754ec88
2025-06-17 21:57:52 +00:00
Davanum Srinivas dd8cd79556 Drop usage of forked copies of goyaml.v2 and goyaml.v3
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 3827d3bc4f1c17ac816b37422dbd449c276e9ff0
2025-06-17 11:00:27 -04:00
Kubernetes Publisher d76c79a4e9 Merge pull request #132221 from dims/new-cmp-diff-impl
New implementation for `Diff` (drop in replacement for `cmp.Diff`)

Kubernetes-commit: 3e39d1074fc717a883aaf57b966dd7a06dfca2ec
2025-06-17 03:53:42 +00:00
Kubernetes Publisher 3b43a1a7f8 Merge pull request #132244 from hakuna-matatah/1.33-regression-w-test-validation
1.33 regression - Consistent paginated lists serve from cache

Kubernetes-commit: 74210dd399c14582754e933de83a9e44b1d69c69
2025-06-16 23:44:47 +00:00
Lukasz Szaszkiewicz 8162f5ea9d apiserver/handlers/watch: stop encoding initialEventsListBlueprint (#132326)
* apiserver/handlers/get: remove constructing versionedList

* endpoints/handlers/response: rm watchListTransformer

* endpoints/handlers/watch: unwire watchListTransformer

* storage/cacher: rm documentation about caching the serialization of bookmark events

Kubernetes-commit: fc198b92c0d5cece06fd4ecc24f6142532beff37
2025-06-16 16:02:59 +02:00
Kubernetes Publisher deb30e35ad Merge pull request #132177 from pgimalac/apiserver-avoid-template-for-dce
Remove use of html/template in apiserver to avoid disabling dead code elimination

Kubernetes-commit: 77bd3f89fbc389d5dfebbed880e08a1e4949312c
2025-06-13 18:09:22 +00:00
Marek Siarkowicz 9b695a5efa Validate requests sent to etcd in TestList "test List with limit" scenario
This adds a regression test to detect fallback to etcd as discovered in https://github.com/kubernetes/kubernetes/issues/132132.

Kubernetes-commit: 4cb6d3d77617f141fefd4994910380c095dac1ad
2025-06-12 11:33:02 +02:00
Davanum Srinivas 6db9ead72a Add a replacement for cmp.Diff using json+go-difflib
Co-authored-by: Jordan Liggitt <jordan@liggitt.net>
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 03afe6471bdbf6462b7035fdaae5aa0dd9545396
2025-06-10 23:08:41 -04:00
Pierre Gimalac 1f47d05362 chore(apiserver): avoid using html template which disables dce
Kubernetes-commit: 40c718864b7231addeeb1a336a88f8a71a024539
2025-06-08 01:03:42 +02:00
Kubernetes Publisher 081f25136a Merge pull request #132165 from gavinkflam/130690/fix-admission-control-response-codes
bug: Fix misleading response codes in admission control metrics

Kubernetes-commit: 060ed4e99aaa30ad65600427ec1b9ee4fa64d3d1
2025-06-13 00:12:29 +00:00
Kubernetes Publisher 89f1e0c9f7 Merge pull request #132269 from dims/update-to-latest-github.com/modern-go/reflect2
Update to latest github.com/modern-go/reflect2

Kubernetes-commit: d55b119d34883bbad2a3436dcb6c62339d963031
2025-06-12 20:23:25 +00:00
Jordan Liggitt 0e38ecf83f Expand webhook test to check rejection metrics
Kubernetes-commit: 9251b2a7a58e8232244508081bd3a6c06d5781d0
2025-06-12 13:41:30 -04:00
Davanum Srinivas a2f3ed4733 Update to latest github.com/modern-go/reflect2
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 3908550c0dc189cfa9de38a84bee508fa0659463
2025-06-12 11:20:39 -04:00
Gavin Lam e4c9db3825 bug: Fix misleading response codes in admission control metrics
Signed-off-by: Gavin Lam <gavin.oss@tutamail.com>

Kubernetes-commit: 601065a7c6b5445ed46fbcca8a888c98be318fec
2025-06-12 09:44:41 -04:00
Kubernetes Publisher 6bf08e15b6 Merge pull request #132135 from jpbetz/options-to-slice-master
Simplify options in declarative validation

Kubernetes-commit: c06a41b31667e83cbdd19734d5716775f9c3937e
2025-06-12 08:22:45 +00:00
Kubernetes Publisher d9e31a74fe Merge pull request #132238 from aramase/aramase/c/cleanup_deprecated_enc_config_metrics
Remove deprecated encryption config controller metrics

Kubernetes-commit: c7b3f5d0b9d3b557d333a7244ed228c8067cf2e6
2025-06-12 04:12:50 +00:00
Kubernetes Publisher 65bd2fadfd Merge pull request #132239 from dims/update-to-etcd-3.6.1-in-vendor
Update to etcd v3.6.1 in vendor/

Kubernetes-commit: 568f7300c9811f5c07a5b2a786fb1d043306c35c
2025-06-12 00:12:42 +00:00
Davanum Srinivas f294209f1e Update to etcd v3.6.1 in vendor/
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 5a2844a766bb0113b969b4519350c962d8dd8428
2025-06-11 16:46:03 -04:00
Anish Ramasekar dc0ee6eda8 Remove deprecated encryption config controller metrics
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: dc3836c49ed6683ebf6c13711a135752a0e611b0
2025-06-11 13:27:34 -07:00
Kubernetes Publisher 8aa4209508 Merge pull request #131916 from aramase/aramase/f/authn_config_ga
Mark StructuredAuthenticationConfiguration feature gate as GA

Kubernetes-commit: 5596cc64c2a1b6a2d0b44a9b7d1d5c5be9b9c8c9
2025-06-11 00:21:58 +00:00
Harish Kuna 80cef81846 Fix -Consistent paginated lists serve from cache
Kubernetes-commit: 2004ee50f5da851b08cca95b4a9c12c84794559d
2025-06-05 20:38:07 +00:00
googs1025 c5cc58d0de fix: data race for patchResource func
Signed-off-by: googs1025 <googs1025@gmail.com>

Kubernetes-commit: 2fd93c0898856ba764adef8efcaace9ff0c49f23
2025-06-01 13:44:23 +08:00
Anish Ramasekar f8343759d9 Update tests for StructuredAuthenticationConfiguration feature gate GA
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 512f000d0f321c568b76b175bc4a44ea9dd73cf3
2025-05-22 17:00:24 -07:00
Anish Ramasekar 6b794dbd82 Set StructuredAuthenticationConfiguration feature gate to GA in v1.34
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: efebfe9e3a5aba82c1c3b23711cc24d8fe457d78
2025-05-13 16:06:37 -07:00
Kubernetes Publisher 8a7311dce3 Merge pull request #132209 from dims/update-github.com/spf13/cobra-v1.9.1eksctl
update github.com/spf13/cobra v1.9.1

Kubernetes-commit: dc19f0b6b9cd14ece6b1929cb4e7ea2c9d322b95
2025-06-10 20:14:05 +00:00
Kubernetes Publisher d9b6bd1d4c Merge pull request #131654 from vinayakankugoyal/anonGA
KEP-4633: Graduate to Stable.

Kubernetes-commit: fa8c5acf5e42891d543c2933e8f3149798ca76be
2025-06-10 20:14:04 +00:00
Davanum Srinivas ed9f8fce83 update github.com/spf13/cobra v1.9.1
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 449320a54a2dac04f953d5f6401d875ea9b7e8de
2025-06-10 10:50:54 -04:00
Kubernetes Publisher f55aaff838 Merge pull request #132191 from AwesomePatrol/pass-ctx-to-count
Add context to Count() method of storage interface

Kubernetes-commit: 78edda21a307ee193fb2ab52210638520af0a1b1
2025-06-10 12:14:05 +00:00
Vinayak Goyal eadbc19007 KEP-4633: Graduate to Stable.
Kubernetes-commit: 26b188aaa8f1f4b37263d028d8e0b95bb73540bb
2025-05-07 17:56:39 +00:00
Joe Betz 13e6a3c329 Change option to a slice
Kubernetes-commit: 501393810064f96808eba093ae5c00780020c667
2025-03-29 08:59:30 -04:00
Paco Xu 9388b76b21 add seperate health check/probe for multi etcd override servers
- grouping health checks for exclusion purposes & add exclude integration test

Signed-off-by: Paco Xu <paco.xu@daocloud.io>

Kubernetes-commit: 891e7fec6e17382389b01f590888375a29491afc
2025-01-26 15:05:59 +08:00
Aleksander Mistewicz 7cd49caffc Add context to Count()
Passing the same context will let us associate etcd traces with those
from apiserver.

Signed-off-by: Aleksander Mistewicz <amistewicz@google.com>

Kubernetes-commit: 96b39187c5fac62e462dc348ccc1e3938464d9e1
2025-01-15 11:42:29 +01:00
Kubernetes Publisher 92c5638afd Merge pull request #132103 from nojnhuh/typed-ring-buffer
Replace queue.FIFOs with k8s.io/utils/buffer.Ring

Kubernetes-commit: 5090812df4fb6cf09a9181635d90c2e154eab8cc
2025-06-06 20:28:32 +00:00
Kubernetes Publisher 2c9afbf9bc Merge pull request #131979 from serathius/watchcache-initialization-ga
Gradute ResilientWatchCacheInitialization to GA

Kubernetes-commit: 7f50c56b1aee651924f39317329d33977f3c736a
2025-06-05 12:29:35 +00:00
Jon Huhn 053a8b2a4c Update k8s.io/utils for new generic ring buffer
Kubernetes-commit: 8cdbbf5cdaef7e37cfd432e9044aa52f4d42adcd
2025-06-04 12:09:53 -05:00
Kubernetes Publisher 7d6aa8a395 Merge pull request #132082 from aramase/aramase/t/kep_3331_revocation_unit_test
KEP-3331: Add test to simulate revocation via user validation rule using unique identifier (jti)

Kubernetes-commit: caa9324842e8f96702661505226a2c97ef62742f
2025-06-04 00:09:37 +00:00
Kubernetes Publisher 02450b6f98 Merge pull request #132061 from miltosdoul/fix_typeprovider_datarace
fix: datarace in ResolverTypeProvider

Kubernetes-commit: bd87e4d2a6f91c64980e0c4b9afe1f48ca57c56f
2025-06-04 00:09:36 +00:00
Anish Ramasekar 851e917827 KEP-3331: Add test to simulate revocation via user validation rule using unique identifier (jti)
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 6a495241ef3dfb828d4ae1112123a7fc98a493b9
2025-06-03 14:40:17 -07:00
Miltiadis Doulgeris 99e4fe9de1 fix: ResolverTypeProvider data race
Kubernetes-commit: de1d6fbf2422eb1da7a1fe38e0d0d6b3bfc53fd1
2025-06-02 23:19:44 +03:00
Kubernetes Publisher b50caf5d66 Merge pull request #131798 from aramase/aramase/f/authn_metrics_beta
Promote automatic_reloads of authn config metrics to BETA

Kubernetes-commit: d70229fac7c2aec4e6a69e0783fa0860a90e1144
2025-05-28 05:54:11 +00:00
Kubernetes Publisher 73e127faf5 Merge pull request #131951 from dims/drop-usages-of-deprecated-otelgrpc-methods
Drop usages of deprecated otelgrpc methods (update to v0.60.0)

Kubernetes-commit: d9c1b4ec9b3df7f09dc23a0cc2b3daf2506d3688
2025-05-27 17:57:57 +00:00
Kubernetes Publisher 255fa69bd1 Merge pull request #131664 from jpbetz/subresources-enable-replicas
Migrate to declarative validation: ReplicationController/scale spec.replicas field

Kubernetes-commit: 144926558984ae41a7328d53bd9fc8602328f10e
2025-05-27 17:57:55 +00:00
Marek Siarkowicz 784d2892e6 Gradute ResilientWatchCacheInitialization to GA
Kubernetes-commit: 741d0e2b81a0820892db18b90f5b691a19676010
2025-05-27 13:17:32 +02:00
Kubernetes Publisher 4b98f13de7 Merge pull request #131768 from aramase/aramase/f/authz_metrics_stable
Promote automatic_reloads of authz config metrics to BETA

Kubernetes-commit: f6530285a85d6f4280711301613a7d3215a25818
2025-05-26 14:06:35 +00:00
Davanum Srinivas b887c9ebec Drop usages of deprecated otelgrpc methods
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 7c0f968ab256486b524ea37014ccf580b12c73e4
2025-05-23 19:40:36 -07:00
Kubernetes Publisher 7937de32ff Merge pull request #131845 from serathius/unify-metrics
Unify references to group resource in metrics

Kubernetes-commit: b5608aea94cfb54fea3a63e1d74235759d036c51
2025-05-22 18:06:37 +00:00
Kubernetes Publisher 08959fe41f Merge pull request #131752 from aramase/aramase/f/kep_3331_v1_api
Duplicate v1beta1 AuthenticationConfiguration to v1

Kubernetes-commit: 6da56bd4b782658a4060f65c24df5830ec01c6c1
2025-05-21 07:48:50 +00:00
Kubernetes Publisher 2055ba24cd Merge pull request #131838 from dims/bump-google.golang.org/grpc-to-google-v1.72.1
Bump google.golang.org/grpc to google v1.72.1

Kubernetes-commit: 444e2b4eb079727d7cdd81ad25041502656370b8
2025-05-20 15:59:23 +00:00
Kubernetes Publisher df39bcd7dd Merge pull request #131704 from karlkfi/karl-watch-subtests
test: Use sub-tests in watch tests

Kubernetes-commit: 4e80b05087cf26188208f1c80d133566be4eae18
2025-05-19 23:49:18 +00:00
Kubernetes Publisher 73a9ddd3c3 Merge pull request #131766 from serathius/flake-TestGetCacheBypass
Separate getList and watch errors to prevent TestGetCacheBypass flakes

Kubernetes-commit: f80233f24bcc49305aab2043b2bc6d66a606c6ab
2025-05-19 19:50:56 +00:00
Joe Betz d6a8a1af27 Clarify errors and improve tests
Kubernetes-commit: 9715c90b31ccc121ba910044c03ecb9936b1f858
2025-05-19 14:12:09 -04:00
Joe Betz 2f8595c47b Clarify group version lookup in validateDeclaratively
Kubernetes-commit: 4cac349f86b730a9e7eebffaad9dd92d77dda594
2025-05-19 11:45:59 -04:00
Joe Betz 5009571787 Add +k8s:isSubresource and +k8s:supportsSubresource tags
Kubernetes-commit: 6ca6b7bb6ab7865ace03601c5d34571196126c8b
2025-05-19 11:18:06 -04:00
Marek Siarkowicz a559cb8be1 Unify references to group resource in metrics
Skip apiserver_storage_objects as it's a stable metrics that doesn't
have "group" label. As defined in KEP-1209 adding a label is considered
a breaking change so this change should be done via deprecation and
introduction of new metric.

Tested via:
```
kubectl get --raw /metrics | grep -i apiservice | grep -v APIServiceRegistrationController | grep -v aggregator_unavailable_apiservice | python3 -c "import sys; print('\n'.join([k+' ' + v for k,v in {a.split('{')[0]:'{'+a.split('{')[1].split('}')[0]+'}' for a in sys.stdin.readlines() if '#' not in a and '_sum' not in a and '_bucket' not in a}.items()]))"
```

Before:
```
apiserver_cache_list_fetched_objects_total {index="",resource_prefix="/apiregistration.k8s.io/apiservices"}
apiserver_cache_list_returned_objects_total {resource_prefix="/apiregistration.k8s.io/apiservices"}
apiserver_cache_list_total {index="",resource_prefix="/apiregistration.k8s.io/apiservices"}
apiserver_longrunning_requests {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="cluster",subresource="",verb="WATCH",version="v1"}
apiserver_request_body_size_bytes_count {resource="apiservices.apiregistration.k8s.io",verb="create"}
apiserver_request_duration_seconds_count {component="apiserver",dry_run="",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_request_sli_duration_seconds_count {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_request_total {code="201",component="apiserver",dry_run="",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_response_sizes_count {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="cluster",subresource="",verb="LIST",version="v1"}
apiserver_selfrequest_total {resource="apiservices",subresource="",verb="POST"}
apiserver_storage_events_received_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_storage_list_evaluated_objects_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_storage_list_fetched_objects_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_storage_list_returned_objects_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_storage_list_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_storage_objects {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_cache_events_dispatched_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_cache_events_received_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_cache_initializations_total {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_cache_resource_version {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_events_sizes_count {group="apiregistration.k8s.io",kind="APIService",version="v1"}
apiserver_watch_events_total {group="apiregistration.k8s.io",kind="APIService",version="v1"}
etcd_request_duration_seconds_count {operation="listWithCount",type="/registry/apiregistration.k8s.io/apiservices/"}
etcd_requests_total {operation="listWithCount",type="/registry/apiregistration.k8s.io/apiservices/"}
watch_cache_capacity {resource="apiservices.apiregistration.k8s.io"}
```

After:
```
apiserver_cache_list_fetched_objects_total {group="apiregistration.k8s.io",index="",resource="apiservices"}
apiserver_cache_list_returned_objects_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_cache_list_total {group="apiregistration.k8s.io",index="",resource="apiservices"}
apiserver_longrunning_requests {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="cluster",subresource="",verb="WATCH",version="v1"}
apiserver_request_body_size_bytes_count {group="apiregistration.k8s.io",resource="apiservices",verb="create"}
apiserver_request_duration_seconds_count {component="apiserver",dry_run="",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_request_sli_duration_seconds_count {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_request_total {code="201",component="apiserver",dry_run="",group="apiregistration.k8s.io",resource="apiservices",scope="resource",subresource="",verb="POST",version="v1"}
apiserver_response_sizes_count {component="apiserver",group="apiregistration.k8s.io",resource="apiservices",scope="cluster",subresource="",verb="WATCH",version="v1"}
apiserver_selfrequest_total {group="apiregistration.k8s.io",resource="apiservices",subresource="",verb="WATCH"}
apiserver_storage_events_received_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_storage_list_evaluated_objects_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_storage_list_fetched_objects_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_storage_list_returned_objects_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_storage_list_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_storage_objects {resource="apiservices.apiregistration.k8s.io"}
apiserver_watch_cache_events_dispatched_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_watch_cache_events_received_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_watch_cache_initializations_total {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_watch_cache_resource_version {group="apiregistration.k8s.io",resource="apiservices"}
apiserver_watch_events_sizes_count {group="apiregistration.k8s.io",resource="apiservices",version="v1"}
apiserver_watch_events_total {group="apiregistration.k8s.io",resource="apiservices",version="v1"}
etcd_bookmark_counts {group="apiregistration.k8s.io",resource="apiservices"}
etcd_request_duration_seconds_count {group="apiregistration.k8s.io",operation="listWithCount",resource="apiservices"}
etcd_requests_total {group="apiregistration.k8s.io",operation="listWithCount",resource="apiservices"}
watch_cache_capacity {group="apiregistration.k8s.io",resource="apiservices"}
```

Kubernetes-commit: f712b01ddb55f6569b930ca714499051ba8cb311
2025-05-19 11:41:09 +02:00
Davanum Srinivas 569dd0421b Bump google.golang.org/grpc v1.72.1
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 9b3830fba234bc4a4f09a1ad4417e4d18b74d6dc
2025-05-18 12:52:05 -04:00
Kubernetes Publisher 062128c843 Merge pull request #128419 from liggitt/etcd-3.6
etcd 3.6 client update

Kubernetes-commit: 09ca440a450e9103a8f835f598c09237dba6ecbb
2025-05-16 04:00:16 +00:00
Anish Ramasekar 2ce736f1ce Promote automatic_reloads of authn config metrics to BETA
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 60b5338d46027c26cd29a829bea5dbff822b3b23
2025-05-15 11:23:10 -07:00
Anish Ramasekar 12fab5de10 Promote automatic_reloads of authz config metrics to BETA
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 5314fcece315c6bab115de4ac723baa43f8d6ec0
2025-05-14 09:51:20 -07:00
Marek Siarkowicz 6764e31cac Separate getList and watch errors to prevent TestGetCacheBypass flakes
The TestGetCacheBypass requires watch cache to be initialized after
which it will want backend to return errors to check what requests are
cached and which are not.

The watch cache is marked as ready after a list succeeds, but before a watch request is executed.
If watch request fail it will immidietly flip back to unready.

Injecting error after watch cache was ready didn't guarantee that watch
request started, sometimes causing watch to be called after and fail.
This immidietly caused the watch cache to be again unready for the rest
of the test.

The fix is just to separate failure injection for List and Watch
responses.

Kubernetes-commit: 70e05132645d5c49cf0ac61a3ae8869dc60f0bde
2025-05-14 15:52:06 +02:00
Anish Ramasekar 9333a5f386 Duplicate v1beta1 AuthenticationConfiguration to v1
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: aea874e5e47c1740d12f1dbea6bba8249407c9f8
2025-05-13 15:48:04 -07:00
Karl Isenberg 80961690c3 test: Use sub-tests in watch tests
- Use sub-tests to avoid side-effects between test cases,
  cancel the context between cases, and make it easier to
  determine the failing case in the test logs.
- Use anonymous closures in benchmarks, instead of sub-tests,
  so the times still include all cases.

Kubernetes-commit: 0e5eab042c314851ae4e653f0037fe901baf94d8
2025-05-01 12:16:42 -07:00
Jordan Liggitt 067a2139bb Set non-experimental WatchProgressNotifyInterval config field
Kubernetes-commit: 6b0ebedccc19f3fbf877487cffa34c3694d0c275
2025-03-27 11:54:39 -04:00
Jordan Liggitt 057e0d26a0 bump etcd client to 3.6
hack/pin-dependency.sh go.etcd.io/etcd/api/v3 v3.6.0
hack/pin-dependency.sh go.etcd.io/etcd/client/pkg/v3 v3.6.0
hack/pin-dependency.sh go.etcd.io/etcd/client/v3 v3.6.0
hack/pin-dependency.sh go.etcd.io/etcd/pkg/v3 v3.6.0
hack/pin-dependency.sh go.etcd.io/etcd/server/v3 v3.6.0

hack/pin-dependency.sh github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0

hack/update-vendor.sh

Kubernetes-commit: cf0bbf1171e918d5d7ba1d3c83b5f347fc8333b0
2025-05-15 21:19:11 -04:00
Kubernetes Publisher e80da78881 Merge pull request #131706 from karlkfi/karl-close-watch-tests
test: Close response body in watch tests

Kubernetes-commit: 5f1a5174c508f6fad9d6c06dc8b5675ef04b9a03
2025-05-15 20:23:50 +00:00
Kubernetes Publisher 9e1714f200 Merge pull request #131725 from dims/avoid-encoding-in-log-response-object-when-we-dont-need-it
Avoid encoding in LogResponseObject when we are not going to use it

Kubernetes-commit: 832be9538ec49cb2b496612eff7c1dff68d8b6ba
2025-05-12 12:15:15 -07:00
Davanum Srinivas bc489d7b1b Update staging/src/k8s.io/apiserver/pkg/audit/request_log_test.go
Co-authored-by: Tim Allclair <timallclair@gmail.com>
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 721947a5703f2ffaafdc9bef983a6b60c6253ca8
2025-05-12 13:29:57 -04:00
Davanum Srinivas b45c4547ed review from tallclair
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 153233c677d62c0254d54c1e7013645a081ac03d
2025-05-12 12:50:38 -04:00
Davanum Srinivas bda7e28bbb Avoid encoding in LogResponseObject when we are not going to use it
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: e418ee3a92ca6c670d26f775b0f669e8a5fe233c
2025-05-12 09:29:22 -04:00
Kubernetes Publisher 9b509bf53b Merge pull request #131694 from dims/eliminate-audit-context-set-event-level
Eliminate AuditContext`s SetEventLevel

Kubernetes-commit: e94babb2aa0e54950c5b1adbadccf59d24436e56
2025-05-10 03:39:42 +00:00
Kubernetes Publisher 2ffdf9039f Merge pull request #131680 from karlkfi/karl-test-http-context
test: Pass test context to http requests

Kubernetes-commit: 43be8301ed4041e7b6d6d517badf95473696d03a
2025-05-09 15:32:55 +00:00
Kubernetes Publisher f2b80d742a Merge pull request #131676 from karlkfi/karl-ioutil
refactor: Stop using ioutil in apiserver

Kubernetes-commit: 7ce0e1ca2b176bc11855944f721a9f6cf73cae54
2025-05-09 11:32:01 +00:00
Davanum Srinivas 1ffdd2403f Eliminate AuditContext`s SetEventLevel
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
Co-Authored-By: Jordan Liggitt <liggitt@google.com>

Set event level during context init

Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 960a4939f2502f2a8f2b923203e9075354e4bdc0
2025-05-09 06:57:31 -04:00
Kubernetes Publisher 2bc51918fe Merge pull request #129472 from dims/api-server-crashes-on-concurrent-map-iteration-and-write
Fix API server crash on concurrent map iteration and write

Kubernetes-commit: f603a0ada810d2671c6440b109c7fe29f67c81ff
2025-05-09 03:39:44 +00:00
Karl Isenberg 46dd96ca03 refactor: Stop using ioutil in apiserver
- The ioutl package is deprecated. Migrate to os package functions.

Kubernetes-commit: f93e4645c18c6f56bfddc158ef7b3f674b3c41dd
2025-05-08 11:28:52 -07:00
Kubernetes Publisher 1527793495 Merge pull request #131656 from karlkfi/karl-request-methods
refactor: Add request method constants

Kubernetes-commit: 0f9987650cca2f24787e4cd38d257b77aabf68db
2025-05-08 11:38:15 +00:00
Kubernetes Publisher 93c8ec73c8 Merge pull request #131616 from jpbetz/typeconverter-cleanup
Reorganize scheme type converter into apimachinery utils

Kubernetes-commit: 7cb2bd78b22c4ac8d9a401920fbcf7e2b240522d
2025-05-08 03:47:17 +00:00
Joe Betz 5f14a1e225 Reorganize scheme type converter into apimachinery utils
This removes a dependency from generated applyconfigurations to a testing
package. To do this, the type converter in the testing package has been
moved out to the apimachinery package and the utilities the converter
depend on have been reorganized.

Kubernetes-commit: 4821604f83a6f4764497879b666087ba7cb05060
2025-05-07 10:07:55 -04:00
Kubernetes Publisher 007464aa0f Merge pull request #131575 from ali-a-a/deflake-watch-not-hanging-on-startup-failure
pkg/storage/cacher/cacher_whitebox_test: deflake TestWatchNotHangingOnStartupFailure when ResilientWatchCacheInitialization is on

Kubernetes-commit: 417662ca933ca58437d3d2d902f2cfdc4294ac45
2025-05-06 23:39:17 +00:00
Kubernetes Publisher 97250949cd Merge pull request #131596 from jpbetz/cel-reflect-extra-tests
Expand CEL UnstructuredToVal and TypedToVal has() tests

Kubernetes-commit: 0da4ada321999ff1d782d77a3101157629b493cb
2025-05-06 19:48:48 +00:00
Kubernetes Publisher 724cb010da Merge pull request #131560 from jpbetz/validation-gen-subresource-simplification
Declarative validation: Simplify handling of subresources

Kubernetes-commit: c6739dd54d56549a8460737f66b1c6aa0fa697bf
2025-05-06 19:48:43 +00:00
Kubernetes Publisher 11e35f7e67 Merge pull request #131627 from dims/mutating-webhook-error
[Attempt #2] apiserver: Treat error decoding a mutating webhook patch as error calling the webhook

Kubernetes-commit: 3aa66a2ba01529a3c5754cab222693d80241d5ac
2025-05-06 07:45:13 -07:00
Davanum Srinivas 71463feb30 Adding test case for the webhook behavior change
Authored-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 3be3051fb77be1a1ad250c04a68efe8c6bf61940
2025-05-06 09:23:46 -04:00
Joe Betz 62514be921 Apply feedback
Kubernetes-commit: 10c5bdd6a1a98222940c72e9c13ed0ccbb65322e
2025-05-05 15:03:11 -04:00
Joe Betz 7e75755a5a Expand has() tests for omitempty and omitzero
Kubernetes-commit: 47fddb08f75939ce6e40d0217ea1f4d5072b1ed0
2025-05-02 20:52:08 -04:00
Ali Abbasi Alaei b6cfd80a0d pkg/storage/cacher/cacher_whitebox_test: deflake TestWatchNotHangingOnStartupFailure when ResilientWatchCacheInitialization is on
Kubernetes-commit: 2073ba2372b2cd1c53b327a50656a2cdd13decba
2025-05-01 16:55:49 -04:00
Karl Isenberg 32e916b79d test: Close response body in watch tests
- Close response body after http calls in the watch tests
- Add apitesting utility methods for closing and testing errors
  from response body and websocket.
- Validate read after close errors.

Kubernetes-commit: 9d963298a3b7b828f01a9b02af57863a7480eb0b
2025-04-29 17:32:48 -07:00
Karl Isenberg 1552f6cea3 test: pass the test context to http requests
This handles canceling the request after the test completes, cleaning
up resources on the client and server.

Kubernetes-commit: 080d6f9ead740ec1358e320e388f79cc4de97697
2025-04-29 17:05:13 -07:00
Karl Isenberg 61451f57b1 refactor: Add request method constants
This avoids linter errors from using inline strings as http request
methods.

Kubernetes-commit: e81887276c65acccc5486f2ff69d8bc54ac3c6ca
2025-04-29 16:45:30 -07:00
Joe Betz 0de899d1ed Add subresource to operation, do not special case subresources in validation-gen
Kubernetes-commit: 2119555e02b357db58e460cd8f38bf187b5f837b
2025-03-26 21:26:14 -04:00
Joe Betz fd89bf895d Add subresource mapping support to ValidateDeclaratively and introduce configs
# Conflicts:
#	staging/src/k8s.io/apiserver/pkg/registry/rest/validate_test.go

Kubernetes-commit: 48e1079cf0301f93ae669695c147e1365f9a7dd0
2025-03-19 22:50:51 -04:00
Paco Xu 2bff744497 add etcd server overrides to etcd probe factory for healthz and readyz
Kubernetes-commit: 8bc7e6c10e0a4dceb738318a3a34f6af94e06158
2024-12-31 16:29:35 +08:00
Kevin Conner 8cf49c7c86 Simplify span handling
Co-authored-by: David Ashpole <dashpole@google.com>

Kubernetes-commit: 9f50740b7bcb41c81ec5b7939581b2bb10d641e4
2024-11-12 12:43:53 -08:00
Kevin Conner 8285a27f7b Trace across start handler invocations, nesting spans
Signed-off-by: Kevin Conner <kev.conner@gmail.com>

Kubernetes-commit: c64b6f80eb7bcf9f0d24e7f56fcced807a263b98
2024-11-11 20:55:05 -07:00
Davanum Srinivas 0f91510ab0 Treat error decoding a mutating webhook patch as error calling the webhook
Co-Authored-By: Matthew Wong <mattwon@amazon.com>
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: cf82fd7e9ceac60b7a336c90958835865c4f2f0a
2024-10-23 15:52:41 -07:00
Kubernetes Publisher 23913f0bf4 Merge pull request #131559 from jpbetz/fix-unstructured-to-val-equality
Fix UnstructuredToVal map equality to respect nil fields

Kubernetes-commit: 3f808638076e9e2be5f53a4aec9d2d5d00b997e1
2025-05-06 03:34:58 +00:00
Kubernetes Publisher eeced267ad Merge pull request #131595 from aojea/utils_fake_clock
update k8s.io/utils to bring fakeClock.Waiters()

Kubernetes-commit: e3e1f80c0110c847acf4381b1790c1c667395010
2025-05-03 03:42:20 +00:00
Kubernetes Publisher d8f5cf79ad Merge pull request #131574 from enj/enj/t/oidc_cel_unescape
jwt: support CEL expressions with escaped names

Kubernetes-commit: 43a5c18ebacf57b23f8431f270bef6c361631f20
2025-05-03 03:42:17 +00:00
Kubernetes Publisher 3dae57efb5 Merge pull request #130989 from liggitt/creationTimestamp-omitzero
Omit null creationTimestamp

Kubernetes-commit: 01899a7c86337b05a16a4155c9351cf947beaee9
2025-05-02 23:43:09 +00:00
Antonio Ojea 73b2a2235b update k8s.io/utils to bring fakeClock.Waiters()
Change-Id: I7e25338df225c2c27457403fbc2f158d08638f87

Kubernetes-commit: c2c003a71fc52fa79c2fff0109afad58573d0216
2025-05-02 11:21:11 +00:00
Monis Khan f2b320dc52 jwt: support CEL expressions with escaped names
This is purely for consistency with other uses of CEL in the
project.  Using `[` for accessing claims or user data is preferred
when names contain characters that would need to be escaped.  CEL
optionals via `?` can be used in places where `has` cannot be used,
i.e. `claims[?"kubernetes.io"]` or `user.extra[?"domain.io/foo"]`.

Signed-off-by: Monis Khan <mok@microsoft.com>

Kubernetes-commit: 7b50c8a510f2645219ee05da5195042c02552932
2025-05-01 13:22:52 -04:00
Joe Betz c199f9d392 Fix CEL equality bug for structs will nil field not marked as omitempty
Kubernetes-commit: 66b8a8427cf0be6f6a87ea3384e7213696bdfd4c
2025-04-30 09:16:44 -04:00
Jordan Liggitt 0d11839195 Drop null creationTimestamp from test fixtures
Kubernetes-commit: 6bb6c9934294d8265197c9dfc4c9dd3adaca147a
2025-03-24 09:37:26 -04:00
Jordan Liggitt b5e431bd82 bump cbor to add omitzero support
Kubernetes-commit: bc6051717137cef288b82305588e675de4a32c0d
2025-03-25 12:27:43 -04:00
Jordan Liggitt d22318d3d2 bump structured-merge-diff to add omitzero support
Kubernetes-commit: 06b0784062f68566daa8eed83c475b738dcf620c
2025-03-24 16:34:01 -04:00
Kubernetes Publisher 8776678b52 Merge pull request #131573 from enj/enj/t/oidc_nested_cel
jwt: add unit tests for using CEL with deeply nested claims

Kubernetes-commit: 03a3c0c89161935bc2338f5754ebb1104f779af1
2025-05-01 12:41:56 -07:00
Monis Khan cb5a7a865d jwt: add unit tests for using CEL with deeply nested claims
Signed-off-by: Monis Khan <mok@microsoft.com>

Kubernetes-commit: 5441f5fdef781298cd7d924eecd00e20e08831ce
2025-04-30 00:03:25 -04:00
Kubernetes Publisher a18370ff46 Merge pull request #131536 from enj/enj/r/oidc_cel_activation
jwt: refactor CEL eval to drop `unstructured` and `map[string]any`

Kubernetes-commit: 1b517e55013479f674f3fac7196f3af307d6e23f
2025-04-30 03:30:37 +00:00
Kubernetes Publisher de95d3511f Merge pull request #131460 from jpbetz/cel-value-reflect
Add lazy reflective CEL object wrapper

Kubernetes-commit: 25f124886c37d07d5550d94306dcd3e677f97b10
2025-04-29 13:43:54 -07:00
Joe Betz 847f0cb7d3 Appease linters
Kubernetes-commit: ea64418271408a6db07b3e6c30f5e42504222af5
2025-04-29 15:37:26 -04:00
Monis Khan dbbb6a075e jwt: refactor CEL eval to drop unstructured and map[string]any
This prepares us to add support for distributed claims support in
CEL expressions.

Signed-off-by: Monis Khan <mok@microsoft.com>

Kubernetes-commit: 43d6ea12e3f757e46e17311801a596aa5e70b06e
2025-04-28 17:19:54 -04:00
Joe Betz f52dfa0eb4 Add lazy reflective CEL object wrapper
Kubernetes-commit: 064074c07ac3c521483b592f37f2a58d4583ee39
2025-04-04 10:03:38 -04:00
Kubernetes Publisher a50d13fe86 Merge pull request #131434 from pacoxu/fsnotify
bump fsnotify v1.9.0

Kubernetes-commit: 1b509a888327c0a7bcbae21b78b1bf3c447cc666
2025-04-25 19:37:03 +00:00
Kubernetes Publisher 201e7749f2 Merge pull request #131444 from erdii/update-cel-go
chore: update github.com/google/cel-go dependency to v0.25.0

Kubernetes-commit: e9379e92db19d826d46edd502dd3a61609b32c52
2025-04-25 11:36:08 +00:00
Josh Gwosdz 3a062dc7cb chore: update github.com/google/cel-go dependency to v0.25.0
Signed-off-by: Josh Gwosdz <jgwosdz@redhat.com>

Kubernetes-commit: 7a24c4ce5d96aab2e9a33c4d62617cfb1c83c9f8
2025-04-24 14:59:35 +02:00
Kubernetes Publisher 4a106441d6 Merge pull request #131435 from wojtek-t/fix_watcher
Fix etcd3 watcher flake

Kubernetes-commit: 6e1d5e310ae1c37667a20655720b3cecc62b50ef
2025-04-24 09:18:31 -07:00
Wojciech Tyczyński fc69168d19 Fix etcd3 watcher flake
Kubernetes-commit: c3bb59d078a023153c6ea0c9a93e535b48f2557d
2025-04-24 11:32:49 +02:00
Paco Xu f541759309 bump fsnotify v1.9.0
Kubernetes-commit: a2281f97bb06233ece3f601f73a7ac1137433610
2025-04-24 17:01:00 +08:00
Kubernetes Publisher 85b0cb4ae1 Merge pull request #129515 from nojnhuh/typos
Fix comment typos

Kubernetes-commit: e0f9955130fd007b66e89594dbed3d9067a301b4
2025-04-24 07:29:44 +00:00
Kubernetes Publisher 42db0bf60a Merge pull request #131366 from xigang/resource_encoding
Fix typo in ResourceEncodingConfig comment

Kubernetes-commit: 25edc4237a346ffaf5afd4fbc1eea6e8e6321c6b
2025-04-24 03:39:17 +00:00
Kubernetes Publisher fe06bdc873 Merge pull request #131323 from karlkfi/karl-watch-test-move
chore: move watch handler tests to handlers pkg

Kubernetes-commit: 360a3bfb3c36a19066d7c93f347d6d029b9aaa16
2025-04-24 03:39:14 +00:00
Kubernetes Publisher cab2303b49 Merge pull request #131215 from tosi3k/cleanup-leader-election
Remove FlowSchemas handling non-leases-backed leader election

Kubernetes-commit: 27de9a82b7de600fa40b4b2add081cefaec6cdc0
2025-04-24 03:39:12 +00:00
Kubernetes Publisher c160237b46 Merge pull request #131162 from wojtek-t/simplify_etcd3_watcher
Simplify etcd3 watcher

Kubernetes-commit: db21f3df3f44b5b4545c8164d0d6030b01db2ed0
2025-04-24 03:39:11 +00:00
Kubernetes Publisher 492c873a80 Merge pull request #130995 from xigang/utils
bump k8s.io/utils for improvements

Kubernetes-commit: 43a7d3be12425cc80ca6ad3599809a19728c5566
2025-04-23 23:44:15 +00:00
Kubernetes Publisher 6da3566330 Merge pull request #130994 from BenTheElder/host-network-no-port
Remove inaccurate doc comment from podspec hostNetwork field

Kubernetes-commit: b775f9b92f98f7b3acbb3864ed53c2f5b835e917
2025-04-23 23:44:14 +00:00
Rafael Franzke 213eed6ea1 Allow disabling caching for webhook authorizers when using `apiserver.config.k8s.io/v1{alpha1,beta1}.AuthorizationConfiguration` (#129237)
* Introduce new boolean `cache{Una,A}uthorizedRequests` field

* Run `hack/update-codegen.sh`

* Respect legacy flags values for caching

With the legacy `--authorization-webhook-cache-{un}authorized-ttl`
flags, caching was disabled when the TTL was set to `0`, so let's
continue doing so when building the authz configuration struct.

* Pass TTL=0 to webhook authz plugin when cache disabled

Kubernetes-commit: fa8e37f7805d608c121f07da5259d3086436d397
2025-04-23 22:30:52 +02:00
Kubernetes Publisher 82f6fe39b0 Merge pull request #127126 from mengqiy/patch-2
Correct etcd override flag help text

Kubernetes-commit: f16176317310b5b920236feb9fd4cb7c6b7df6a2
2025-04-23 23:44:10 +00:00
Kubernetes Publisher 8181c85b8b Merge pull request #131359 from deads2k/disable
Stop exposing list-via-watch from the server

Kubernetes-commit: 66931f07d9c3a4b8b7aecb5649d710896001047c
2025-04-18 07:55:08 -07:00
xigang 056896e970 Fix typo in ResourceEncodingConfig comment
Signed-off-by: xigang <wangxigang2014@gmail.com>

Kubernetes-commit: f844abfc6f950fd90a3b66355641ec53879d79a2
2025-04-18 15:55:38 +08:00
David Eads f5da7d2a32 Stop exposing list-via-watch from the server
With StreamingCollectionEncodingToJSON and
StreamingCollectionEncodingToProtobuf, the WatchList must re-justify its
necessity.  To prevent an ecosystem from building around a feature that
may not be promoted, we will stop serving list-via-watch until
performance numbers can justify its inclusion.

This also stops the kube-controller-manager from using the
list-via-watch by default.  The fallback is a regular list, so during
the skew during an upgrade the "right" thing will happen and the new
StreamingCollectionEncoding will be used.

Kubernetes-commit: 660df229bf3929741cf31659187060d0c651dcf9
2025-04-17 16:34:46 -04:00
Karl Isenberg 4c858d18eb chore: move watch handler tests to handlers pkg
- Move the watch handler unit tests to the same package as the
  WatchServer implementation.
  k8s.io/apiserver/pkg/endpoints -> k8s.io/apiserver/endpoints/handlers
- Copy over minimal scheme and codec test setup
- Refactor the tests to use testify assert and require

This unblocks making WatchServer private, if we decide to do that.

Kubernetes-commit: 7fcc1bcf1d1fdb2da6ea1c5b49798a7c7eeb6e6d
2025-04-15 16:34:28 -07:00
Kubernetes Publisher 03ddc411f7 Merge pull request #131196 from siyuanfoundation/forward-api
bug fix: fix version order in emulation forward compatibility.

Kubernetes-commit: 640489ae0cefea2358b4d248aaae9b3b2128cf7d
2025-04-08 22:46:41 +00:00
Kubernetes Publisher 2a113dbe6b Merge pull request #131204 from dims/move-to-released-version-of-prometheus/client_golang-v1.22.0-from-rc.0
Move to released version of prometheus/client_golang v1.22.0 from rc.0

Kubernetes-commit: 92af6ab6926f192a3d4543a1d6fa39f20edad3ea
2025-04-08 22:46:39 +00:00
Davanum Srinivas e87c9dbf8f Move to released version of prometheus/client_golang v1.22.0 from rc.0
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 2ef4a8426c2c1b6e3495de08c4686382a752f8f7
2025-04-08 08:35:18 -04:00
Antoni Zawodny cd728bc91b Remove FlowSchemas handling non-leases-backed leader election
Kubernetes-commit: 2800c16c8b97991b228c00b86934daa134f08add
2025-04-08 13:57:46 +02:00
Siyuan Zhang 5a4ec0a797 bug fix: fix version order in emulation forward compatibility.
Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: b1a9cc347311012bade7230b55ab95229a1e22c9
2025-04-07 18:38:43 -07:00
Kubernetes Publisher d4f2fc56b5 Merge pull request #131020 from wojtek-t/fix_asynchronous_error
Fix race for sending errors in watch

Kubernetes-commit: b4d139094698687043b36f1c378dfeb1b654198a
2025-04-02 22:40:48 +00:00
Kubernetes Publisher beaef1d3ec Merge pull request #131103 from ahrtr/etcd_sdk_20250328
Bump etcd 3.5.21 sdk

Kubernetes-commit: f4d1686120d2367dd4c00df53e93dad51c414435
2025-04-01 10:59:01 +00:00
Jordan Liggitt 1776f0c3f2 Parallelize cacher list tests
Kubernetes-commit: eca90dab3f553c5794e780c67e17ae75d9acb65b
2025-03-31 15:17:04 -04:00
Marek Siarkowicz e228aeaf39 Don't start etcd for skipped test
Kubernetes-commit: 1a15d582ae5fc84177f305d93ff473cca5de6f93
2025-03-31 21:06:54 +02:00
Marek Siarkowicz 29a5d82129 Stop cacher in TestWatchStreamSeparation to speed up shutdown
Kubernetes-commit: 75186095c58630fde0b3f89892c69c8ef91fffab
2025-03-31 21:28:21 +02:00
Marek Siarkowicz 30b60eb0a6 Fix flake, non-consistent list doesn't give any guarantees about staleness
Kubernetes-commit: 38d5cb368dd95b7f185dbba97fc3e193f48a83f2
2025-03-31 08:10:42 +02:00
Marek Siarkowicz aed144f141 Ensure that cacher is terminated in TestGetListRecursivePrefix
Kubernetes-commit: 9b5c4504ee49c366be3d7c806482ef4665dc5f70
2025-03-31 18:17:08 +02:00
Benjamin Wang 51e9232644 bump etcd 3.5.21 sdk
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>

Kubernetes-commit: f3b80a858225178e3f7a3ae07bd1b9894e7b3456
2025-03-28 14:30:47 +00:00
Wojciech Tyczyński 4f42467c04 Simplify etcd3 watcher
Kubernetes-commit: 6d6abaab7d1b8f288ed949a115cc769d83bf0fe2
2025-03-24 14:02:07 +01:00
Wojciech Tyczyński b9e86eb851 Fix race for sending errors in watch
Kubernetes-commit: c8c2844aaf1d04835624ff2d46417492e10dec11
2025-03-24 14:02:07 +01:00
xigang 8ff7962ff8 bump k8s.io/utils
Kubernetes-commit: fe14689f221a968806b771b226581efb834654cd
2025-03-22 10:14:01 +08:00
Benjamin Elder 0710a6fd0a make update
Kubernetes-commit: 1c3dc397ae137cc8b1d2095ea33217a239b81b55
2025-03-21 18:19:43 -07:00
Benjamin Elder 81c5d13c4d remove inaccurate hostNetwork doc comment
also remove from copies in example / test APIs

Kubernetes-commit: 8af1629f7aeeabeaec21f3fbcee5bc60d9ad2015
2025-03-21 18:19:29 -07:00
Kubernetes Publisher 26bd744afc Merge pull request #127053 from dashpole/tracing_context_propagation
APIServerTracing: Respect trace context only for privileged users

Kubernetes-commit: b2b6c4d0235085d090ca73b62a1361302db81afd
2025-03-21 05:24:21 +00:00
Kubernetes Publisher 37736ec2c1 Merge pull request #129872 from seans3/websocket-https-proxy
WebSocket HTTPS Proxy support

Kubernetes-commit: 6f13ba03dac1865174b4edf2b43f6a0f453a8ac7
2025-03-21 05:24:20 +00:00
Kubernetes Publisher b1b5987c22 Merge pull request #130937 from serathius/watchcache-unify-delegate-list
Unify should delegate list

Kubernetes-commit: 03e818744a8f92eb87155f2576dad982da7e6a43
2025-03-20 21:45:25 +00:00
Marek Siarkowicz 6811fdeb2d Unify should delegate list
Kubernetes-commit: 8fdd6fe4768d81da09f339c1dda831a05bb26f00
2025-03-20 11:08:37 +01:00
Kubernetes Publisher b1020cee14 Merge pull request #130423 from serathius/watchcache-continue
Serve LISTs with exact RV and continuations from cache

Kubernetes-commit: aa35eff1b636f587f418f9cc16a020353735d125
2025-03-20 13:45:34 +00:00
Kubernetes Publisher 3a206e1457 Merge pull request #130930 from siyuanfoundation/help
chore: update emulation version help msg.

Kubernetes-commit: b4c6895d0b0a913e3461bdc78358aa9514604b8f
2025-03-20 01:45:09 +00:00
Kubernetes Publisher a11f874f2c Merge pull request #130121 from yongruilin/featuregate-unversion-clean
[compatibility version] clean using unversioned featuregate

Kubernetes-commit: 67bdb110b44319a45188c034f817afb8ddab9cc9
2025-03-20 01:45:08 +00:00
Siyuan Zhang b94acad08e chore: update emulation version help msg.
Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: 0ec6566c68c4e10b0379518bb91fdc4edfce7adc
2025-03-19 10:29:42 -07:00
yongruilin 8702b38eb1 chore: Remove unused unversioned feature gate map by consolidating feature gate files
Kubernetes-commit: 7b5cbbb9618ae369fc5d5379703b3c2bda3f9d73
2025-02-12 13:41:01 -08:00
Kubernetes Publisher 7d24a9eb1b Merge pull request #130925 from serathius/watchcache-snapshotter-interface
Create Snapshotter interface to fake the implementation

Kubernetes-commit: f9b27edf392b283ab5c4437aa2803046635927e5
2025-03-19 17:45:38 +00:00
Kubernetes Publisher 23be1a4749 Merge pull request #130924 from serathius/watchcache-delegate-precedense
Change precedence order for continue and legacy exact match

Kubernetes-commit: 593906d607a9a48b2e8c18c68d15fb64eb259440
2025-03-19 17:45:37 +00:00
Kubernetes Publisher dfc7cb5fe1 Merge pull request #130922 from serathius/watchcache-delegate-state
Extend shouldDelegateList testing incorportating state of cacher

Kubernetes-commit: 32260dfa7b0603816619702858ba49201e0cc3c0
2025-03-19 17:45:36 +00:00
Kubernetes Publisher a581683e3c Merge pull request #130899 from serathius/watchcache-error
Implement watchcache returning error from etcd that caused cache reinitialization

Kubernetes-commit: e5558a81c93fef5463b02ae7c2a8c0c4b15ecc3a
2025-03-19 17:45:35 +00:00
Marek Siarkowicz fa558b198a Create Snapshotter interface to fake the implementation
Kubernetes-commit: 3edeb60c089106229b582a8c6800388de433426a
2025-03-19 14:04:47 +01:00
Marek Siarkowicz 91724cfd41 Change precedence order for continue and legacy exact match
This doesn't matter for shouldDelegateList, but matters when picking
source of RV. RV from continue takes precedence.

Kubernetes-commit: 7da942ca7486310893d4f11f3af062957f953555
2025-03-19 13:58:43 +01:00
Marek Siarkowicz edd1d1f6ba Extend shouldDelegateList testing incorportating state of cacher
Kubernetes-commit: 929a9c0cad9b5c2c411a325fd4f356a2b5e01f13
2025-03-19 12:23:08 +01:00
Kubernetes Publisher 1a83f0ce07 Merge pull request #128402 from richabanker/mvp-agg-discovery
KEP 4020: Replace StorageVersionAPI with aggregated discovery to fetch served resources by a peer apiserver

Kubernetes-commit: a6227695ab10a79219c253c94e65c0ee1c4cf18d
2025-03-19 05:52:39 +00:00
Kubernetes Publisher 2566cd2659 Merge pull request #130115 from danmillwood/danmillwood-dispatcher-test-patch
Fix intermittent failure in TestDispatcher test

Kubernetes-commit: f287bc21b731ce31375a3c2348404ef8a199698e
2025-03-19 05:52:38 +00:00
Kubernetes Publisher 7db8aee1f8 Merge pull request #130906 from serathius/streaming-validation
Update kube-openapi and integrate streaming tags validation

Kubernetes-commit: 32b1819423de505da855cf7544e871a04e63d6ed
2025-03-19 05:52:36 +00:00
Marek Siarkowicz f50e0ed3bf Update kube-openapi and integrate streaming tags validation
Kubernetes-commit: 75a4d136abac241f728407515e3d0d8305594675
2025-03-18 21:26:22 +01:00
Kubernetes Publisher 98865c84e6 Merge pull request #130863 from serathius/watchcache-negative-RV-consistent
Extend tests for negative RV with consistent reads

Kubernetes-commit: 4b848a555f3626f62dce39fda5c303e60cf98121
2025-03-18 17:45:02 +00:00
Kubernetes Publisher 0f51ac53c8 Merge pull request #130560 from stlaz/remote-uid-config-beta
RemoteRequestHeaderUID: bump to beta, enabled by default

Kubernetes-commit: 8312d8e85eb7e9590a0bf2e31dd6295b0486ac0c
2025-03-18 17:45:01 +00:00
Marek Siarkowicz 50f48ce4b3 Implement watchcache returning error from etcd that caused cache reinitialization
Kubernetes-commit: c09d87f79c90a5ebb0ef6a99abd13dec82b497e3
2025-03-18 16:48:33 +01:00
Kubernetes Publisher 52e218fc61 Merge pull request #130873 from serathius/watchcache-consistency-typo
Panic on failed consistency check and fix typo in logs

Kubernetes-commit: bce5886c975c933c02583213f72ea9a27c9e2296
2025-03-18 13:45:26 +00:00
Kubernetes Publisher 3482808f92 Merge pull request #130866 from serathius/watchcache-delegate-helper
Extract delegator.Helper interface to allow making delegate decision based on cache state

Kubernetes-commit: fd347070332137fa291e70f594667384d4505982
2025-03-18 13:45:25 +00:00
Kubernetes Publisher aac1558d35 Merge pull request #130875 from aramase/aramase/f/fix_email_verified_godoc
Fix godoc for `claims.email_verified` usage in claim validation rules

Kubernetes-commit: c608791a110a96b15a45c17d22f6ed29b01d7e9b
2025-03-18 05:53:12 +00:00
Anish Ramasekar 3a95207b18 Add unit test to validate email_verified in claim validation rules
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: af291a44c3a2e31ef58851d27aaa70e9a02fedaa
2025-03-17 15:38:35 -07:00
Anish Ramasekar 67dfc24d13 fix godoc for email_verified requirement when username contains claims.email
Using 'claims.?email_verified.orValue(true) == true' in the example
validation rule. By explicitly comparing the value to true, we let type-checking see the result
will be a boolean, and to make sure a non-boolean email_verified claim will be caught at runtime.

Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>

Kubernetes-commit: 916c7867f7ea766824728851a25b01ebbc600491
2025-03-17 15:18:05 -07:00
Marek Siarkowicz 4da0062093 Fix missing recursive in consistency check, enable panic on failed check and fix typo in logs
Kubernetes-commit: 4f1912abf2d139c57036c5333f62bd5bddd289fe
2025-03-17 19:24:16 +01:00
Kubernetes Publisher d750e2f2bf Merge pull request #130595 from tkashem/omit-admission
KEP-3926: skip admission validation for unsafe delete

Kubernetes-commit: 61529d54f22802523e28fd7b6b5d4483d381bfad
2025-03-17 17:56:55 +00:00
Kubernetes Publisher ba3fbbb53e Merge pull request #130688 from serathius/watchcache-validate
Use ValidateListOptions in watch cache

Kubernetes-commit: abaa73bb76855de032920831112409920ceda408
2025-03-17 17:56:53 +00:00
Kubernetes Publisher fa03ee3ea0 Merge pull request #130347 from Jefftree/remove-v2beta1-agg-discovery
Add a deprecated feature gate to stop serving apidiscovery.k8s.io/v2beta1

Kubernetes-commit: 8906223b000d94ad3947c1582c5ba452c6766e6c
2025-03-17 17:56:52 +00:00
Kubernetes Publisher 544ce3df68 Merge pull request #130741 from googs1025/fix/data_race
flake: fix data race for TestApfWatchHandlePanic unit test

Kubernetes-commit: fd0a3484176f8f29f038b4b28132dd3c7583eb00
2025-03-17 17:56:48 +00:00
Marek Siarkowicz cc5ef43352 Extract delegator.Helper interface to allow making delegate decision based on cache state
Kubernetes-commit: 984b475e74904dd61c10b23472798a21496edc8f
2025-03-17 15:46:02 +01:00
Kubernetes Publisher 5df5358ff9 Merge pull request #130811 from serathius/watchcache-test-negative-rv
Add test cases for negative resource version in TestList

Kubernetes-commit: 5a6ace2aa0342eb3103351bb7681066e0b4225af
2025-03-17 13:45:58 +00:00
Kubernetes Publisher 2265efa65a Merge pull request #130815 from serathius/watchcache-simplify-bypass-test
Simplify bypass test by just testing shouldDelegateList function

Kubernetes-commit: e2a77c2a0527da148dacd5febf15dab62d5e63cb
2025-03-17 13:45:57 +00:00
Kubernetes Publisher 8aa636f1b5 Merge pull request #130813 from serathius/watchcache-consistent-list-flake
Fix flaky RunTestConsistentList

Kubernetes-commit: d2ef120924eb289997a0755a47d1a516a42f5b8f
2025-03-17 13:45:56 +00:00
Marek Siarkowicz c59961a007 Test continue with negative RV for reading consistent RV
Kubernetes-commit: 6d21d8f2376b6e25064b10148b4f416e8d89a508
2025-03-17 12:10:54 +01:00
Kubernetes Publisher 05ed2e066d Merge pull request #130437 from srivastav-abhishek/fix-unsafe-conversions-test
Removed parallel execution for test/subtest where AllocsPerRun is used

Kubernetes-commit: e7eb076349dbb1343c71da8d31ea208457e6684d
2025-03-14 17:53:30 +00:00
Kubernetes Publisher b6404642e4 Merge pull request #130588 from serathius/watchcache-test-recursive
Test recursive in TestGetListCacheBypass and separate overrides

Kubernetes-commit: 611abd3bcdeb8ee513ab7814c4ac251575e48cbd
2025-03-14 13:46:25 +00:00
Marek Siarkowicz 3a2e1b53e5 Simplify bypass test by just testing shouldDelegateList function
Kubernetes-commit: d263344a9b400890409166c5823598a92bbb79fb
2025-03-14 14:26:44 +01:00
Marek Siarkowicz 6ace22f694 Fix flaky RunTestConsistentList
Noticed that cache might not nesseserly observe the write causing test
to flake. Fixed that changing the logic to require LessOrEqual of
writeRV instead of equal to writeRV. Also added comments explaining
edge cases.

Kubernetes-commit: 86169a7a1e09c120cadafc0213afbf9630f0d8af
2025-03-14 13:45:55 +01:00
Marek Siarkowicz 6f6da8e97b Add test cases for negative resource version in TestList
Kubernetes-commit: c4d77a07993302057441a886125c1c887e7869f1
2025-03-14 12:22:17 +01:00
Marek Siarkowicz a67992576e Test bypass for negative RV
Kubernetes-commit: 58d9b5c7b6467bb2cb14d49247cdada02e8f4a83
2025-03-14 14:34:43 +01:00
Kubernetes Publisher 84cc815637 Merge pull request #130354 from siyuanfoundation/forward-api
KEP-4330: add forward compatibility for compatibility mode

Kubernetes-commit: 8b08487283d563efa0bc849ac3a3701463bc49bd
2025-03-14 05:45:39 +00:00
Kubernetes Publisher 70820c9c98 Merge pull request #130019 from yongruilin/version-intro
KEP-4330: extend version information with more detailed version fields

Kubernetes-commit: 23d63770284cb30a2eb90b79ace0f1c7e32fb16f
2025-03-14 01:45:55 +00:00
Kubernetes Publisher a91b0013af Merge pull request #130788 from jpbetz/fix-subresources
Fix subresource parsing for declarative validation

Kubernetes-commit: dabb4e2445c0d9f8ccf9e8c596060c62307b80ef
2025-03-14 01:45:53 +00:00
Kubernetes Publisher 543428d1c4 Merge pull request #130775 from serathius/watchcache-consistent-read
Fix detecting consistent read when watchcache starts handling continue

Kubernetes-commit: 54e7d2760d1c941c8db50d059dbbe0cfb54a909a
2025-03-14 01:45:52 +00:00
Kubernetes Publisher d88392f1f6 Merge pull request #130754 from aaron-prindle/validation-gen-add-metric-and-runtime-verification-review-comments-upstream
[Declarative Validation] chore: change Info->Error log level related to declarative validation runtime tests and refactor panic wrapper names

Kubernetes-commit: 020c4b7c655f63cd0ab1b8466492da528961f930
2025-03-13 21:53:43 +00:00
Kubernetes Publisher c31bd9905e Merge pull request #130751 from Jefftree/cle-promote-beta
[KEP-4355] Promote Coordinated Leader Election to Beta

Kubernetes-commit: be127ae0e27644edead7007834b5c8437fb6eb0b
2025-03-13 21:53:39 +00:00
Jefftree cba5376d4f Gate apidiscovery/v2beta1 serving with a feature gate
Kubernetes-commit: 95d3d4a22d705ef6bf2d494c065743d356914e8d
2025-03-13 17:58:06 +00:00
Kubernetes Publisher 79feac10d8 Merge pull request #130777 from serathius/watchcache-consistency-test
Fix typo and pass the environment variable required to enable watchcache consistency checking in GCE tests

Kubernetes-commit: 9475c92a6efd1402f00e8b72e03473c5c93b9b78
2025-03-13 17:44:17 +00:00
Kubernetes Publisher 7b991eb8ee Merge pull request #124360 from carlory/kep-3751-quota-2
Add quota support for PVC with VolumeAttributesClass

Kubernetes-commit: 68899f8e6d5861e7b6197c51b0dee9f8a486e3e0
2025-03-13 17:44:16 +00:00
Joe Betz 24d512c91f Fix subresource parsing for declarative validation
Kubernetes-commit: d9a2dee622c0d2f2079194ff9700310041c10ed2
2025-03-13 13:05:54 -04:00
Kubernetes Publisher 8e8b957b64 Merge pull request #130693 from novahe/fix/test-cases
Fix test cases that may potentially cause a panic.

Kubernetes-commit: 336a32a270997731873b6d8b616f4ae91d903fcf
2025-03-13 13:52:00 +00:00
Kubernetes Publisher 6056c27674 Merge pull request #130752 from serathius/watchcache-simplify-delagate
Simplify shouldDelegateList

Kubernetes-commit: 2e9bb32ee8defbd37ce9754ae8362356ce4c3796
2025-03-13 13:51:56 +00:00
Marek Siarkowicz 36c1a58d7e Fix typo and pass the environment variable required to enable watchcache consistency checking in GCE tests
Kubernetes-commit: 8b0294daed236dcaf2b2f74ad4a38405118ebbaa
2025-03-13 11:55:23 +01:00
Kubernetes Publisher ae901d5b33 Merge pull request #130648 from jpbetz/semver-tolerant
Enable Semver CEL library, add normalization support

Kubernetes-commit: 69467d354737025482a1b2a5af34e56245f1be49
2025-03-12 21:45:20 +00:00
Kubernetes Publisher 96b9726a3c Merge pull request #130705 from aaron-prindle/validation-gen-add-metric-and-runtime-verification-upstream
[Declarative Validation] feat: add declarative validation metrics and associated runtime verification tests

Kubernetes-commit: 21f7eaa8e2b9c1a70b607cc42d0f038a9efc1906
2025-03-12 21:45:18 +00:00
Aaron Prindle 4fe686a430 chore: change Info->Error log level related to declarative validation runtime tests and refactor panic wrapper names
Kubernetes-commit: 08745086e2df0cf1a91cbe5bb305c968f1d5bf2a
2025-03-12 17:40:33 +00:00
Marek Siarkowicz 3cb2448d98 Fix detecting consistent read when watchcache starts handling continue
Kubernetes-commit: 8f83f2446a5e2f11eb751fb56067c663b51cfd12
2025-03-12 18:37:10 +01:00
Marek Siarkowicz 6ed423348f Simplify shouldDelegateList
When ResourceVersionMatch is set to NotOlderThan, there is no need to handle continue or resourceVersion="".
The validation in apimachinery will not pass and return:
* "resourceVersionMatch is forbidden when continue is provided"
* "resourceVersionMatch is forbidden unless resourceVersion is provided"

Kubernetes-commit: a0cc02e264ead76dfb0ae75a505e4d2e54219def
2025-03-12 18:20:47 +01:00
Jefftree 1623f6691b Promote CLE to beta
Kubernetes-commit: 3b88db4f2350498513c994710bfba65c074eaf2e
2025-03-12 17:07:29 +00:00
Kubernetes Publisher 3832c300e8 Merge pull request #130708 from fuweid/reduce-spans-in-writer
*: reduce tracing events during streaming JSON objects

Kubernetes-commit: c28e7ffe2467efef443ff83952280368c1fd9fce
2025-03-12 06:17:50 +00:00
googs1025 7af25044da flake: fix data race for TestApfWatchHandlePanic unit test
Signed-off-by: googs1025 <googs1025@gmail.com>

Kubernetes-commit: 1a660d3d0c9e93279c8faae56a4f8e1cca0003a4
2025-03-12 10:44:49 +08:00
Kubernetes Publisher 1a6db11afb Merge pull request #129407 from serathius/streaming-proto-list-encoder
Implement streaming proto list encoder

Kubernetes-commit: 1b6e321e2311757a521615917f99dbe8e58f623c
2025-03-12 01:57:40 +00:00
Wei Fu 9ff9bbbc47 *: reduce tracing events during streaming JSON objects
If apiserver is handing heavy traffic volume, it's likely to trigger
tracing events. After streaming JSON objects, the number of tracing events
are same to object number. It's unneccessary to log each write call.
This patch is to reduce tracing events.

Signed-off-by: Wei Fu <fuweid89@gmail.com>

Kubernetes-commit: 003f2157671a694aefecd4dbb7df786e27200a18
2025-03-11 13:26:55 -04:00
Kubernetes Publisher b2bc62b37f Merge pull request #130475 from serathius/watchcache-consistency
Implement consistency checking

Kubernetes-commit: 4c311c9fcf6a67c665127d67fb30cd602ba5b88d
2025-03-11 13:44:28 +00:00
Kubernetes Publisher 67d2550df7 Merge pull request #130530 from pacoxu/v1.33-fg-cleanup
v1.33 feature gate cleanup

Kubernetes-commit: 8f97ac7fcf1a5db05e0bd418266d5759ef3b77a7
2025-03-11 09:44:27 +00:00
novahe a2c8b5531e Fix test cases that may potentially cause a panic.
Kubernetes-commit: 9e53371ddaaeab4083fde45e43c803071238e686
2025-03-11 17:41:37 +08:00
Joe Betz 408f50382f Apply feedback
Kubernetes-commit: 2d810ddfa9c8ee55ebdb001f78b832169204fc79
2025-03-10 18:56:54 -04:00
Kubernetes Publisher dccab55151 Merge pull request #130637 from serathius/watchcache-unify-validation
Unify ListOptions validation between cache and etcd

Kubernetes-commit: 9d2fc46556af162ff42a4773349d0f92f9ef8d50
2025-03-10 13:43:54 +00:00
Marek Siarkowicz 7a33f524c6 Use ValidateListOptions in watch cache
Kubernetes-commit: 9e7c080b863896ffbe9eff2a7edc63aa72ec30cf
2025-03-10 14:29:24 +01:00
Kubernetes Publisher 855c0d44c8 Merge pull request #130555 from thockin/k_k_randfill
Use randfill in k/k

Kubernetes-commit: 0f2bde7745f3b4eadcf317bc5056dfeb96859bd3
2025-03-09 13:54:52 +00:00
Joe Betz 92171c8c10 Add normalization support to CEL semver library, enable in base env
Kubernetes-commit: 41469004282b2ad9034993427ce4ec9d1c7f88bb
2025-03-07 11:10:43 -05:00
Joe Betz 782d90765e Add tolerant parse option to semver
Kubernetes-commit: c510b93d28faf8dbce5d761675de9b5d258ae485
2025-03-07 10:10:57 -05:00
Marek Siarkowicz 73e72d16c5 Unify ListOptions validation between cache and etcd
Kubernetes-commit: ccb607f06b91496d02a3b94253261e03e3280630
2025-03-07 12:26:05 +01:00
Aaron Prindle b8750e7396 feat: add declarative validation metrics and associated runtime verification tests
Kubernetes-commit: de904f8099252fd740b4d93e5a661b20aad12ef1
2025-03-06 21:33:12 +00:00
Aaron Prindle 97b6cb1aeb chore: change error_matcher.go to use test interface instead of importing testing pkg
Kubernetes-commit: cd9df2f115a95835e07cddf740861dbd8f6f3988
2025-03-11 05:24:07 +00:00
yongruilin 2b4f068bdb refactor: detach Info from apimachinery util version
- Remove `info` field from `Version` struct
- Modify `WithInfo` and `Info` methods to be deprecated
- Update version information retrieval to use base version info
- Simplify version information generation in compatibility tests
- Remove unnecessary version info passing in build and test scenarios

Kubernetes-commit: 14934b481ef6522d6c1003ded19002ea45abe5d1
2025-03-05 23:55:08 +00:00
Abu Kashem 4c88a5c5ae skip admission for unsafe delete
Kubernetes-commit: ef3cb5c5afa0c9bedf52bd6c271af05430183f97
2025-03-05 13:45:45 -05:00
Marek Siarkowicz f76f81aa6f Test recursive in TestGetListCacheBypass and separate overrides
Kubernetes-commit: 6d3bff83213b35797b23e89c90bfe939dd30c2cd
2025-03-04 20:07:41 +01:00
Tim Hockin 7ee837dd68 Vendor randfill
Kubernetes-commit: 0ce4268b1fe4f78d77249e329b0349b9d2dd2c65
2025-03-03 23:46:48 -08:00
Paco Xu d44a862c51 remove feature gate AdmissionWebhookMatchConditions that was GAed in v1.30
Kubernetes-commit: f16745437182ec50f51253cef39cd5c89041ee95
2025-03-03 10:54:46 +08:00
Paco Xu bd0e774416 remove AggregatedDiscoveryEndpoint that was GAed in v1.30
Kubernetes-commit: 8195f82fe82e7bcf36ba50ddc8b78c00fa8df2bc
2025-03-03 11:01:02 +08:00
Paco Xu 01307e4b8d remove feature gate RemainingItemCount that was GAed in v1.29
Kubernetes-commit: bb79c29dd51f46003e0d35cd3d3683a2338448b1
2025-03-03 10:45:39 +08:00
Marek Siarkowicz 23e9b2c9d4 Implement consistency checking
Kubernetes-commit: e4d73c56cd055a6e3a23068bd70c424579df40fe
2025-02-27 17:53:06 +01:00
Abhishek Kr Srivastav 1b0427a576 Removed parallel execution for test/subtest where AllocsPerRun is used
Kubernetes-commit: bed838955fa1b15169e6d1923ed4da4c09ca555a
2025-02-26 10:57:02 +05:30
Tim Hockin 9641d30242 Use randfill, do API renames
Kubernetes-commit: e54719bb6674fac228671e0786d19c2cf27b08a3
2025-02-20 09:45:22 -08:00
Kubernetes Publisher c2e94ca503 Merge pull request #130569 from dims/update-to-latest-cadvisor-v0.52.0
Update to latest cadvisor @ v0.52.1 and new opencontainer/cgroups and drops opencontainers/runc

Kubernetes-commit: 0eaee48ecb8669dc65bfdf9a3583326ab88fc39d
2025-03-08 01:52:06 +00:00
Davanum Srinivas e36558fb20 update to v1.22.0-rc.0
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 97a54dc4b04b7d2938d11c5ae9a6233348e854ef
2025-03-07 13:45:34 -05:00
Kubernetes Publisher 7377dfa3e5 Merge pull request #130417 from serathius/watchcache-compact
Separate compactWatchCache from compactStore

Kubernetes-commit: 07e65dac2d969cffdde6416927f4884005dcda43
2025-03-06 06:53:45 -08:00
Davanum Srinivas 337542d65b update to latest cadvisor @ v0.52.0
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 5ecddb65715af7e2afc4f3cbb1abe393bfb4346a
2025-03-04 14:29:08 -05:00
Marek Siarkowicz 4305a14262 Separate compactWatchCache from increaseRV
Kubernetes-commit: 15cb82b3b3fa95ba5b914a5a02ac01d42eda892f
2025-02-25 14:44:50 +01:00
Kubernetes Publisher d3e44dff6c Merge pull request #130589 from serathius/watchcache-opts
Pass storage.ListOptions to WaitUntilFreshAndList

Kubernetes-commit: c30b1eb09b6355f88ac514ec97cb7d87bdf6c2c3
2025-03-06 09:43:45 +00:00
Kubernetes Publisher c5b8df417a Merge pull request #130543 from thockin/error_matcher_and_origin
Fix up ErrorMatcher from feedback

Kubernetes-commit: 4696667025efa26a7b192b1cb5cf79cec276f2b4
2025-03-06 09:43:44 +00:00
Kubernetes Publisher 163865fa38 Merge pull request #130320 from Jefftree/relax-openapi-verify
Relax OpenAPI Verification to pass for both strict and non-strict alpha enforcement

Kubernetes-commit: 4f32f64036e43122cc34448fda8ab845932d5c6c
2025-03-05 15:49:44 -08:00
Tim Hockin 0b0eaa35e1 Fix up ErrorMatcher from feedback
a) Rename the type and drop the constructor
b) Make MatchErrors() into a Test() method

For followup:

c) Consider making ByType() assumed
d) Consider making ByField() assumed and handle nil as "don't care"
e) Consider making ByValue() assumed and handle nil as "don't care"

Kubernetes-commit: 0a9f492eedf6dd68fee12e4606d3fef4d608d88f
2025-03-03 10:23:18 -08:00
Jefftree b12d7a1290 Allow OpenAPI verification to pass both with and without strict alpha
handling

Kubernetes-commit: c597cc1f30977bcfaba5aebb2ed7983f578b1f2c
2025-02-20 15:57:37 +00:00
Kubernetes Publisher 5edb11aa43 Merge pull request #130571 from hakuna-matatah/debug-upstream
Help debug latencies in authn and authz phase of Request

Kubernetes-commit: 2b025e645975d6d51bf38c008f972c632cf49657
2025-03-05 17:47:14 +00:00
Kubernetes Publisher 821b679880 Merge pull request #130587 from serathius/watchcache-subtests
Run lists tests in subtests

Kubernetes-commit: 91d6fd3455c4a071408df20c7f48df221f2b6d30
2025-03-05 06:03:46 -08:00
Marek Siarkowicz 79ec45326d Run lists tests in subtests
Kubernetes-commit: 7a84e7630f91014fa3b632d8800e9a943003001c
2025-03-03 20:50:37 +01:00
Kubernetes Publisher 345ad05c0c Merge pull request #130549 from jpbetz/validation-gen-pr2
KEP-5073: Add declarative validation to scheme

Kubernetes-commit: 89d0b7022a81dd8b54efcc203b0cfa4502171cae
2025-03-05 01:47:23 +00:00
Joe Betz 7c0ba21066 Add declarative validation utility for use from strategies
Kubernetes-commit: ffc1b32c660e3480381f4b13d0fbaa1313cf1318
2025-03-03 19:37:11 -05:00
Kubernetes Publisher 70fe4e2735 Merge pull request #128919 from dashpole/update_otel
Update go.opentelemetry.io dependencies to v1.33.0/v0.58.0

Kubernetes-commit: eea2f78e61fe91bb8fcd3c4a357ea3a10d1389db
2025-03-02 00:23:54 +00:00
David Ashpole 9b3bebdbac update go.opentelemetry.io dependencies to v1.33.0/v0.58.0
Kubernetes-commit: 29c219dcebe30be99d6917623f8d8707a47194c1
2025-03-01 19:17:16 +00:00
Kubernetes Publisher 990bed7c73 Merge pull request #130450 from JoelSpeed/fix-contains-cidr
Fix implementation of ContainsCIDR to allow non-equal addresses

Kubernetes-commit: c9d54b92ca8d52048e1d59deae9a6c4bb5ed9db7
2025-03-01 04:18:02 +00:00
Kubernetes Publisher 6a65641968 Merge pull request #129334 from serathius/streaming-json-list-encoder
Streaming json list encoder

Kubernetes-commit: 2fc329c857035676492aa6e6a995ef31448465f0
2025-03-01 00:18:21 +00:00
Kubernetes Publisher f2b1ab6bbc Merge pull request #130474 from dims/bump-x/crypto-and-x/oauth2
Bump x/oauth2 and x/crypto

Kubernetes-commit: 01ed8ed4ff0a0cbea99370c7a268019829d19e82
2025-02-28 20:25:28 +00:00
Kubernetes Publisher 69cfb424ed Merge pull request #129688 from cpanato/update-main-go124
[go] Bump images, dependencies and versions to go 1.24.0

Kubernetes-commit: b8c95e1954ef222988c0dfe5b45d5cc96c09bcb8
2025-02-27 20:27:02 +00:00
Davanum Srinivas e1e2202f0a Bump x/oauth2 and x/crypto
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 0fede7b8a2fb4c7f120876c9ef1e826f8ef28da2
2025-02-27 10:59:37 -05:00
Kubernetes Publisher 205c0f56b5 Merge pull request #130281 from z1cheng/issue_130264
Implement chunking for gzip encoder in deferredResponseWriter

Kubernetes-commit: 25dc6c98209b50db1f0a023020003a4051b06138
2025-02-26 21:46:14 +00:00
Joel Speed 64791740ae Fix implementation of ContainsCIDR to allow non-equal addresses
Kubernetes-commit: b7c80f7f1592356e796a64958bec9a05e0fe3ba1
2025-02-26 14:24:58 +00:00
Kubernetes Publisher 82c8af5dbe Merge pull request #130443 from serathius/watchcache-limit
Remove limit support from btree store

Kubernetes-commit: 126a5824de4086d4749c7a9f178fc559c30e7564
2025-02-26 13:45:04 +00:00
Kubernetes Publisher e03f7e4910 Merge pull request #130400 from serathius/storage-current-rv
Move GetCurrentResourceVersion to storage.Interface

Kubernetes-commit: 2e073d6334f4d70a3fc8d0b0c29bc052b8c0c06e
2025-02-26 03:40:30 -08:00
Marek Siarkowicz 9e523945a2 Remove limit support from btree store
We cannot use limit as it would apply it before filtering, which is done
in cacher. Limit is not currently used, but let's remove it to be save,
until filtering is implemented in store.

Kubernetes-commit: 168c338f7cb44a08f3d1a7e1d0e72cac241e9a29
2025-02-25 19:17:30 +01:00
cpanato 585eff559f bump go.mod to set min go1.24
Signed-off-by: cpanato <ctadeu@gmail.com>

Kubernetes-commit: 88300c406b9199ed017e1bada29951fc18e66ae1
2025-02-25 13:21:52 +01:00
Harish Kuna 6faeace534 Debug latencies in request handler
Kubernetes-commit: 186e6ee2bd55da286f39eef56c83376f3f79e09d
2025-02-25 01:33:14 +00:00
Marek Siarkowicz 3ad93853da Move GetCurrentResourceVersion to storage.Interface
Kubernetes-commit: fea89f25d1bfd7290bb0165f49a6d288ab5f717a
2025-02-24 19:49:45 +01:00
Kubernetes Publisher 2ebe70a0a7 Merge pull request #130412 from serathius/watchcache-progress
Move watch progress to separate package.

Kubernetes-commit: 3d9fcb7c0107d888722dd2a08da3326bcce0723a
2025-02-26 09:45:19 +00:00
Kubernetes Publisher 0230ffb631 Merge pull request #130399 from serathius/cache-delegator
Rename CacheProxy to CacheDelegator

Kubernetes-commit: 6ff0354c15c5b8ca1db0bec3a645b49843f1c300
2025-02-26 00:16:29 -08:00
Marek Siarkowicz a4587170bd Move watch progress to separate package.
Kubernetes-commit: 740db0f01d9bceaa7bd6c0b6c5e5f96fc78c04dd
2025-02-25 13:53:17 +01:00
Marek Siarkowicz a64613cb08 Rename CacheProxy to CacheDelegator
Kubernetes-commit: 4c635ecf8250c7493481b9b8fb88e384de1b41db
2025-02-24 19:07:25 +01:00
Kubernetes Publisher ed3efcd313 Merge pull request #130060 from carlory/fix-quota-scope
Fix the `ResourceQuota` admission plugin does not respect ANY scope change

Kubernetes-commit: ffad281e3eab096f87b53ae7e533469e513db4b2
2025-02-25 17:45:59 +00:00
Kubernetes Publisher 1e7b28d116 Merge pull request #129657 from p0lyn0mial/upstream-cacher-resilient-init-back-off
storage/cacher/ready: dynamically calculate the retryAfterSeconds

Kubernetes-commit: 49f419e84ef5db6a4c5f14bab542bd53f58bf89a
2025-02-25 17:45:57 +00:00
Kubernetes Publisher fcfce5aef7 Merge pull request #130279 from serathius/watchcache-snapshot
Watchcache snapshot

Kubernetes-commit: 4b12e89d0d1b8eefbe94f615ede351ccb9501164
2025-02-25 13:45:55 +00:00
Kubernetes Publisher 4a787e9b76 Merge pull request #130344 from tosi3k/wc-upper-bound-capacity
Add watch cache capacity upper bound adjusting logic

Kubernetes-commit: c13f6b9d7604e839702b32ccaa6fa09f621de35e
2025-02-25 04:21:10 +00:00
Kubernetes Publisher 710763dd43 Merge pull request #130118 from lucasrattz/update-anp
Bump konnectivity-client to v0.31.2

Kubernetes-commit: 7c59b07533ba4bca1766c10763d8b4a6d7ad00c4
2025-02-24 16:15:46 +00:00
Kubernetes Publisher 8dccd76acd Merge pull request #130359 from my-git9/assertion1
fix wrong assertion on tests

Kubernetes-commit: 06d81cfc7a485487375814fd8d5cefdf644c2d28
2025-02-24 16:15:44 +00:00
xin.li a3d85c236b enable go-required check
Signed-off-by: xin.li <xin.li@daocloud.io>

Kubernetes-commit: d92c70b82693f3c974e63dcf7abd2d5068c0530c
2025-02-23 16:54:43 +08:00
Kubernetes Publisher 95d27c97c9 Merge pull request #130187 from mansikulkarni96/129084
fix:  Sweep and fix stat, lstat, evalsymlink usage for go1.23 on Windows

Kubernetes-commit: ef54ac803b712137871c1a1f8d635d50e69ffa6c
2025-02-23 00:07:50 +00:00
xin.li afb79f83b3 fix wrong assertion on tests
Signed-off-by: xin.li <xin.li@daocloud.io>

Kubernetes-commit: bc4ae15d77beab23f321bf6547f82c04ba27c3fa
2025-02-22 12:39:01 +08:00
Antoni Zawodny efe7a1b26d Add watch cache capacity upper bound adjusting logic
Kubernetes-commit: 2173a0fafd448e55b7738b88fbbab392125dd975
2025-02-21 15:07:01 +01:00
z1cheng c576a626de Implement chunking for gzip encoder in deferredResponseWriter
Signed-off-by: z1cheng <imchench@gmail.com>

Kubernetes-commit: 2472f4965fe2f2013b993b6b56539946a21a3740
2025-02-20 18:36:47 +08:00
Marek Siarkowicz 09c0e7d0cd Add snapshotting of watch cache behind a feature gate
Kubernetes-commit: 2de2093bcef6544ef17c84116fbd751fc429820a
2025-02-19 17:03:48 +01:00
Marek Siarkowicz d522031d97 Ensure that btree threadedStoreIndexer implements orderedLister
Kubernetes-commit: 99881453838a63730fb34b6bd02775ae08320184
2025-02-19 11:47:26 +01:00
Marek Siarkowicz f422062046 Pass storage.ListOptions to WaitUntilFreshAndList
Kubernetes-commit: e6cf9dd1663a9a54fa673873e8e97641f69bcefd
2025-02-19 11:20:04 +01:00
Lucas Rattz 4831145b6d Bump konnectivity-client to v0.31.2
Kubernetes-commit: f8728b62228faec0048e55100747d7aee92d14ca
2025-02-12 18:47:51 +00:00
Dan Millwood 10c2760fab Fix intermittent test failure
Start the informerFactory before WaitForCacheSync

Kubernetes-commit: b9cd017a2146996677aa28ec992f7ed796f88c9b
2025-02-12 16:22:47 +00:00
carlory 13a27b8dd7 Fix a bug where the `ResourceQuota` admission plugin does not respect ANY scope change when a resource is being updated. i.e. to set/unset an existing pod's `terminationGracePeriodSeconds` field.
Kubernetes-commit: eb0f003d25209c850b47a275358aea53252274b4
2025-02-10 14:30:50 +08:00
Siyuan Zhang 942f114031 Add option to explicitly enable future gv or gvr in runtime-config.
Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: 3d2d8db83509eadcad0529fda1f8ef81e1682ca5
2025-02-07 16:43:58 -08:00
yongruilin b6717882da feat: extend version information with more detailed version fields
- Add new version fields to version.Info struct:
  * EmulationMajor and EmulationMinor to track emulated version
  * MinCompatibilityMajor and MinCompatibilityMinor for compatibility tracking
- Update related code to populate and use these new fields
- Improve version information documentation and OpenAPI generation
- Modify version routes and documentation to reflect new version information structure

Kubernetes-commit: a3094ccbe6f9f134da29aedf4d6d87a9a97bf463
2025-02-06 16:11:12 -08:00
Jordan Liggitt 3a5523026c Drop winsymlink go 1.23 workaround
(cherry picked from commit 3990b6324d0427eaf9ff970da2be02711567ef5f)

Kubernetes-commit: 1f642c79c3192994e76bbe8e7360fd661cd21ab4
2025-02-06 12:45:52 -05:00
Kubernetes Publisher 644f8e67b2 Merge pull request #130242 from serathius/watchcache-test
Test continuations and exact revision LISTs

Kubernetes-commit: 05b526c2d7b1ed7f2eb099dd06bc57cce828a12a
2025-02-21 20:02:43 +00:00
Marek Siarkowicz 476d81d4ba Test continuations and exact revision LISTs
Kubernetes-commit: 034285dc4774f2217ca4df4626ca44b8f5f4f261
2025-02-18 17:32:41 +01:00
Kubernetes Publisher b9bc02fc91 Merge pull request #130280 from serathius/watchcache-test-refactor
Refactor TestList to allow testing continuations and exact

Kubernetes-commit: afc57a752110ac0633ff5df896ebe02ee1b19ec5
2025-02-20 16:20:34 +00:00
Kubernetes Publisher b9f760c579 Merge pull request #130297 from 249043822/br0004
Fix non-recursive list should also read RequestWatchProgress feature when consistent list from cache is enabled

Kubernetes-commit: 49bbe194605dd7468b7db07cc803bbdcdbb8c276
2025-02-20 16:20:33 +00:00
张可10140699 9da16fa551 Fix non-recursive list should also read RequestWatchProgress feature when consistent list from cache is enabled
Kubernetes-commit: bdf2e2d0646fcb6fa56289d85222e2de0b686244
2025-02-20 08:39:36 +08:00
Kubernetes Publisher f98455cb25 Merge pull request #122646 from liggitt/deletionTimestamp
prevent deletionTimestamp from moving into the past

Kubernetes-commit: 2ca9e2d28f0146fe881c8b9007f2926b07ff403d
2025-02-20 00:05:59 +00:00
Kubernetes Publisher 8dd4460107 Merge pull request #130047 from HirazawaUi/modify-loopback-cert-valid-period
Extending loopback certificate validity in kube-apiserver

Kubernetes-commit: 77667834b072db7e26a69d78c5e9f3181e12959f
2025-02-19 16:35:01 +00:00
Marek Siarkowicz 1e6e6f0a46 Refactor TestList and validate continuations to allow testing pagination and more exact RVs in the future
Kubernetes-commit: 764e13e27aedfd9e304e6014af23f20b5619216b
2025-02-19 17:10:58 +01:00
Kubernetes Publisher b6fda29776 Merge pull request #130190 from nkeert/test-validate-deferredResponseWriter-for-multiple-writes
Add a test to validate deferredResponseWriter on multiple writes

Kubernetes-commit: 7fc8a86381d874e3bb47b6d343c20f93ace42981
2025-02-19 12:02:06 +00:00
Kubernetes Publisher 938d466e86 Merge pull request #130249 from seans3/bump-websockets-version
Update gorilla/websockets library from 1.5.0 to latest 1.5.3

Kubernetes-commit: 728dc0d8c7a4d68157b2106330b65abcd5faac87
2025-02-19 04:10:41 +00:00
Sean Sullivan ff5a72e86f Update gorilla/websockets library from 1.5.0 to latest 1.5.3
Kubernetes-commit: 3100bbab2f7f013b08910f28d8a3debc28a57ea9
2025-02-19 00:26:21 +00:00
Kubernetes Publisher 52dde339a1 Merge pull request #130126 from fuweid/fix-128314
proxy: should add PingPeriod for websocket translator

Kubernetes-commit: fc876787b81a54f144bf4750136fad229056cccc
2025-02-18 20:03:21 +00:00
Kubernetes Publisher 35a4ee03bf Merge pull request #129852 from p0lyn0mial/upstream-clock-test-cache
cacher: decrease the running time of TestConsistentReadFallback

Kubernetes-commit: e279ae43358b4a95773647ff7644e9585201208d
2025-02-17 12:01:22 +00:00
nkeert 11288ef6c1 Add a test to validate deferredResponseWriteron multiple write calls
Signed-off-by: nkeert <197718357+nkeert@users.noreply.github.com>

Kubernetes-commit: 45e2f3e438e18b74f3b7a6645ff2073862ef0e38
2025-02-15 10:23:21 +05:30
Wei Fu 2a04234bdc proxy: should add PingPeriod for websocket translator
IIUC, before using the translator handler, the ping data can be delivered from
the client to the runtime side since kube-apiserver does not parse any client
data. However, with WebSocket, the server responds with a pong to the client
without forwarding the data to the runtime side. If a proxy is present, it may
close the connection due to inactivity. SPDY's PingPeriod can help address this
issue.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
Co-authored-by: Antonio Ojea <aojea@google.com>

Kubernetes-commit: dc59c0246fb407dcf035afc224f63fcf0da8244e
2025-02-12 21:39:59 -05:00
Kubernetes Publisher 08a05f9af7 Merge pull request #130113 from AwesomePatrol/129931-fix-3
Make ResourceQuota LIST requests only when Informer is not synced

Kubernetes-commit: 75909b89201386c8a555eadc79d14fb11f91747c
2025-02-12 16:03:12 +00:00
Aleksander Mistewicz 87cccf7779 Limit ResourceQuota LIST requests to times when informer is not synced
This should reduce the number of slow (100ms) LIST requests when there
are no ResourceQuota objects present in the namespace. The behavior
stays virtually the same.

Kubernetes-commit: b346ac0f8e013cedb8d91b4065d385f84e81c43e
2025-02-12 13:34:09 +01:00
Kubernetes Publisher c4717788c4 Merge pull request #129934 from serathius/graduate-btree
Graduate BtreeWatchCache feature gate to GA

Kubernetes-commit: e2b0cfa3a1fb2c425a975b8c6ba0e9509bd35452
2025-02-10 21:02:27 +00:00
HirazawaUi c533eff8e7 adjusting loopback certificate validity in kube-apiserver
Kubernetes-commit: 553e9bf84d199be3d6a3da6675671859723219f4
2025-02-08 19:43:48 +08:00
Kubernetes Publisher 4628bb89a6 Merge pull request #129416 from siyuanfoundation/refactor
KEP-4330: Refactor compatibility version code

Kubernetes-commit: e6be5f96022ea6d4a2e370a56a3d28859e1db72d
2025-02-06 21:02:03 +00:00
Kubernetes Publisher 9bb5fd51d1 Merge pull request #129929 from serathius/deprecate-separate-rpc
Flip SeparateCacheWatchRPC feature gate to false and deprecate it

Kubernetes-commit: 9a03243789677637762eb0f907e1b4e45a0136c1
2025-02-06 05:02:19 +00:00
Kubernetes Publisher 7b8dc61f0b Merge pull request #129930 from serathius/deprecate-watch-from-storage
Deprecate WatchFromStorageWithoutResourceVersion

Kubernetes-commit: 925cf7db71c5e36072f99e8b7129523f659ee3a1
2025-02-05 21:02:52 +00:00
Kubernetes Publisher 0198fdbe95 Merge pull request #129921 from srivastav-abhishek/fix-etcd-test
Additional timeout to receive all watchEvents

Kubernetes-commit: 1527a145b110f9907e3efde483d784fe362901f4
2025-02-05 21:02:51 +00:00
Stanislav Láznička a9904eef9e bump RemoteRequestHeaderUID featuregate to Beta, on by default
Kubernetes-commit: b3890d9fa0d054b9b97b3496423664c0baf1c567
2025-02-05 15:32:57 +01:00
Siyuan Zhang 5a72bc815b Add emulation forward compatibility into api enablement and RemoveDeletedKinds.
Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: 819cb8fe22fe37bf691f460bc32d0f03f53cce09
2025-02-04 10:11:56 -08:00
Kubernetes Publisher 2ce508cc43 Merge pull request #129844 from cici37/bumCEL
Bump cel-go to v0.23.2

Kubernetes-commit: 28ba942659a6fb8c8b9a22234176250fe004af06
2025-02-04 04:48:31 +00:00
Cici Huang 69f7857a7a Update the env option.
Kubernetes-commit: 8a3d0d68a20958d82f119c56036750f18bc52963
2025-02-03 18:07:23 +00:00
Marek Siarkowicz c1a2d5992c Graduate BtreeWatchCache feature gate to GA
Kubernetes-commit: e0f548183c46b1a488afa788666638b99499fb3a
2025-01-31 15:33:07 +01:00
Marek Siarkowicz 0167eb5d20 Deprecate WatchFromStorageWithoutResourceVersion
Around the 1.31 release, we discovered that a change introduced in 1.27 allowead
clients to open WATCH requests directly to etcd. This had detrimental consequences,
enabling abusive clients to bypass caching and overwhelm etcd.
Unlike the API server, etcd lacks protection against such behavior.

To mitigate this, we redirected all WATCH requests to be served from the cache.
The WatchFromStorageWithoutResourceVersion feature gate was retained as an escape hatch.
However, since we have no plans to allow direct WATCH requests to etcd again,
this flag is now obsolete.

Direct WATCH requests to etcd offer no advantage, as they don't provide stronger
consistency guarantees. WATCH operations are inherently inconsistent; unlike LIST
operations, they do not confirm the resource version with a quorum. While Kubernetes
uses the WithRequireLeader option on WATCH requests to prevent maintaining connections
to isolated etcd members, the API server provides the same level of guarantee through
its health checks, which fail if it cannot connect to etcd member.  Therefore,
the WatchFromStorageWithoutResourceVersion feature gate can be deprecated and removed.

Kubernetes-commit: 065bf2004d27e5e3f1be3c0f128347d4060d8954
2025-01-31 11:49:28 +01:00
Marek Siarkowicz 66f788143e Flip SeparateCacheWatchRPC feature gate to false and deprecate it.
Watch requests to etcd are mapped to a single stream that has a limited throughput.
By opening a lot of concurrent watch requests to single resource, users
could starve other watches from getting any events.

Separating the RPC was meant to protect the watch opened by cache.
However, as we are no longer planning to allow users to open watch directly to etcd,
the flag is not needed.

Kubernetes-commit: 4a5bbc4c159ec7d185d5fc39b95c48dbf3fab7d9
2025-01-31 11:38:58 +01:00
Abhishek Kr Srivastav 55da1afddb Additional timeout to receive all watchEvents
Kubernetes-commit: f6b527cb54e37513bbe60edb52890f3de481d000
2025-01-31 10:19:19 +05:30
Kubernetes Publisher 39a73cd3bd Merge pull request #129813 from yongruilin/golangci-featuregate-add
feat: add a lint rule to prevent Add unversioned featuregate

Kubernetes-commit: 547654a8a1da26aaf75e9506a57c210711dcaec9
2025-01-30 04:37:41 +00:00
Sean Sullivan 3b2a820e45 Websocket HTTPS proxy support
Kubernetes-commit: f73945aae56b51078318199ff2f0ecae91bc489e
2025-01-29 03:56:55 +00:00
Lukasz Szaszkiewicz 23e8a6cc2f cacher: decrease the running time of TestConsistentReadFallback
Kubernetes-commit: 601c0e359dc959bbfaf42c5d8a8a0a9a2175db74
2025-01-28 13:31:43 +01:00
Kubernetes Publisher 52f2fda3f7 Merge pull request #129596 from cici37/cvTest
Add tests for CEL library with compatible version

Kubernetes-commit: 964e5e0f192724de4c2a8e28ad8b511fd71a78b8
2025-01-27 20:41:34 +00:00
Lukasz Szaszkiewicz 8a149c9296 cacher/cacher_whitebox_test: newTestCacherWithoutSyncing allow passing a clock
Kubernetes-commit: cfd6d9a2b4476d4256959dc2ebdd517f20191ea3
2025-01-27 19:51:35 +01:00
Cici Huang 7e0cbb5924 Bump cel-go to v0.23.2.
Kubernetes-commit: c1e0443232f9c6da9119ae71e8bd7d7ef8271088
2025-01-27 18:43:12 +00:00
Kubernetes Publisher 6c0d90b944 Merge pull request #129751 from pacoxu/EfficientWatchResumption
remove GAed EfficientWatchResumption

Kubernetes-commit: 3f26d005571dc5903e7cebae33ada67986bc40f3
2025-01-27 16:36:00 +00:00
Kubernetes Publisher 2911f5b534 Merge pull request #129815 from dims/linter-to-ensure-go-cmp/cmp-is-used-only-in-tests
Linter to ensure go-cmp/cmp is used ONLY in tests

Kubernetes-commit: d36322f8d76c8e2a456e381bcc6bb43e4bbe602c
2025-01-26 00:42:24 +00:00
Davanum Srinivas 0a703e3517 Linter to ensure go-cmp/cmp is used ONLY in tests
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 4e05bc20db99ff89b2d2205218d24b9935a7fdd7
2025-01-24 17:03:29 -05:00
yongruilin ee59411d80 feat: add a lint rule to prevent Add unversioned featuregate
Kubernetes-commit: 8a0937c03467d04a25e10473e9570d2c8286cf4b
2025-01-24 11:02:16 -08:00
Kubernetes Publisher f6d3d889a6 Merge pull request #129786 from JoelSpeed/drop-netip-variables
Drop declaration of IP/CDIR type CEL variables

Kubernetes-commit: 6b7b8e89caafa8291e9992912583977e2f0c1d4c
2025-01-23 10:14:59 -08:00
Joel Speed a3f27ceda4 Drop declaration of IP/CDIR type CEL variables
Kubernetes-commit: 2b24c518b04b67070c2e6bdbeb9f8ee74eb429c8
2025-01-23 15:15:42 +00:00
Kubernetes Publisher e35b5a7595 Merge pull request #129732 from dims/switch-to-v2.6.3-of-gopkg.in/go-jose/go-jose.v2
Switch to gopkg.in/go-jose/go-jose.v2 @ v2.6.3 and github.com/coreos/go-oidc @ v2.3.0

Kubernetes-commit: a444a5bfedb2807632447bfb8350bd41fd1a3d77
2025-01-23 00:36:41 +00:00
Kubernetes Publisher cf7237e44d Merge pull request #127709 from pohly/log-client-go-rest
client-go/rest: finish context support

Kubernetes-commit: 427cd18f726be3e3c4f657258dc17a97beca92d5
2025-01-22 20:59:02 +00:00
Davanum Srinivas 736476d22b update github.com/coreos/go-oidc to v2.3.0
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: faf30b30679e51f45ed70c714a0e9937d226329a
2025-01-22 13:41:04 -05:00
Paco Xu a2ab8dc0e3 remove GAed EfficientWatchResumption since v1.24
Kubernetes-commit: 69964319d1466d39a190a634a78440247ef83316
2025-01-22 16:50:26 +08:00
Davanum Srinivas 6e7ca2c0dc Switch to gopkg.in/go-jose/go-jose.v2 @ v2.6.3
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: c9e81cd84ca12d0a60c8e11eb318c13f657217c1
2025-01-21 09:21:27 -05:00
Kubernetes Publisher 6885e995e1 Merge pull request #129538 from hzxuzhonghu/http2-clean
Cleanup: only initiate http2 server options when http2 is not disabled

Kubernetes-commit: 2c9153576ec0eef9dfb4acac591874a71ff72cbb
2025-01-20 08:35:51 +00:00
Kubernetes Publisher 0e1bb963f7 Merge pull request #129679 from pacoxu/remove-APIListChunking
remove APIListChunking which was GAed since v1.29

Kubernetes-commit: bd55d18c75f4648b934ad0b548c017c523dd705b
2025-01-17 12:35:40 +00:00
Paco Xu b66aedfe5c remove APIListChunking which was GAed since v1.29
Kubernetes-commit: 8d7aed698b772d38087103f385569ab769647923
2025-01-17 15:56:19 +08:00
Kubernetes Publisher 626adbf67c Merge pull request #129303 from sttts/sttts-vap-jsonpatch-typeresolver-tests
apiserver/admission/cel: add unit tests for JSONPatch expressions

Kubernetes-commit: a935bb769eef444f7fe087b62ee04d5a7ef44f6a
2025-01-16 20:42:22 +00:00
Kubernetes Publisher ae92d91104 Merge pull request #129628 from 249043822/br004
remove duplicate getAttrsFunc calls to reduce temporary memory allocations

Kubernetes-commit: 63cb5837ddf5a9fdc542f6f26e84a35d19caa0ec
2025-01-16 08:35:25 +00:00
Kubernetes Publisher 2387b5d4a9 Merge pull request #129633 from skitt/revert-go-difflib-go-spew
Revert to go-difflib and go-spew releases

Kubernetes-commit: 6d570c923f66a1f214d0c3ba3eddd9a0cd0fae68
2025-01-15 20:42:29 +00:00
Kubernetes Publisher 2c1a1fa4ee Merge pull request #129547 from serathius/watchcache-bypass-test-valid
Only test requests that pass validation

Kubernetes-commit: ec2e0de35a298363872897e5904501b029817af3
2025-01-15 16:34:31 +00:00
Stephen Kitt 695a3a4c4e Revert to go-difflib and go-spew releases
The last dependency pulling in the tips of go-difflib and go-spew has
reverted to the last release of both projects, so k/k can revert to
the releases too. As can be seen from the contents of vendor, this
doesn't result in any actual change in the code.

Signed-off-by: Stephen Kitt <skitt@redhat.com>

Kubernetes-commit: 3986472b3c7202716f92e586ccfaa4b4fe573dc5
2025-01-15 09:07:27 +01:00
张可10140699 e802cf6daf remove duplicate getAttrsFunc calls to reduce temporary memory allocations
Kubernetes-commit: 479ff5a02b026caec40e8262785e8ffffb42085a
2025-01-15 10:15:02 +08:00
Kubernetes Publisher cd99eadfc3 Merge pull request #129622 from dims/update-to-latest-kustomize-v5.6.0
Update to latest kustomize v5.6.0 to drop `github.com/asaskevich/govalidator`

Kubernetes-commit: 42811635adc4840a6769d7a9f7fd47be8df99c43
2025-01-15 00:35:45 +00:00
Kubernetes Publisher 37d4665f53 Merge pull request #127375 from omerap12/issue_126311
Add test for CEL reserved symbols without double underscore

Kubernetes-commit: 165da9ad0fc7e895a9b72a463062cbf754f89f2b
2025-01-14 21:26:46 +00:00
Davanum Srinivas 5f060d93ca Drop github.com/asaskevich/govalidator
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 43d86c2a3ef056789c67b0f80bd1ebfcd375a0d4
2025-01-14 13:33:54 -05:00
Omer Aplatony 7ca4de7334 lint: removed empty line
Signed-off-by: Omer Aplatony <omerap12@gmail.com>

Kubernetes-commit: c0b49120e5318202b79a28212db150079acdfb01
2025-01-14 11:42:50 +02:00
Kubernetes Publisher 76f1672b11 Merge pull request #129590 from wojtek-t/cleanup_feature_gates
Remove WatchBookmark feature gate

Kubernetes-commit: f3cbd79db7f0c86a2d3602fdff6b174543d2cf1c
2025-01-14 00:42:32 -08:00
Cici Huang 3a132bfa52 Add test for compatible version
Kubernetes-commit: e179f0e364d58681377286c76af66e6084310f02
2025-01-13 19:11:32 +00:00
Wojciech Tyczyński 30363fdd34 Remove WatchBookmark feature gate
Kubernetes-commit: a7937f5391598b50bc5d6eafdad69a462bc55dec
2025-01-13 15:54:17 +01:00
Kubernetes Publisher 5edcd3c1b7 Merge pull request #124087 from krzysdabro/tests-apiserver-options-kms
apiserver: decrease timeout for TestKMSHealthzEndpoint

Kubernetes-commit: 36d316ebc524a47d05e479b848148c1acf1cee7b
2025-01-13 08:37:10 +00:00
Kubernetes Publisher e62b626c0f Merge pull request #129443 from serathius/watchcache-proxy
Watchcache proxy

Kubernetes-commit: cace64ab7ea82d9f9aa6a4913a500fb30f92a214
2025-01-10 20:47:37 +00:00
Kubernetes Publisher 6c470468a0 Merge pull request #129439 from serathius/refactor-delegate-2
Refactor shouldDelegateList

Kubernetes-commit: 20e1944f88484284a03b6e029bb2d64f53cf3e9d
2025-01-10 20:47:36 +00:00
Marek Siarkowicz a6c0914bb9 Only test requests that pass validation
Kubernetes-commit: 1b2bacda5bd978b68a6dc704606495b29b181690
2025-01-09 12:55:45 +01:00
Zhonghu Xu 29de537bfa Cleanupï: only initiate http2 server options when http2 is not disabled
Kubernetes-commit: a2a0a7521027c2887855dcc0c16857c79f720826
2025-01-09 11:28:51 +08:00
Jon Huhn a4a670721b Fix comment typos
Kubernetes-commit: 006ebbc33a842ed102983c390892d03e908593b9
2025-01-07 21:18:10 -06:00
Marek Siarkowicz 74be087390 Extract and unify cache bypass logic by creating a CacheProxy struct
Kubernetes-commit: 4a4fc9da801f299176c7200e66224aa79b1c0817
2024-12-31 14:04:00 +01:00
Marek Siarkowicz b43177846d Refactor shouldDelegateList
Kubernetes-commit: e5a3bdb3a71575af0d165e8b08cfaba7d572b802
2024-12-31 11:57:43 +01:00
Kubernetes Publisher a2cdf2cd0f Merge pull request #129540 from serathius/test-list-cache-bypass
Test all possible combinations of input for shouldDelegateList

Kubernetes-commit: 75531ccc9ccd70f59207bd22e91938c4ba5c47da
2025-01-09 17:00:13 +00:00
Kubernetes Publisher 2241ea0052 Merge pull request #129542 from serathius/watchcache-benchmark-namespace
Add benchmarking of namespace index

Kubernetes-commit: 30de989fb57fb5921a7ae3e3203cf7ecac9cf3f0
2025-01-09 13:06:56 +00:00
Marek Siarkowicz 3c47ed7b1d Test all possible combinations of input for shouldDelegateList
Kubernetes-commit: fe895563d92f55068c6090e29dfbd21291b203d8
2024-12-31 11:42:28 +01:00
Siyuan Zhang 9bb4aa730a Refactor compatibility version code
Replace DefaultComponentGlobalsRegistry with new instance of componentGlobalsRegistry in test api server.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

move kube effective version validation out of component base.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

move DefaultComponentGlobalsRegistry out of component base.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

move ComponentGlobalsRegistry out of featuregate pkg.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

remove usage of DefaultComponentGlobalsRegistry in test files.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

change non-test DefaultKubeEffectiveVersion to use DefaultBuildEffectiveVersion.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

Restore useDefaultBuildBinaryVersion in effective version.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

rename DefaultKubeEffectiveVersion to DefaultKubeEffectiveVersionForTest.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

pass options.ComponentGlobalsRegistry into config for controller manager and scheduler.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

Pass apiserver effective version to DefaultResourceEncodingConfig.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

change statusz registry to take effective version from the components.

Signed-off-by: Siyuan Zhang <sizhang@google.com>

Address review comments

Signed-off-by: Siyuan Zhang <sizhang@google.com>

update vendor

Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: 8fc3a33454ba38783bb63de41ecf5343e2ced67c
2024-12-20 07:03:03 +00:00
Marek Siarkowicz 67ec836891 Implement streaming proto encoding
Kubernetes-commit: f5dd7107f7144c4f76ca6159c1eeddb48a12feaa
2024-12-19 12:30:39 +01:00
Dr. Stefan Schimanski ca7102a0c4 apiserver/admission/cel: add unit tests for JSONPatch expressions
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>

Kubernetes-commit: 78f9f214c02f8476b49749d23ffcd2fc312b5c39
2024-12-19 11:59:52 +01:00
Marek Siarkowicz 38b01a1f78 Streaming JSON encoder for List
Kubernetes-commit: e7c743b2ebfaed1e3132027c0369ac25b14b6f47
2024-12-19 10:38:30 +01:00
Marek Siarkowicz 8161d73803 Add benchmarking of namespace index
Kubernetes-commit: 13a21d5854855671ca0256e39b1657dacd301371
2024-11-05 10:32:59 +01:00
Kubernetes Publisher c7ea66111e Merge pull request #129441 from serathius/watchcache-benchmark
Improve benchmark to handle multiple dimensions

Kubernetes-commit: b56d38e7d47c1ca29670699d7fde9223886c0eeb
2025-01-08 16:39:45 +00:00
Kubernetes Publisher 893803dc85 Merge pull request #129440 from serathius/watchcache-extract-list-response
Extract list response struct to manage all the response fields

Kubernetes-commit: 0e78cf18d19592e63d069e9a8bd72c2e87dbee0c
2025-01-08 01:06:27 +00:00
Kubernetes Publisher 2cad252f0c Merge pull request #129430 from MadhavJivrajani/go124-webhook-regex-ut
[go1.24] webhook: alter regex to account for x509sha1 GODEBUG removal

Kubernetes-commit: c3f3fdc1aa62002a58bec1141fe69e86bbb27491
2025-01-07 00:34:43 +00:00
Kubernetes Publisher e6eb58901f Merge pull request #129349 from dims/bump-x/net-to-v0.33.0
Bump x/net to v0.33.0

Kubernetes-commit: b7ef173c59065f9a5f68eb514ef0483c6f3887ae
2025-01-06 20:41:37 +00:00
Kubernetes Publisher 006dd593ee Merge pull request #128872 from alvaroaleman/generics
Use generic btree in watchcache

Kubernetes-commit: 8f8c94a04d00e59d286fe4387197bc62c6a4f374
2025-01-03 16:41:31 +00:00
Madhav Jivrajani 7c924dc3c8 webhook: alter regex to account for x509sha1 GODEBUG removal
go1.24 removes the x509sha1 GODEBUG variable, and with it the
support for SHA-1 signed certs. This commit alters the regex
in unit tests to account for that and prep for go1.24.

Signed-off-by: Madhav Jivrajani <madhav.jiv@gmail.com>

Kubernetes-commit: cff0f4009f17c84141553c143872d47756209f4d
2024-12-30 13:39:17 -08:00
Davanum Srinivas 825f36b139 Bump x/net to v0.33.0
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 0b6e3718340fa7e3846cf9b7d5a0f7a684a6fa5a
2024-12-20 14:30:57 -05:00
Marek Siarkowicz 62c90b1dff Extract list response struct to manage all the response fields
Kubernetes-commit: 78a6402755905f14d72ee47fdb1e169dbdaa6853
2024-11-24 13:10:17 +01:00
Alvaro Aleman 84b3c4c640 Use generic btree in watchcache
This change makes us use the generic btree available in newer versions
of github.com/google/btree. This avoids a bunch of type assertions and
makes the code easier to read.

Kubernetes-commit: b1cb471982b74c13c26dbcc0f4e1b5ae92ea47e6
2024-11-19 22:04:08 -05:00
Alvaro Aleman a53d8f189c Update github.com/google/btree
Kubernetes-commit: a97ed3c98bcd2c520260aa04c516a24e975e7d69
2025-01-02 19:44:07 -05:00
Kubernetes Publisher 494066f4a4 Merge pull request #128279 from Jefftree/compat-133
Bump DefaultKubeBinaryVersion to 1.33

Kubernetes-commit: 9d82148924751d350080ffb681b4d5265aa01f6f
2024-12-21 00:32:54 +00:00
Jefftree 15b54ba29c Expand emulated version range to n-3 with 1.31 floor
Kubernetes-commit: cf28c0405c02e82e1028193a4ce1aa75d473ae8e
2024-12-10 16:34:34 +00:00
Kubernetes Publisher c7fb780f6b Merge pull request #129074 from siyuanfoundation/fgv
Add Validation to versioned feature specs.

Kubernetes-commit: 4a0b0365efd6a4c072a1545f7beed3b6664497c2
2024-12-18 06:04:08 +00:00
Siyuan Zhang 0daeb9f98b Add Validation to versioned feature specs.
Co-authored-by: Jordan Liggitt <liggitt@google.com>
Co-authored-by: Siyuan Zhang <sizhang@google.com>

Signed-off-by: Siyuan Zhang <sizhang@google.com>

Kubernetes-commit: 00dab9dffa6a35fbfaad4ebcdd17be00f40e423c
2024-12-03 18:48:07 +00:00
Kubernetes Publisher b3597c01bb Merge pull request #129205 from tosi3k/wc-configurable-retention
Configure watch cache history window based on request timeout

Kubernetes-commit: 107be8feccfce7259b402ed75415309268744a24
2024-12-17 22:05:11 +00:00
Kubernetes Publisher f5b4a60379 Merge pull request #129213 from Jefftree/k-openapi
Bump kube-openapi

Kubernetes-commit: 13eb074ddd231d127709f0410185eeca68a69c8a
2024-12-14 02:10:08 +00:00
Kubernetes Publisher 665a8df3fd Merge pull request #128343 from Jefftree/responsewriter-test
Add tests for InMemoryResponseWriter

Kubernetes-commit: c644f4d18506fb4055858646a01ec8a00802d97e
2024-12-14 02:10:06 +00:00
Jefftree 68ddbb0384 bump kube-openapi
Kubernetes-commit: 3269f4bb94c58dfe577621c42f88ea06fbdd79a7
2024-12-13 20:50:49 +00:00
Antoni Zawodny 0dcf3e9d26 Configure watch cache history window based on request timeout
Kubernetes-commit: 4a2b7ee5699331df31b7483be082c201a1e7f51f
2024-12-13 15:40:03 +01:00
Kubernetes Publisher b62222be7c Merge pull request #129195 from dims/update-x/crypto/ssh-dependency
Update x/crypto/ssh dependency to v0.31.0

Kubernetes-commit: b21ab179c74a270cd276d2dbb5f4b55730838096
2024-12-13 10:10:13 +00:00
Kubernetes Publisher 6ecac9f4d1 Merge pull request #128844 from cheftako/updateANP
Bump konnectivity-client to v0.31.1

Kubernetes-commit: f7b1d107c6127781ef2a4d11381e59198151f1e2
2024-12-13 06:04:17 +00:00
Davanum Srinivas dbfbe37046 Update x/crypto/ssh dependency
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 80735180ab2c61232dcc4646e693ddcaeaf96ca3
2024-12-12 20:46:15 -05:00
Kubernetes Publisher 988c0f82a8 Merge pull request #129054 from pohly/remove-import-name
remove import doc comments

Kubernetes-commit: e8615e27125518f0ed0ba06244b7ecee21451bb0
2024-12-12 10:07:15 +00:00
Kubernetes Publisher 0a3c89578c Merge pull request #128890 from kei01234kei/output_log_when_server_shutdown_is_failed
📝 output log when server shutdown is failed

Kubernetes-commit: 516b2c2e41799046363bf48444624bdda91bffb6
2024-12-12 06:13:13 +00:00
Kubernetes Publisher 47024d970a Merge pull request #128862 from MariamFahmy98/map-unit-tests
fix: remove duplicated unit tests in JSONPatch and ApplyConfiguration

Kubernetes-commit: 43f50b4e51302e443b4836c45666bfedbaf70406
2024-12-12 06:13:12 +00:00
Kubernetes Publisher ea0b9ced4d Merge pull request #128621 from kmala/master
update the github.com/golang-jwt/jwt/v4 dependency

Kubernetes-commit: a892f0fd80c548c4caedc35933bb441572135c35
2024-12-12 06:13:11 +00:00
Kubernetes Publisher df1723ca5c Merge pull request #127897 from modulitos/add-x509-uid-to-user
Set User.UID from x509 cert

Kubernetes-commit: ed8999ed64d4f6e05859f83456f279949bac7907
2024-12-12 06:13:09 +00:00
Kubernetes Publisher 3658357fea Merge pull request #129103 from liggitt/drop-winreadlinkvolume
Drop use of winreadlinkvolume godebug option

Kubernetes-commit: bfe431b53e600c9a36c46eef0f6ecfcf37265d60
2024-12-06 18:57:54 +00:00
Jordan Liggitt 9add4d0573 Drop use of winreadlinkvolume godebug option
Kubernetes-commit: 3046fe23d4fe4ba86713ffd61bf0e07156b2b7c3
2024-12-06 02:40:53 -05:00
Kubernetes Publisher 99abadede2 Merge pull request #129081 from stlaz/fg_remote_uid
featuregate UID in RequestHeader authenticator

Kubernetes-commit: 1504f10e7946f95a8b1da35e28e4c7453ff62775
2024-12-05 02:51:03 +00:00
Kubernetes Publisher 79e6f1fbcf Merge pull request #129083 from liggitt/go1.23windows
Revert to go1.22 windows filesystem stdlib behavior

Kubernetes-commit: 6fc64a261c1dca857a5a7fd1bc87fae38dbe1c8a
2024-12-04 22:41:51 +00:00
Jordan Liggitt aaeb01be6d Revert to go1.22 windows filesystem stdlib behavior
Kubernetes-commit: 3878a3a6de64660e356a35f70471c27a09698090
2024-12-04 09:52:56 -05:00
Stanislav Láznička 5047b8fe41 featuregate UID in RequestHeader authenticator
Kubernetes-commit: a051b067cdffc92fbe40bcc5a8e8f1bf974348c4
2024-12-04 15:44:45 +01:00
Patrick Ohly b84662911c remove import doc comments
The "// import <path>" comment has been superseded by Go modules.
We don't have to remove them, but doing so has some advantages:

- They are used inconsistently, which is confusing.
- We can then also remove the (currently broken) hack/update-vanity-imports.sh.
- Last but not least, it would be a first step towards avoiding the k8s.io domain.

This commit was generated with
   sed -i -e 's;^package \(.*\) // import.*;package \1;' $(git grep -l '^package.*// import' | grep -v 'vendor/')

Everything was included, except for
   package labels // import k8s.io/kubernetes/pkg/util/labels
because that package is marked as "read-only".

Kubernetes-commit: 8a908e0c0bd96a3455edf7e3b5f5af90564e65b0
2024-12-02 14:43:58 +01:00
Keisuke Ishigami 753940e964 📝 output log when server shutdown is failed
Kubernetes-commit: dd1300df98682f524a2f028e3b296b3e8783a711
2024-11-21 00:58:27 +09:00
Mariam Fahmy b858201395 fix: remove duplicated unit tests in JSONPatch and ApplyConfiguration
Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>

Kubernetes-commit: f87bcd9b3a8166acb62e3f39e207bda3673f0ed6
2024-11-19 15:42:29 +02:00
Walter Fender c8d9720a72 Bump konnectivity-client to v0.31.1
Bump konnectivity-client to v0.31.1
Includes a feature which allows KNP server count to be determined by
lease.

Kubernetes-commit: 588408df1cd733f1bceeb69632b010b83e1f21df
2024-11-18 14:10:03 -08:00
Kubernetes Publisher cccad306d6 Merge pull request #128722 from dims/possible-fix-for-alpha-feature-breaking-tests
Fix for alpha CI jobs failing with AllowUnsafeMalformedObjectDeletion switched on

Kubernetes-commit: 1b08de5f7f964323f1e65a7db5e861429087efe6
2024-11-09 17:17:38 +00:00
Davanum Srinivas 51b4b4971a Possible fix for alpha CI jobs failing with AllowUnsafeMalformedObjectDeletion switched on
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 9c6126e29c2dd63668c5d2320a4c26ff173fc499
2024-11-09 08:56:55 -05:00
Keerthan Reddy Mala d513755309 update the github.com/golang-jwt/jwt/v4 dependency
Kubernetes-commit: 7e977d824cf2740c4ce7f71fdaeecd39f4bb04b1
2024-11-06 11:02:32 -08:00
Marek Siarkowicz fd21d18170 Improve benchmark to handle multiple dimensions
Kubernetes-commit: 4a0578e3dee093aec23e16556ac8fb8642060362
2024-11-05 10:32:59 +01:00
Richa Banker ae08979dcc Replace StorageVersion API with aggregated discovery to fetch served resources by a peer for MVP
Co-authored-by: Joe Betz <jpbetz@google.com>

Co-authored-by: Jordan Liggitt <jordan@liggitt.net>

Kubernetes-commit: 8b2cee83c15b1fbc304123902e1bd8e8e06f0a12
2024-10-28 23:04:26 -07:00
Jefftree ada3ee1529 add test for inmemory response writer
Kubernetes-commit: bf1b9c45ea976a9e871b35b644f34ec508f3d57d
2024-10-25 20:54:18 +00:00
Lukasz Szaszkiewicz 3aea7778be storage/cacher/ready: dynamically calculate the retryAfterSeconds
retryAfterSeconds is based on the time elapsed since the state (ready, unready) was last changed.

Kubernetes-commit: 04f0bd4e83bbc0a24b8a924333544be86b252c97
2024-10-14 08:17:14 +02:00
modulitos 026bd8791b set user.DefaultInfo.UID from x509 cert
Kubernetes-commit: b577972a551ea0dbc22f29ac97f0a0e621d42e1b
2024-10-06 19:28:21 -07:00
Omer Aplatony 81ab7e0c68 Add test for CEL reserved symbols without double underscore
Signed-off-by: Omer Aplatony <omerap12@gmail.com>

Kubernetes-commit: 1b371d0d4693da66343aa7f8642a694ea318692d
2024-09-15 18:14:25 +03:00
David Mengqi Yu c9834df380 Add example in etcd override flag help text
Kubernetes-commit: 44d31af29bf442520722024f7fa58a64b44d68de
2024-09-04 12:28:53 -07:00
Patrick Ohly c2262d518b client-go/rest: backoff with context support
The BackoffManager interface sleeps without considering the caller's context,
i.e. cancellation is not supported. This alone is reason enough to deprecate it
and to replace it with an interface that supports a context parameter.

The other reason is that contextual logging needs that parameter.

Kubernetes-commit: b15a1943d51adfb8c5e0185d58d25e038c3d6ade
2024-09-02 20:18:47 +02:00
David Ashpole 6898b8387d restrict trace context propagation to system:master and system:monitoring
Kubernetes-commit: 3842d74d97d803372eb8e2d6cfc3d3d56a4c7a0d
2024-09-01 18:03:26 +00:00
Marek Siarkowicz 5a059075db Serve LISTs with exact RV and continuations from cache
Kubernetes-commit: f82c9e56d928d1028d4b298578f275a2e5e69490
2024-07-03 21:36:51 +02:00
carlory 21560784da Add quota support for PVC with VolumeAttributesClass
Signed-off-by: carlory <baofa.fan@daocloud.io>

Kubernetes-commit: 27706a0b54cadf1ec2f1f0850ac8ab8f2f1d1c5b
2024-04-18 15:31:12 +08:00
Krzysztof Dąbrowski 2146712740 apiserver: decrease timeout for TestKMSHealthzEndpoint
Kubernetes-commit: ee3e9a7bd448b26f49e07a89247276687b8a535d
2024-03-27 20:58:35 +01:00
sxllwx e6df86ea96 Fix API server crash on concurrent map iteration and write
Improve audit context handling by encapsulating event data and operations behind a structured API. Make
the Audit system more robust in concurrent environments by properly isolating mutable state. The cleaner
API simplifies interaction with audit events, improving maintainability. Encapsulation reduces bugs
by preventing direct manipulation of audit events.

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
Co-Authored-By: Jordan Liggitt <liggitt@google.com>
Co-Authored-By: sxllwx <scottwangsxll@gmail.com>

Kubernetes-commit: 75afa1e0acfb309d984be14937a06f796f220cd6
2023-10-23 20:59:40 +08:00
Jordan Liggitt 1bac1a3a1c prevent deletionTimestamp from moving into the past
Kubernetes-commit: 88090c49732ff53ce09d4872b6029e21d33361ba
2023-09-02 13:09:42 -04:00
338 changed files with 19982 additions and 6241 deletions

2
doc.go
View File

@ -14,4 +14,4 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package apiserver // import "k8s.io/apiserver"
package apiserver

139
go.mod
View File

@ -2,124 +2,125 @@
module k8s.io/apiserver
go 1.23.0
go 1.24.0
godebug default=go1.23
godebug default=go1.24
require (
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/blang/semver/v4 v4.0.0
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/coreos/go-oidc v2.3.0+incompatible
github.com/coreos/go-systemd/v22 v22.5.0
github.com/emicklei/go-restful/v3 v3.11.0
github.com/fsnotify/fsnotify v1.7.0
github.com/emicklei/go-restful/v3 v3.12.2
github.com/fsnotify/fsnotify v1.9.0
github.com/go-logr/logr v1.4.2
github.com/gogo/protobuf v1.3.2
github.com/google/btree v1.0.1
github.com/google/cel-go v0.22.0
github.com/google/gnostic-models v0.6.8
github.com/google/go-cmp v0.6.0
github.com/google/gofuzz v1.2.0
github.com/google/btree v1.1.3
github.com/google/cel-go v0.25.0
github.com/google/gnostic-models v0.7.0
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.0
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
go.etcd.io/etcd/api/v3 v3.5.16
go.etcd.io/etcd/client/pkg/v3 v3.5.16
go.etcd.io/etcd/client/v3 v3.5.16
go.etcd.io/etcd/server/v3 v3.5.16
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0
go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0
go.opentelemetry.io/otel/metric v1.28.0
go.opentelemetry.io/otel/sdk v1.28.0
go.opentelemetry.io/otel/trace v1.28.0
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
go.etcd.io/etcd/api/v3 v3.6.1
go.etcd.io/etcd/client/pkg/v3 v3.6.1
go.etcd.io/etcd/client/v3 v3.6.1
go.etcd.io/etcd/server/v3 v3.6.1
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0
go.opentelemetry.io/otel v1.35.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0
go.opentelemetry.io/otel/metric v1.35.0
go.opentelemetry.io/otel/sdk v1.34.0
go.opentelemetry.io/otel/trace v1.35.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.28.0
golang.org/x/net v0.30.0
golang.org/x/sync v0.8.0
golang.org/x/sys v0.26.0
golang.org/x/time v0.7.0
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.35.1
golang.org/x/crypto v0.36.0
golang.org/x/net v0.38.0
golang.org/x/sync v0.12.0
golang.org/x/sys v0.31.0
golang.org/x/time v0.9.0
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
google.golang.org/grpc v1.72.1
google.golang.org/protobuf v1.36.5
gopkg.in/evanphx/json-patch.v4 v4.12.0
gopkg.in/go-jose/go-jose.v2 v2.6.3
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/square/go-jose.v2 v2.6.0
k8s.io/api v0.0.0-20241108114315-3f43b5a94246
k8s.io/apimachinery v0.0.0-20241108022104-96b97de8d6ba
k8s.io/client-go v0.0.0-20241108115827-ec126553e25c
k8s.io/component-base v0.0.0-20241108123302-804c0075c12f
k8s.io/api v0.0.0-20250705010445-839e6c7fb630
k8s.io/apimachinery v0.0.0-20250710005335-ed63805e81ef
k8s.io/client-go v0.0.0-20250709010832-5439ef7b0c5e
k8s.io/component-base v0.0.0-20250708051227-72837f691197
k8s.io/klog/v2 v2.130.1
k8s.io/kms v0.0.0-20241107031913-7a7a59ea9c74
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3
sigs.k8s.io/structured-merge-diff/v4 v4.4.2
sigs.k8s.io/yaml v1.4.0
k8s.io/kms v0.0.0-20250701212550-c0cb85aa532f
k8s.io/kube-openapi v0.0.0-20250628140032-d90c4fd18f59
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8
sigs.k8s.io/randfill v1.0.0
sigs.k8s.io/structured-merge-diff/v4 v4.7.0
sigs.k8s.io/yaml v1.5.0
)
require (
cel.dev/expr v0.18.0 // indirect
cel.dev/expr v0.23.1 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 // indirect
go.etcd.io/bbolt v1.3.11 // indirect
go.etcd.io/etcd/client/v2 v2.305.16 // indirect
go.etcd.io/etcd/pkg/v3 v3.5.16 // indirect
go.etcd.io/etcd/raft/v3 v3.5.16 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.etcd.io/bbolt v1.4.0 // indirect
go.etcd.io/etcd/pkg/v3 v3.6.1 // indirect
go.etcd.io/raft/v3 v3.6.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

352
go.sum
View File

@ -1,59 +1,42 @@
cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc v2.3.0+incompatible h1:+5vEsrgprdLjjQ9FzIKAzQz1wwPD+83hQRfUIPh7rO0=
github.com/coreos/go-oidc v2.3.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -69,63 +52,52 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
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/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g=
github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY=
github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@ -133,6 +105,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
@ -140,8 +114,9 @@ github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVO
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 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
@ -150,54 +125,48 @@ github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
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/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@ -206,116 +175,97 @@ github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chq
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0=
go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28=
go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q=
go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E=
go.etcd.io/etcd/client/v2 v2.305.16 h1:kQrn9o5czVNaukf2A2At43cE9ZtWauOtf9vRZuiKXow=
go.etcd.io/etcd/client/v2 v2.305.16/go.mod h1:h9YxWCzcdvZENbfzBTFCnoNumr2ax3F19sKMqHFmXHE=
go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE=
go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50=
go.etcd.io/etcd/pkg/v3 v3.5.16 h1:cnavs5WSPWeK4TYwPYfmcr3Joz9BH+TZ6qoUtz6/+mc=
go.etcd.io/etcd/pkg/v3 v3.5.16/go.mod h1:+lutCZHG5MBBFI/U4eYT5yL7sJfnexsoM20Y0t2uNuY=
go.etcd.io/etcd/raft/v3 v3.5.16 h1:zBXA3ZUpYs1AwiLGPafYAKKl/CORn/uaxYDwlNwndAk=
go.etcd.io/etcd/raft/v3 v3.5.16/go.mod h1:P4UP14AxofMJ/54boWilabqqWoW9eLodl6I5GdGzazI=
go.etcd.io/etcd/server/v3 v3.5.16 h1:d0/SAdJ3vVsZvF8IFVb1k8zqMZ+heGcNfft71ul9GWE=
go.etcd.io/etcd/server/v3 v3.5.16/go.mod h1:ynhyZZpdDp1Gq49jkUg5mfkDWZwXnn3eIqCqtJnrD/s=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
go.etcd.io/etcd/api/v3 v3.6.1 h1:yJ9WlDih9HT457QPuHt/TH/XtsdN2tubyxyQHSHPsEo=
go.etcd.io/etcd/api/v3 v3.6.1/go.mod h1:lnfuqoGsXMlZdTJlact3IB56o3bWp1DIlXPIGKRArto=
go.etcd.io/etcd/client/pkg/v3 v3.6.1 h1:CxDVv8ggphmamrXM4Of8aCC8QHzDM4tGcVr9p2BSoGk=
go.etcd.io/etcd/client/pkg/v3 v3.6.1/go.mod h1:aTkCp+6ixcVTZmrJGa7/Mc5nMNs59PEgBbq+HCmWyMc=
go.etcd.io/etcd/client/v3 v3.6.1 h1:KelkcizJGsskUXlsxjVrSmINvMMga0VWwFF0tSPGEP0=
go.etcd.io/etcd/client/v3 v3.6.1/go.mod h1:fCbPUdjWNLfx1A6ATo9syUmFVxqHH9bCnPLBZmnLmMY=
go.etcd.io/etcd/pkg/v3 v3.6.1 h1:Qpshk3/SLra217k7FxcFGaH2niFAxFf1Dug57f0IUiw=
go.etcd.io/etcd/pkg/v3 v3.6.1/go.mod h1:nS0ahQoZZ9qXjQAtYGDt80IEHKl9YOF7mv6J0lQmBoQ=
go.etcd.io/etcd/server/v3 v3.6.1 h1:Y/mh94EeImzXyTBIMVgR0v5H+ANtRFDY4g1s5sxOZGE=
go.etcd.io/etcd/server/v3 v3.6.1/go.mod h1:nCqJGTP9c2WlZluJB59j3bqxZEI/GYBfQxno0MguVjE=
go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@ -325,67 +275,53 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw=
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.0.0-20241108114315-3f43b5a94246 h1:lTiwDILcPkCelpoYPkQ0jt8tmY0/s6Q9sM2mq2qie8g=
k8s.io/api v0.0.0-20241108114315-3f43b5a94246/go.mod h1:jw6pQTESH9mdZL2vOK3twojvpPxipl5TpLZpPyl5ZYU=
k8s.io/apimachinery v0.0.0-20241108022104-96b97de8d6ba h1:ghB5Iygt6Ge8UyIwW7C1kJx4kP7AUTCL9Qg6GCsUUOY=
k8s.io/apimachinery v0.0.0-20241108022104-96b97de8d6ba/go.mod h1:HqhdaJUgQqky29T1V0o2yFkt/pZqLFIDyn9Zi/8rxoY=
k8s.io/client-go v0.0.0-20241108115827-ec126553e25c h1:oFkwLbL3wiQ1J3kiXB3e8RekXFhWB4G3jtWxX4qz/fk=
k8s.io/client-go v0.0.0-20241108115827-ec126553e25c/go.mod h1:qdg0yiHKZF4DimKIPqdu9N9y1VLkHDn8Jtbsblkf6O0=
k8s.io/component-base v0.0.0-20241108123302-804c0075c12f h1:zBczlQ6ESDT3aiohj4+/Bl8IWFr8VX6WHXX785ovbIg=
k8s.io/component-base v0.0.0-20241108123302-804c0075c12f/go.mod h1:sML5FQmBLTD6jQvLcucPw9JohoW6PnlBvP7NBkLIYb8=
k8s.io/api v0.0.0-20250705010445-839e6c7fb630 h1:pnI9Db0bmtO4qa+X6jGK8WslPvzLwW8wrAe5B2//yGU=
k8s.io/api v0.0.0-20250705010445-839e6c7fb630/go.mod h1:cQb0K/knyMnN0b7QfEoYB+YzMbFk6PMoa/XTGxEJ7iw=
k8s.io/apimachinery v0.0.0-20250710005335-ed63805e81ef h1:87QT4Qmn87cD8y09BKqHmXrBC+eIZd9YTG2tDwkGhCc=
k8s.io/apimachinery v0.0.0-20250710005335-ed63805e81ef/go.mod h1:Th679JJyaVRDNFk3vKPKY43ypziDeoGnbEiEgBCz8s4=
k8s.io/client-go v0.0.0-20250709010832-5439ef7b0c5e h1:NGKcA9W2nQjLWlZrHfTcMPkPpjFci2M+SnmkusqoIHo=
k8s.io/client-go v0.0.0-20250709010832-5439ef7b0c5e/go.mod h1:mSlS6FavM9KR26OMw/g4NsTn4BtRSGVKE0DlKfOoE2c=
k8s.io/component-base v0.0.0-20250708051227-72837f691197 h1:HPpnKAvWicINIJb5H0yd7sMnvXjAcCeoN2j8NkIK+s8=
k8s.io/component-base v0.0.0-20250708051227-72837f691197/go.mod h1:U4cTVU7iRxFIlHEFNsrq7AYzG4lxdaliabhy0qPB/Ww=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kms v0.0.0-20241107031913-7a7a59ea9c74 h1:4Ib0RezwyOw06/9W8ACHhLDxtRCgZc0IERyyivhOp/E=
k8s.io/kms v0.0.0-20241107031913-7a7a59ea9c74/go.mod h1:SYc/vvTslZFejoOBnAF/ZLaqnmJMXVJzxWZakvq0LOg=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
k8s.io/kms v0.0.0-20250701212550-c0cb85aa532f h1:IiE5Db+Ha45v4GSmZtR4OLdkk8j7Nk/76SP1gvVAjnM=
k8s.io/kms v0.0.0-20250701212550-c0cb85aa532f/go.mod h1:qCbYSZ7AgfskxlzZlEYmu4XfrmaR8oXyYSAiwvh/fTk=
k8s.io/kube-openapi v0.0.0-20250628140032-d90c4fd18f59 h1:Jc4GiFTK2HHOpfQFoQEGXTBTs2pETwHukmoD4yoTqwo=
k8s.io/kube-openapi v0.0.0-20250628140032-d90c4fd18f59/go.mod h1:GLOk5B+hDbRROvt0X2+hqX64v/zO3vXN7J78OUmBSKw=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=

View File

@ -83,7 +83,7 @@ func ensureAnnotationGetter(a Attributes) error {
}
func (handler *auditHandler) logAnnotations(ctx context.Context, a Attributes) {
ae := audit.AuditEventFrom(ctx)
ae := audit.AuditContextFrom(ctx)
if ae == nil {
return
}
@ -91,9 +91,9 @@ func (handler *auditHandler) logAnnotations(ctx context.Context, a Attributes) {
var annotations map[string]string
switch a := a.(type) {
case privateAnnotationsGetter:
annotations = a.getAnnotations(ae.Level)
annotations = a.getAnnotations(ae.GetEventLevel())
case AnnotationsGetter:
annotations = a.GetAnnotations(ae.Level)
annotations = a.GetAnnotations(ae.GetEventLevel())
default:
// this will never happen, because we have already checked it in ensureAnnotationGetter
}

View File

@ -144,8 +144,10 @@ func TestWithAudit(t *testing.T) {
var handler Interface = fakeHandler{tc.admit, tc.admitAnnotations, tc.validate, tc.validateAnnotations, tc.handles}
ctx := audit.WithAuditContext(context.Background())
ac := audit.AuditContextFrom(ctx)
ae := &ac.Event
ae.Level = auditinternal.LevelMetadata
if err := ac.Init(audit.RequestAuditConfig{Level: auditinternal.LevelMetadata}, nil); err != nil {
t.Fatal(err)
}
auditHandler := WithAudit(handler)
a := attributes()
@ -171,9 +173,9 @@ func TestWithAudit(t *testing.T) {
annotations[k] = v
}
if len(annotations) == 0 {
assert.Nil(t, ae.Annotations, tcName+": unexptected annotations set in audit event")
assert.Nil(t, ac.GetEventAnnotations(), tcName+": unexptected annotations set in audit event")
} else {
assert.Equal(t, annotations, ae.Annotations, tcName+": unexptected annotations set in audit event")
assert.Equal(t, annotations, ac.GetEventAnnotations(), tcName+": unexptected annotations set in audit event")
}
}
}
@ -187,8 +189,6 @@ func TestWithAuditConcurrency(t *testing.T) {
}
var handler Interface = fakeHandler{admitAnnotations: admitAnnotations, handles: true}
ctx := audit.WithAuditContext(context.Background())
ac := audit.AuditContextFrom(ctx)
ac.Event.Level = auditinternal.LevelMetadata
auditHandler := WithAudit(handler)
a := attributes()
@ -200,9 +200,15 @@ func TestWithAuditConcurrency(t *testing.T) {
go func() {
defer wg.Done()
mutator, ok := handler.(MutationInterface)
require.True(t, ok)
if !ok {
t.Error("handler is not an interface of type MutationInterface")
return
}
auditMutator, ok := auditHandler.(MutationInterface)
require.True(t, ok)
if !ok {
t.Error("handler is not an interface of type MutationInterface")
return
}
assert.Equal(t, mutator.Admit(ctx, a, nil), auditMutator.Admit(ctx, a, nil), "WithAudit decorator should not effect the return value")
}()
}

View File

@ -305,6 +305,11 @@ func (m *AdmissionMetrics) ObserveWebhookRejection(ctx context.Context, name, st
m.webhookRejection.WithContext(ctx).WithLabelValues(name, stepType, operation, string(errorType), strconv.Itoa(rejectionCode)).Inc()
}
// WebhookRejectionGathererForTest exposes admission webhook rejection metric for access by unit test.
func (m *AdmissionMetrics) WebhookRejectionGathererForTest() *metrics.CounterVec {
return m.webhookRejection
}
// ObserveWebhookFailOpen records validating or mutating webhook that fail open.
func (m *AdmissionMetrics) ObserveWebhookFailOpen(ctx context.Context, name, stepType string) {
m.webhookFailOpen.WithContext(ctx).WithLabelValues(name, stepType).Inc()

View File

@ -184,6 +184,7 @@ func TestCondition(t *testing.T) {
v130 := version.MajorMinor(1, 30)
v131 := version.MajorMinor(1, 31)
v127 := version.MajorMinor(1, 27)
var nilUnstructured *unstructured.Unstructured
cases := []struct {
@ -200,6 +201,7 @@ func TestCondition(t *testing.T) {
enableSelectors bool
compatibilityVersion *version.Version
envType environment.Type
}{
{
name: "valid syntax for object",
@ -867,6 +869,52 @@ func TestCondition(t *testing.T) {
hasParamKind: false,
namespaceObject: nsObject,
},
{
name: "cel lib not recognized in version earlier than introduced version",
validations: []ExpressionAccessor{
&testCondition{
Expression: "isQuantity(\"20M\")",
},
},
attributes: newValidAttribute(&podObject, false),
results: []EvaluationResult{
{
Error: fmt.Errorf("isQuantity"),
},
},
compatibilityVersion: v127,
},
{
name: "cel lib recognized in version later than introduced version",
validations: []ExpressionAccessor{
&testCondition{
Expression: "isQuantity(\"20M\")",
},
},
results: []EvaluationResult{
{
EvalResult: celtypes.True,
},
},
attributes: newValidAttribute(&podObject, false),
compatibilityVersion: v130,
},
{
name: "cel lib always recognized in stored expression",
validations: []ExpressionAccessor{
&testCondition{
Expression: "isQuantity(\"20M\")",
},
},
attributes: newValidAttribute(&podObject, false),
results: []EvaluationResult{
{
EvalResult: celtypes.True,
},
},
envType: environment.StoredExpressions,
compatibilityVersion: version.MajorMinor(1, 2),
},
}
for _, tc := range cases {
@ -891,7 +939,11 @@ func TestCondition(t *testing.T) {
t.Fatal(err)
}
c := NewConditionCompiler(env)
f := c.CompileCondition(tc.validations, OptionalVariableDeclarations{HasParams: tc.hasParamKind, HasAuthorizer: tc.authorizer != nil, StrictCost: tc.strictCost}, environment.NewExpressions)
envType := tc.envType
if envType == "" {
envType = environment.NewExpressions
}
f := c.CompileCondition(tc.validations, OptionalVariableDeclarations{HasParams: tc.hasParamKind, HasAuthorizer: tc.authorizer != nil, StrictCost: tc.strictCost}, envType)
if f == nil {
t.Fatalf("unexpected nil validator")
}

View File

@ -199,7 +199,9 @@ func TestReconcile(t *testing.T) {
go func() {
defer wg.Done()
stopReason := myController.Run(testContext)
require.ErrorIs(t, stopReason, context.Canceled)
if !errors.Is(stopReason, context.Canceled) {
t.Errorf("expected error to be context.Canceled, but got: %v", stopReason)
}
}()
// The controller is blocked because the reconcile function sends on an
@ -255,7 +257,9 @@ func TestShutdown(t *testing.T) {
go func() {
defer wg.Done()
stopReason := myController.Run(testContext)
require.ErrorIs(t, stopReason, context.Canceled)
if !errors.Is(stopReason, context.Canceled) {
t.Errorf("expected error to be context.Canceled, but got: %v", stopReason)
}
}()
// Wait for controller and informer to start up
@ -287,7 +291,9 @@ func TestInformerNeverStarts(t *testing.T) {
go func() {
defer wg.Done()
stopReason := myController.Run(testContext)
require.ErrorIs(t, stopReason, context.DeadlineExceeded)
if !errors.Is(stopReason, context.DeadlineExceeded) {
t.Errorf("expected error to be context.Canceled, but got: %v", stopReason)
}
}()
// Wait for deadline to pass without syncing the cache
@ -335,7 +341,9 @@ func TestIgnoredUpdate(t *testing.T) {
go func() {
defer wg.Done()
stopReason := myController.Run(testContext)
require.ErrorIs(t, stopReason, context.Canceled)
if !errors.Is(stopReason, context.Canceled) {
t.Errorf("expected error to be context.Canceled, but got: %v", stopReason)
}
}()
// The controller is blocked because the reconcile function sends on an
@ -392,7 +400,9 @@ func TestReconcileRetry(t *testing.T) {
go func() {
defer wg.Done()
stopReason := myController.Run(testContext)
require.ErrorIs(t, stopReason, context.Canceled)
if !errors.Is(stopReason, context.Canceled) {
t.Errorf("expected error to be context.Canceled, but got: %v", stopReason)
}
}()
// Add object to informer

View File

@ -656,8 +656,8 @@ func TestDispatcher(t *testing.T) {
if err != nil {
t.Fatal(err)
}
informerFactory.WaitForCacheSync(ctx.Done())
informerFactory.Start(ctx.Done())
informerFactory.WaitForCacheSync(ctx.Done())
for i, h := range tc.policyHooks {
tc.policyHooks[i].ParamInformer = paramInformer
tc.policyHooks[i].ParamScope = testParamScope{}

View File

@ -46,16 +46,6 @@ func TestJSONPatch(t *testing.T) {
expectedResult runtime.Object
expectedErr string
}{
{
name: "jsonPatch with false test operation",
expression: `[
JSONPatch{op: "test", path: "/spec/replicas", value: 100},
JSONPatch{op: "replace", path: "/spec/replicas", value: 3},
]`,
gvr: deploymentGVR,
object: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{Replicas: ptr.To[int32](1)}},
expectedResult: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{Replicas: ptr.To[int32](1)}},
},
{
name: "jsonPatch with false test operation",
expression: `[

View File

@ -51,35 +51,6 @@ func TestApplyConfiguration(t *testing.T) {
expectedResult runtime.Object
expectedErr string
}{
{
name: "apply configuration add to listType=map",
expression: `Object{
spec: Object.spec{
template: Object.spec.template{
spec: Object.spec.template.spec{
volumes: [Object.spec.template.spec.volumes{
name: "y"
}]
}
}
}
}`,
gvr: deploymentGVR,
object: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{{Name: "x"}},
},
},
}},
expectedResult: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{{Name: "x"}, {Name: "y"}},
},
},
}},
},
{
name: "apply configuration add to listType=map",
expression: `Object{

View File

@ -114,7 +114,9 @@ func (a *QuotaAdmission) SetExternalKubeClientSet(client kubernetes.Interface) {
// SetExternalKubeInformerFactory registers an informer factory into QuotaAdmission
func (a *QuotaAdmission) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
a.quotaAccessor.lister = f.Core().V1().ResourceQuotas().Lister()
quotas := f.Core().V1().ResourceQuotas()
a.quotaAccessor.lister = quotas.Lister()
a.quotaAccessor.hasSynced = quotas.Informer().HasSynced
}
// SetQuotaConfiguration assigns and initializes configuration and evaluator for QuotaAdmission
@ -144,6 +146,9 @@ func (a *QuotaAdmission) ValidateInitialization() error {
if a.quotaAccessor.lister == nil {
return fmt.Errorf("missing quotaAccessor.lister")
}
if a.quotaAccessor.hasSynced == nil {
return fmt.Errorf("missing quotaAccessor.hasSynced")
}
if a.quotaConfiguration == nil {
return fmt.Errorf("missing quotaConfiguration")
}

View File

@ -16,4 +16,4 @@ limitations under the License.
// +k8s:deepcopy-gen=package
package resourcequota // import "k8s.io/apiserver/pkg/admission/plugin/resourcequota/apis/resourcequota"
package resourcequota

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=resourcequota.admission.k8s.io
// Package v1 is the v1 version of the API.
package v1 // import "k8s.io/apiserver/pkg/admission/plugin/resourcequota/apis/resourcequota/v1"
package v1

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=resourcequota.admission.k8s.io
// Package v1alpha1 is the v1alpha1 version of the API.
package v1alpha1 // import "k8s.io/apiserver/pkg/admission/plugin/resourcequota/apis/resourcequota/v1alpha1"
package v1alpha1

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=resourcequota.admission.k8s.io
// Package v1beta1 is the v1beta1 version of the API.
package v1beta1 // import "k8s.io/apiserver/pkg/admission/plugin/resourcequota/apis/resourcequota/v1beta1"
package v1beta1

View File

@ -492,16 +492,26 @@ func CheckRequest(quotas []corev1.ResourceQuota, a admission.Attributes, evaluat
// as a result, we need to measure the usage of this object for quota
// on updates, we need to subtract the previous measured usage
// if usage shows no change, just return since it has no impact on quota
deltaUsage, err := evaluator.Usage(inputObject)
inputUsage, err := evaluator.Usage(inputObject)
if err != nil {
return quotas, err
}
// ensure that usage for input object is never negative (this would mean a resource made a negative resource requirement)
if negativeUsage := quota.IsNegative(deltaUsage); len(negativeUsage) > 0 {
if negativeUsage := quota.IsNegative(inputUsage); len(negativeUsage) > 0 {
return nil, admission.NewForbidden(a, fmt.Errorf("quota usage is negative for resource(s): %s", prettyPrintResourceNames(negativeUsage)))
}
// initialize a map of delta usage for each interesting quota index.
deltaUsageIndexMap := make(map[int]corev1.ResourceList, len(interestingQuotaIndexes))
for _, index := range interestingQuotaIndexes {
deltaUsageIndexMap[index] = inputUsage
}
var deltaUsageWhenNoInterestingQuota corev1.ResourceList
if admission.Create == a.GetOperation() && len(interestingQuotaIndexes) == 0 {
deltaUsageWhenNoInterestingQuota = inputUsage
}
if admission.Update == a.GetOperation() {
prevItem := a.GetOldObject()
if prevItem == nil {
@ -511,20 +521,55 @@ func CheckRequest(quotas []corev1.ResourceQuota, a admission.Attributes, evaluat
// if we can definitively determine that this is not a case of "create on update",
// then charge based on the delta. Otherwise, bill the maximum
metadata, err := meta.Accessor(prevItem)
if err == nil && len(metadata.GetResourceVersion()) > 0 {
prevUsage, innerErr := evaluator.Usage(prevItem)
if innerErr != nil {
return quotas, innerErr
if err == nil {
if len(metadata.GetResourceVersion()) > 0 {
prevUsage, innerErr := evaluator.Usage(prevItem)
if innerErr != nil {
return quotas, innerErr
}
deltaUsage := quota.SubtractWithNonNegativeResult(inputUsage, prevUsage)
if len(interestingQuotaIndexes) == 0 {
deltaUsageWhenNoInterestingQuota = deltaUsage
}
for _, index := range interestingQuotaIndexes {
resourceQuota := quotas[index]
match, err := evaluator.Matches(&resourceQuota, prevItem)
if err != nil {
klog.ErrorS(err, "Error occurred while matching resource quota against the existing object",
"resourceQuota", resourceQuota)
return quotas, err
}
if match {
deltaUsageIndexMap[index] = deltaUsage
}
}
} else if len(interestingQuotaIndexes) == 0 {
deltaUsageWhenNoInterestingQuota = inputUsage
}
deltaUsage = quota.SubtractWithNonNegativeResult(deltaUsage, prevUsage)
}
}
// ignore items in deltaUsage with zero usage
deltaUsage = quota.RemoveZeros(deltaUsage)
// ignore items in deltaUsageIndexMap with zero usage,
// as they will not impact the quota.
for index := range deltaUsageIndexMap {
deltaUsageIndexMap[index] = quota.RemoveZeros(deltaUsageIndexMap[index])
if len(deltaUsageIndexMap[index]) == 0 {
delete(deltaUsageIndexMap, index)
}
}
// if there is no remaining non-zero usage, short-circuit and return
if len(deltaUsage) == 0 {
return quotas, nil
if len(interestingQuotaIndexes) != 0 {
if len(deltaUsageIndexMap) == 0 {
return quotas, nil
}
} else {
deltaUsage := quota.RemoveZeros(deltaUsageWhenNoInterestingQuota)
if len(deltaUsage) == 0 {
return quotas, nil
}
}
// verify that for every resource that had limited by default consumption
@ -557,22 +602,29 @@ func CheckRequest(quotas []corev1.ResourceQuota, a admission.Attributes, evaluat
for _, index := range interestingQuotaIndexes {
resourceQuota := outQuotas[index]
deltaUsage, ok := deltaUsageIndexMap[index]
if !ok {
continue
}
hardResources := quota.ResourceNames(resourceQuota.Status.Hard)
requestedUsage := quota.Mask(deltaUsage, hardResources)
newUsage := quota.Add(resourceQuota.Status.Used, requestedUsage)
maskedNewUsage := quota.Mask(newUsage, quota.ResourceNames(requestedUsage))
if allowed, exceeded := quota.LessThanOrEqual(maskedNewUsage, resourceQuota.Status.Hard); !allowed {
failedRequestedUsage := quota.Mask(requestedUsage, exceeded)
failedUsed := quota.Mask(resourceQuota.Status.Used, exceeded)
failedHard := quota.Mask(resourceQuota.Status.Hard, exceeded)
return nil, admission.NewForbidden(a,
fmt.Errorf("exceeded quota: %s, requested: %s, used: %s, limited: %s",
resourceQuota.Name,
prettyPrint(failedRequestedUsage),
prettyPrint(failedUsed),
prettyPrint(failedHard)))
if a.GetSubresource() != "status" {
maskedNewUsage := quota.Mask(newUsage, quota.ResourceNames(requestedUsage))
if allowed, exceeded := quota.LessThanOrEqual(maskedNewUsage, resourceQuota.Status.Hard); !allowed {
failedRequestedUsage := quota.Mask(requestedUsage, exceeded)
failedUsed := quota.Mask(resourceQuota.Status.Used, exceeded)
failedHard := quota.Mask(resourceQuota.Status.Hard, exceeded)
return nil, admission.NewForbidden(a,
fmt.Errorf("exceeded quota: %s, requested: %s, used: %s, limited: %s",
resourceQuota.Name,
prettyPrint(failedRequestedUsage),
prettyPrint(failedUsed),
prettyPrint(failedHard)))
}
}
// update to the new usage number

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package resourcequota enforces all incoming requests against any applied quota
// in the namespace context of the request
package resourcequota // import "k8s.io/apiserver/pkg/admission/plugin/resourcequota"
package resourcequota

View File

@ -48,6 +48,9 @@ type quotaAccessor struct {
// lister can list/get quota objects from a shared informer's cache
lister corev1listers.ResourceQuotaLister
// hasSynced indicates whether the lister has completed its initial sync
hasSynced func() bool
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
// This lets us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
// We track the lookup result here so that for repeated requests, we don't look it up very often.
@ -112,8 +115,8 @@ func (e *quotaAccessor) GetQuotas(namespace string) ([]corev1.ResourceQuota, err
return nil, fmt.Errorf("error resolving quota: %v", err)
}
// if there are no items held in our indexer, check our live-lookup LRU, if that misses, do the live lookup to prime it.
if len(items) == 0 {
// if there are no items held in our unsynced lister, check our live-lookup LRU, if that misses, do the live lookup to prime it.
if len(items) == 0 && !e.hasSynced() {
lruItemObj, ok := e.liveLookupCache.Get(namespace)
if !ok || lruItemObj.(liveLookupEntry).expiry.Before(time.Now()) {
// use singleflight.Group to avoid flooding the apiserver with repeated

View File

@ -97,6 +97,7 @@ func TestLRUCacheLookup(t *testing.T) {
accessor, _ := newQuotaAccessor()
accessor.client = kubeClient
accessor.lister = informerFactory.Core().V1().ResourceQuotas().Lister()
accessor.hasSynced = func() bool { return false }
accessor.liveLookupCache = liveLookupCache
for _, q := range tc.cacheInput {
@ -151,6 +152,7 @@ func TestGetQuotas(t *testing.T) {
accessor, _ := newQuotaAccessor()
accessor.client = kubeClient
accessor.lister = informerFactory.Core().V1().ResourceQuotas().Lister()
accessor.hasSynced = func() bool { return false }
kubeClient.AddReactor("list", "resourcequotas", func(action core.Action) (bool, runtime.Object, error) {
switch action.GetNamespace() {

View File

@ -22,16 +22,16 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
fuzz "github.com/google/gofuzz"
v1 "k8s.io/api/admissionregistration/v1"
"sigs.k8s.io/randfill"
)
func TestMutatingWebhookAccessor(t *testing.T) {
f := fuzz.New()
f := randfill.New()
for i := 0; i < 100; i++ {
t.Run(fmt.Sprintf("Run %d/100", i), func(t *testing.T) {
orig := &v1.MutatingWebhook{}
f.Fuzz(orig)
f.Fill(orig)
// zero out any accessor type specific fields not included in the accessor
orig.ReinvocationPolicy = nil
@ -72,11 +72,11 @@ func TestMutatingWebhookAccessor(t *testing.T) {
}
func TestValidatingWebhookAccessor(t *testing.T) {
f := fuzz.New()
f := randfill.New()
for i := 0; i < 100; i++ {
t.Run(fmt.Sprintf("Run %d/100", i), func(t *testing.T) {
orig := &v1.ValidatingWebhook{}
f.Fuzz(orig)
f.Fill(orig)
uid := fmt.Sprintf("test.configuration.admission/%s/0", orig.Name)
accessor := NewValidatingWebhookAccessor(uid, "test.configuration.admission", orig)
if uid != accessor.GetUID() {

View File

@ -16,4 +16,4 @@ limitations under the License.
// +k8s:deepcopy-gen=package
package webhookadmission // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
package webhookadmission

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=apiserver.config.k8s.io
// Package v1 is the v1 version of the API.
package v1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1"
package v1

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=apiserver.config.k8s.io
// Package v1alpha1 is the v1alpha1 version of the API.
package v1alpha1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
package v1alpha1

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package errors contains utilities for admission webhook specific errors
package errors // import "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
package errors

View File

@ -261,7 +261,7 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admiss
// Make the webhook request
client, err := invocation.Webhook.GetRESTClient(a.cm)
if err != nil {
return false, &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("could not get REST client: %w", err), Status: apierrors.NewBadRequest("error getting REST client")}
return false, &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("could not get REST client: %w", err), Status: apierrors.NewInternalError(err)}
}
ctx, span := tracing.Start(ctx, "Call mutating webhook",
attribute.String("configuration", configurationName),
@ -305,7 +305,7 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admiss
if se, ok := err.(*apierrors.StatusError); ok {
status = se
} else {
status = apierrors.NewBadRequest("error calling webhook")
status = apierrors.NewServiceUnavailable("error calling webhook")
}
return false, &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("failed to call webhook: %w", err), Status: status}
}
@ -335,7 +335,7 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admiss
}
patchObj, err := jsonpatch.DecodePatch(result.Patch)
if err != nil {
return false, apierrors.NewInternalError(err)
return false, &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("received undecodable patch in webhook response: %w", err), Status: apierrors.NewServiceUnavailable("error decoding patch in webhook response")}
}
if len(patchObj) == 0 {

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package mutating makes calls to mutating webhooks during the admission
// process.
package mutating // import "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
package mutating

View File

@ -26,14 +26,16 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/apiserver/pkg/endpoints/request"
clocktesting "k8s.io/utils/clock/testing"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/component-base/metrics/testutil"
clocktesting "k8s.io/utils/clock/testing"
)
// BenchmarkAdmit tests the performance cost of invoking a mutating webhook
@ -156,6 +158,9 @@ func TestAdmit(t *testing.T) {
attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels, tt.IsDryRun)
}
if len(tt.ExpectRejectionMetrics) > 0 {
admissionmetrics.Metrics.WebhookRejectionGathererForTest().Reset()
}
err = wh.Admit(context.TODO(), attr, objectInterfaces)
if tt.ExpectAllow != (err == nil) {
t.Errorf("expected allowed=%v, but got err=%v", tt.ExpectAllow, err)
@ -178,6 +183,15 @@ func TestAdmit(t *testing.T) {
t.Errorf("expected status code %d, got %d", tt.ExpectStatusCode, statusErr.ErrStatus.Code)
}
}
if len(tt.ExpectRejectionMetrics) > 0 {
expectedMetrics := `
# HELP apiserver_admission_webhook_rejection_count [ALPHA] Admission webhook rejection count, identified by name and broken out for each admission type (validating or admit) and operation. Additional labels specify an error type (calling_webhook_error or apiserver_internal_error if an error occurred; no_error otherwise) and optionally a non-zero rejection code if the webhook rejects the request with an HTTP status code (honored by the apiserver when the code is greater or equal to 400). Codes greater than 600 are truncated to 600, to keep the metrics cardinality bounded.
# TYPE apiserver_admission_webhook_rejection_count counter
` + tt.ExpectRejectionMetrics + "\n"
if err := testutil.CollectAndCompare(admissionmetrics.Metrics.WebhookRejectionGathererForTest(), strings.NewReader(expectedMetrics), "apiserver_admission_webhook_rejection_count"); err != nil {
t.Errorf("unexpected collecting result:\n%s", err)
}
}
fakeAttr, ok := attr.(*webhooktesting.FakeAttributes)
if !ok {
t.Errorf("Unexpected error, failed to convert attr to webhooktesting.FakeAttributes")

View File

@ -17,4 +17,4 @@ limitations under the License.
// Package namespace defines the utilities that are used by the webhook
// plugin to decide if a webhook should be applied to an object based on its
// namespace.
package namespace // import "k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/namespace"
package namespace

View File

@ -95,8 +95,8 @@ func (m *Matcher) GetNamespaceLabels(attr admission.Attributes) (map[string]stri
return namespace.Labels, nil
}
// MatchNamespaceSelector decideds whether the request matches the
// namespaceSelctor of the webhook. Only when they match, the webhook is called.
// MatchNamespaceSelector decides whether the request matches the
// namespaceSelector of the webhook. Only when they match, the webhook is called.
func (m *Matcher) MatchNamespaceSelector(p NamespaceSelectorProvider, attr admission.Attributes) (bool, *apierrors.StatusError) {
namespaceName := attr.GetNamespace()
if len(namespaceName) == 0 && attr.GetResource().Resource != "namespaces" {

View File

@ -17,4 +17,4 @@ limitations under the License.
// Package object defines the utilities that are used by the webhook plugin to
// decide if a webhook should run, as long as either the old object or the new
// object has labels matching the webhook config's objectSelector.
package object // import "k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/object"
package object

View File

@ -47,7 +47,7 @@ func matchObject(obj runtime.Object, selector labels.Selector) bool {
}
// MatchObjectSelector decideds whether the request matches the ObjectSelector
// MatchObjectSelector decides whether the request matches the ObjectSelector
// of the webhook. Only when they match, the webhook is called.
func (m *Matcher) MatchObjectSelector(p ObjectSelectorProvider, attr admission.Attributes) (bool, *apierrors.StatusError) {
selector, err := p.GetParsedObjectSelector()

View File

@ -36,7 +36,7 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/webhook"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/authentication/user"
utilpointer "k8s.io/utils/pointer"
"k8s.io/utils/ptr"
)
func TestVerifyAdmissionResponse(t *testing.T) {
@ -535,7 +535,7 @@ func TestCreateAdmissionObjects(t *testing.T) {
},
Object: runtime.RawExtension{Object: versionedObj},
OldObject: runtime.RawExtension{Object: versionedObjOld},
DryRun: utilpointer.BoolPtr(false),
DryRun: ptr.To(false),
Options: runtime.RawExtension{Object: &metav1.UpdateOptions{FieldManager: "foo"}},
},
}
@ -578,7 +578,7 @@ func TestCreateAdmissionObjects(t *testing.T) {
},
Object: runtime.RawExtension{Object: versionedObj},
OldObject: runtime.RawExtension{Object: versionedObjOld},
DryRun: utilpointer.BoolPtr(false),
DryRun: ptr.To(false),
Options: runtime.RawExtension{Object: &metav1.UpdateOptions{FieldManager: "foo"}},
},
}

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package request creates admissionReview request based on admission attributes.
package request // import "k8s.io/apiserver/pkg/admission/plugin/webhook/request"
package request

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package testcerts contains generated key pairs used by the unit tests of
// mutating and validating webhooks. They are for testing only.
package testcerts // import "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts"
package testcerts

View File

@ -38,6 +38,7 @@ import (
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
fakeclientset "k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
var matchEverythingRules = []registrationv1.RuleWithOperations{{
@ -224,6 +225,7 @@ type ValidatingTest struct {
ErrorContains string
ExpectAnnotations map[string]string
ExpectStatusCode int32
ExpectRejectionMetrics string
ExpectReinvokeWebhooks map[string]bool
}
@ -241,6 +243,7 @@ type MutatingTest struct {
ErrorContains string
ExpectAnnotations map[string]string
ExpectStatusCode int32
ExpectRejectionMetrics string
ExpectReinvokeWebhooks map[string]bool
}
@ -288,7 +291,8 @@ func ConvertToMutatingTestCases(tests []ValidatingTest, configurationName string
t.ExpectAnnotations[newKey] = value
delete(t.ExpectAnnotations, key)
}
r[i] = MutatingTest{t.Name, ConvertToMutatingWebhooks(t.Webhooks), t.Path, t.IsCRD, t.IsDryRun, t.AdditionalLabels, t.SkipBenchmark, t.ExpectLabels, t.ExpectAllow, t.ErrorContains, t.ExpectAnnotations, t.ExpectStatusCode, t.ExpectReinvokeWebhooks}
expectedMetrics := strings.ReplaceAll(t.ExpectRejectionMetrics, `type="validating"`, `type="admit"`)
r[i] = MutatingTest{t.Name, ConvertToMutatingWebhooks(t.Webhooks), t.Path, t.IsCRD, t.IsDryRun, t.AdditionalLabels, t.SkipBenchmark, t.ExpectLabels, t.ExpectAllow, t.ErrorContains, t.ExpectAnnotations, t.ExpectStatusCode, expectedMetrics, t.ExpectReinvokeWebhooks}
}
return r
}
@ -506,6 +510,34 @@ func NewNonMutatingTestCases(url *url.URL) []ValidatingTest {
ExpectStatusCode: http.StatusInternalServerError,
ExpectAllow: false,
},
{
Name: "match & invalid client config",
Webhooks: []registrationv1.ValidatingWebhook{{
Name: "invalidClientConfig",
ClientConfig: registrationv1.WebhookClientConfig{},
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
}},
ExpectStatusCode: http.StatusInternalServerError,
ExpectRejectionMetrics: `apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="invalidClientConfig",operation="UPDATE",rejection_code="500",type="validating"} 1`,
ErrorContains: "could not get REST client",
},
{
Name: "match & non-status error",
Webhooks: []registrationv1.ValidatingWebhook{{
Name: "nonStatusError",
ClientConfig: ccfgSVC("nonStatusError"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
}},
ExpectStatusCode: http.StatusInternalServerError,
ExpectRejectionMetrics: `apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="nonStatusError",operation="UPDATE",rejection_code="503",type="validating"} 1`,
ErrorContains: "failed to call webhook",
},
{
Name: "match & allow (url)",
Webhooks: []registrationv1.ValidatingWebhook{{
@ -897,6 +929,74 @@ func NewMutatingTestCases(url *url.URL, configurationName string) []MutatingTest
"mutation.webhook.admission.k8s.io/round_0_index_0": mutationAnnotationValue(configurationName, "invalidMutation", false),
},
},
{
Name: "match & invalid patch",
Webhooks: []registrationv1.MutatingWebhook{{
Name: "invalidPatch",
ClientConfig: ccfgSVC("invalidPatch"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
}},
ExpectStatusCode: http.StatusInternalServerError,
ErrorContains: "unexpected end of JSON input",
ExpectAnnotations: map[string]string{
"mutation.webhook.admission.k8s.io/round_0_index_0": mutationAnnotationValue(configurationName, "invalidPatch", false),
},
},
{
Name: "match & invalid patch fail open",
Webhooks: []registrationv1.MutatingWebhook{{
Name: "invalidPatch",
ClientConfig: ccfgSVC("invalidPatch"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
FailurePolicy: ptr.To(registrationv1.Ignore),
}},
ExpectAllow: true,
ExpectStatusCode: http.StatusOK,
ExpectAnnotations: map[string]string{
"failed-open.mutation.webhook.admission.k8s.io/round_0_index_0": "invalidPatch",
"mutation.webhook.admission.k8s.io/round_0_index_0": mutationAnnotationValue(configurationName, "invalidPatch", false),
},
},
{
Name: "match & invalid client config",
Webhooks: []registrationv1.MutatingWebhook{{
Name: "invalidClientConfig",
ClientConfig: registrationv1.WebhookClientConfig{},
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
}},
ExpectStatusCode: http.StatusInternalServerError,
ExpectRejectionMetrics: `apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="invalidClientConfig",operation="UPDATE",rejection_code="500",type="admit"} 1`,
ErrorContains: "could not get REST client",
ExpectAnnotations: map[string]string{
"mutation.webhook.admission.k8s.io/round_0_index_0": mutationAnnotationValue(configurationName, "invalidClientConfig", false),
},
},
{
Name: "match & non-status error",
Webhooks: []registrationv1.MutatingWebhook{{
Name: "nonStatusError",
ClientConfig: ccfgSVC("nonStatusError"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
AdmissionReviewVersions: []string{"v1beta1"},
}},
ExpectStatusCode: http.StatusInternalServerError,
ExpectRejectionMetrics: `apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="nonStatusError",operation="UPDATE",rejection_code="503",type="admit"} 1`,
ErrorContains: "failed to call webhook",
ExpectAnnotations: map[string]string{
"mutation.webhook.admission.k8s.io/round_0_index_0": mutationAnnotationValue(configurationName, "nonStatusError", false),
},
},
{
Name: "match & remove label dry run unsupported",
Webhooks: []registrationv1.MutatingWebhook{{

View File

@ -137,6 +137,16 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) {
Patch: []byte(`[{"op": "add", "path": "/metadata/labels/added", "value": "test"}]`),
},
})
case "/invalidPatch":
w.Header().Set("Content-Type", "application/json")
pt := v1beta1.PatchTypeJSONPatch
json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{
Response: &v1beta1.AdmissionResponse{
Allowed: true,
PatchType: &pt,
Patch: []byte(`[{`),
},
})
case "/invalidMutation":
w.Header().Set("Content-Type", "application/json")
pt := v1beta1.PatchTypeJSONPatch
@ -147,6 +157,11 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) {
Patch: []byte(`[{"op": "add", "CORRUPTED_KEY":}]`),
},
})
case "/nonStatusError":
hj, _ := w.(http.Hijacker)
conn, _, _ := hj.Hijack()
defer conn.Close() //nolint:errcheck
conn.Write([]byte("bad-http")) //nolint:errcheck
case "/nilResponse":
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{})

View File

@ -262,7 +262,7 @@ func (d *validatingDispatcher) callHook(ctx context.Context, h *v1.ValidatingWeb
// Make the webhook request
client, err := invocation.Webhook.GetRESTClient(d.cm)
if err != nil {
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("could not get REST client: %w", err), Status: apierrors.NewBadRequest("error getting REST client")}
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("could not get REST client: %w", err), Status: apierrors.NewInternalError(err)}
}
ctx, span := tracing.Start(ctx, "Call validating webhook",
attribute.String("configuration", invocation.Webhook.GetConfigurationName()),
@ -306,7 +306,7 @@ func (d *validatingDispatcher) callHook(ctx context.Context, h *v1.ValidatingWeb
if se, ok := err.(*apierrors.StatusError); ok {
status = se
} else {
status = apierrors.NewBadRequest("error calling webhook")
status = apierrors.NewServiceUnavailable("error calling webhook")
}
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("failed to call webhook: %w", err), Status: status}
}

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package validating makes calls to validating (i.e., non-mutating) webhooks
// during the admission process.
package validating // import "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
package validating

View File

@ -24,12 +24,14 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/apiserver/pkg/endpoints/request"
clocktesting "k8s.io/utils/clock/testing"
"k8s.io/apimachinery/pkg/api/errors"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/component-base/metrics/testutil"
clocktesting "k8s.io/utils/clock/testing"
)
// BenchmarkValidate tests that ValidatingWebhook#Validate works as expected
@ -135,6 +137,10 @@ func TestValidate(t *testing.T) {
continue
}
if len(tt.ExpectRejectionMetrics) > 0 {
admissionmetrics.Metrics.WebhookRejectionGathererForTest().Reset()
}
attr := webhooktesting.NewAttribute(ns, nil, tt.IsDryRun)
err = wh.Validate(context.TODO(), attr, objectInterfaces)
if tt.ExpectAllow != (err == nil) {
@ -149,6 +155,15 @@ func TestValidate(t *testing.T) {
if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr {
t.Errorf("%s: expected a StatusError, got %T", tt.Name, err)
}
if len(tt.ExpectRejectionMetrics) > 0 {
expectedMetrics := `
# HELP apiserver_admission_webhook_rejection_count [ALPHA] Admission webhook rejection count, identified by name and broken out for each admission type (validating or admit) and operation. Additional labels specify an error type (calling_webhook_error or apiserver_internal_error if an error occurred; no_error otherwise) and optionally a non-zero rejection code if the webhook rejects the request with an HTTP status code (honored by the apiserver when the code is greater or equal to 400). Codes greater than 600 are truncated to 600, to keep the metrics cardinality bounded.
# TYPE apiserver_admission_webhook_rejection_count counter
` + tt.ExpectRejectionMetrics + "\n"
if err := testutil.CollectAndCompare(admissionmetrics.Metrics.WebhookRejectionGathererForTest(), strings.NewReader(expectedMetrics), "apiserver_admission_webhook_rejection_count"); err != nil {
t.Errorf("unexpected collecting result:\n%s", err)
}
}
fakeAttr, ok := attr.(*webhooktesting.FakeAttributes)
if !ok {
t.Errorf("Unexpected error, failed to convert attr to webhooktesting.FakeAttributes")

View File

@ -16,4 +16,4 @@ limitations under the License.
// +groupName=apidiscovery.k8s.io
package v2 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
package v2

View File

@ -29,8 +29,8 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
"github.com/google/go-cmp/cmp"
fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/require"
"sigs.k8s.io/randfill"
)
func TestConversionRoundTrip(t *testing.T) {
@ -42,12 +42,12 @@ func TestConversionRoundTrip(t *testing.T) {
err = v2scheme.RegisterConversions(scheme)
require.NoError(t, err)
fuzzer := fuzz.NewWithSeed(2374375)
fuzzer := randfill.NewWithSeed(2374375)
// v2 -> v2beta1 -> v2
for i := 0; i < 100; i++ {
expected := &v2.APIGroupDiscoveryList{}
fuzzer.Fuzz(expected)
fuzzer.Fill(expected)
expected.TypeMeta = metav1.TypeMeta{
Kind: "APIGroupDiscoveryList",
APIVersion: "apidiscovery.k8s.io/v2",
@ -68,7 +68,7 @@ func TestConversionRoundTrip(t *testing.T) {
// v2beta1 -> v2 -> v2beta1
for i := 0; i < 100; i++ {
expected := &v2beta1.APIGroupDiscoveryList{}
fuzzer.Fuzz(expected)
fuzzer.Fill(expected)
expected.TypeMeta = metav1.TypeMeta{
Kind: "APIGroupDiscoveryList",
APIVersion: "apidiscovery.k8s.io/v2beta1",

View File

@ -16,4 +16,4 @@ limitations under the License.
// +groupName=apidiscovery.k8s.io
package v2beta1 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2beta1"
package v2beta1

View File

@ -18,4 +18,4 @@ limitations under the License.
// +groupName=apiserver.k8s.io
// Package apiserver is the internal version of the API.
package apiserver // import "k8s.io/apiserver/pkg/apis/apiserver"
package apiserver

View File

@ -213,8 +213,10 @@ func TestLoadFromData(t *testing.T) {
Type: "Webhook",
Name: "default",
Webhook: &api.WebhookConfiguration{
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
CacheAuthorizedRequests: true,
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
CacheUnauthorizedRequests: true,
},
}},
},
@ -252,8 +254,10 @@ authorizers:
Type: "Webhook",
Name: "default",
Webhook: &api.WebhookConfiguration{
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
CacheAuthorizedRequests: true,
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
CacheUnauthorizedRequests: true,
},
}},
},
@ -291,8 +295,10 @@ authorizers:
Type: "Webhook",
Name: "default",
Webhook: &api.WebhookConfiguration{
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
CacheAuthorizedRequests: true,
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
CacheUnauthorizedRequests: true,
},
}},
},

View File

@ -334,11 +334,21 @@ type WebhookConfiguration struct {
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration
// CacheAuthorizedRequests specifies whether authorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// AuthorizedTTL field.
// Default: true
CacheAuthorizedRequests bool
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration
// CacheUnauthorizedRequests specifies whether unauthorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// UnauthorizedTTL field.
// Default: true
CacheUnauthorizedRequests bool
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.

View File

@ -21,6 +21,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
)
var (
@ -53,7 +54,13 @@ func SetDefaults_WebhookConfiguration(obj *WebhookConfiguration) {
if obj.AuthorizedTTL.Duration == 0 {
obj.AuthorizedTTL.Duration = 5 * time.Minute
}
if obj.CacheAuthorizedRequests == nil {
obj.CacheAuthorizedRequests = ptr.To(true)
}
if obj.UnauthorizedTTL.Duration == 0 {
obj.UnauthorizedTTL.Duration = 30 * time.Second
}
if obj.CacheUnauthorizedRequests == nil {
obj.CacheUnauthorizedRequests = ptr.To(true)
}
}

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=apiserver.config.k8s.io
// Package v1 is the v1 version of the API.
package v1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1"
package v1

View File

@ -47,6 +47,7 @@ func init() {
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&AdmissionConfiguration{},
&AuthenticationConfiguration{},
&AuthorizationConfiguration{},
&EncryptionConfiguration{},
)

View File

@ -51,6 +51,349 @@ type AdmissionPluginConfiguration struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AuthenticationConfiguration provides versioned configuration for authentication.
type AuthenticationConfiguration struct {
metav1.TypeMeta
// jwt is a list of authenticator to authenticate Kubernetes users using
// JWT compliant tokens. The authenticator will attempt to parse a raw ID token,
// verify it's been signed by the configured issuer. The public key to verify the
// signature is discovered from the issuer's public endpoint using OIDC discovery.
// For an incoming token, each JWT authenticator will be attempted in
// the order in which it is specified in this list. Note however that
// other authenticators may run before or after the JWT authenticators.
// The specific position of JWT authenticators in relation to other
// authenticators is neither defined nor stable across releases. Since
// each JWT authenticator must have a unique issuer URL, at most one
// JWT authenticator will attempt to cryptographically validate the token.
//
// The minimum valid JWT payload must contain the following claims:
// {
// "iss": "https://issuer.example.com",
// "aud": ["audience"],
// "exp": 1234567890,
// "<username claim>": "username"
// }
JWT []JWTAuthenticator `json:"jwt"`
// If present --anonymous-auth must not be set
Anonymous *AnonymousAuthConfig `json:"anonymous,omitempty"`
}
// AnonymousAuthConfig provides the configuration for the anonymous authenticator.
type AnonymousAuthConfig struct {
Enabled bool `json:"enabled"`
// If set, anonymous auth is only allowed if the request meets one of the
// conditions.
Conditions []AnonymousAuthCondition `json:"conditions,omitempty"`
}
// AnonymousAuthCondition describes the condition under which anonymous auth
// should be enabled.
type AnonymousAuthCondition struct {
// Path for which anonymous auth is enabled.
Path string `json:"path"`
}
// JWTAuthenticator provides the configuration for a single JWT authenticator.
type JWTAuthenticator struct {
// issuer contains the basic OIDC provider connection options.
// +required
Issuer Issuer `json:"issuer"`
// claimValidationRules are rules that are applied to validate token claims to authenticate users.
// +optional
ClaimValidationRules []ClaimValidationRule `json:"claimValidationRules,omitempty"`
// claimMappings points claims of a token to be treated as user attributes.
// +required
ClaimMappings ClaimMappings `json:"claimMappings"`
// userValidationRules are rules that are applied to final user before completing authentication.
// These allow invariants to be applied to incoming identities such as preventing the
// use of the system: prefix that is commonly used by Kubernetes components.
// The validation rules are logically ANDed together and must all return true for the validation to pass.
// +optional
UserValidationRules []UserValidationRule `json:"userValidationRules,omitempty"`
}
// Issuer provides the configuration for an external provider's specific settings.
type Issuer struct {
// url points to the issuer URL in a format https://url or https://url/path.
// This must match the "iss" claim in the presented JWT, and the issuer returned from discovery.
// Same value as the --oidc-issuer-url flag.
// Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
// Required to be unique across all JWT authenticators.
// Note that egress selection configuration is not used for this network connection.
// +required
URL string `json:"url"`
// discoveryURL, if specified, overrides the URL used to fetch discovery
// information instead of using "{url}/.well-known/openid-configuration".
// The exact value specified is used, so "/.well-known/openid-configuration"
// must be included in discoveryURL if needed.
//
// The "issuer" field in the fetched discovery information must match the "issuer.url" field
// in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
// This is for scenarios where the well-known and jwks endpoints are hosted at a different
// location than the issuer (such as locally in the cluster).
//
// Example:
// A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
// and discovery information is available at '/.well-known/openid-configuration'.
// discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
// certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
// must be set to 'oidc.oidc-namespace'.
//
// curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
// {
// issuer: "https://oidc.example.com" (.url field)
// }
//
// discoveryURL must be different from url.
// Required to be unique across all JWT authenticators.
// Note that egress selection configuration is not used for this network connection.
// +optional
DiscoveryURL *string `json:"discoveryURL,omitempty"`
// certificateAuthority contains PEM-encoded certificate authority certificates
// used to validate the connection when fetching discovery information.
// If unset, the system verifier is used.
// Same value as the content of the file referenced by the --oidc-ca-file flag.
// +optional
CertificateAuthority string `json:"certificateAuthority,omitempty"`
// audiences is the set of acceptable audiences the JWT must be issued to.
// At least one of the entries must match the "aud" claim in presented JWTs.
// Same value as the --oidc-client-id flag (though this field supports an array).
// Required to be non-empty.
// +required
Audiences []string `json:"audiences"`
// audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT.
// Allowed values are:
// 1. "MatchAny" when multiple audiences are specified and
// 2. empty (or unset) or "MatchAny" when a single audience is specified.
//
// - MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
// For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both).
//
// - "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others).
//
// For more nuanced audience validation, use claimValidationRules.
// example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match.
// +optional
AudienceMatchPolicy AudienceMatchPolicyType `json:"audienceMatchPolicy,omitempty"`
}
// AudienceMatchPolicyType is a set of valid values for issuer.audienceMatchPolicy
type AudienceMatchPolicyType string
// Valid types for AudienceMatchPolicyType
const (
// MatchAny means the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
AudienceMatchPolicyMatchAny AudienceMatchPolicyType = "MatchAny"
)
// ClaimValidationRule provides the configuration for a single claim validation rule.
type ClaimValidationRule struct {
// claim is the name of a required claim.
// Same as --oidc-required-claim flag.
// Only string claim keys are supported.
// Mutually exclusive with expression and message.
// +optional
Claim string `json:"claim,omitempty"`
// requiredValue is the value of a required claim.
// Same as --oidc-required-claim flag.
// Only string claim values are supported.
// If claim is set and requiredValue is not set, the claim must be present with a value set to the empty string.
// Mutually exclusive with expression and message.
// +optional
RequiredValue string `json:"requiredValue,omitempty"`
// expression represents the expression which will be evaluated by CEL.
// Must produce a boolean.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
// Must return true for the validation to pass.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim and requiredValue.
// +optional
Expression string `json:"expression,omitempty"`
// message customizes the returned error message when expression returns false.
// message is a literal string.
// Mutually exclusive with claim and requiredValue.
// +optional
Message string `json:"message,omitempty"`
}
// ClaimMappings provides the configuration for claim mapping
type ClaimMappings struct {
// username represents an option for the username attribute.
// The claim's value must be a singular string.
// Same as the --oidc-username-claim and --oidc-username-prefix flags.
// If username.expression is set, the expression must produce a string value.
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
// An example claim validation rule expression that matches the validation automatically
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing
// the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified
// claim will be caught at runtime.
//
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
// For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config.
// For prefix:
// (1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config,
// set username.prefix=""
// (2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "<value of --oidc-issuer-url>#". For the same
// behavior using authentication config, set username.prefix="<value of issuer.url>#"
// (3) --oidc-username-prefix="<value>". For the same behavior using authentication config, set username.prefix="<value>"
// +required
Username PrefixedClaimOrExpression `json:"username"`
// groups represents an option for the groups attribute.
// The claim's value must be a string or string array claim.
// If groups.claim is set, the prefix must be specified (and can be the empty string).
// If groups.expression is set, the expression must produce a string or string array value.
// "", [], and null values are treated as the group mapping not being present.
// +optional
Groups PrefixedClaimOrExpression `json:"groups,omitempty"`
// uid represents an option for the uid attribute.
// Claim must be a singular string claim.
// If uid.expression is set, the expression must produce a string value.
// +optional
UID ClaimOrExpression `json:"uid"`
// extra represents an option for the extra attribute.
// expression must produce a string or string array value.
// If the value is empty, the extra mapping will not be present.
//
// hard-coded extra key/value
// - key: "foo"
// valueExpression: "'bar'"
// This will result in an extra attribute - foo: ["bar"]
//
// hard-coded key, value copying claim value
// - key: "foo"
// valueExpression: "claims.some_claim"
// This will result in an extra attribute - foo: [value of some_claim]
//
// hard-coded key, value derived from claim value
// - key: "admin"
// valueExpression: '(has(claims.is_admin) && claims.is_admin) ? "true":""'
// This will result in:
// - if is_admin claim is present and true, extra attribute - admin: ["true"]
// - if is_admin claim is present and false or is_admin claim is not present, no extra attribute will be added
//
// +optional
Extra []ExtraMapping `json:"extra,omitempty"`
}
// PrefixedClaimOrExpression provides the configuration for a single prefixed claim or expression.
type PrefixedClaimOrExpression struct {
// claim is the JWT claim to use.
// Mutually exclusive with expression.
// +optional
Claim string `json:"claim,omitempty"`
// prefix is prepended to claim's value to prevent clashes with existing names.
// prefix needs to be set if claim is set and can be the empty string.
// Mutually exclusive with expression.
// +optional
Prefix *string `json:"prefix,omitempty"`
// expression represents the expression which will be evaluated by CEL.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim and prefix.
// +optional
Expression string `json:"expression,omitempty"`
}
// ClaimOrExpression provides the configuration for a single claim or expression.
type ClaimOrExpression struct {
// claim is the JWT claim to use.
// Either claim or expression must be set.
// Mutually exclusive with expression.
// +optional
Claim string `json:"claim,omitempty"`
// expression represents the expression which will be evaluated by CEL.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim.
// +optional
Expression string `json:"expression,omitempty"`
}
// ExtraMapping provides the configuration for a single extra mapping.
type ExtraMapping struct {
// key is a string to use as the extra attribute key.
// key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid
// subdomain as defined by RFC 1123. All characters trailing the first "/" must
// be valid HTTP Path characters as defined by RFC 3986.
// key must be lowercase.
// Required to be unique.
// +required
Key string `json:"key"`
// valueExpression is a CEL expression to extract extra attribute value.
// valueExpression must produce a string or string array value.
// "", [], and null values are treated as the extra mapping not being present.
// Empty string values contained within a string array are filtered out.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// +required
ValueExpression string `json:"valueExpression"`
}
// UserValidationRule provides the configuration for a single user info validation rule.
type UserValidationRule struct {
// expression represents the expression which will be evaluated by CEL.
// Must return true for the validation to pass.
//
// CEL expressions have access to the contents of UserInfo, organized into CEL variable:
// - 'user' - authentication.k8s.io/v1, Kind=UserInfo object
// Refer to https://github.com/kubernetes/api/blob/release-1.28/authentication/v1/types.go#L105-L122 for the definition.
// API documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#userinfo-v1-authentication-k8s-io
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// +required
Expression string `json:"expression"`
// message customizes the returned error message when rule returns false.
// message is a literal string.
// +optional
Message string `json:"message,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AuthorizationConfiguration struct {
metav1.TypeMeta
@ -97,11 +440,23 @@ type WebhookConfiguration struct {
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration `json:"authorizedTTL"`
// CacheAuthorizedRequests specifies whether authorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// AuthorizedTTL field.
// Default: true
// +optional
CacheAuthorizedRequests *bool `json:"cacheAuthorizedRequests,omitempty"`
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration `json:"unauthorizedTTL"`
// CacheUnauthorizedRequests specifies whether unauthorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// UnauthorizedTTL field.
// Default: true
// +optional
CacheUnauthorizedRequests *bool `json:"cacheUnauthorizedRequests,omitempty"`
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.

View File

@ -67,6 +67,36 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AnonymousAuthCondition)(nil), (*apiserver.AnonymousAuthCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AnonymousAuthCondition_To_apiserver_AnonymousAuthCondition(a.(*AnonymousAuthCondition), b.(*apiserver.AnonymousAuthCondition), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AnonymousAuthCondition)(nil), (*AnonymousAuthCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AnonymousAuthCondition_To_v1_AnonymousAuthCondition(a.(*apiserver.AnonymousAuthCondition), b.(*AnonymousAuthCondition), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AnonymousAuthConfig)(nil), (*apiserver.AnonymousAuthConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AnonymousAuthConfig_To_apiserver_AnonymousAuthConfig(a.(*AnonymousAuthConfig), b.(*apiserver.AnonymousAuthConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AnonymousAuthConfig)(nil), (*AnonymousAuthConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AnonymousAuthConfig_To_v1_AnonymousAuthConfig(a.(*apiserver.AnonymousAuthConfig), b.(*AnonymousAuthConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthenticationConfiguration)(nil), (*apiserver.AuthenticationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(a.(*AuthenticationConfiguration), b.(*apiserver.AuthenticationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AuthenticationConfiguration)(nil), (*AuthenticationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AuthenticationConfiguration_To_v1_AuthenticationConfiguration(a.(*apiserver.AuthenticationConfiguration), b.(*AuthenticationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthorizationConfiguration)(nil), (*apiserver.AuthorizationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(a.(*AuthorizationConfiguration), b.(*apiserver.AuthorizationConfiguration), scope)
}); err != nil {
@ -87,6 +117,36 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimMappings)(nil), (*apiserver.ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ClaimMappings_To_apiserver_ClaimMappings(a.(*ClaimMappings), b.(*apiserver.ClaimMappings), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimMappings)(nil), (*ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimMappings_To_v1_ClaimMappings(a.(*apiserver.ClaimMappings), b.(*ClaimMappings), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimOrExpression)(nil), (*apiserver.ClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression(a.(*ClaimOrExpression), b.(*apiserver.ClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimOrExpression)(nil), (*ClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression(a.(*apiserver.ClaimOrExpression), b.(*ClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimValidationRule)(nil), (*apiserver.ClaimValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ClaimValidationRule_To_apiserver_ClaimValidationRule(a.(*ClaimValidationRule), b.(*apiserver.ClaimValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimValidationRule)(nil), (*ClaimValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimValidationRule_To_v1_ClaimValidationRule(a.(*apiserver.ClaimValidationRule), b.(*ClaimValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*EncryptionConfiguration)(nil), (*apiserver.EncryptionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(a.(*EncryptionConfiguration), b.(*apiserver.EncryptionConfiguration), scope)
}); err != nil {
@ -97,6 +157,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExtraMapping)(nil), (*apiserver.ExtraMapping)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ExtraMapping_To_apiserver_ExtraMapping(a.(*ExtraMapping), b.(*apiserver.ExtraMapping), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ExtraMapping)(nil), (*ExtraMapping)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ExtraMapping_To_v1_ExtraMapping(a.(*apiserver.ExtraMapping), b.(*ExtraMapping), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*IdentityConfiguration)(nil), (*apiserver.IdentityConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(a.(*IdentityConfiguration), b.(*apiserver.IdentityConfiguration), scope)
}); err != nil {
@ -107,6 +177,26 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Issuer)(nil), (*apiserver.Issuer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Issuer_To_apiserver_Issuer(a.(*Issuer), b.(*apiserver.Issuer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.Issuer)(nil), (*Issuer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_Issuer_To_v1_Issuer(a.(*apiserver.Issuer), b.(*Issuer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*JWTAuthenticator)(nil), (*apiserver.JWTAuthenticator)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator(a.(*JWTAuthenticator), b.(*apiserver.JWTAuthenticator), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.JWTAuthenticator)(nil), (*JWTAuthenticator)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator(a.(*apiserver.JWTAuthenticator), b.(*JWTAuthenticator), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*KMSConfiguration)(nil), (*apiserver.KMSConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(a.(*KMSConfiguration), b.(*apiserver.KMSConfiguration), scope)
}); err != nil {
@ -127,6 +217,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PrefixedClaimOrExpression)(nil), (*apiserver.PrefixedClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(a.(*PrefixedClaimOrExpression), b.(*apiserver.PrefixedClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.PrefixedClaimOrExpression)(nil), (*PrefixedClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(a.(*apiserver.PrefixedClaimOrExpression), b.(*PrefixedClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ProviderConfiguration)(nil), (*apiserver.ProviderConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(a.(*ProviderConfiguration), b.(*apiserver.ProviderConfiguration), scope)
}); err != nil {
@ -157,6 +257,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*UserValidationRule)(nil), (*apiserver.UserValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_UserValidationRule_To_apiserver_UserValidationRule(a.(*UserValidationRule), b.(*apiserver.UserValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.UserValidationRule)(nil), (*UserValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_UserValidationRule_To_v1_UserValidationRule(a.(*apiserver.UserValidationRule), b.(*UserValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*WebhookConfiguration)(nil), (*apiserver.WebhookConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_WebhookConfiguration_To_apiserver_WebhookConfiguration(a.(*WebhookConfiguration), b.(*apiserver.WebhookConfiguration), scope)
}); err != nil {
@ -254,8 +364,102 @@ func Convert_apiserver_AdmissionPluginConfiguration_To_v1_AdmissionPluginConfigu
return autoConvert_apiserver_AdmissionPluginConfiguration_To_v1_AdmissionPluginConfiguration(in, out, s)
}
func autoConvert_v1_AnonymousAuthCondition_To_apiserver_AnonymousAuthCondition(in *AnonymousAuthCondition, out *apiserver.AnonymousAuthCondition, s conversion.Scope) error {
out.Path = in.Path
return nil
}
// Convert_v1_AnonymousAuthCondition_To_apiserver_AnonymousAuthCondition is an autogenerated conversion function.
func Convert_v1_AnonymousAuthCondition_To_apiserver_AnonymousAuthCondition(in *AnonymousAuthCondition, out *apiserver.AnonymousAuthCondition, s conversion.Scope) error {
return autoConvert_v1_AnonymousAuthCondition_To_apiserver_AnonymousAuthCondition(in, out, s)
}
func autoConvert_apiserver_AnonymousAuthCondition_To_v1_AnonymousAuthCondition(in *apiserver.AnonymousAuthCondition, out *AnonymousAuthCondition, s conversion.Scope) error {
out.Path = in.Path
return nil
}
// Convert_apiserver_AnonymousAuthCondition_To_v1_AnonymousAuthCondition is an autogenerated conversion function.
func Convert_apiserver_AnonymousAuthCondition_To_v1_AnonymousAuthCondition(in *apiserver.AnonymousAuthCondition, out *AnonymousAuthCondition, s conversion.Scope) error {
return autoConvert_apiserver_AnonymousAuthCondition_To_v1_AnonymousAuthCondition(in, out, s)
}
func autoConvert_v1_AnonymousAuthConfig_To_apiserver_AnonymousAuthConfig(in *AnonymousAuthConfig, out *apiserver.AnonymousAuthConfig, s conversion.Scope) error {
out.Enabled = in.Enabled
out.Conditions = *(*[]apiserver.AnonymousAuthCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_v1_AnonymousAuthConfig_To_apiserver_AnonymousAuthConfig is an autogenerated conversion function.
func Convert_v1_AnonymousAuthConfig_To_apiserver_AnonymousAuthConfig(in *AnonymousAuthConfig, out *apiserver.AnonymousAuthConfig, s conversion.Scope) error {
return autoConvert_v1_AnonymousAuthConfig_To_apiserver_AnonymousAuthConfig(in, out, s)
}
func autoConvert_apiserver_AnonymousAuthConfig_To_v1_AnonymousAuthConfig(in *apiserver.AnonymousAuthConfig, out *AnonymousAuthConfig, s conversion.Scope) error {
out.Enabled = in.Enabled
out.Conditions = *(*[]AnonymousAuthCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_apiserver_AnonymousAuthConfig_To_v1_AnonymousAuthConfig is an autogenerated conversion function.
func Convert_apiserver_AnonymousAuthConfig_To_v1_AnonymousAuthConfig(in *apiserver.AnonymousAuthConfig, out *AnonymousAuthConfig, s conversion.Scope) error {
return autoConvert_apiserver_AnonymousAuthConfig_To_v1_AnonymousAuthConfig(in, out, s)
}
func autoConvert_v1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
if in.JWT != nil {
in, out := &in.JWT, &out.JWT
*out = make([]apiserver.JWTAuthenticator, len(*in))
for i := range *in {
if err := Convert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.JWT = nil
}
out.Anonymous = (*apiserver.AnonymousAuthConfig)(unsafe.Pointer(in.Anonymous))
return nil
}
// Convert_v1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration is an autogenerated conversion function.
func Convert_v1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
return autoConvert_v1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in, out, s)
}
func autoConvert_apiserver_AuthenticationConfiguration_To_v1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
if in.JWT != nil {
in, out := &in.JWT, &out.JWT
*out = make([]JWTAuthenticator, len(*in))
for i := range *in {
if err := Convert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.JWT = nil
}
out.Anonymous = (*AnonymousAuthConfig)(unsafe.Pointer(in.Anonymous))
return nil
}
// Convert_apiserver_AuthenticationConfiguration_To_v1_AuthenticationConfiguration is an autogenerated conversion function.
func Convert_apiserver_AuthenticationConfiguration_To_v1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_AuthenticationConfiguration_To_v1_AuthenticationConfiguration(in, out, s)
}
func autoConvert_v1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]apiserver.AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_v1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -265,7 +469,17 @@ func Convert_v1_AuthorizationConfiguration_To_apiserver_AuthorizationConfigurati
}
func autoConvert_apiserver_AuthorizationConfiguration_To_v1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_apiserver_AuthorizerConfiguration_To_v1_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -277,7 +491,15 @@ func Convert_apiserver_AuthorizationConfiguration_To_v1_AuthorizationConfigurati
func autoConvert_v1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
out.Type = apiserver.AuthorizerType(in.Type)
out.Name = in.Name
out.Webhook = (*apiserver.WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(apiserver.WebhookConfiguration)
if err := Convert_v1_WebhookConfiguration_To_apiserver_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -289,7 +511,15 @@ func Convert_v1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in
func autoConvert_apiserver_AuthorizerConfiguration_To_v1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
out.Type = string(in.Type)
out.Name = in.Name
out.Webhook = (*WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(WebhookConfiguration)
if err := Convert_apiserver_WebhookConfiguration_To_v1_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -298,6 +528,92 @@ func Convert_apiserver_AuthorizerConfiguration_To_v1_AuthorizerConfiguration(in
return autoConvert_apiserver_AuthorizerConfiguration_To_v1_AuthorizerConfiguration(in, out, s)
}
func autoConvert_v1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
if err := Convert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
return err
}
if err := Convert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
return err
}
if err := Convert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
return err
}
out.Extra = *(*[]apiserver.ExtraMapping)(unsafe.Pointer(&in.Extra))
return nil
}
// Convert_v1_ClaimMappings_To_apiserver_ClaimMappings is an autogenerated conversion function.
func Convert_v1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
return autoConvert_v1_ClaimMappings_To_apiserver_ClaimMappings(in, out, s)
}
func autoConvert_apiserver_ClaimMappings_To_v1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
return err
}
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
return err
}
if err := Convert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
return err
}
out.Extra = *(*[]ExtraMapping)(unsafe.Pointer(&in.Extra))
return nil
}
// Convert_apiserver_ClaimMappings_To_v1_ClaimMappings is an autogenerated conversion function.
func Convert_apiserver_ClaimMappings_To_v1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
return autoConvert_apiserver_ClaimMappings_To_v1_ClaimMappings(in, out, s)
}
func autoConvert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Expression = in.Expression
return nil
}
// Convert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression is an autogenerated conversion function.
func Convert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
return autoConvert_v1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in, out, s)
}
func autoConvert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Expression = in.Expression
return nil
}
// Convert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression is an autogenerated conversion function.
func Convert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
return autoConvert_apiserver_ClaimOrExpression_To_v1_ClaimOrExpression(in, out, s)
}
func autoConvert_v1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in *ClaimValidationRule, out *apiserver.ClaimValidationRule, s conversion.Scope) error {
out.Claim = in.Claim
out.RequiredValue = in.RequiredValue
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_v1_ClaimValidationRule_To_apiserver_ClaimValidationRule is an autogenerated conversion function.
func Convert_v1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in *ClaimValidationRule, out *apiserver.ClaimValidationRule, s conversion.Scope) error {
return autoConvert_v1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in, out, s)
}
func autoConvert_apiserver_ClaimValidationRule_To_v1_ClaimValidationRule(in *apiserver.ClaimValidationRule, out *ClaimValidationRule, s conversion.Scope) error {
out.Claim = in.Claim
out.RequiredValue = in.RequiredValue
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_apiserver_ClaimValidationRule_To_v1_ClaimValidationRule is an autogenerated conversion function.
func Convert_apiserver_ClaimValidationRule_To_v1_ClaimValidationRule(in *apiserver.ClaimValidationRule, out *ClaimValidationRule, s conversion.Scope) error {
return autoConvert_apiserver_ClaimValidationRule_To_v1_ClaimValidationRule(in, out, s)
}
func autoConvert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(in *EncryptionConfiguration, out *apiserver.EncryptionConfiguration, s conversion.Scope) error {
out.Resources = *(*[]apiserver.ResourceConfiguration)(unsafe.Pointer(&in.Resources))
return nil
@ -318,6 +634,28 @@ func Convert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(in
return autoConvert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(in, out, s)
}
func autoConvert_v1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
out.Key = in.Key
out.ValueExpression = in.ValueExpression
return nil
}
// Convert_v1_ExtraMapping_To_apiserver_ExtraMapping is an autogenerated conversion function.
func Convert_v1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
return autoConvert_v1_ExtraMapping_To_apiserver_ExtraMapping(in, out, s)
}
func autoConvert_apiserver_ExtraMapping_To_v1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
out.Key = in.Key
out.ValueExpression = in.ValueExpression
return nil
}
// Convert_apiserver_ExtraMapping_To_v1_ExtraMapping is an autogenerated conversion function.
func Convert_apiserver_ExtraMapping_To_v1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
return autoConvert_apiserver_ExtraMapping_To_v1_ExtraMapping(in, out, s)
}
func autoConvert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(in *IdentityConfiguration, out *apiserver.IdentityConfiguration, s conversion.Scope) error {
return nil
}
@ -336,6 +674,72 @@ func Convert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(in *api
return autoConvert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(in, out, s)
}
func autoConvert_v1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
out.URL = in.URL
if err := metav1.Convert_Pointer_string_To_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
return err
}
out.CertificateAuthority = in.CertificateAuthority
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
out.AudienceMatchPolicy = apiserver.AudienceMatchPolicyType(in.AudienceMatchPolicy)
return nil
}
// Convert_v1_Issuer_To_apiserver_Issuer is an autogenerated conversion function.
func Convert_v1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
return autoConvert_v1_Issuer_To_apiserver_Issuer(in, out, s)
}
func autoConvert_apiserver_Issuer_To_v1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
out.URL = in.URL
if err := metav1.Convert_string_To_Pointer_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
return err
}
out.CertificateAuthority = in.CertificateAuthority
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
out.AudienceMatchPolicy = AudienceMatchPolicyType(in.AudienceMatchPolicy)
return nil
}
// Convert_apiserver_Issuer_To_v1_Issuer is an autogenerated conversion function.
func Convert_apiserver_Issuer_To_v1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
return autoConvert_apiserver_Issuer_To_v1_Issuer(in, out, s)
}
func autoConvert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
if err := Convert_v1_Issuer_To_apiserver_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
return err
}
out.ClaimValidationRules = *(*[]apiserver.ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
if err := Convert_v1_ClaimMappings_To_apiserver_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
return err
}
out.UserValidationRules = *(*[]apiserver.UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
return nil
}
// Convert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator is an autogenerated conversion function.
func Convert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
return autoConvert_v1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in, out, s)
}
func autoConvert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
if err := Convert_apiserver_Issuer_To_v1_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
return err
}
out.ClaimValidationRules = *(*[]ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
if err := Convert_apiserver_ClaimMappings_To_v1_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
return err
}
out.UserValidationRules = *(*[]UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
return nil
}
// Convert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator is an autogenerated conversion function.
func Convert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
return autoConvert_apiserver_JWTAuthenticator_To_v1_JWTAuthenticator(in, out, s)
}
func autoConvert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(in *KMSConfiguration, out *apiserver.KMSConfiguration, s conversion.Scope) error {
out.APIVersion = in.APIVersion
out.Name = in.Name
@ -386,6 +790,30 @@ func Convert_apiserver_Key_To_v1_Key(in *apiserver.Key, out *Key, s conversion.S
return autoConvert_apiserver_Key_To_v1_Key(in, out, s)
}
func autoConvert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in *PrefixedClaimOrExpression, out *apiserver.PrefixedClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Prefix = (*string)(unsafe.Pointer(in.Prefix))
out.Expression = in.Expression
return nil
}
// Convert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression is an autogenerated conversion function.
func Convert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in *PrefixedClaimOrExpression, out *apiserver.PrefixedClaimOrExpression, s conversion.Scope) error {
return autoConvert_v1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in, out, s)
}
func autoConvert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(in *apiserver.PrefixedClaimOrExpression, out *PrefixedClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Prefix = (*string)(unsafe.Pointer(in.Prefix))
out.Expression = in.Expression
return nil
}
// Convert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression is an autogenerated conversion function.
func Convert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(in *apiserver.PrefixedClaimOrExpression, out *PrefixedClaimOrExpression, s conversion.Scope) error {
return autoConvert_apiserver_PrefixedClaimOrExpression_To_v1_PrefixedClaimOrExpression(in, out, s)
}
func autoConvert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(in *ProviderConfiguration, out *apiserver.ProviderConfiguration, s conversion.Scope) error {
out.AESGCM = (*apiserver.AESConfiguration)(unsafe.Pointer(in.AESGCM))
out.AESCBC = (*apiserver.AESConfiguration)(unsafe.Pointer(in.AESCBC))
@ -456,9 +884,37 @@ func Convert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(in *a
return autoConvert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(in, out, s)
}
func autoConvert_v1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_v1_UserValidationRule_To_apiserver_UserValidationRule is an autogenerated conversion function.
func Convert_v1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
return autoConvert_v1_UserValidationRule_To_apiserver_UserValidationRule(in, out, s)
}
func autoConvert_apiserver_UserValidationRule_To_v1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_apiserver_UserValidationRule_To_v1_UserValidationRule is an autogenerated conversion function.
func Convert_apiserver_UserValidationRule_To_v1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
return autoConvert_apiserver_UserValidationRule_To_v1_UserValidationRule(in, out, s)
}
func autoConvert_v1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := metav1.Convert_Pointer_bool_To_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := metav1.Convert_Pointer_bool_To_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
@ -477,7 +933,13 @@ func Convert_v1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *Webho
func autoConvert_apiserver_WebhookConfiguration_To_v1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := metav1.Convert_bool_To_Pointer_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := metav1.Convert_bool_To_Pointer_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion

View File

@ -100,6 +100,80 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AnonymousAuthCondition) DeepCopyInto(out *AnonymousAuthCondition) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnonymousAuthCondition.
func (in *AnonymousAuthCondition) DeepCopy() *AnonymousAuthCondition {
if in == nil {
return nil
}
out := new(AnonymousAuthCondition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AnonymousAuthConfig) DeepCopyInto(out *AnonymousAuthConfig) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]AnonymousAuthCondition, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnonymousAuthConfig.
func (in *AnonymousAuthConfig) DeepCopy() *AnonymousAuthConfig {
if in == nil {
return nil
}
out := new(AnonymousAuthConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthenticationConfiguration) DeepCopyInto(out *AuthenticationConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.JWT != nil {
in, out := &in.JWT, &out.JWT
*out = make([]JWTAuthenticator, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Anonymous != nil {
in, out := &in.Anonymous, &out.Anonymous
*out = new(AnonymousAuthConfig)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationConfiguration.
func (in *AuthenticationConfiguration) DeepCopy() *AuthenticationConfiguration {
if in == nil {
return nil
}
out := new(AuthenticationConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AuthenticationConfiguration) 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 *AuthorizationConfiguration) DeepCopyInto(out *AuthorizationConfiguration) {
*out = *in
@ -153,6 +227,62 @@ func (in *AuthorizerConfiguration) DeepCopy() *AuthorizerConfiguration {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
*out = *in
in.Username.DeepCopyInto(&out.Username)
in.Groups.DeepCopyInto(&out.Groups)
out.UID = in.UID
if in.Extra != nil {
in, out := &in.Extra, &out.Extra
*out = make([]ExtraMapping, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimMappings.
func (in *ClaimMappings) DeepCopy() *ClaimMappings {
if in == nil {
return nil
}
out := new(ClaimMappings)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimOrExpression) DeepCopyInto(out *ClaimOrExpression) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimOrExpression.
func (in *ClaimOrExpression) DeepCopy() *ClaimOrExpression {
if in == nil {
return nil
}
out := new(ClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimValidationRule) DeepCopyInto(out *ClaimValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimValidationRule.
func (in *ClaimValidationRule) DeepCopy() *ClaimValidationRule {
if in == nil {
return nil
}
out := new(ClaimValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EncryptionConfiguration) DeepCopyInto(out *EncryptionConfiguration) {
*out = *in
@ -185,6 +315,22 @@ func (in *EncryptionConfiguration) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtraMapping) DeepCopyInto(out *ExtraMapping) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraMapping.
func (in *ExtraMapping) DeepCopy() *ExtraMapping {
if in == nil {
return nil
}
out := new(ExtraMapping)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IdentityConfiguration) DeepCopyInto(out *IdentityConfiguration) {
*out = *in
@ -201,6 +347,60 @@ func (in *IdentityConfiguration) DeepCopy() *IdentityConfiguration {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Issuer) DeepCopyInto(out *Issuer) {
*out = *in
if in.DiscoveryURL != nil {
in, out := &in.DiscoveryURL, &out.DiscoveryURL
*out = new(string)
**out = **in
}
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 Issuer.
func (in *Issuer) DeepCopy() *Issuer {
if in == nil {
return nil
}
out := new(Issuer)
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
in.Issuer.DeepCopyInto(&out.Issuer)
if in.ClaimValidationRules != nil {
in, out := &in.ClaimValidationRules, &out.ClaimValidationRules
*out = make([]ClaimValidationRule, len(*in))
copy(*out, *in)
}
in.ClaimMappings.DeepCopyInto(&out.ClaimMappings)
if in.UserValidationRules != nil {
in, out := &in.UserValidationRules, &out.UserValidationRules
*out = make([]UserValidationRule, len(*in))
copy(*out, *in)
}
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
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KMSConfiguration) DeepCopyInto(out *KMSConfiguration) {
*out = *in
@ -243,6 +443,27 @@ func (in *Key) DeepCopy() *Key {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PrefixedClaimOrExpression) DeepCopyInto(out *PrefixedClaimOrExpression) {
*out = *in
if in.Prefix != nil {
in, out := &in.Prefix, &out.Prefix
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrefixedClaimOrExpression.
func (in *PrefixedClaimOrExpression) DeepCopy() *PrefixedClaimOrExpression {
if in == nil {
return nil
}
out := new(PrefixedClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) {
*out = *in
@ -333,11 +554,37 @@ func (in *SecretboxConfiguration) DeepCopy() *SecretboxConfiguration {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserValidationRule) DeepCopyInto(out *UserValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserValidationRule.
func (in *UserValidationRule) DeepCopy() *UserValidationRule {
if in == nil {
return nil
}
out := new(UserValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in
out.AuthorizedTTL = in.AuthorizedTTL
if in.CacheAuthorizedRequests != nil {
in, out := &in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests
*out = new(bool)
**out = **in
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if in.CacheUnauthorizedRequests != nil {
in, out := &in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests
*out = new(bool)
**out = **in
}
out.Timeout = in.Timeout
in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
if in.MatchConditions != nil {

View File

@ -20,6 +20,7 @@ import (
"time"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
@ -30,7 +31,13 @@ func SetDefaults_WebhookConfiguration(obj *WebhookConfiguration) {
if obj.AuthorizedTTL.Duration == 0 {
obj.AuthorizedTTL.Duration = 5 * time.Minute
}
if obj.CacheAuthorizedRequests == nil {
obj.CacheAuthorizedRequests = ptr.To(true)
}
if obj.UnauthorizedTTL.Duration == 0 {
obj.UnauthorizedTTL.Duration = 30 * time.Second
}
if obj.CacheUnauthorizedRequests == nil {
obj.CacheUnauthorizedRequests = ptr.To(true)
}
}

View File

@ -21,4 +21,4 @@ limitations under the License.
// +groupName=apiserver.config.k8s.io
// Package v1alpha1 is the v1alpha1 version of the API.
package v1alpha1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
package v1alpha1

View File

@ -352,7 +352,9 @@ type ClaimMappings struct {
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
// An example claim validation rule expression that matches the validation automatically
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing
// the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified
// claim will be caught at runtime.
//
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
@ -548,11 +550,23 @@ type WebhookConfiguration struct {
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration `json:"authorizedTTL"`
// CacheAuthorizedRequests specifies whether authorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// AuthorizedTTL field.
// Default: true
// +optional
CacheAuthorizedRequests *bool `json:"cacheAuthorizedRequests,omitempty"`
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration `json:"unauthorizedTTL"`
// CacheUnauthorizedRequests specifies whether unauthorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// UnauthorizedTTL field.
// Default: true
// +optional
CacheUnauthorizedRequests *bool `json:"cacheUnauthorizedRequests,omitempty"`
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.

View File

@ -429,7 +429,17 @@ func Convert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationCon
}
func autoConvert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]apiserver.AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -439,7 +449,17 @@ func Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfi
}
func autoConvert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -451,7 +471,15 @@ func Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfi
func autoConvert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
out.Type = apiserver.AuthorizerType(in.Type)
out.Name = in.Name
out.Webhook = (*apiserver.WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(apiserver.WebhookConfiguration)
if err := Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -463,7 +491,15 @@ func Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfigurati
func autoConvert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
out.Type = string(in.Type)
out.Name = in.Name
out.Webhook = (*WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(WebhookConfiguration)
if err := Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -885,7 +921,13 @@ func Convert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule(in *api
func autoConvert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := v1.Convert_Pointer_bool_To_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := v1.Convert_Pointer_bool_To_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
@ -904,7 +946,13 @@ func Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in
func autoConvert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := v1.Convert_bool_To_Pointer_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := v1.Convert_bool_To_Pointer_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion

View File

@ -547,7 +547,17 @@ func (in *UserValidationRule) DeepCopy() *UserValidationRule {
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in
out.AuthorizedTTL = in.AuthorizedTTL
if in.CacheAuthorizedRequests != nil {
in, out := &in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests
*out = new(bool)
**out = **in
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if in.CacheUnauthorizedRequests != nil {
in, out := &in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests
*out = new(bool)
**out = **in
}
out.Timeout = in.Timeout
in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
if in.MatchConditions != nil {

View File

@ -20,6 +20,7 @@ import (
"time"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
@ -30,7 +31,13 @@ func SetDefaults_WebhookConfiguration(obj *WebhookConfiguration) {
if obj.AuthorizedTTL.Duration == 0 {
obj.AuthorizedTTL.Duration = 5 * time.Minute
}
if obj.CacheAuthorizedRequests == nil {
obj.CacheAuthorizedRequests = ptr.To(true)
}
if obj.UnauthorizedTTL.Duration == 0 {
obj.UnauthorizedTTL.Duration = 30 * time.Second
}
if obj.CacheUnauthorizedRequests == nil {
obj.CacheUnauthorizedRequests = ptr.To(true)
}
}

View File

@ -20,4 +20,4 @@ limitations under the License.
// +groupName=apiserver.k8s.io
// Package v1beta1 is the v1beta1 version of the API.
package v1beta1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1beta1"
package v1beta1

View File

@ -323,7 +323,9 @@ type ClaimMappings struct {
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
// An example claim validation rule expression that matches the validation automatically
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing
// the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified
// claim will be caught at runtime.
//
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
@ -519,11 +521,23 @@ type WebhookConfiguration struct {
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration `json:"authorizedTTL"`
// CacheAuthorizedRequests specifies whether authorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// AuthorizedTTL field.
// Default: true
// +optional
CacheAuthorizedRequests *bool `json:"cacheAuthorizedRequests,omitempty"`
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration `json:"unauthorizedTTL"`
// CacheUnauthorizedRequests specifies whether unauthorized requests should be cached.
// If set to true, the TTL for cached decisions can be configured via the
// UnauthorizedTTL field.
// Default: true
// +optional
CacheUnauthorizedRequests *bool `json:"cacheUnauthorizedRequests,omitempty"`
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.

View File

@ -365,7 +365,17 @@ func Convert_apiserver_AuthenticationConfiguration_To_v1beta1_AuthenticationConf
}
func autoConvert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]apiserver.AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -375,7 +385,17 @@ func Convert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfig
}
func autoConvert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]AuthorizerConfiguration, len(*in))
for i := range *in {
if err := Convert_apiserver_AuthorizerConfiguration_To_v1beta1_AuthorizerConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Authorizers = nil
}
return nil
}
@ -387,7 +407,15 @@ func Convert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfig
func autoConvert_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
out.Type = apiserver.AuthorizerType(in.Type)
out.Name = in.Name
out.Webhook = (*apiserver.WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(apiserver.WebhookConfiguration)
if err := Convert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -399,7 +427,15 @@ func Convert_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguratio
func autoConvert_apiserver_AuthorizerConfiguration_To_v1beta1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
out.Type = string(in.Type)
out.Name = in.Name
out.Webhook = (*WebhookConfiguration)(unsafe.Pointer(in.Webhook))
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(WebhookConfiguration)
if err := Convert_apiserver_WebhookConfiguration_To_v1beta1_WebhookConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.Webhook = nil
}
return nil
}
@ -821,7 +857,13 @@ func Convert_apiserver_UserValidationRule_To_v1beta1_UserValidationRule(in *apis
func autoConvert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := v1.Convert_Pointer_bool_To_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := v1.Convert_Pointer_bool_To_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
@ -840,7 +882,13 @@ func Convert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *
func autoConvert_apiserver_WebhookConfiguration_To_v1beta1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
if err := v1.Convert_bool_To_Pointer_bool(&in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests, s); err != nil {
return err
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if err := v1.Convert_bool_To_Pointer_bool(&in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests, s); err != nil {
return err
}
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion

View File

@ -494,7 +494,17 @@ func (in *UserValidationRule) DeepCopy() *UserValidationRule {
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in
out.AuthorizedTTL = in.AuthorizedTTL
if in.CacheAuthorizedRequests != nil {
in, out := &in.CacheAuthorizedRequests, &out.CacheAuthorizedRequests
*out = new(bool)
**out = **in
}
out.UnauthorizedTTL = in.UnauthorizedTTL
if in.CacheUnauthorizedRequests != nil {
in, out := &in.CacheUnauthorizedRequests, &out.CacheUnauthorizedRequests
*out = new(bool)
**out = **in
}
out.Timeout = in.Timeout
in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
if in.MatchConditions != nil {

View File

@ -128,7 +128,7 @@ func validateIssuer(issuer api.Issuer, disallowedIssuers sets.Set[string], fldPa
func validateIssuerURL(issuerURL string, disallowedIssuers sets.Set[string], fldPath *field.Path) field.ErrorList {
if len(issuerURL) == 0 {
return field.ErrorList{field.Required(fldPath, "URL is required")}
return field.ErrorList{field.Required(fldPath, "")}
}
return validateURL(issuerURL, disallowedIssuers, fldPath)
@ -198,7 +198,7 @@ func validateAudiences(audiences []string, audienceMatchPolicy api.AudienceMatch
for i, audience := range audiences {
fldPath := fldPath.Index(i)
if len(audience) == 0 {
allErrs = append(allErrs, field.Required(fldPath, "audience can't be empty"))
allErrs = append(allErrs, field.Required(fldPath, ""))
}
if seenAudiences.Has(audience) {
allErrs = append(allErrs, field.Duplicate(fldPath, audience))
@ -364,7 +364,7 @@ func validateClaimMappings(compiler authenticationcel.Compiler, state *validatio
seenExtraKeys.Insert(mapping.Key)
if len(mapping.ValueExpression) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("valueExpression"), "valueExpression is required"))
allErrs = append(allErrs, field.Required(fldPath.Child("valueExpression"), ""))
continue
}
@ -564,7 +564,7 @@ func validateUserValidationRules(compiler authenticationcel.Compiler, state *val
fldPath := fldPath.Index(i)
if len(rule.Expression) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("expression"), "expression is required"))
allErrs = append(allErrs, field.Required(fldPath.Child("expression"), ""))
continue
}

View File

@ -35,16 +35,11 @@ import (
api "k8s.io/apiserver/pkg/apis/apiserver"
authenticationcel "k8s.io/apiserver/pkg/authentication/cel"
authorizationcel "k8s.io/apiserver/pkg/authorization/cel"
"k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
certutil "k8s.io/client-go/util/cert"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
)
func TestValidateAuthenticationConfiguration(t *testing.T) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthenticationConfiguration, true)
testCases := []struct {
name string
in *api.AuthenticationConfiguration
@ -74,7 +69,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -92,7 +87,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -119,7 +114,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -138,7 +133,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -158,7 +153,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -188,7 +183,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -213,7 +208,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
},
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -239,7 +234,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
UserValidationRules: []api.UserValidationRule{
@ -269,7 +264,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -585,6 +580,61 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
},
want: "",
},
{
name: "valid authentication configuration that uses verified email via claim validation rule",
in: &api.AuthenticationConfiguration{
JWT: []api.JWTAuthenticator{
{
Issuer: api.Issuer{
URL: "https://issuer-url",
Audiences: []string{"audience"},
},
ClaimValidationRules: []api.ClaimValidationRule{
{
// By explicitly comparing the value to true, we let type-checking see the result will be
// a boolean, and to make sure a non-boolean email_verified claim will be caught at runtime.
Expression: `claims.?email_verified.orValue(true) == true`,
},
},
// allow email claim only when email_verified is present and true
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Expression: `{claims.?email: "panda"}`,
},
},
},
},
},
want: "",
},
{
name: "valid authentication configuration that uses verified email via claim validation rule incorrectly",
in: &api.AuthenticationConfiguration{
JWT: []api.JWTAuthenticator{
{
Issuer: api.Issuer{
URL: "https://issuer-url",
Audiences: []string{"audience"},
},
ClaimValidationRules: []api.ClaimValidationRule{
{
// This expression was previously documented in the godoc for the JWT authenticator
// and was incorrect. It was changed to the above expression in the previous test case.
// Testing the old expression here to confirm it fails validation.
Expression: `claims.?email_verified.orValue(true)`,
},
},
// allow email claim only when email_verified is present and true
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Expression: `{claims.?email: "panda"}`,
},
},
},
},
},
want: `[jwt[0].claimValidationRules[0].expression: Invalid value: "claims.?email_verified.orValue(true)": must evaluate to bool, jwt[0].claimMappings.username.expression: Invalid value: "{claims.?email: \"panda\"}": claims.email_verified must be used in claimMappings.username.expression or claimMappings.extra[*].valueExpression or claimValidationRules[*].expression when claims.email is used in claimMappings.username.expression]`,
},
{
name: "valid authentication configuration",
in: &api.AuthenticationConfiguration{
@ -603,7 +653,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) {
ClaimMappings: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "sub",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
},
@ -635,7 +685,7 @@ func TestValidateIssuerURL(t *testing.T) {
{
name: "url is empty",
in: "",
want: "issuer.url: Required value: URL is required",
want: "issuer.url: Required value",
},
{
name: "url parse error",
@ -807,7 +857,7 @@ func TestValidateAudiences(t *testing.T) {
{
name: "audience is empty",
in: []string{""},
want: "issuer.audiences[0]: Required value: audience can't be empty",
want: "issuer.audiences[0]: Required value",
},
{
name: "invalid match policy with single audience",
@ -850,7 +900,7 @@ func TestValidateAudiences(t *testing.T) {
name: "multiple audiences set when structured authn feature is disabled",
in: []string{"audience1", "audience2"},
matchPolicy: "MatchAny",
want: `issuer.audiences: Invalid value: []string{"audience1", "audience2"}: multiple audiences are not supported when StructuredAuthenticationConfiguration feature gate is disabled`,
want: `issuer.audiences: Invalid value: ["audience1","audience2"]: multiple audiences are not supported when StructuredAuthenticationConfiguration feature gate is disabled`,
},
}
@ -1087,7 +1137,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Expression: "claims.username",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
structuredAuthnFeatureEnabled: true,
@ -1120,7 +1170,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Groups: api.PrefixedClaimOrExpression{
Claim: "claim",
@ -1135,11 +1185,11 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Groups: api.PrefixedClaimOrExpression{
Expression: "claims.groups",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
},
structuredAuthnFeatureEnabled: true,
@ -1150,7 +1200,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Groups: api.PrefixedClaimOrExpression{
Claim: "claim",
@ -1164,7 +1214,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Groups: api.PrefixedClaimOrExpression{
Expression: "foo.bar",
@ -1180,7 +1230,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
UID: api.ClaimOrExpression{
Claim: "claim",
@ -1195,7 +1245,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
UID: api.ClaimOrExpression{
Expression: "foo.bar",
@ -1211,7 +1261,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Extra: []api.ExtraMapping{
{Key: "", ValueExpression: "claims.extra"},
@ -1225,21 +1275,21 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Extra: []api.ExtraMapping{
{Key: "example.org/foo", ValueExpression: ""},
},
},
structuredAuthnFeatureEnabled: true,
want: `issuer.claimMappings.extra[0].valueExpression: Required value: valueExpression is required`,
want: `issuer.claimMappings.extra[0].valueExpression: Required value`,
},
{
name: "extra mapping value expression is invalid",
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Extra: []api.ExtraMapping{
{Key: "example.org/foo", ValueExpression: "foo.bar"},
@ -1267,7 +1317,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Groups: api.PrefixedClaimOrExpression{
Expression: "foo.bar",
@ -1283,7 +1333,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
UID: api.ClaimOrExpression{
Expression: "foo.bar",
@ -1299,7 +1349,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
UID: api.ClaimOrExpression{
Claim: "claim",
@ -1313,7 +1363,7 @@ func TestValidateClaimMappings(t *testing.T) {
in: api.ClaimMappings{
Username: api.PrefixedClaimOrExpression{
Claim: "claim",
Prefix: pointer.String("prefix"),
Prefix: ptr.To("prefix"),
},
Extra: []api.ExtraMapping{
{Key: "example.org/foo", ValueExpression: "claims.extra"},
@ -1605,7 +1655,7 @@ func TestValidateUserValidationRules(t *testing.T) {
name: "user info validation rule, expression is empty",
in: []api.UserValidationRule{{}},
structuredAuthnFeatureEnabled: true,
want: "issuer.userValidationRules[0].expression: Required value: expression is required",
want: "issuer.userValidationRules[0].expression: Required value",
},
{
name: "duplicate expression",

View File

@ -17,4 +17,4 @@ limitations under the License.
// +k8s:deepcopy-gen=package
// +groupName=audit.k8s.io
package audit // import "k8s.io/apiserver/pkg/apis/audit"
package audit

View File

@ -19,7 +19,7 @@ package fuzzer
import (
"strings"
fuzz "github.com/google/gofuzz"
"sigs.k8s.io/randfill"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
@ -29,9 +29,9 @@ import (
// Funcs returns the fuzzer functions for the audit api group.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(e *audit.Event, c fuzz.Continue) {
c.FuzzNoCustom(e)
switch c.RandBool() {
func(e *audit.Event, c randfill.Continue) {
c.FillNoCustom(e)
switch c.Bool() {
case true:
e.RequestObject = nil
case false:
@ -41,7 +41,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
ContentType: runtime.ContentTypeJSON,
}
}
switch c.RandBool() {
switch c.Bool() {
case true:
e.ResponseObject = nil
case false:
@ -52,8 +52,8 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
}
}
},
func(o *audit.ObjectReference, c fuzz.Continue) {
c.FuzzNoCustom(o)
func(o *audit.ObjectReference, c randfill.Continue) {
c.FillNoCustom(o)
switch c.Intn(3) {
case 0:
// core api group

View File

@ -22,4 +22,4 @@ limitations under the License.
// +groupName=audit.k8s.io
package v1 // import "k8s.io/apiserver/pkg/apis/audit/v1"
package v1

View File

@ -19,4 +19,4 @@ limitations under the License.
// package example contains an example API used to demonstrate how to create api groups. Moreover, this is
// used within tests.
package example // import "k8s.io/apiserver/pkg/apis/example"
package example

View File

@ -19,7 +19,7 @@ package fuzzer
import (
"fmt"
"github.com/google/gofuzz"
"sigs.k8s.io/randfill"
apitesting "k8s.io/apimachinery/pkg/api/apitesting"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
@ -33,9 +33,9 @@ import (
// values in a Kubernetes context.
func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *runtime.Object, c fuzz.Continue) {
func(j *runtime.Object, c randfill.Continue) {
// TODO: uncomment when round trip starts from a versioned object
if true { //c.RandBool() {
if true { // c.Bool() {
*j = &runtime.Unknown{
// We do not set TypeMeta here because it is not carried through a round trip
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
@ -44,15 +44,15 @@ func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
} else {
types := []runtime.Object{&example.Pod{}}
t := types[c.Rand.Intn(len(types))]
c.Fuzz(t)
c.Fill(t)
*j = t
}
},
func(r *runtime.RawExtension, c fuzz.Continue) {
func(r *runtime.RawExtension, c randfill.Continue) {
// Pick an arbitrary type and fuzz it
types := []runtime.Object{&example.Pod{}}
obj := types[c.Rand.Intn(len(types))]
c.Fuzz(obj)
c.Fill(obj)
// Convert the object to raw bytes
bytes, err := runtime.Encode(apitesting.TestCodec(codecs, examplev1.SchemeGroupVersion), obj)
@ -68,11 +68,11 @@ func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
func exampleFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *example.PodSpec, c fuzz.Continue) {
c.FuzzNoCustom(s)
func(s *example.PodSpec, c randfill.Continue) {
c.FillNoCustom(s)
// has a default value
ttl := int64(30)
if c.RandBool() {
if c.Bool() {
ttl = int64(c.Uint32())
}
s.TerminationGracePeriodSeconds = &ttl
@ -81,11 +81,11 @@ func exampleFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
s.SchedulerName = "default-scheduler"
}
},
func(j *example.PodPhase, c fuzz.Continue) {
func(j *example.PodPhase, c randfill.Continue) {
statuses := []example.PodPhase{"Pending", "Running", "Succeeded", "Failed", "Unknown"}
*j = statuses[c.Rand.Intn(len(statuses))]
},
func(rp *example.RestartPolicy, c fuzz.Continue) {
func(rp *example.RestartPolicy, c randfill.Continue) {
policies := []example.RestartPolicy{"Always", "Never", "OnFailure"}
*rp = policies[c.Rand.Intn(len(policies))]
},

View File

@ -22,4 +22,4 @@ limitations under the License.
// +groupName=example.apiserver.k8s.io
package v1 // import "k8s.io/apiserver/pkg/apis/example/v1"
package v1

View File

@ -138,7 +138,6 @@ message PodSpec {
optional string nodeName = 10;
// Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
// Default to false.
// +k8s:conversion-gen=false
// +optional

View File

@ -151,7 +151,6 @@ type PodSpec struct {
// +optional
NodeName string `json:"nodeName,omitempty" protobuf:"bytes,10,opt,name=nodeName"`
// Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
// Default to false.
// +k8s:conversion-gen=false
// +optional

View File

@ -21,4 +21,4 @@ limitations under the License.
// another group ("example"). This happens if a type is moved to a different
// group. It's not recommended to move types across groups, though Kubernetes
// have a few cases due to historical reasons. This package is for tests.
package example2 // import "k8s.io/apiserver/pkg/apis/example2"
package example2

View File

@ -23,4 +23,4 @@ limitations under the License.
// +groupName=example2.apiserver.k8s.io
package v1 // import "k8s.io/apiserver/pkg/apis/example2/v1"
package v1

View File

@ -73,8 +73,6 @@ var (
SuggestedFlowSchemaSystemNodeHigh, // references "node-high" priority-level
SuggestedFlowSchemaProbes, // references "exempt" priority-level
SuggestedFlowSchemaSystemLeaderElection, // references "leader-election" priority-level
SuggestedFlowSchemaWorkloadLeaderElection, // references "leader-election" priority-level
SuggestedFlowSchemaEndpointsController, // references "workload-high" priority-level
SuggestedFlowSchemaKubeControllerManager, // references "workload-high" priority-level
SuggestedFlowSchemaKubeScheduler, // references "workload-high" priority-level
SuggestedFlowSchemaKubeSystemServiceAccounts, // references "workload-high" priority-level
@ -310,52 +308,6 @@ var (
},
},
)
// We add an explicit rule for endpoint-controller with high precedence
// to ensure that those calls won't get caught by the following
// <workload-leader-election> flow-schema.
//
// TODO(#80289): Get rid of this rule once we get rid of support for
// using endpoints and configmaps objects for leader election.
SuggestedFlowSchemaEndpointsController = newFlowSchema(
"endpoint-controller", "workload-high", 150,
flowcontrol.FlowDistinguisherMethodByUserType,
flowcontrol.PolicyRulesWithSubjects{
Subjects: append(
users(user.KubeControllerManager),
kubeSystemServiceAccount("endpoint-controller", "endpointslicemirroring-controller")...),
ResourceRules: []flowcontrol.ResourcePolicyRule{
resourceRule(
[]string{"get", "create", "update"},
[]string{corev1.GroupName},
[]string{"endpoints"},
[]string{flowcontrol.NamespaceEvery},
false),
},
},
)
// TODO(#80289): Get rid of this rule once we get rid of support for
// using endpoints and configmaps objects for leader election.
SuggestedFlowSchemaWorkloadLeaderElection = newFlowSchema(
"workload-leader-election", "leader-election", 200,
flowcontrol.FlowDistinguisherMethodByUserType,
flowcontrol.PolicyRulesWithSubjects{
Subjects: kubeSystemServiceAccount(flowcontrol.NameAll),
ResourceRules: []flowcontrol.ResourcePolicyRule{
resourceRule(
[]string{"get", "create", "update"},
[]string{corev1.GroupName},
[]string{"endpoints", "configmaps"},
[]string{flowcontrol.NamespaceEvery},
false),
resourceRule(
[]string{"get", "create", "update"},
[]string{coordinationv1.GroupName},
[]string{"leases"},
[]string{flowcontrol.NamespaceEvery},
false),
},
},
)
SuggestedFlowSchemaSystemNodeHigh = newFlowSchema(
"system-node-high", "node-high", 400,
flowcontrol.FlowDistinguisherMethodByUserType,

View File

@ -18,10 +18,18 @@ package audit
import (
"context"
"errors"
"maps"
"sync"
"sync/atomic"
"time"
authnv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authentication/user"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/klog/v2"
)
@ -35,22 +43,223 @@ const auditKey key = iota
// AuditContext holds the information for constructing the audit events for the current request.
type AuditContext struct {
// RequestAuditConfig is the audit configuration that applies to the request
RequestAuditConfig RequestAuditConfig
// initialized indicates whether requestAuditConfig and sink have been populated and are safe to read unguarded.
// This should only be set via Init().
initialized atomic.Bool
// requestAuditConfig is the audit configuration that applies to the request.
// This should only be written via Init(RequestAuditConfig, Sink), and only read when initialized.Load() is true.
requestAuditConfig RequestAuditConfig
// sink is the sink to use when processing event stages.
// This should only be written via Init(RequestAuditConfig, Sink), and only read when initialized.Load() is true.
sink Sink
// Event is the audit Event object that is being captured to be written in
// lock guards event
lock sync.Mutex
// event is the audit Event object that is being captured to be written in
// the API audit log.
Event auditinternal.Event
event auditinternal.Event
// annotationMutex guards event.Annotations
annotationMutex sync.Mutex
// unguarded copy of auditID from the event
auditID atomic.Value
}
// Enabled checks whether auditing is enabled for this audit context.
func (ac *AuditContext) Enabled() bool {
// Note: An unset Level should be considered Enabled, so that request data (e.g. annotations)
// can still be captured before the audit policy is evaluated.
return ac != nil && ac.RequestAuditConfig.Level != auditinternal.LevelNone
if ac == nil {
// protect against nil pointers
return false
}
if !ac.initialized.Load() {
// Note: An unset Level should be considered Enabled, so that request data (e.g. annotations)
// can still be captured before the audit policy is evaluated.
return true
}
return ac.requestAuditConfig.Level != auditinternal.LevelNone
}
func (ac *AuditContext) Init(requestAuditConfig RequestAuditConfig, sink Sink) error {
ac.lock.Lock()
defer ac.lock.Unlock()
if ac.initialized.Load() {
return errors.New("audit context was already initialized")
}
ac.requestAuditConfig = requestAuditConfig
ac.sink = sink
ac.event.Level = requestAuditConfig.Level
ac.initialized.Store(true)
return nil
}
func (ac *AuditContext) AuditID() types.UID {
// return the unguarded copy of the auditID
id, _ := ac.auditID.Load().(types.UID)
return id
}
func (ac *AuditContext) visitEvent(f func(event *auditinternal.Event)) {
ac.lock.Lock()
defer ac.lock.Unlock()
f(&ac.event)
}
// ProcessEventStage returns true on success, false if there was an error processing the stage.
func (ac *AuditContext) ProcessEventStage(ctx context.Context, stage auditinternal.Stage) bool {
if ac == nil || !ac.initialized.Load() {
return true
}
if ac.sink == nil {
return true
}
for _, omitStage := range ac.requestAuditConfig.OmitStages {
if stage == omitStage {
return true
}
}
processed := false
ac.visitEvent(func(event *auditinternal.Event) {
event.Stage = stage
if stage == auditinternal.StageRequestReceived {
event.StageTimestamp = event.RequestReceivedTimestamp
} else {
event.StageTimestamp = metav1.NewMicroTime(time.Now())
}
ObserveEvent(ctx)
processed = ac.sink.ProcessEvents(event)
})
return processed
}
func (ac *AuditContext) LogImpersonatedUser(user user.Info) {
ac.visitEvent(func(ev *auditinternal.Event) {
if ev == nil || ev.Level.Less(auditinternal.LevelMetadata) {
return
}
ev.ImpersonatedUser = &authnv1.UserInfo{
Username: user.GetName(),
}
ev.ImpersonatedUser.Groups = user.GetGroups()
ev.ImpersonatedUser.UID = user.GetUID()
ev.ImpersonatedUser.Extra = map[string]authnv1.ExtraValue{}
for k, v := range user.GetExtra() {
ev.ImpersonatedUser.Extra[k] = authnv1.ExtraValue(v)
}
})
}
func (ac *AuditContext) LogResponseObject(status *metav1.Status, obj *runtime.Unknown) {
ac.visitEvent(func(ae *auditinternal.Event) {
if status != nil {
// selectively copy the bounded fields.
ae.ResponseStatus = &metav1.Status{
Status: status.Status,
Message: status.Message,
Reason: status.Reason,
Details: status.Details,
Code: status.Code,
}
}
if ae.Level.Less(auditinternal.LevelRequestResponse) {
return
}
ae.ResponseObject = obj
})
}
// LogRequestPatch fills in the given patch as the request object into an audit event.
func (ac *AuditContext) LogRequestPatch(patch []byte) {
ac.visitEvent(func(ae *auditinternal.Event) {
ae.RequestObject = &runtime.Unknown{
Raw: patch,
ContentType: runtime.ContentTypeJSON,
}
})
}
func (ac *AuditContext) GetEventAnnotation(key string) (string, bool) {
var val string
var ok bool
ac.visitEvent(func(event *auditinternal.Event) {
val, ok = event.Annotations[key]
})
return val, ok
}
func (ac *AuditContext) GetEventLevel() auditinternal.Level {
var level auditinternal.Level
ac.visitEvent(func(event *auditinternal.Event) {
level = event.Level
})
return level
}
func (ac *AuditContext) SetEventStage(stage auditinternal.Stage) {
ac.visitEvent(func(event *auditinternal.Event) {
event.Stage = stage
})
}
func (ac *AuditContext) GetEventStage() auditinternal.Stage {
var stage auditinternal.Stage
ac.visitEvent(func(event *auditinternal.Event) {
stage = event.Stage
})
return stage
}
func (ac *AuditContext) SetEventStageTimestamp(timestamp metav1.MicroTime) {
ac.visitEvent(func(event *auditinternal.Event) {
event.StageTimestamp = timestamp
})
}
func (ac *AuditContext) GetEventResponseStatus() *metav1.Status {
var status *metav1.Status
ac.visitEvent(func(event *auditinternal.Event) {
status = event.ResponseStatus
})
return status
}
func (ac *AuditContext) GetEventRequestReceivedTimestamp() metav1.MicroTime {
var timestamp metav1.MicroTime
ac.visitEvent(func(event *auditinternal.Event) {
timestamp = event.RequestReceivedTimestamp
})
return timestamp
}
func (ac *AuditContext) GetEventStageTimestamp() metav1.MicroTime {
var timestamp metav1.MicroTime
ac.visitEvent(func(event *auditinternal.Event) {
timestamp = event.StageTimestamp
})
return timestamp
}
func (ac *AuditContext) SetEventResponseStatus(status *metav1.Status) {
ac.visitEvent(func(event *auditinternal.Event) {
event.ResponseStatus = status
})
}
func (ac *AuditContext) SetEventResponseStatusCode(statusCode int32) {
ac.visitEvent(func(event *auditinternal.Event) {
if event.ResponseStatus == nil {
event.ResponseStatus = &metav1.Status{}
}
event.ResponseStatus.Code = statusCode
})
}
func (ac *AuditContext) GetEventAnnotations() map[string]string {
var annotations map[string]string
ac.visitEvent(func(event *auditinternal.Event) {
annotations = maps.Clone(event.Annotations)
})
return annotations
}
// AddAuditAnnotation sets the audit annotation for the given key, value pair.
@ -66,8 +275,8 @@ func AddAuditAnnotation(ctx context.Context, key, value string) {
return
}
ac.annotationMutex.Lock()
defer ac.annotationMutex.Unlock()
ac.lock.Lock()
defer ac.lock.Unlock()
addAuditAnnotationLocked(ac, key, value)
}
@ -81,8 +290,8 @@ func AddAuditAnnotations(ctx context.Context, keysAndValues ...string) {
return
}
ac.annotationMutex.Lock()
defer ac.annotationMutex.Unlock()
ac.lock.Lock()
defer ac.lock.Unlock()
if len(keysAndValues)%2 != 0 {
klog.Errorf("Dropping mismatched audit annotation %q", keysAndValues[len(keysAndValues)-1])
@ -100,8 +309,8 @@ func AddAuditAnnotationsMap(ctx context.Context, annotations map[string]string)
return
}
ac.annotationMutex.Lock()
defer ac.annotationMutex.Unlock()
ac.lock.Lock()
defer ac.lock.Unlock()
for k, v := range annotations {
addAuditAnnotationLocked(ac, k, v)
@ -110,8 +319,7 @@ func AddAuditAnnotationsMap(ctx context.Context, annotations map[string]string)
// addAuditAnnotationLocked records the audit annotation on the event.
func addAuditAnnotationLocked(ac *AuditContext, key, value string) {
ae := &ac.Event
ae := &ac.event
if ae.Annotations == nil {
ae.Annotations = make(map[string]string)
}
@ -128,15 +336,11 @@ func WithAuditContext(parent context.Context) context.Context {
return parent // Avoid double registering.
}
return genericapirequest.WithValue(parent, auditKey, &AuditContext{})
}
// AuditEventFrom returns the audit event struct on the ctx
func AuditEventFrom(ctx context.Context) *auditinternal.Event {
if ac := AuditContextFrom(ctx); ac.Enabled() {
return &ac.Event
}
return nil
return genericapirequest.WithValue(parent, auditKey, &AuditContext{
event: auditinternal.Event{
Stage: auditinternal.StageResponseStarted,
},
})
}
// AuditContextFrom returns the pair of the audit configuration object
@ -154,7 +358,10 @@ func WithAuditID(ctx context.Context, auditID types.UID) {
return
}
if ac := AuditContextFrom(ctx); ac != nil {
ac.Event.AuditID = auditID
ac.visitEvent(func(event *auditinternal.Event) {
ac.auditID.Store(auditID)
event.AuditID = auditID
})
}
}
@ -162,7 +369,8 @@ func WithAuditID(ctx context.Context, auditID types.UID) {
// auditing is enabled.
func AuditIDFrom(ctx context.Context) (types.UID, bool) {
if ac := AuditContextFrom(ctx); ac != nil {
return ac.Event.AuditID, true
id, _ := ac.auditID.Load().(types.UID)
return id, true
}
return "", false
}

View File

@ -40,16 +40,34 @@ func TestEnabled(t *testing.T) {
ctx: &AuditContext{},
expectEnabled: true, // An AuditContext should be considered enabled before the level is set
}, {
name: "level None",
ctx: &AuditContext{RequestAuditConfig: RequestAuditConfig{Level: auditinternal.LevelNone}},
name: "level None",
ctx: func() *AuditContext {
ctx := &AuditContext{}
if err := ctx.Init(RequestAuditConfig{Level: auditinternal.LevelNone}, nil); err != nil {
t.Fatal(err)
}
return ctx
}(),
expectEnabled: false,
}, {
name: "level Metadata",
ctx: &AuditContext{RequestAuditConfig: RequestAuditConfig{Level: auditinternal.LevelMetadata}},
name: "level Metadata",
ctx: func() *AuditContext {
ctx := &AuditContext{}
if err := ctx.Init(RequestAuditConfig{Level: auditinternal.LevelMetadata}, nil); err != nil {
t.Fatal(err)
}
return ctx
}(),
expectEnabled: true,
}, {
name: "level RequestResponse",
ctx: &AuditContext{RequestAuditConfig: RequestAuditConfig{Level: auditinternal.LevelRequestResponse}},
name: "level RequestResponse",
ctx: func() *AuditContext {
ctx := &AuditContext{}
if err := ctx.Init(RequestAuditConfig{Level: auditinternal.LevelRequestResponse}, nil); err != nil {
t.Fatal(err)
}
return ctx
}(),
expectEnabled: true,
}}
@ -72,7 +90,7 @@ func TestAddAuditAnnotation(t *testing.T) {
assert.Len(t, annotations, numAnnotations)
}
ctxWithAnnotation := withAuditContextAndLevel(context.Background(), auditinternal.LevelMetadata)
ctxWithAnnotation := withAuditContextAndLevel(context.Background(), t, auditinternal.LevelMetadata)
AddAuditAnnotation(ctxWithAnnotation, fmt.Sprintf(annotationKeyTemplate, 0), annotationExtraValue)
tests := []struct {
@ -89,28 +107,28 @@ func TestAddAuditAnnotation(t *testing.T) {
// Annotations should be retained.
ctx: WithAuditContext(context.Background()),
validator: func(t *testing.T, ctx context.Context) {
ev := AuditContextFrom(ctx).Event
ev := AuditContextFrom(ctx).event
expectAnnotations(t, ev.Annotations)
},
}, {
description: "with metadata level",
ctx: withAuditContextAndLevel(context.Background(), auditinternal.LevelMetadata),
ctx: withAuditContextAndLevel(context.Background(), t, auditinternal.LevelMetadata),
validator: func(t *testing.T, ctx context.Context) {
ev := AuditContextFrom(ctx).Event
ev := AuditContextFrom(ctx).event
expectAnnotations(t, ev.Annotations)
},
}, {
description: "with none level",
ctx: withAuditContextAndLevel(context.Background(), auditinternal.LevelNone),
ctx: withAuditContextAndLevel(context.Background(), t, auditinternal.LevelNone),
validator: func(t *testing.T, ctx context.Context) {
ev := AuditContextFrom(ctx).Event
ev := AuditContextFrom(ctx).event
assert.Empty(t, ev.Annotations)
},
}, {
description: "with overlapping annotations",
ctx: ctxWithAnnotation,
validator: func(t *testing.T, ctx context.Context) {
ev := AuditContextFrom(ctx).Event
ev := AuditContextFrom(ctx).event
expectAnnotations(t, ev.Annotations)
// Verify that the pre-existing annotation is not overwritten.
assert.Equal(t, annotationExtraValue, ev.Annotations[fmt.Sprintf(annotationKeyTemplate, 0)])
@ -144,8 +162,8 @@ func TestAuditAnnotationsWithAuditLoggingSetup(t *testing.T) {
AddAuditAnnotation(ctx, "before-evaluation", "1")
// policy evaluated, audit logging enabled
if ac := AuditContextFrom(ctx); ac != nil {
ac.RequestAuditConfig.Level = auditinternal.LevelMetadata
if err := AuditContextFrom(ctx).Init(RequestAuditConfig{Level: auditinternal.LevelMetadata}, nil); err != nil {
t.Fatal(err)
}
AddAuditAnnotation(ctx, "after-evaluation", "2")
@ -153,13 +171,14 @@ func TestAuditAnnotationsWithAuditLoggingSetup(t *testing.T) {
"before-evaluation": "1",
"after-evaluation": "2",
}
actual := AuditContextFrom(ctx).Event.Annotations
actual := AuditContextFrom(ctx).event.Annotations
assert.Equal(t, expected, actual)
}
func withAuditContextAndLevel(ctx context.Context, l auditinternal.Level) context.Context {
func withAuditContextAndLevel(ctx context.Context, t *testing.T, l auditinternal.Level) context.Context {
ctx = WithAuditContext(ctx)
ac := AuditContextFrom(ctx)
ac.RequestAuditConfig.Level = l
if err := AuditContextFrom(ctx).Init(RequestAuditConfig{Level: l}, nil); err != nil {
t.Fatal(err)
}
return ctx
}

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/utils/ptr"
)
var (
@ -359,10 +360,6 @@ func TestOmitManagedFields(t *testing.T) {
},
}
boolPtr := func(v bool) *bool {
return &v
}
tests := []struct {
name string
policy func() audit.Policy
@ -395,7 +392,7 @@ func TestOmitManagedFields(t *testing.T) {
name: "global policy default is true, rule overrides to false",
policy: func() audit.Policy {
rule := matchingPolicyRule.DeepCopy()
rule.OmitManagedFields = boolPtr(false)
rule.OmitManagedFields = ptr.To(false)
return audit.Policy{
OmitManagedFields: true,
Rules: []audit.PolicyRule{*rule},
@ -407,7 +404,7 @@ func TestOmitManagedFields(t *testing.T) {
name: "global policy default is false, rule overrides to true",
policy: func() audit.Policy {
rule := matchingPolicyRule.DeepCopy()
rule.OmitManagedFields = boolPtr(true)
rule.OmitManagedFields = ptr.To(true)
return audit.Policy{
OmitManagedFields: false,
Rules: []audit.PolicyRule{*rule},

View File

@ -18,7 +18,7 @@ package policy
import (
"fmt"
"io/ioutil"
"os"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -47,7 +47,7 @@ func LoadPolicyFromFile(filePath string) (*auditinternal.Policy, error) {
if filePath == "" {
return nil, fmt.Errorf("file path not specified")
}
policyDef, err := ioutil.ReadFile(filePath)
policyDef, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("failed to read file path %q: %+v", filePath, err)
}

View File

@ -17,7 +17,6 @@ limitations under the License.
package policy
import (
"io/ioutil"
"os"
"reflect"
"strings"
@ -158,7 +157,7 @@ kind: Policy`,
}
func writePolicy(t *testing.T, policy string) (string, error) {
f, err := ioutil.TempFile("", "policy.yaml")
f, err := os.CreateTemp("", "policy.yaml")
require.NoError(t, err)
_, err = f.WriteString(policy)

View File

@ -40,110 +40,73 @@ const (
userAgentTruncateSuffix = "...TRUNCATED"
)
func LogRequestMetadata(ctx context.Context, req *http.Request, requestReceivedTimestamp time.Time, level auditinternal.Level, attribs authorizer.Attributes) {
func LogRequestMetadata(ctx context.Context, req *http.Request, requestReceivedTimestamp time.Time, attribs authorizer.Attributes) {
ac := AuditContextFrom(ctx)
if !ac.Enabled() {
return
}
ev := &ac.Event
ev.RequestReceivedTimestamp = metav1.NewMicroTime(requestReceivedTimestamp)
ev.Verb = attribs.GetVerb()
ev.RequestURI = req.URL.RequestURI()
ev.UserAgent = maybeTruncateUserAgent(req)
ev.Level = level
ac.visitEvent(func(ev *auditinternal.Event) {
ev.RequestReceivedTimestamp = metav1.NewMicroTime(requestReceivedTimestamp)
ev.Verb = attribs.GetVerb()
ev.RequestURI = req.URL.RequestURI()
ev.UserAgent = maybeTruncateUserAgent(req)
ips := utilnet.SourceIPs(req)
ev.SourceIPs = make([]string, len(ips))
for i := range ips {
ev.SourceIPs[i] = ips[i].String()
}
if user := attribs.GetUser(); user != nil {
ev.User.Username = user.GetName()
ev.User.Extra = map[string]authnv1.ExtraValue{}
for k, v := range user.GetExtra() {
ev.User.Extra[k] = authnv1.ExtraValue(v)
ips := utilnet.SourceIPs(req)
ev.SourceIPs = make([]string, len(ips))
for i := range ips {
ev.SourceIPs[i] = ips[i].String()
}
ev.User.Groups = user.GetGroups()
ev.User.UID = user.GetUID()
}
if attribs.IsResourceRequest() {
ev.ObjectRef = &auditinternal.ObjectReference{
Namespace: attribs.GetNamespace(),
Name: attribs.GetName(),
Resource: attribs.GetResource(),
Subresource: attribs.GetSubresource(),
APIGroup: attribs.GetAPIGroup(),
APIVersion: attribs.GetAPIVersion(),
if user := attribs.GetUser(); user != nil {
ev.User.Username = user.GetName()
ev.User.Extra = map[string]authnv1.ExtraValue{}
for k, v := range user.GetExtra() {
ev.User.Extra[k] = authnv1.ExtraValue(v)
}
ev.User.Groups = user.GetGroups()
ev.User.UID = user.GetUID()
}
}
if attribs.IsResourceRequest() {
ev.ObjectRef = &auditinternal.ObjectReference{
Namespace: attribs.GetNamespace(),
Name: attribs.GetName(),
Resource: attribs.GetResource(),
Subresource: attribs.GetSubresource(),
APIGroup: attribs.GetAPIGroup(),
APIVersion: attribs.GetAPIVersion(),
}
}
})
}
// LogImpersonatedUser fills in the impersonated user attributes into an audit event.
func LogImpersonatedUser(ae *auditinternal.Event, user user.Info) {
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
func LogImpersonatedUser(ctx context.Context, user user.Info) {
ac := AuditContextFrom(ctx)
if !ac.Enabled() {
return
}
ae.ImpersonatedUser = &authnv1.UserInfo{
Username: user.GetName(),
}
ae.ImpersonatedUser.Groups = user.GetGroups()
ae.ImpersonatedUser.UID = user.GetUID()
ae.ImpersonatedUser.Extra = map[string]authnv1.ExtraValue{}
for k, v := range user.GetExtra() {
ae.ImpersonatedUser.Extra[k] = authnv1.ExtraValue(v)
}
ac.LogImpersonatedUser(user)
}
// LogRequestObject fills in the request object into an audit event. The passed runtime.Object
// will be converted to the given gv.
func LogRequestObject(ctx context.Context, obj runtime.Object, objGV schema.GroupVersion, gvr schema.GroupVersionResource, subresource string, s runtime.NegotiatedSerializer) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
ac := AuditContextFrom(ctx)
if !ac.Enabled() {
return
}
// complete ObjectRef
if ae.ObjectRef == nil {
ae.ObjectRef = &auditinternal.ObjectReference{}
if ac.GetEventLevel().Less(auditinternal.LevelMetadata) {
return
}
// meta.Accessor is more general than ObjectMetaAccessor, but if it fails, we can just skip setting these bits
if meta, err := meta.Accessor(obj); err == nil {
if len(ae.ObjectRef.Namespace) == 0 {
ae.ObjectRef.Namespace = meta.GetNamespace()
}
if len(ae.ObjectRef.Name) == 0 {
ae.ObjectRef.Name = meta.GetName()
}
if len(ae.ObjectRef.UID) == 0 {
ae.ObjectRef.UID = meta.GetUID()
}
if len(ae.ObjectRef.ResourceVersion) == 0 {
ae.ObjectRef.ResourceVersion = meta.GetResourceVersion()
}
}
if len(ae.ObjectRef.APIVersion) == 0 {
ae.ObjectRef.APIGroup = gvr.Group
ae.ObjectRef.APIVersion = gvr.Version
}
if len(ae.ObjectRef.Resource) == 0 {
ae.ObjectRef.Resource = gvr.Resource
}
if len(ae.ObjectRef.Subresource) == 0 {
ae.ObjectRef.Subresource = subresource
}
if ae.Level.Less(auditinternal.LevelRequest) {
return
}
if shouldOmitManagedFields(ctx) {
objMeta, _ := meta.Accessor(obj)
if shouldOmitManagedFields(ac) {
copy, ok, err := copyWithoutManagedFields(obj)
if err != nil {
klog.ErrorS(err, "Error while dropping managed fields from the request", "auditID", ae.AuditID)
klog.ErrorS(err, "Error while dropping managed fields from the request", "auditID", ac.AuditID())
}
if ok {
obj = copy
@ -151,54 +114,75 @@ func LogRequestObject(ctx context.Context, obj runtime.Object, objGV schema.Grou
}
// TODO(audit): hook into the serializer to avoid double conversion
var err error
ae.RequestObject, err = encodeObject(obj, objGV, s)
requestObject, err := encodeObject(obj, objGV, s)
if err != nil {
// TODO(audit): add error slice to audit event struct
klog.ErrorS(err, "Encoding failed of request object", "auditID", ae.AuditID, "gvr", gvr.String(), "obj", obj)
klog.ErrorS(err, "Encoding failed of request object", "auditID", ac.AuditID(), "gvr", gvr.String(), "obj", obj)
return
}
ac.visitEvent(func(ae *auditinternal.Event) {
if ae.ObjectRef == nil {
ae.ObjectRef = &auditinternal.ObjectReference{}
}
if objMeta != nil {
if len(ae.ObjectRef.Namespace) == 0 {
ae.ObjectRef.Namespace = objMeta.GetNamespace()
}
if len(ae.ObjectRef.Name) == 0 {
ae.ObjectRef.Name = objMeta.GetName()
}
if len(ae.ObjectRef.UID) == 0 {
ae.ObjectRef.UID = objMeta.GetUID()
}
if len(ae.ObjectRef.ResourceVersion) == 0 {
ae.ObjectRef.ResourceVersion = objMeta.GetResourceVersion()
}
}
if len(ae.ObjectRef.APIVersion) == 0 {
ae.ObjectRef.APIGroup = gvr.Group
ae.ObjectRef.APIVersion = gvr.Version
}
if len(ae.ObjectRef.Resource) == 0 {
ae.ObjectRef.Resource = gvr.Resource
}
if len(ae.ObjectRef.Subresource) == 0 {
ae.ObjectRef.Subresource = subresource
}
if ae.Level.Less(auditinternal.LevelRequest) {
return
}
ae.RequestObject = requestObject
})
}
// LogRequestPatch fills in the given patch as the request object into an audit event.
func LogRequestPatch(ctx context.Context, patch []byte) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelRequest) {
ac := AuditContextFrom(ctx)
if ac.GetEventLevel().Less(auditinternal.LevelRequest) {
return
}
ae.RequestObject = &runtime.Unknown{
Raw: patch,
ContentType: runtime.ContentTypeJSON,
}
ac.LogRequestPatch(patch)
}
// LogResponseObject fills in the response object into an audit event. The passed runtime.Object
// will be converted to the given gv.
func LogResponseObject(ctx context.Context, obj runtime.Object, gv schema.GroupVersion, s runtime.NegotiatedSerializer) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
ac := AuditContextFrom(WithAuditContext(ctx))
status, _ := obj.(*metav1.Status)
if ac.GetEventLevel().Less(auditinternal.LevelMetadata) {
return
}
if status, ok := obj.(*metav1.Status); ok {
// selectively copy the bounded fields.
ae.ResponseStatus = &metav1.Status{
Status: status.Status,
Message: status.Message,
Reason: status.Reason,
Details: status.Details,
Code: status.Code,
}
}
if ae.Level.Less(auditinternal.LevelRequestResponse) {
} else if ac.GetEventLevel().Less(auditinternal.LevelRequestResponse) {
ac.LogResponseObject(status, nil)
return
}
if shouldOmitManagedFields(ctx) {
if shouldOmitManagedFields(ac) {
copy, ok, err := copyWithoutManagedFields(obj)
if err != nil {
klog.ErrorS(err, "Error while dropping managed fields from the response", "auditID", ae.AuditID)
klog.ErrorS(err, "Error while dropping managed fields from the response", "auditID", ac.AuditID())
}
if ok {
obj = copy
@ -207,10 +191,11 @@ func LogResponseObject(ctx context.Context, obj runtime.Object, gv schema.GroupV
// TODO(audit): hook into the serializer to avoid double conversion
var err error
ae.ResponseObject, err = encodeObject(obj, gv, s)
responseObject, err := encodeObject(obj, gv, s)
if err != nil {
klog.ErrorS(err, "Encoding failed of response object", "auditID", ae.AuditID, "obj", obj)
klog.ErrorS(err, "Encoding failed of response object", "auditID", ac.AuditID(), "obj", obj)
}
ac.LogResponseObject(status, responseObject)
}
func encodeObject(obj runtime.Object, gv schema.GroupVersion, serializer runtime.NegotiatedSerializer) (*runtime.Unknown, error) {
@ -301,9 +286,9 @@ func removeManagedFields(obj runtime.Object) error {
return nil
}
func shouldOmitManagedFields(ctx context.Context) bool {
if auditContext := AuditContextFrom(ctx); auditContext != nil {
return auditContext.RequestAuditConfig.OmitManagedFields
func shouldOmitManagedFields(ac *AuditContext) bool {
if ac != nil && ac.initialized.Load() && ac.requestAuditConfig.OmitManagedFields {
return true
}
// If we can't decide, return false to maintain current behavior which is

View File

@ -0,0 +1,362 @@
/*
Copyright 2025 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package audit
import (
"context"
"io"
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
)
func TestLogResponseObjectWithPod(t *testing.T) {
testPod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-pod",
Namespace: "test-namespace",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "test-container",
Image: "test-image",
},
},
},
}
scheme := runtime.NewScheme()
if err := corev1.AddToScheme(scheme); err != nil {
t.Fatalf("Failed to add core/v1 to scheme: %v", err)
}
codecs := serializer.NewCodecFactory(scheme)
negotiatedSerializer := codecs.WithoutConversion()
// Create audit context with RequestResponse level
ctx := WithAuditContext(context.Background())
ac := AuditContextFrom(ctx)
captureSink := &capturingAuditSink{}
if err := ac.Init(RequestAuditConfig{Level: auditinternal.LevelRequestResponse}, captureSink); err != nil {
t.Fatalf("Failed to initialize audit context: %v", err)
}
LogResponseObject(ctx, testPod, schema.GroupVersion{Group: "", Version: "v1"}, negotiatedSerializer)
ac.ProcessEventStage(ctx, auditinternal.StageResponseComplete)
if len(captureSink.events) != 1 {
t.Fatalf("Expected one audit event to be captured, got %d", len(captureSink.events))
}
event := captureSink.events[0]
if event.ResponseObject == nil {
t.Fatal("Expected ResponseObject to be set, but it was nil")
}
if event.ResponseObject.ContentType != runtime.ContentTypeJSON {
t.Errorf("Expected ContentType to be %q, got %q", runtime.ContentTypeJSON, event.ResponseObject.ContentType)
}
if len(event.ResponseObject.Raw) == 0 {
t.Error("Expected ResponseObject.Raw to contain data, but it was empty")
}
responseJSON := string(event.ResponseObject.Raw)
expectedFields := []string{"test-pod", "test-namespace", "test-container", "test-image"}
for _, field := range expectedFields {
if !strings.Contains(responseJSON, field) {
t.Errorf("Response should contain %q but didn't. Response: %s", field, responseJSON)
}
}
if event.ResponseStatus != nil {
t.Errorf("Expected ResponseStatus to be nil for regular object, got: %+v", event.ResponseStatus)
}
}
func TestLogResponseObjectWithStatus(t *testing.T) {
testCases := []struct {
name string
level auditinternal.Level
status *metav1.Status
shouldEncode bool
expectResponseObj bool
expectStatusFields bool
}{
{
name: "RequestResponse level should encode and log status fields",
level: auditinternal.LevelRequestResponse,
status: &metav1.Status{Status: "Success", Message: "Test message", Code: 200},
shouldEncode: true,
expectResponseObj: true,
expectStatusFields: true,
},
{
name: "Metadata level should log status fields without encoding",
level: auditinternal.LevelMetadata,
status: &metav1.Status{Status: "Success", Message: "Test message", Code: 200},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
scheme := runtime.NewScheme()
if err := metav1.AddMetaToScheme(scheme); err != nil {
t.Fatalf("Failed to add meta to scheme: %v", err)
}
scheme.AddKnownTypes(schema.GroupVersion{Version: "v1"}, &metav1.Status{})
codecs := serializer.NewCodecFactory(scheme)
negotiatedSerializer := codecs.WithoutConversion()
ctx := WithAuditContext(context.Background())
ac := AuditContextFrom(ctx)
captureSink := &capturingAuditSink{}
if err := ac.Init(RequestAuditConfig{Level: tc.level}, captureSink); err != nil {
t.Fatalf("Failed to initialize audit context: %v", err)
}
LogResponseObject(ctx, tc.status, schema.GroupVersion{Group: "", Version: "v1"}, negotiatedSerializer)
ac.ProcessEventStage(ctx, auditinternal.StageResponseComplete)
if len(captureSink.events) != 1 {
t.Fatalf("Expected one audit event to be captured, got %d", len(captureSink.events))
}
event := captureSink.events[0]
if tc.expectResponseObj {
if event.ResponseObject == nil {
t.Error("Expected ResponseObject to be set, but it was nil")
}
} else {
if event.ResponseObject != nil {
t.Error("Expected ResponseObject to be nil")
}
}
if tc.expectStatusFields {
if event.ResponseStatus == nil {
t.Fatal("Expected ResponseStatus to be set, but it was nil")
}
if event.ResponseStatus.Status != tc.status.Status {
t.Errorf("Expected ResponseStatus.Status to be %q, got %q", tc.status.Status, event.ResponseStatus.Status)
}
if event.ResponseStatus.Message != tc.status.Message {
t.Errorf("Expected ResponseStatus.Message to be %q, got %q", tc.status.Message, event.ResponseStatus.Message)
}
if event.ResponseStatus.Code != tc.status.Code {
t.Errorf("Expected ResponseStatus.Code to be %d, got %d", tc.status.Code, event.ResponseStatus.Code)
}
} else if event.ResponseStatus != nil {
t.Error("Expected ResponseStatus to be nil")
}
})
}
}
func TestLogResponseObjectLevelCheck(t *testing.T) {
testCases := []struct {
name string
level auditinternal.Level
obj runtime.Object
shouldEncode bool
expectResponseObj bool
expectStatusFields bool
}{
{
name: "None level should not encode or log anything",
level: auditinternal.LevelNone,
obj: &corev1.Pod{},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: false,
},
{
name: "Metadata level should not encode or log anything",
level: auditinternal.LevelMetadata,
obj: &corev1.Pod{},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: false,
},
{
name: "Metadata level with Status should log status fields without encoding",
level: auditinternal.LevelMetadata,
obj: &metav1.Status{
Status: "Success",
Message: "Test message",
Code: 200,
},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: true,
},
{
name: "Request level with Pod should not encode or log",
level: auditinternal.LevelRequest,
obj: &corev1.Pod{},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: false,
},
{
name: "Request level with Status should log status fields without encoding",
level: auditinternal.LevelRequest,
obj: &metav1.Status{
Status: "Success",
Message: "Test message",
Code: 200,
},
shouldEncode: false,
expectResponseObj: false,
expectStatusFields: true,
},
{
name: "RequestResponse level with Pod should encode",
level: auditinternal.LevelRequestResponse,
obj: &corev1.Pod{},
shouldEncode: true,
expectResponseObj: true,
expectStatusFields: false,
},
{
name: "RequestResponse level with Status should encode and log status fields",
level: auditinternal.LevelRequestResponse,
obj: &metav1.Status{
Status: "Success",
Message: "Test message",
Code: 200,
},
shouldEncode: true,
expectResponseObj: true,
expectStatusFields: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
ctx := WithAuditContext(context.Background())
ac := AuditContextFrom(ctx)
captureSink := &capturingAuditSink{}
if err := ac.Init(RequestAuditConfig{Level: tc.level}, captureSink); err != nil {
t.Fatalf("Failed to initialize audit context: %v", err)
}
mockSerializer := &mockNegotiatedSerializer{}
LogResponseObject(ctx, tc.obj, schema.GroupVersion{Group: "", Version: "v1"}, mockSerializer)
ac.ProcessEventStage(ctx, auditinternal.StageResponseComplete)
if mockSerializer.encodeCalled != tc.shouldEncode {
t.Errorf("Expected encoding to be called: %v, but got: %v", tc.shouldEncode, mockSerializer.encodeCalled)
}
if len(captureSink.events) != 1 {
t.Fatalf("Expected one audit event to be captured, got %d", len(captureSink.events))
}
event := captureSink.events[0]
if tc.expectResponseObj {
if event.ResponseObject == nil {
t.Error("Expected ResponseObject to be set, but it was nil")
}
} else {
if event.ResponseObject != nil {
t.Error("Expected ResponseObject to be nil")
}
}
// Check ResponseStatus for Status objects
status, isStatus := tc.obj.(*metav1.Status)
if isStatus && tc.expectStatusFields {
if event.ResponseStatus == nil {
t.Error("Expected ResponseStatus to be set for Status object, but it was nil")
} else {
if event.ResponseStatus.Status != status.Status {
t.Errorf("Expected ResponseStatus.Status to be %q, got %q", status.Status, event.ResponseStatus.Status)
}
if event.ResponseStatus.Message != status.Message {
t.Errorf("Expected ResponseStatus.Message to be %q, got %q", status.Message, event.ResponseStatus.Message)
}
if event.ResponseStatus.Code != status.Code {
t.Errorf("Expected ResponseStatus.Code to be %d, got %d", status.Code, event.ResponseStatus.Code)
}
}
} else if event.ResponseStatus != nil {
t.Error("Expected ResponseStatus to be nil")
}
})
}
}
type mockNegotiatedSerializer struct {
encodeCalled bool
}
func (m *mockNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
return []runtime.SerializerInfo{
{
MediaType: runtime.ContentTypeJSON,
EncodesAsText: true,
Serializer: nil,
PrettySerializer: nil,
StreamSerializer: nil,
},
}
}
func (m *mockNegotiatedSerializer) EncoderForVersion(serializer runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
m.encodeCalled = true
return &mockEncoder{}
}
func (m *mockNegotiatedSerializer) DecoderToVersion(serializer runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
return nil
}
type mockEncoder struct{}
func (e *mockEncoder) Encode(obj runtime.Object, w io.Writer) error {
return nil
}
func (e *mockEncoder) Identifier() runtime.Identifier {
return runtime.Identifier("mock")
}
type capturingAuditSink struct {
events []*auditinternal.Event
}
func (s *capturingAuditSink) ProcessEvents(events ...*auditinternal.Event) bool {
for _, event := range events {
eventCopy := event.DeepCopy()
s.events = append(s.events, eventCopy)
}
return true
}

View File

@ -22,8 +22,7 @@ import (
celgo "github.com/google/cel-go/cel"
"github.com/google/cel-go/common/types/ref"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/google/cel-go/common/types/traits"
)
// ExpressionAccessor is an interface that provides access to a CEL expression.
@ -55,17 +54,17 @@ type Compiler interface {
type ClaimsMapper interface {
// EvalClaimMapping evaluates the given claim mapping expression and returns a EvaluationResult.
// This is used for username, groups and uid claim mapping that contains a single expression.
EvalClaimMapping(ctx context.Context, claims *unstructured.Unstructured) (EvaluationResult, error)
EvalClaimMapping(ctx context.Context, claims traits.Mapper) (EvaluationResult, error)
// EvalClaimMappings evaluates the given expressions and returns a list of EvaluationResult.
// This is used for extra claim mapping and claim validation that contains a list of expressions.
EvalClaimMappings(ctx context.Context, claims *unstructured.Unstructured) ([]EvaluationResult, error)
EvalClaimMappings(ctx context.Context, claims traits.Mapper) ([]EvaluationResult, error)
}
// UserMapper provides a CEL expression mapper configured with the user CEL variable.
type UserMapper interface {
// EvalUser evaluates the given user expressions and returns a list of EvaluationResult.
// This is used for user validation that contains a list of expressions.
EvalUser(ctx context.Context, userInfo *unstructured.Unstructured) ([]EvaluationResult, error)
EvalUser(ctx context.Context, userInfo traits.Mapper) ([]EvaluationResult, error)
}
var _ ExpressionAccessor = &ClaimMappingExpression{}

View File

@ -20,7 +20,8 @@ import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/google/cel-go/common/types/traits"
"github.com/google/cel-go/interpreter"
)
var _ ClaimsMapper = &mapper{}
@ -57,8 +58,8 @@ func NewUserMapper(compilationResults []CompilationResult) UserMapper {
}
// EvalClaimMapping evaluates the given claim mapping expression and returns a EvaluationResult.
func (m *mapper) EvalClaimMapping(ctx context.Context, claims *unstructured.Unstructured) (EvaluationResult, error) {
results, err := m.eval(ctx, map[string]interface{}{claimsVarName: claims.Object})
func (m *mapper) EvalClaimMapping(ctx context.Context, claims traits.Mapper) (EvaluationResult, error) {
results, err := m.eval(ctx, &varNameActivation{name: claimsVarName, value: claims})
if err != nil {
return EvaluationResult{}, err
}
@ -69,16 +70,16 @@ func (m *mapper) EvalClaimMapping(ctx context.Context, claims *unstructured.Unst
}
// EvalClaimMappings evaluates the given expressions and returns a list of EvaluationResult.
func (m *mapper) EvalClaimMappings(ctx context.Context, claims *unstructured.Unstructured) ([]EvaluationResult, error) {
return m.eval(ctx, map[string]interface{}{claimsVarName: claims.Object})
func (m *mapper) EvalClaimMappings(ctx context.Context, claims traits.Mapper) ([]EvaluationResult, error) {
return m.eval(ctx, &varNameActivation{name: claimsVarName, value: claims})
}
// EvalUser evaluates the given user expressions and returns a list of EvaluationResult.
func (m *mapper) EvalUser(ctx context.Context, userInfo *unstructured.Unstructured) ([]EvaluationResult, error) {
return m.eval(ctx, map[string]interface{}{userVarName: userInfo.Object})
func (m *mapper) EvalUser(ctx context.Context, userInfo traits.Mapper) ([]EvaluationResult, error) {
return m.eval(ctx, &varNameActivation{name: userVarName, value: userInfo})
}
func (m *mapper) eval(ctx context.Context, input map[string]interface{}) ([]EvaluationResult, error) {
func (m *mapper) eval(ctx context.Context, input *varNameActivation) ([]EvaluationResult, error) {
evaluations := make([]EvaluationResult, len(m.compilationResults))
for i, compilationResult := range m.compilationResults {
@ -95,3 +96,19 @@ func (m *mapper) eval(ctx context.Context, input map[string]interface{}) ([]Eval
return evaluations, nil
}
var _ interpreter.Activation = &varNameActivation{}
type varNameActivation struct {
name string
value traits.Mapper
}
func (v *varNameActivation) ResolveName(name string) (any, bool) {
if v.name != name {
return nil, false
}
return v.value, true
}
func (v *varNameActivation) Parent() interpreter.Activation { return nil }

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package x509 provides a request authenticator that validates and
// extracts user information from client certificates
package x509 // import "k8s.io/apiserver/pkg/authentication/request/x509"
package x509

View File

@ -21,15 +21,19 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"errors"
"fmt"
"net/http"
"strings"
"time"
asn1util "k8s.io/apimachinery/pkg/apis/asn1"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
)
@ -281,9 +285,14 @@ var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate
fp := sha256.Sum256(chain[0].Raw)
id := "X509SHA256=" + hex.EncodeToString(fp[:])
uid, err := parseUIDFromCert(chain[0])
if err != nil {
return nil, false, err
}
return &authenticator.Response{
User: &user.DefaultInfo{
Name: chain[0].Subject.CommonName,
UID: uid,
Groups: chain[0].Subject.Organization,
Extra: map[string][]string{
user.CredentialIDKey: {id},
@ -291,3 +300,33 @@ var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate
},
}, true, nil
})
var uidOID = asn1util.X509UID()
func parseUIDFromCert(cert *x509.Certificate) (string, error) {
if !utilfeature.DefaultFeatureGate.Enabled(features.AllowParsingUserUIDFromCertAuth) {
return "", nil
}
uids := []string{}
for _, name := range cert.Subject.Names {
if !name.Type.Equal(uidOID) {
continue
}
uid, ok := name.Value.(string)
if !ok {
return "", fmt.Errorf("unable to parse UID into a string")
}
uids = append(uids, uid)
}
if len(uids) == 0 {
return "", nil
}
if len(uids) != 1 {
return "", fmt.Errorf("expected 1 UID, but found multiple: %v", uids)
}
if uids[0] == "" {
return "", errors.New("UID cannot be an empty string")
}
return uids[0], nil
}

View File

@ -19,18 +19,26 @@ package x509
import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"errors"
"io/ioutil"
"net/http"
"os"
"regexp"
"sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
asn1util "k8s.io/apimachinery/pkg/apis/asn1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
)
const (
@ -124,21 +132,21 @@ const (
*/
rootCACert = `-----BEGIN CERTIFICATE-----
MIICtjCCAh+gAwIBAgIULXMaLteLiSCDnEKabvf19qHsr4wwDQYJKoZIhvcNAQEF
MIICtjCCAh+gAwIBAgIUXipc16GmHC8Q64wKx+gegIcA0wAwDQYJKoZIhvcNAQEF
BQAwZzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE15IFN0YXRlMRAwDgYDVQQHDAdN
eSBDaXR5MQ8wDQYDVQQKDAZNeSBPcmcxEDAOBgNVBAsMB015IFVuaXQxEDAOBgNV
BAMMB1JPT1QgQ0EwIBcNMjQwNTAyMDU0MzUxWhgPMjEyNDA0MDgwNTQzNTFaMGcx
BAMMB1JPT1QgQ0EwIBcNMjQxMDA2MjAzNTIwWhgPMjEyNDA5MTIyMDM1MjBaMGcx
CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNeSBTdGF0ZTEQMA4GA1UEBwwHTXkgQ2l0
eTEPMA0GA1UECgwGTXkgT3JnMRAwDgYDVQQLDAdNeSBVbml0MRAwDgYDVQQDDAdS
T09UIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCow9zeGvY+lZcq1b+L
cpMGhXJLNirZY6ic+4A+my+ExlfS/zMTvzLpkGbbCpoFwePBCbsldbLX/JwJhoAV
sGxnxRrpdgEyQCJY7E6ht8UFAUlV2E9LiB2/ZtPeWErnJra/rzPYV0LxvDRnRIi0
MfZKSrMewsprSy5aMiObGz+XNQIDAQABo10wWzAdBgNVHQ4EFgQU0wfNcua+ClrY
6WAgr8LyNn4zYgswHwYDVR0jBBgwFoAU0wfNcua+ClrY6WAgr8LyNn4zYgswDAYD
VR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEASlQHRnHB
sqLTMuffSYyvh0argRHGxUu+Cwzqfl84FHlDkvm7gm/2BqZDGeJ8UmY2E28PcxY9
eV/5pshMGPn/ICvefxXgq65E+mV6horf0GOCsVzz+FwFl04fCdbZVec2/Ag+P2aZ
aLYxRA9jIGqygVA5GdBH3iCU8KIs62mTk6M=
T09UIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt8DHt/ni9y/6lqWss
uv2eFvW6N9RvYhxRmuuxQK74F5/VRAfhEMvDOU+woG/HBXMyPOgLL1uWt4dk3DGu
WYNwYP2oN6D04KkWYgcxwYFjcduzWxynr5zT1T2B3bxZFMkvqshyrHWD38Vge080
NU3Pns7Z53AZu673srH+OSU8WwIDAQABo10wWzAdBgNVHQ4EFgQUSHB11O1rSTtT
2+mm+ZxVklG9luYwHwYDVR0jBBgwFoAUSHB11O1rSTtT2+mm+ZxVklG9luYwDAYD
VR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEAj/zGCbq+
POo9thqGg2i2/bzHzAr4X9ylJaeM8oaBhk0pvliTcWGb/usjqwWpcXIqHY8jjBrN
GFJEH6elL1Q63W+JCwWS14i2jQExjPk7/AWLBv/J7XqgiUhPfF/P9iQp+lGcInNR
6TGXeFKLtsrySVfQ4TvEW1zNJj9qJ819YwU=
-----END CERTIFICATE-----
`
@ -246,9 +254,13 @@ u7ESEaSlma8XEeex
openssl genrsa -out client.key 1024 && \
openssl rsa -in ./client.key -outform PEM \
-pubout -out ./client.pub && \
OID_CONF="oid_section = my_oids\n\n" && \
OID_CONF="${OID_CONF}[ my_oids ]\n" && \
OID_CONF="${OID_CONF}kube_uid=1.3.6.1.4.1.57683.2\n" && \
openssl req -key ./client.key -new\
-config <(printf "${OID_CONF}") \
-sha1 -out ./client.csr \
-subj "/C=US/ST=My State/L=My City/O=My Org/OU=My Unit/CN=client_cn" \
-subj "/C=US/ST=My State/L=My City/O=My Org/OU=My Unit/CN=client_cn2/CN=client_cn/kube_uid=client_id" \
&& \
EXTFILE="subjectKeyIdentifier=hash\n" && \
EXTFILE="${EXTFILE}authorityKeyIdentifier=keyid,issuer\n" && \
@ -277,63 +289,64 @@ u7ESEaSlma8XEeex
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = My State, L = My City, O = My Org, OU = My Unit, CN = ROOT CA
Issuer: C=US, ST=My State, L=My City, O=My Org, OU=My Unit, CN=ROOT CA
Validity
Not Before: May 2 05:46:24 2024 GMT
Not After : Apr 8 05:46:24 2124 GMT
Subject: C = US, ST = My State, L = My City, O = My Org, OU = My Unit, CN = client_cn
Not Before: Oct 27 00:43:31 2024 GMT
Not After : Oct 3 00:43:31 2124 GMT
Subject: C=US, ST=My State, L=My City, O=My Org, OU=My Unit, CN=client_cn2, CN=client_cn, 1.3.6.1.4.1.57683.2=client_id
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:bd:3f:2d:d1:86:73:6d:b5:09:9c:ff:42:fb:27:
8e:07:69:a3:b6:d1:c7:72:d1:de:98:14:a5:61:9b:
83:03:1d:da:54:d1:d4:0d:7f:de:98:2e:cc:db:6f:
e4:19:c7:41:43:59:ff:34:7b:82:06:80:01:ab:79:
b3:40:d3:45:1f:52:2d:10:f9:55:40:a7:7a:61:f7:
fd:9c:41:eb:d1:ec:7e:30:ca:1a:fa:0e:9e:0f:1e:
50:93:9a:ca:55:ea:64:80:6e:bb:49:7d:12:15:d8:
6f:a8:aa:3f:b9:10:24:6f:72:22:e9:4f:f3:a4:29:
1e:4e:71:a6:82:af:39:78:a9
00:d1:61:6d:94:0e:a2:7b:3e:ae:2c:d4:39:66:a5:
ec:3a:d1:90:d1:85:fd:de:3c:1d:7d:cc:cd:fd:93:
50:06:26:02:a7:89:e4:92:45:d5:96:ba:b0:04:6b:
29:a9:93:ff:c9:d5:f2:5c:50:b5:1c:5a:1d:48:4f:
eb:a9:bf:f9:28:24:a2:5e:da:08:d1:01:1a:1a:c8:
00:35:d0:4a:51:46:f0:02:2b:89:3b:b2:aa:a9:68:
33:ee:08:d4:61:06:62:e6:ea:53:f6:4a:13:49:66:
67:03:82:22:08:28:2e:be:dd:81:91:28:a5:aa:89:
78:41:33:3b:5d:65:b2:f7:0b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
FB:77:D6:D0:84:A8:10:DF:FA:4E:A4:E0:F1:2A:BB:B4:80:FD:4F:3F
X509v3 Authority Key Identifier:
D3:07:CD:72:E6:BE:0A:5A:D8:E9:60:20:AF:C2:F2:36:7E:33:62:0B
X509v3 Basic Constraints:
X509v3 Subject Key Identifier:
64:84:5E:B7:37:A2:82:F9:62:1A:01:00:FE:1B:B4:4B:F4:18:92:F6
X509v3 Authority Key Identifier:
48:70:75:D4:ED:6B:49:3B:53:DB:E9:A6:F9:9C:55:92:51:BD:96:E6
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Alternative Name:
X509v3 Subject Alternative Name:
<EMPTY>
X509v3 Extended Key Usage:
X509v3 Extended Key Usage:
TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
6b:24:0f:2f:81:46:32:c4:c1:57:09:cd:64:6d:9f:50:ee:29:
4d:a7:14:d0:a0:0c:ea:a6:dc:e5:15:52:9a:42:08:eb:a2:91:
3c:ce:94:0e:f0:82:bc:fd:d7:23:d1:ad:d1:98:07:94:05:fa:
ca:37:45:d7:f0:7d:aa:d2:ec:94:2b:8b:03:85:00:fb:af:1d:
35:28:53:a8:1d:f8:44:e1:ea:48:3f:a4:2a:46:3b:f6:19:bf:
30:df:b2:0e:8d:79:b0:0a:f5:34:c7:8a:6d:bf:58:39:9d:5d:
a1:f5:35:a0:54:87:98:c6:5d:bf:ea:4e:46:f9:47:6d:d7:e6:
5a:f3
59:a5:81:1c:61:12:ad:1e:b8:3d:a5:e6:c2:dd:dd:8f:09:3c:
8f:61:fc:96:e6:ff:70:d1:77:b0:b8:18:7f:f5:9e:e7:61:a1:
cc:b6:53:75:d4:b3:a7:cb:77:1c:7f:e2:01:22:6b:30:44:df:
e0:c2:9e:f6:56:a8:1e:13:0b:02:a7:fa:25:cb:f8:6c:0b:85:
32:be:a7:1d:50:07:5d:76:0c:e5:ec:58:88:3e:ab:21:09:58:
1f:af:06:26:80:77:48:1a:a4:37:50:35:e5:b3:d0:d0:4c:d7:
ad:bb:29:2b:f5:eb:56:94:c0:8b:4d:69:37:f6:1c:d2:fd:87:
d5:af
-----BEGIN CERTIFICATE-----
MIICtTCCAh6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzER
MIIC5TCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzER
MA8GA1UECAwITXkgU3RhdGUxEDAOBgNVBAcMB015IENpdHkxDzANBgNVBAoMBk15
IE9yZzEQMA4GA1UECwwHTXkgVW5pdDEQMA4GA1UEAwwHUk9PVCBDQTAgFw0yNDA1
MDIwNTQ2MjRaGA8yMTI0MDQwODA1NDYyNFowaTELMAkGA1UEBhMCVVMxETAPBgNV
BAgMCE15IFN0YXRlMRAwDgYDVQQHDAdNeSBDaXR5MQ8wDQYDVQQKDAZNeSBPcmcx
EDAOBgNVBAsMB015IFVuaXQxEjAQBgNVBAMMCWNsaWVudF9jbjCBnzANBgkqhkiG
9w0BAQEFAAOBjQAwgYkCgYEAvT8t0YZzbbUJnP9C+yeOB2mjttHHctHemBSlYZuD
Ax3aVNHUDX/emC7M22/kGcdBQ1n/NHuCBoABq3mzQNNFH1ItEPlVQKd6Yff9nEHr
0ex+MMoa+g6eDx5Qk5rKVepkgG67SX0SFdhvqKo/uRAkb3Ii6U/zpCkeTnGmgq85
eKkCAwEAAaNtMGswHQYDVR0OBBYEFPt31tCEqBDf+k6k4PEqu7SA/U8/MB8GA1Ud
IwQYMBaAFNMHzXLmvgpa2OlgIK/C8jZ+M2ILMAkGA1UdEwQCMAAwCQYDVR0RBAIw
ADATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQBrJA8vgUYy
xMFXCc1kbZ9Q7ilNpxTQoAzqptzlFVKaQgjropE8zpQO8IK8/dcj0a3RmAeUBfrK
N0XX8H2q0uyUK4sDhQD7rx01KFOoHfhE4epIP6QqRjv2Gb8w37IOjXmwCvU0x4pt
v1g5nV2h9TWgVIeYxl2/6k5G+Udt1+Za8w==
IE9yZzEQMA4GA1UECwwHTXkgVW5pdDEQMA4GA1UEAwwHUk9PVCBDQTAgFw0yNDEw
MjcwMDQzMzFaGA8yMTI0MTAwMzAwNDMzMVowgZgxCzAJBgNVBAYTAlVTMREwDwYD
VQQIDAhNeSBTdGF0ZTEQMA4GA1UEBwwHTXkgQ2l0eTEPMA0GA1UECgwGTXkgT3Jn
MRAwDgYDVQQLDAdNeSBVbml0MRMwEQYDVQQDDApjbGllbnRfY24yMRIwEAYDVQQD
DAljbGllbnRfY24xGDAWBgkrBgEEAYPCUwIMCWNsaWVudF9pZDCBnzANBgkqhkiG
9w0BAQEFAAOBjQAwgYkCgYEA0WFtlA6iez6uLNQ5ZqXsOtGQ0YX93jwdfczN/ZNQ
BiYCp4nkkkXVlrqwBGspqZP/ydXyXFC1HFodSE/rqb/5KCSiXtoI0QEaGsgANdBK
UUbwAiuJO7KqqWgz7gjUYQZi5upT9koTSWZnA4IiCCguvt2BkSilqol4QTM7XWWy
9wsCAwEAAaNtMGswHQYDVR0OBBYEFGSEXrc3ooL5YhoBAP4btEv0GJL2MB8GA1Ud
IwQYMBaAFEhwddTta0k7U9vppvmcVZJRvZbmMAkGA1UdEwQCMAAwCQYDVR0RBAIw
ADATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQBZpYEcYRKt
Hrg9pebC3d2PCTyPYfyW5v9w0XewuBh/9Z7nYaHMtlN11LOny3ccf+IBImswRN/g
wp72VqgeEwsCp/oly/hsC4UyvqcdUAdddgzl7FiIPqshCVgfrwYmgHdIGqQ3UDXl
s9DQTNetuykr9etWlMCLTWk39hzS/YfVrw==
-----END CERTIFICATE-----`
/*
@ -374,66 +387,199 @@ v1g5nV2h9TWgVIeYxl2/6k5G+Udt1+Za8w==
Version: 3 (0x2)
Serial Number: 7 (0x7)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = My State, L = My City, O = My Org, OU = My Unit, CN = ROOT CA
Issuer: C=US, ST=My State, L=My City, O=My Org, OU=My Unit, CN=ROOT CA
Validity
Not Before: May 2 05:47:31 2024 GMT
Not After : Apr 8 05:47:31 2124 GMT
Subject: C = US, ST = My State, L = My City, O = My Org, OU = My Unit, CN = 127.0.0.1
Not Before: Oct 6 20:38:02 2024 GMT
Not After : Sep 12 20:38:02 2124 GMT
Subject: C=US, ST=My State, L=My City, O=My Org, OU=My Unit, CN=127.0.0.1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:9d:1f:c3:9e:ac:51:92:27:df:2a:3a:48:b7:59:
40:23:a5:c3:a1:61:71:7a:00:df:d5:8b:a2:8a:7c:
54:f0:19:69:fe:ae:19:a3:e1:eb:1e:1b:39:2c:61:
fb:7b:21:10:81:b2:ef:29:94:b6:14:6f:ca:eb:4d:
f3:f6:84:93:5f:51:2c:7a:ab:9f:34:05:15:62:c4:
55:54:2e:75:b9:26:d1:0e:c5:63:41:e5:36:02:3f:
1c:5f:fc:1b:07:20:d2:1c:70:a5:a1:e8:08:1d:8f:
4c:c3:57:e0:54:72:a6:c9:24:1b:b0:fa:0d:86:f5:
26:1f:20:e5:1c:1c:c3:8f:d3
00:b6:d5:2f:a6:7a:78:5d:40:a6:0d:76:6f:e9:9d:
54:6d:d9:e9:d6:32:00:f2:8a:fb:da:87:be:05:07:
b4:58:ab:88:25:f8:38:e7:50:25:23:47:99:8f:3c:
ff:8a:cc:61:7c:21:db:39:c9:81:f6:0c:f2:22:a8:
19:65:7a:ae:c6:32:74:63:4d:a5:14:fa:b5:04:ab:
a4:83:c5:0f:26:38:b3:65:9d:68:bb:4f:55:e4:0b:
e5:71:49:dd:5b:b8:a0:ed:7d:13:6f:29:03:44:20:
d0:2d:9c:44:e4:0e:8b:d7:71:79:fe:35:cd:6c:7c:
79:a4:01:08:ae:9e:95:46:d9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
F2:AE:B7:50:D5:02:C1:E9:8D:38:0E:76:A5:D8:24:0B:1C:DB:08:0E
X509v3 Authority Key Identifier:
D3:07:CD:72:E6:BE:0A:5A:D8:E9:60:20:AF:C2:F2:36:7E:33:62:0B
X509v3 Basic Constraints:
X509v3 Subject Key Identifier:
CA:72:DA:A3:17:BB:56:CC:14:A9:BA:12:F2:88:7F:F4:15:69:33:CB
X509v3 Authority Key Identifier:
48:70:75:D4:ED:6B:49:3B:53:DB:E9:A6:F9:9C:55:92:51:BD:96:E6
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Alternative Name:
X509v3 Subject Alternative Name:
<EMPTY>
X509v3 Extended Key Usage:
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
3f:3d:d1:5d:d5:9f:c1:ab:6e:ba:c1:c2:1b:63:1a:a8:4f:d9:
df:03:13:ff:6d:a8:ed:c9:8d:19:a6:8f:a6:e2:a8:23:a0:f7:
5d:5e:22:01:d1:29:9b:d0:95:75:66:46:f2:51:a7:08:1c:8c:
aa:ca:4a:57:d8:ab:ed:1b:b3:77:25:58:38:1f:89:e0:a4:13:
0a:f2:99:d5:3d:24:00:08:06:7e:b3:1a:b0:0b:07:33:a7:c7:
ff:f8:ef:bc:7c:c9:2e:aa:3f:7a:3e:8e:8a:49:cf:a4:5a:b5:
41:07:57:f1:36:f4:57:dc:6e:3f:70:38:0d:4e:71:9c:24:20:
b4:36
08:14:37:cd:ec:d6:4e:81:d2:d7:09:ba:5a:50:84:6a:1b:f2:
02:49:44:94:5d:e3:41:48:09:dc:88:0b:37:d6:e9:c7:b6:4b:
42:58:b3:cb:81:5b:a6:0d:78:47:1b:4a:5a:5f:d5:14:4c:37:
bd:b6:64:c4:d5:ac:17:d0:6c:2d:f5:1b:aa:d8:de:27:f1:1e:
26:42:dd:45:90:ef:97:0b:e6:c9:01:c5:4b:7c:c3:81:18:c6:
28:d9:8a:f5:a5:8c:b4:ec:75:c2:b8:43:83:d0:db:09:e1:58:
a6:2a:65:52:97:0b:d0:d6:c7:43:8f:10:63:23:b4:ce:c9:15:
4d:4a
-----BEGIN CERTIFICATE-----
MIICtTCCAh6gAwIBAgIBBzANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzER
MA8GA1UECAwITXkgU3RhdGUxEDAOBgNVBAcMB015IENpdHkxDzANBgNVBAoMBk15
IE9yZzEQMA4GA1UECwwHTXkgVW5pdDEQMA4GA1UEAwwHUk9PVCBDQTAgFw0yNDA1
MDIwNTQ3MzFaGA8yMTI0MDQwODA1NDczMVowaTELMAkGA1UEBhMCVVMxETAPBgNV
IE9yZzEQMA4GA1UECwwHTXkgVW5pdDEQMA4GA1UEAwwHUk9PVCBDQTAgFw0yNDEw
MDYyMDM4MDJaGA8yMTI0MDkxMjIwMzgwMlowaTELMAkGA1UEBhMCVVMxETAPBgNV
BAgMCE15IFN0YXRlMRAwDgYDVQQHDAdNeSBDaXR5MQ8wDQYDVQQKDAZNeSBPcmcx
EDAOBgNVBAsMB015IFVuaXQxEjAQBgNVBAMMCTEyNy4wLjAuMTCBnzANBgkqhkiG
9w0BAQEFAAOBjQAwgYkCgYEAnR/DnqxRkiffKjpIt1lAI6XDoWFxegDf1YuiinxU
8Blp/q4Zo+HrHhs5LGH7eyEQgbLvKZS2FG/K603z9oSTX1EsequfNAUVYsRVVC51
uSbRDsVjQeU2Aj8cX/wbByDSHHCloegIHY9Mw1fgVHKmySQbsPoNhvUmHyDlHBzD
j9MCAwEAAaNtMGswHQYDVR0OBBYEFPKut1DVAsHpjTgOdqXYJAsc2wgOMB8GA1Ud
IwQYMBaAFNMHzXLmvgpa2OlgIK/C8jZ+M2ILMAkGA1UdEwQCMAAwCQYDVR0RBAIw
ADATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOBgQA/PdFd1Z/B
q266wcIbYxqoT9nfAxP/bajtyY0Zpo+m4qgjoPddXiIB0Smb0JV1ZkbyUacIHIyq
ykpX2KvtG7N3JVg4H4ngpBMK8pnVPSQACAZ+sxqwCwczp8f/+O+8fMkuqj96Po6K
Sc+kWrVBB1fxNvRX3G4/cDgNTnGcJCC0Ng==
9w0BAQEFAAOBjQAwgYkCgYEAttUvpnp4XUCmDXZv6Z1Ubdnp1jIA8or72oe+BQe0
WKuIJfg451AlI0eZjzz/isxhfCHbOcmB9gzyIqgZZXquxjJ0Y02lFPq1BKukg8UP
JjizZZ1ou09V5AvlcUndW7ig7X0TbykDRCDQLZxE5A6L13F5/jXNbHx5pAEIrp6V
RtkCAwEAAaNtMGswHQYDVR0OBBYEFMpy2qMXu1bMFKm6EvKIf/QVaTPLMB8GA1Ud
IwQYMBaAFEhwddTta0k7U9vppvmcVZJRvZbmMAkGA1UdEwQCMAAwCQYDVR0RBAIw
ADATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOBgQAIFDfN7NZO
gdLXCbpaUIRqG/ICSUSUXeNBSAnciAs31unHtktCWLPLgVumDXhHG0paX9UUTDe9
tmTE1awX0Gwt9Ruq2N4n8R4mQt1FkO+XC+bJAcVLfMOBGMYo2Yr1pYy07HXCuEOD
0NsJ4VimKmVSlwvQ1sdDjxBjI7TOyRVNSg==
-----END CERTIFICATE-----
`
/*
openssl genrsa -out ca.key 4096 && \
OID_CONF="oid_section = my_oids\n\n" && \
OID_CONF="${OID_CONF}[ my_oids ]\n" && \
OID_CONF="${OID_CONF}kube_uid=1.3.6.1.4.1.57683.2\n" && \
openssl req -new -x509 -days 36500 \
-config <(printf "${OID_CONF}") \
-sha256 -key ca.key \
-out ca.crt \
-subj "/C=US/ST=My State/L=My City/CN=caWithMultiUIDs"/kube_uid=client_uid1/kube_uid=client_uid2 && \
openssl x509 -in ca.crt -text
*/
// A certificate with multiple UIDs.
caWithMultiUIDs = `Certificate:
Data:
Version: 3 (0x2)
Serial Number:
2d:92:d9:46:70:49:59:58:3c:d0:12:06:ed:3e:ee:15:f3:17:62:d4
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=My State, L=My City, CN=caWithMultiUIDs, 1.3.6.1.4.1.57683.2=client_uid1, 1.3.6.1.4.1.57683.2=client_uid2
Validity
Not Before: Nov 2 19:44:52 2024 GMT
Not After : Oct 9 19:44:52 2124 GMT
Subject: C=US, ST=My State, L=My City, CN=caWithMultiUIDs, 1.3.6.1.4.1.57683.2=client_uid1, 1.3.6.1.4.1.57683.2=client_uid2
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:a4:c1:9d:6e:a2:e7:af:07:14:7f:5f:00:60:92:
1b:ec:51:77:3d:ac:93:4d:a8:ac:ee:15:93:9d:5f:
62:44:5d:97:70:a2:c9:63:59:79:79:84:86:98:2e:
4b:cb:fd:99:2e:e7:0c:7d:e2:c3:65:f5:80:5d:bb:
38:3f:0e:09:11:40:9f:56:b0:91:04:2b:66:02:a4:
28:9a:fc:a4:e9:0d:6b:f0:31:41:90:95:f2:4a:d7:
af:5d:50:f8:28:1d:6d:2b:01:e4:38:bf:15:9c:9e:
93:2b:44:7e:29:33:c0:96:66:4f:5f:43:74:c2:eb:
c9:45:e1:16:22:33:b7:d9:93:5f:1c:af:bb:95:f5:
64:15:53:15:c3:a6:4c:0e:2c:6e:f7:45:c1:c5:4a:
c3:8c:29:c3:42:aa:e1:eb:53:da:c2:0d:9c:dc:5a:
e1:01:9c:59:b4:43:1c:2b:c5:ff:d7:cf:cf:4c:76:
a4:7b:ce:00:a1:78:4a:38:0f:f3:ab:48:0f:5e:86:
49:7f:24:85:71:db:c8:3c:7e:dc:f5:26:5f:54:aa:
a6:e2:41:83:3c:5b:eb:e4:f0:e4:76:78:a3:82:68:
46:b1:50:54:a7:d0:c4:aa:12:4d:fd:7f:b4:c2:92:
f1:d0:2d:0a:e9:df:9b:0f:95:88:94:3f:77:35:57:
e6:8e:a7:b1:50:9a:80:51:62:19:49:9b:2c:81:f5:
97:b3:f4:23:b7:94:9e:96:2e:22:d3:6e:6a:56:50:
77:1c:ad:3a:60:52:eb:b6:ba:34:fe:f5:1e:ba:fd:
e3:dc:b8:9d:c1:59:b2:42:fa:5e:88:d3:fe:4a:1a:
3d:1d:a6:55:ce:af:dc:71:e7:8a:4a:dd:37:00:0a:
64:79:14:b3:29:ed:7c:4a:42:c6:f1:38:72:e5:36:
19:64:9f:3c:23:8a:b1:ee:18:a7:7e:cf:12:48:53:
0c:27:fb:12:82:62:bc:9a:7f:fc:5d:97:ae:2d:38:
bd:ff:74:23:1b:62:1c:2e:4a:26:7e:85:6c:6d:82:
01:96:95:86:15:1c:db:40:d9:01:d6:df:68:6d:e9:
5b:0b:6d:cc:6f:40:95:34:f8:b4:1c:13:ab:95:0f:
5b:0b:dc:65:93:87:a0:4c:0d:e6:b0:0a:a6:7e:ac:
0b:04:6d:f9:ee:42:7b:14:0f:b4:22:53:e2:58:bc:
6f:05:41:f0:d3:3a:98:1a:c4:3a:6e:0b:a9:85:fe:
e9:4d:7a:50:b4:4d:28:bd:fc:6a:78:e2:b8:9d:cd:
15:a3:ac:03:a9:94:38:8e:94:b1:00:12:fc:1f:70:
1b:b8:f4:1a:7b:a9:cc:17:c5:2a:42:c6:40:c7:b4:
40:ba:fd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
87:40:3F:E7:DD:73:C8:A6:62:6A:B2:8E:AF:82:52:F6:8D:26:C1:68
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
3c:9f:c8:86:2b:97:45:ab:10:44:a2:f1:b7:06:d1:2d:54:a3:
34:85:40:e2:6f:8b:6f:7f:84:a4:e5:e5:23:6d:f9:e3:b5:63:
55:23:f5:14:7f:c1:b9:b4:68:86:c4:75:d9:fa:03:fc:c8:aa:
26:a7:38:44:be:7d:c6:3c:1d:60:7b:31:83:6b:76:43:95:f3:
2a:9a:2d:71:86:ea:fb:8a:2c:2a:f2:7e:79:a5:78:cf:cf:aa:
92:67:1a:01:2b:4f:32:a9:2e:48:10:27:89:77:67:1c:ba:97:
3d:05:2e:38:ff:6c:a6:9b:13:2a:20:9c:8e:b3:32:3f:11:51:
5f:28:3d:c3:21:64:8f:7a:0b:df:62:8e:7a:27:57:86:90:cd:
58:69:4f:51:9d:b3:0e:cb:47:68:1e:2f:8e:a4:58:9a:5b:f2:
a9:51:0b:2f:22:8a:14:b7:69:d1:22:bf:10:a8:59:ca:0e:7f:
16:18:80:0f:e6:42:5a:7d:2f:b0:2f:c5:c1:35:9d:99:75:57:
c4:0d:0d:be:da:23:9e:82:d0:14:c7:12:07:1d:b7:9d:44:09:
84:83:d0:31:fc:aa:c5:bb:f3:ba:e9:a0:60:01:df:5d:4b:f6:
73:5b:98:62:a0:82:ae:5c:8d:41:6b:e7:d0:62:c2:70:80:51:
43:8f:6d:f5:52:3e:1c:a3:18:9b:c1:12:eb:f3:f0:89:59:3b:
44:c1:3c:33:fa:30:99:86:7a:1a:01:e7:8a:1e:41:04:7f:96:
9d:63:c8:93:ee:76:05:15:8d:16:59:45:e0:99:36:e2:16:68:
ea:54:13:3b:98:12:2e:30:84:c5:0f:c1:63:10:0c:a6:d0:93:
73:54:c7:5d:10:aa:3b:9a:4d:0a:82:e8:e2:0f:3a:cb:93:a1:
97:1c:d7:51:eb:ba:be:ed:84:cc:76:a7:73:e0:9a:18:b5:9b:
eb:d4:fc:a7:b2:3a:90:fa:71:d8:c8:e3:88:f9:25:44:a4:63:
f1:4d:ab:d5:1e:04:62:d9:40:a0:ea:e7:f7:78:03:12:90:c4:
02:58:fd:ef:62:2d:78:85:e5:f6:25:20:85:8e:e5:52:a2:0d:
4e:9d:a1:4a:1b:4b:17:9a:ba:9c:42:08:0b:f3:85:8c:8d:00:
76:b9:48:4f:11:cb:d2:42:03:06:a5:2c:38:15:40:39:ec:3b:
c4:ca:bf:07:c0:33:54:6e:6f:7a:21:f6:47:1f:95:3a:24:56:
06:73:c2:84:1e:c1:9d:6c:02:81:61:87:3a:58:f7:62:fb:55:
c9:34:9c:c2:52:dd:8c:3a:51:a0:1b:d2:ab:5e:d3:50:a2:e5:
2a:ab:85:95:de:a0:a2:fc
-----BEGIN CERTIFICATE-----
MIIFuzCCA6OgAwIBAgIULZLZRnBJWVg80BIG7T7uFfMXYtQwDQYJKoZIhvcNAQEL
BQAwgYQxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNeSBTdGF0ZTEQMA4GA1UEBwwH
TXkgQ2l0eTEYMBYGA1UEAwwPY2FXaXRoTXVsdGlVSURzMRowGAYJKwYBBAGDwlMC
DAtjbGllbnRfdWlkMTEaMBgGCSsGAQQBg8JTAgwLY2xpZW50X3VpZDIwIBcNMjQx
MTAyMTk0NDUyWhgPMjEyNDEwMDkxOTQ0NTJaMIGEMQswCQYDVQQGEwJVUzERMA8G
A1UECAwITXkgU3RhdGUxEDAOBgNVBAcMB015IENpdHkxGDAWBgNVBAMMD2NhV2l0
aE11bHRpVUlEczEaMBgGCSsGAQQBg8JTAgwLY2xpZW50X3VpZDExGjAYBgkrBgEE
AYPCUwIMC2NsaWVudF91aWQyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEApMGdbqLnrwcUf18AYJIb7FF3PayTTais7hWTnV9iRF2XcKLJY1l5eYSGmC5L
y/2ZLucMfeLDZfWAXbs4Pw4JEUCfVrCRBCtmAqQomvyk6Q1r8DFBkJXyStevXVD4
KB1tKwHkOL8VnJ6TK0R+KTPAlmZPX0N0wuvJReEWIjO32ZNfHK+7lfVkFVMVw6ZM
Dixu90XBxUrDjCnDQqrh61Pawg2c3FrhAZxZtEMcK8X/18/PTHake84AoXhKOA/z
q0gPXoZJfySFcdvIPH7c9SZfVKqm4kGDPFvr5PDkdnijgmhGsVBUp9DEqhJN/X+0
wpLx0C0K6d+bD5WIlD93NVfmjqexUJqAUWIZSZssgfWXs/Qjt5Seli4i025qVlB3
HK06YFLrtro0/vUeuv3j3LidwVmyQvpeiNP+Sho9HaZVzq/cceeKSt03AApkeRSz
Ke18SkLG8Thy5TYZZJ88I4qx7hinfs8SSFMMJ/sSgmK8mn/8XZeuLTi9/3QjG2Ic
LkomfoVsbYIBlpWGFRzbQNkB1t9obelbC23Mb0CVNPi0HBOrlQ9bC9xlk4egTA3m
sAqmfqwLBG357kJ7FA+0IlPiWLxvBUHw0zqYGsQ6bguphf7pTXpQtE0ovfxqeOK4
nc0Vo6wDqZQ4jpSxABL8H3AbuPQae6nMF8UqQsZAx7RAuv0CAwEAAaMhMB8wHQYD
VR0OBBYEFIdAP+fdc8imYmqyjq+CUvaNJsFoMA0GCSqGSIb3DQEBCwUAA4ICAQA8
n8iGK5dFqxBEovG3BtEtVKM0hUDib4tvf4Sk5eUjbfnjtWNVI/UUf8G5tGiGxHXZ
+gP8yKompzhEvn3GPB1gezGDa3ZDlfMqmi1xhur7iiwq8n55pXjPz6qSZxoBK08y
qS5IECeJd2ccupc9BS44/2ymmxMqIJyOszI/EVFfKD3DIWSPegvfYo56J1eGkM1Y
aU9RnbMOy0doHi+OpFiaW/KpUQsvIooUt2nRIr8QqFnKDn8WGIAP5kJafS+wL8XB
NZ2ZdVfEDQ2+2iOegtAUxxIHHbedRAmEg9Ax/KrFu/O66aBgAd9dS/ZzW5hioIKu
XI1Ba+fQYsJwgFFDj231Uj4coxibwRLr8/CJWTtEwTwz+jCZhnoaAeeKHkEEf5ad
Y8iT7nYFFY0WWUXgmTbiFmjqVBM7mBIuMITFD8FjEAym0JNzVMddEKo7mk0Kguji
DzrLk6GXHNdR67q+7YTMdqdz4JoYtZvr1PynsjqQ+nHYyOOI+SVEpGPxTavVHgRi
2UCg6uf3eAMSkMQCWP3vYi14heX2JSCFjuVSog1OnaFKG0sXmrqcQggL84WMjQB2
uUhPEcvSQgMGpSw4FUA57DvEyr8HwDNUbm96IfZHH5U6JFYGc8KEHsGdbAKBYYc6
WPdi+1XJNJzCUt2MOlGgG9KrXtNQouUqq4WV3qCi/A==
-----END CERTIFICATE-----`
/*
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 36500 \
@ -584,6 +730,9 @@ func TestX509(t *testing.T) {
ExpectOK bool
ExpectResponse *authenticator.Response
ExpectErr bool
ExpectErrMsg *regexp.Regexp
setupFunc func(t *testing.T)
}{
"non-tls": {
Insecure: true,
@ -623,14 +772,35 @@ func TestX509(t *testing.T) {
Name: "127.0.0.1",
Groups: []string{"My Org"},
Extra: map[string][]string{
user.CredentialIDKey: {"X509SHA256=92209d1e0dd36a018f244f5e1b88e2d47b049e9cfcd4b7c87c65875866872230"},
user.CredentialIDKey: {"X509SHA256=04adf2b65e6325a8c467256eb3a9a373d818398d9a1f1d9eca1cbc2c237fe75f"},
},
},
},
ExpectErr: false,
},
"common name": {
"common name and UID": {
Opts: getDefaultVerifyOptions(t),
Certs: getCerts(t, clientCNCert),
User: CommonNameUserConversion,
ExpectOK: true,
ExpectResponse: &authenticator.Response{
User: &user.DefaultInfo{
Name: "client_cn",
Groups: []string{"My Org"},
UID: "client_id",
Extra: map[string][]string{
user.CredentialIDKey: {"X509SHA256=0a016b6c2ff14c5431e4a2b448e941fcaa21fb3d7ad105e9a53d4e8ce12824f0"},
},
},
},
ExpectErr: false,
setupFunc: func(t *testing.T) {
t.Helper()
},
},
"common name and empty UID with feature gate disabled": {
Opts: getDefaultVerifyOptions(t),
Certs: getCerts(t, clientCNCert),
User: CommonNameUserConversion,
@ -641,11 +811,50 @@ func TestX509(t *testing.T) {
Name: "client_cn",
Groups: []string{"My Org"},
Extra: map[string][]string{
user.CredentialIDKey: {"X509SHA256=dd0a6a295055fa94455c522b0d54ef0499186f454a7cf978b8b346dc35b254f7"},
user.CredentialIDKey: {"X509SHA256=0a016b6c2ff14c5431e4a2b448e941fcaa21fb3d7ad105e9a53d4e8ce12824f0"},
},
},
},
ExpectErr: false,
setupFunc: func(t *testing.T) {
t.Helper()
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.AllowParsingUserUIDFromCertAuth, false)
},
},
"ca with empty UID": {
Opts: getDefaultVerifyOptions(t),
Certs: toCertWithUIDValue(t, clientCNCert, ""),
User: CommonNameUserConversion,
ExpectOK: false,
ExpectErr: true,
ExpectErrMsg: regexp.MustCompile("UID cannot be an empty string"),
setupFunc: func(t *testing.T) {
t.Helper()
},
},
"ca with non-string UID": {
Opts: getDefaultVerifyOptions(t),
Certs: toCertWithUIDValue(t, clientCNCert, asn1.RawValue{Tag: 16, Bytes: []byte("custom_value")}),
User: CommonNameUserConversion,
ExpectOK: false,
ExpectErr: true,
ExpectErrMsg: regexp.MustCompile("unable to parse UID into a string"),
setupFunc: func(t *testing.T) {
t.Helper()
},
},
"ca with multiple UIDs": {
Opts: x509.VerifyOptions{
Roots: getRootCertPoolFor(t, caWithMultiUIDs),
},
Certs: getCerts(t, caWithMultiUIDs),
User: CommonNameUserConversion,
ExpectOK: false,
ExpectErr: true,
ExpectErrMsg: regexp.MustCompile("expected 1 UID, but found multiple"),
setupFunc: func(t *testing.T) {
t.Helper()
},
},
"ca with multiple organizations": {
Opts: x509.VerifyOptions{
@ -744,6 +953,10 @@ func TestX509(t *testing.T) {
for k, testCase := range testCases {
t.Run(k, func(t *testing.T) {
if testCase.setupFunc != nil {
testCase.setupFunc(t)
}
req, _ := http.NewRequest("GET", "/", nil)
if !testCase.Insecure {
req.TLS = &tls.ConnectionState{PeerCertificates: testCase.Certs}
@ -760,6 +973,9 @@ func TestX509(t *testing.T) {
if !testCase.ExpectErr && err != nil {
t.Fatalf("Got unexpected error: %v", err)
}
if testCase.ExpectErrMsg != nil && err != nil {
assert.Regexp(t, testCase.ExpectErrMsg, err.Error())
}
if testCase.ExpectOK != ok {
t.Fatalf("Expected ok=%v, got %v", testCase.ExpectOK, ok)
@ -956,7 +1172,7 @@ func getCertsFromFile(t *testing.T, names ...string) []*x509.Certificate {
certs := []*x509.Certificate{}
for _, name := range names {
filename := "testdata/" + name + ".pem"
data, err := ioutil.ReadFile(filename)
data, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("error reading %s: %v", filename, err)
}
@ -985,6 +1201,29 @@ func getCerts(t *testing.T, pemData ...string) []*x509.Certificate {
return certs
}
// Modifies the cert's Subject to use custom value for the UID.
func toCertWithUIDValue(t *testing.T, pemData string, val any) []*x509.Certificate {
cert := getCert(t, pemData)
oid := asn1util.X509UID()
attrs := []pkix.AttributeTypeAndValue{}
for _, attr := range cert.Subject.Names {
if !attr.Type.Equal(oid) {
attrs = append(attrs, attr)
}
}
cert.Subject.Names = attrs
cert.Subject.Names = append(
cert.Subject.Names,
pkix.AttributeTypeAndValue{
Type: asn1util.X509UID(),
Value: val,
},
)
return []*x509.Certificate{cert}
}
func TestCertificateIdentifier(t *testing.T) {
tt := []struct {
name string
@ -994,7 +1233,7 @@ func TestCertificateIdentifier(t *testing.T) {
{
name: "client cert",
cert: getCert(t, clientCNCert),
expectedIdentifier: "SN=1, SKID=FB:77:D6:D0:84:A8:10:DF:FA:4E:A4:E0:F1:2A:BB:B4:80:FD:4F:3F, AKID=D3:07:CD:72:E6:BE:0A:5A:D8:E9:60:20:AF:C2:F2:36:7E:33:62:0B",
expectedIdentifier: "SN=1, SKID=64:84:5E:B7:37:A2:82:F9:62:1A:01:00:FE:1B:B4:4B:F4:18:92:F6, AKID=48:70:75:D4:ED:6B:49:3B:53:DB:E9:A6:F9:9C:55:92:51:BD:96:E6",
},
{
name: "nil serial",
@ -1003,7 +1242,7 @@ func TestCertificateIdentifier(t *testing.T) {
c.SerialNumber = nil
return c
}(),
expectedIdentifier: "SN=<nil>, SKID=FB:77:D6:D0:84:A8:10:DF:FA:4E:A4:E0:F1:2A:BB:B4:80:FD:4F:3F, AKID=D3:07:CD:72:E6:BE:0A:5A:D8:E9:60:20:AF:C2:F2:36:7E:33:62:0B",
expectedIdentifier: "SN=<nil>, SKID=64:84:5E:B7:37:A2:82:F9:62:1A:01:00:FE:1B:B4:4B:F4:18:92:F6, AKID=48:70:75:D4:ED:6B:49:3B:53:DB:E9:A6:F9:9C:55:92:51:BD:96:E6",
},
{
name: "empty SKID",
@ -1012,7 +1251,7 @@ func TestCertificateIdentifier(t *testing.T) {
c.SubjectKeyId = nil
return c
}(),
expectedIdentifier: "SN=1, SKID=, AKID=D3:07:CD:72:E6:BE:0A:5A:D8:E9:60:20:AF:C2:F2:36:7E:33:62:0B",
expectedIdentifier: "SN=1, SKID=, AKID=48:70:75:D4:ED:6B:49:3B:53:DB:E9:A6:F9:9C:55:92:51:BD:96:E6",
},
{
name: "empty AKID",
@ -1021,7 +1260,7 @@ func TestCertificateIdentifier(t *testing.T) {
c.AuthorityKeyId = nil
return c
}(),
expectedIdentifier: "SN=1, SKID=FB:77:D6:D0:84:A8:10:DF:FA:4E:A4:E0:F1:2A:BB:B4:80:FD:4F:3F, AKID=",
expectedIdentifier: "SN=1, SKID=64:84:5E:B7:37:A2:82:F9:62:1A:01:00:FE:1B:B4:4B:F4:18:92:F6, AKID=",
},
{
name: "self-signed",

View File

@ -33,7 +33,6 @@ import (
"golang.org/x/sync/singleflight"
apierrors "k8s.io/apimachinery/pkg/api/errors"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/warning"
@ -199,12 +198,9 @@ func (a *cachedTokenAuthenticator) doAuthenticateToken(ctx context.Context, toke
ctx = audit.WithAuditContext(ctx)
ac := audit.AuditContextFrom(ctx)
// since this is shared work between multiple requests, we have no way of knowing if any
// particular request supports audit annotations. thus we always attempt to record them.
ac.Event.Level = auditinternal.LevelMetadata
record.resp, record.ok, record.err = a.authenticator.AuthenticateToken(ctx, token)
record.annotations = ac.Event.Annotations
record.annotations = ac.GetEventAnnotations()
record.warnings = recorder.extractWarnings()
if !a.cacheErrs && record.err != nil {

View File

@ -35,7 +35,6 @@ import (
utilrand "k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/uuid"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
@ -306,7 +305,7 @@ func TestCachedAuditAnnotations(t *testing.T) {
ctx := withAudit(context.Background())
_, _, _ = a.AuthenticateToken(ctx, "token")
allAnnotations <- audit.AuditEventFrom(ctx).Annotations
allAnnotations <- audit.AuditContextFrom(ctx).GetEventAnnotations()
}()
}
@ -343,7 +342,7 @@ func TestCachedAuditAnnotations(t *testing.T) {
for i := 0; i < cap(allAnnotations); i++ {
ctx := withAudit(context.Background())
_, _, _ = a.AuthenticateToken(ctx, "token")
allAnnotations = append(allAnnotations, audit.AuditEventFrom(ctx).Annotations)
allAnnotations = append(allAnnotations, audit.AuditContextFrom(ctx).GetEventAnnotations())
}
if len(allAnnotations) != cap(allAnnotations) {
@ -370,14 +369,14 @@ func TestCachedAuditAnnotations(t *testing.T) {
ctx1 := withAudit(context.Background())
_, _, _ = a.AuthenticateToken(ctx1, "token1")
annotations1 := audit.AuditEventFrom(ctx1).Annotations
annotations1 := audit.AuditContextFrom(ctx1).GetEventAnnotations()
// guarantee different now times
time.Sleep(time.Second)
ctx2 := withAudit(context.Background())
_, _, _ = a.AuthenticateToken(ctx2, "token2")
annotations2 := audit.AuditEventFrom(ctx2).Annotations
annotations2 := audit.AuditContextFrom(ctx2).GetEventAnnotations()
if ok := len(annotations1) == 1 && len(annotations1["timestamp"]) > 0; !ok {
t.Errorf("invalid annotations 1: %v", annotations1)
@ -546,13 +545,10 @@ func (s *singleBenchmark) bench(b *testing.B) {
// extraction.
func withAudit(ctx context.Context) context.Context {
ctx = audit.WithAuditContext(ctx)
ac := audit.AuditContextFrom(ctx)
ac.Event.Level = auditinternal.LevelMetadata
return ctx
}
func TestUnsafeConversions(t *testing.T) {
t.Parallel()
// needs to be large to force allocations so we pick a random value between [1024, 2048]
size := utilrand.IntnRange(1024, 2048+1)
@ -574,7 +570,6 @@ func TestUnsafeConversions(t *testing.T) {
})
t.Run("toBytes allocations", func(t *testing.T) {
t.Parallel()
s := utilrand.String(size)
f := func() {
@ -606,7 +601,6 @@ func TestUnsafeConversions(t *testing.T) {
})
t.Run("toString allocations", func(t *testing.T) {
t.Parallel()
b := make([]byte, size)
if _, err := rand.Read(b); err != nil {

View File

@ -18,7 +18,6 @@ package tokenfile
import (
"context"
"io/ioutil"
"os"
"reflect"
"testing"
@ -137,14 +136,14 @@ func TestEmptyTokenTokenFile(t *testing.T) {
}
func newWithContents(t *testing.T, contents string) (auth *TokenAuthenticator, err error) {
f, err := ioutil.TempFile("", "tokenfile_test")
f, err := os.CreateTemp("", "tokenfile_test")
if err != nil {
t.Fatalf("unexpected error creating tokenfile: %v", err)
}
f.Close()
defer os.Remove(f.Name())
if err := ioutil.WriteFile(f.Name(), []byte(contents), 0700); err != nil {
if err := os.WriteFile(f.Name(), []byte(contents), 0700); err != nil {
t.Fatalf("unexpected error writing tokenfile: %v", err)
}

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package user contains utilities for dealing with simple user exchange in the auth
// packages. The user.Info interface defines an interface for exchanging that info.
package user // import "k8s.io/apiserver/pkg/authentication/user"
package user

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package path contains an authorizer that allows certain paths and path prefixes.
package path // import "k8s.io/apiserver/pkg/authorization/path"
package path

View File

@ -105,23 +105,13 @@ func (p *ResolverTypeProvider) FindIdent(identName string) (ref.Val, bool) {
return p.underlyingTypeProvider.FindIdent(identName)
}
// ResolverEnvOption creates the ResolverTypeProvider with a given DynamicTypeResolver,
// and also returns the CEL ResolverEnvOption to apply it to the env.
// ResolverEnvOption creates the ResolverTypeProvider with a given DynamicTypeResolver
// and returns the CEL ResolverEnvOption to apply it to the env.
func ResolverEnvOption(resolver TypeResolver) cel.EnvOption {
_, envOpt := NewResolverTypeProviderAndEnvOption(resolver)
return envOpt
}
// NewResolverTypeProviderAndEnvOption creates the ResolverTypeProvider with a given DynamicTypeResolver,
// and also returns the CEL ResolverEnvOption to apply it to the env.
func NewResolverTypeProviderAndEnvOption(resolver TypeResolver) (*ResolverTypeProvider, cel.EnvOption) {
tp := &ResolverTypeProvider{typeResolver: resolver}
var envOption cel.EnvOption = func(e *cel.Env) (*cel.Env, error) {
// wrap the existing type provider (acquired from the env)
// and set new type provider for the env.
tp.underlyingTypeProvider = e.CELTypeProvider()
return func(e *cel.Env) (*cel.Env, error) {
tp := &ResolverTypeProvider{typeResolver: resolver, underlyingTypeProvider: e.CELTypeProvider()}
// set new type provider for the env.
typeProviderOption := cel.CustomTypeProvider(tp)
return typeProviderOption(e)
}
return tp, envOption
}

View File

@ -58,7 +58,7 @@ func TestTypeProvider(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
_, option := NewResolverTypeProviderAndEnvOption(&mockTypeResolver{})
option := ResolverEnvOption(&mockTypeResolver{})
env := mustCreateEnv(t, option)
ast, issues := env.Compile(tc.expression)
if len(tc.expectCompileError) > 0 {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,678 @@
/*
Copyright 2025 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"encoding/json"
"fmt"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"reflect"
"sigs.k8s.io/structured-merge-diff/v4/value"
"sync"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
)
// TypedToVal wraps "typed" Go value as CEL ref.Val types using reflection.
// "typed" values must be values declared by Kubernetes API types.go definitions.
func TypedToVal(val interface{}, schema Schema) ref.Val {
if val == nil {
return types.NullValue
}
v := reflect.ValueOf(val)
if !v.IsValid() {
return types.NewErr("invalid data, got invalid reflect value: %v", v)
}
for v.Kind() == reflect.Pointer {
if v.IsNil() {
return types.NullValue
}
v = v.Elem()
}
val = v.Interface()
switch typedVal := val.(type) {
case bool:
return types.Bool(typedVal)
case int:
return types.Int(typedVal)
case int32:
return types.Int(typedVal)
case int64:
return types.Int(typedVal)
case float32:
return types.Double(typedVal)
case float64:
return types.Double(typedVal)
case string:
return types.String(typedVal)
case []byte:
if typedVal == nil {
return types.NullValue
}
return types.Bytes(typedVal)
case metav1.Time:
return types.Timestamp{Time: typedVal.Time}
case metav1.MicroTime:
return types.Timestamp{Time: typedVal.Time}
case metav1.Duration:
return types.Duration{Duration: typedVal.Duration}
case intstr.IntOrString:
switch typedVal.Type {
case intstr.Int:
return types.Int(typedVal.IntVal)
case intstr.String:
return types.String(typedVal.StrVal)
}
case resource.Quantity:
// For compatibility with CRD Validation rules, represent quantity as a plain string.
return types.String(typedVal.String())
case json.Marshaler:
// All JSON marshaled types must be mapped to a CEL type in the above switch.
// This ensures that all types are purposefully mapped to CEL types.
return types.NewErr("unsupported Go type for CEL: %T", typedVal)
default:
// continue on to the next switch
}
switch v.Kind() {
case reflect.Slice:
if schema.Items() == nil {
return types.NewErr("invalid schema for slice type: %v", schema)
}
typedList := typedList{value: v, itemsSchema: schema.Items()}
listType := schema.XListType()
if listType != "" {
switch listType {
case "map":
mapKeys := schema.XListMapKeys()
return &typedMapList{typedList: typedList, escapedKeyProps: escapeKeyProps(mapKeys)}
case "set":
return &typedSetList{typedList: typedList}
case "atomic":
return &typedList
default:
return types.NewErr("invalid x-kubernetes-list-type, expected 'map', 'set' or 'atomic' but got %s", listType)
}
}
return &typedList
case reflect.Map:
if schema.AdditionalProperties() == nil || schema.AdditionalProperties().Schema() == nil {
return types.NewErr("invalid schema for map type: %v", schema)
}
return &typedMap{value: v, valuesSchema: schema.AdditionalProperties().Schema()}
case reflect.Struct:
if schema.Properties() == nil {
return types.NewErr("invalid schema for struct type: %v", schema)
}
return &typedStruct{
value: v,
propSchema: func(key string) (Schema, bool) {
if schema, ok := schema.Properties()[key]; ok {
return schema, true
}
return nil, false
},
}
// Match type aliases to primitives by kind
case reflect.Bool:
return types.Bool(v.Bool())
case reflect.String:
return types.String(v.String())
case reflect.Int, reflect.Int32, reflect.Int64:
return types.Int(v.Int())
case reflect.Float32, reflect.Float64:
return types.Double(v.Float())
default:
return types.NewErr("unsupported Go type for CEL: %v", v.Type())
}
}
// typedStruct wraps a struct as a CEL ref.Val and provides lazy access to fields via reflection.
type typedStruct struct {
value reflect.Value // Kind is required to be: reflect.Struct
// propSchema finds the schema to use for a particular map key.
propSchema func(key string) (Schema, bool)
}
func (s *typedStruct) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
if s.value.Type().AssignableTo(typeDesc) {
return s.value.Interface(), nil
}
return nil, fmt.Errorf("type conversion error from struct type %v to %v", s.value.Type(), typeDesc)
}
func (s *typedStruct) ConvertToType(typeValue ref.Type) ref.Val {
switch typeValue {
case s.Type():
return s
case types.MapType:
return s
case types.TypeType:
return s.objType()
}
return types.NewErr("type conversion error from struct %s to %s", s.Type().TypeName(), typeValue.TypeName())
}
func (s *typedStruct) Equal(other ref.Val) ref.Val {
otherStruct, ok := other.(*typedStruct)
if ok {
return types.Bool(apiequality.Semantic.DeepEqual(s.value.Interface(), otherStruct.value.Interface()))
}
return types.MaybeNoSuchOverloadErr(other)
}
func (s *typedStruct) Type() ref.Type {
return s.objType()
}
func (s *typedStruct) objType() *types.Type {
typeName := s.value.Type().Name()
if pkgPath := s.value.Type().PkgPath(); pkgPath != "" {
typeName = pkgPath + "." + typeName
}
return types.NewObjectType(typeName)
}
func (s *typedStruct) Value() interface{} {
return s.value.Interface()
}
func (s *typedStruct) IsSet(field ref.Val) ref.Val {
v, found := s.lookupField(field)
if v != nil && types.IsUnknownOrError(v) {
return v
}
return types.Bool(found)
}
func (s *typedStruct) Get(key ref.Val) ref.Val {
v, found := s.lookupField(key)
if !found {
return types.NewErr("no such key: %v", key)
}
return v
}
func (s *typedStruct) lookupField(key ref.Val) (ref.Val, bool) {
keyStr, ok := key.(types.String)
if !ok {
return types.MaybeNoSuchOverloadErr(key), true
}
fieldName := keyStr.Value().(string)
cacheEntry := value.TypeReflectEntryOf(s.value.Type())
fieldCache, ok := cacheEntry.Fields()[fieldName]
if !ok {
return nil, false
}
if e := fieldCache.GetFrom(s.value); !fieldCache.CanOmit(e) {
if propSchema, ok := s.propSchema(fieldName); ok {
v := TypedToVal(e.Interface(), propSchema)
if v == types.NullValue {
return nil, false
}
return v, true
}
}
return nil, false
}
type typedList struct {
value reflect.Value // Kind is required to be: reflect.Slice
itemsSchema Schema
}
func (t *typedList) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
switch typeDesc.Kind() {
case reflect.Slice:
return t.value.Interface(), nil
default:
return nil, fmt.Errorf("type conversion error from '%s' to '%s'", t.Type(), typeDesc)
}
}
func (t *typedList) ConvertToType(typeValue ref.Type) ref.Val {
switch typeValue {
case types.ListType:
return t
case types.TypeType:
return types.ListType
}
return types.NewErr("type conversion error from '%s' to '%s'", t.Type(), typeValue.TypeName())
}
func (t *typedList) Equal(other ref.Val) ref.Val {
oList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
sz := types.Int(t.value.Len())
if sz != oList.Size() {
return types.False
}
for i := types.Int(0); i < sz; i++ {
eq := t.Get(i).Equal(oList.Get(i))
if eq != types.True {
return eq // either false or error
}
}
return types.True
}
func (t *typedList) Type() ref.Type {
return types.ListType
}
func (t *typedList) Value() interface{} {
return t.value
}
func (t *typedList) Add(other ref.Val) ref.Val {
oList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
resultValue := t.value
for it := oList.Iterator(); it.HasNext() == types.True; {
next := it.Next().Value()
resultValue = reflect.Append(resultValue, reflect.ValueOf(next))
}
return &typedList{value: resultValue, itemsSchema: t.itemsSchema}
}
func (t *typedList) Contains(val ref.Val) ref.Val {
if types.IsUnknownOrError(val) {
return val
}
var err ref.Val
sz := t.value.Len()
for i := 0; i < sz; i++ {
elem := TypedToVal(t.value.Index(i).Interface(), t.itemsSchema)
cmp := elem.Equal(val)
b, ok := cmp.(types.Bool)
if !ok && err == nil {
err = types.MaybeNoSuchOverloadErr(cmp)
}
if b == types.True {
return types.True
}
}
if err != nil {
return err
}
return types.False
}
func (t *typedList) Get(idx ref.Val) ref.Val {
iv, isInt := idx.(types.Int)
if !isInt {
return types.ValOrErr(idx, "unsupported index: %v", idx)
}
i := int(iv)
if i < 0 || i >= t.value.Len() {
return types.NewErr("index out of bounds: %v", idx)
}
return TypedToVal(t.value.Index(i).Interface(), t.itemsSchema)
}
func (t *typedList) Iterator() traits.Iterator {
elements := make([]ref.Val, t.value.Len())
sz := t.value.Len()
for i := 0; i < sz; i++ {
elements[i] = TypedToVal(t.value.Index(i).Interface(), t.itemsSchema)
}
return &sliceIter{typedList: t, elements: elements}
}
func (t *typedList) Size() ref.Val {
return types.Int(t.value.Len())
}
type sliceIter struct {
*typedList
elements []ref.Val
idx int
}
func (it *sliceIter) HasNext() ref.Val {
return types.Bool(it.idx < len(it.elements))
}
func (it *sliceIter) Next() ref.Val {
if it.idx >= len(it.elements) {
return types.NewErr("iterator exhausted")
}
elem := it.elements[it.idx]
it.idx++
return elem
}
type typedMapList struct {
typedList
escapedKeyProps []string
sync.Once // for lazy load of mapOfList since it is only needed if Equals is called
mapOfList map[interface{}]interface{}
}
func (t *typedMapList) getMap() map[interface{}]interface{} {
t.Do(func() {
sz := t.value.Len()
t.mapOfList = make(map[interface{}]interface{}, sz)
for i := types.Int(0); i < types.Int(sz); i++ {
v := t.Get(i)
e := reflect.ValueOf(v.Value())
t.mapOfList[t.toMapKey(e)] = e.Interface()
}
})
return t.mapOfList
}
// toMapKey returns a valid golang map key for the given element of the map list.
// element must be a valid map list entry where all map key props are scalar types (which are comparable in go
// and valid for use in a golang map key).
func (t *typedMapList) toMapKey(element reflect.Value) interface{} {
if element.Kind() != reflect.Struct {
return types.NewErr("unexpected data format for element of array with x-kubernetes-list-type=map: %T", element)
}
cacheEntry := value.TypeReflectEntryOf(element.Type())
var fieldEntries []*value.FieldCacheEntry
for i := 0; i < len(t.escapedKeyProps); i++ {
if ce, ok := cacheEntry.Fields()[t.escapedKeyProps[i]]; !ok {
return types.NewErr("unexpected data format for element of array with x-kubernetes-list-type=map: %T", element)
} else {
fieldEntries = append(fieldEntries, ce)
}
}
// Arrays are comparable in go and may be used as map keys, but maps and slices are not.
// So we can special case small numbers of key props as arrays and fall back to serialization
// for larger numbers of key props
if len(fieldEntries) == 1 {
return fieldEntries[0].GetFrom(element).Interface()
}
if len(fieldEntries) == 2 {
return [2]interface{}{fieldEntries[0].GetFrom(element).Interface(), fieldEntries[1].GetFrom(element).Interface()}
}
if len(fieldEntries) == 3 {
return [3]interface{}{fieldEntries[0].GetFrom(element).Interface(), fieldEntries[1].GetFrom(element).Interface(), fieldEntries[3].GetFrom(element).Interface()}
}
key := make([]interface{}, len(fieldEntries))
for i := range fieldEntries {
key[i] = fieldEntries[i].GetFrom(element).Interface()
}
return fmt.Sprintf("%v", key)
}
// Equal on a map list ignores list element order.
func (t *typedMapList) Equal(other ref.Val) ref.Val {
oMapList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
sz := types.Int(t.value.Len())
if sz != oMapList.Size() {
return types.False
}
tMap := t.getMap()
for it := oMapList.Iterator(); it.HasNext() == types.True; {
v := it.Next()
k := t.toMapKey(reflect.ValueOf(v.Value()))
tVal, ok := tMap[k]
if !ok {
return types.False
}
eq := TypedToVal(tVal, t.itemsSchema).Equal(v)
if eq != types.True {
return eq // either false or error
}
}
return types.True
}
// Add for a map list `X + Y` performs a merge where the array positions of all keys in `X` are preserved but the values
// are overwritten by values in `Y` when the key sets of `X` and `Y` intersect. Elements in `Y` with
// non-intersecting keys are appended, retaining their partial order.
func (t *typedMapList) Add(other ref.Val) ref.Val {
sliceType := t.value.Type()
elementType := sliceType.Elem()
oMapList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
sz := t.value.Len()
elements := reflect.MakeSlice(sliceType, sz, sz)
keyToIdx := map[interface{}]int{}
for i := 0; i < sz; i++ {
e := t.Get(types.Int(i)).Value()
re := reflect.ValueOf(e)
k := t.toMapKey(re)
keyToIdx[k] = i
elements.Index(i).Set(re.Convert(elementType))
}
for it := oMapList.Iterator(); it.HasNext() == types.True; {
e := it.Next()
re := reflect.ValueOf(e.Value())
k := t.toMapKey(re)
if overwritePosition, ok := keyToIdx[k]; ok {
elements.Index(overwritePosition).Set(re)
} else {
elements = reflect.Append(elements, re.Convert(elementType))
}
}
return &typedMapList{
typedList: typedList{value: elements, itemsSchema: t.itemsSchema},
escapedKeyProps: t.escapedKeyProps,
}
}
type typedSetList struct {
typedList
sync.Once // for lazy load of setOfList since it is only needed if Equals is called
set map[interface{}]struct{}
}
func (t *typedSetList) getSet() map[interface{}]struct{} {
// sets are only allowed to contain scalar elements, which are comparable in go, and can safely be used as
// golang map keys
t.Do(func() {
sz := t.value.Len()
t.set = make(map[interface{}]struct{}, sz)
for i := types.Int(0); i < types.Int(sz); i++ {
e := t.Get(i).Value()
t.set[e] = struct{}{}
}
})
return t.set
}
// Equal on a map list ignores list element order.
func (t *typedSetList) Equal(other ref.Val) ref.Val {
oSetList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
sz := types.Int(t.value.Len())
if sz != oSetList.Size() {
return types.False
}
tSet := t.getSet()
for it := oSetList.Iterator(); it.HasNext() == types.True; {
next := it.Next().Value()
_, ok := tSet[next]
if !ok {
return types.False
}
}
return types.True
}
// Add for a set list `X + Y` performs a union where the array positions of all elements in `X` are preserved and
// non-intersecting elements in `Y` are appended, retaining their partial order.
func (t *typedSetList) Add(other ref.Val) ref.Val {
setType := t.value.Type()
elementType := setType.Elem()
oSetList, ok := other.(traits.Lister)
if !ok {
return types.MaybeNoSuchOverloadErr(other)
}
sz := t.value.Len()
elements := reflect.MakeSlice(setType, sz, sz)
for i := 0; i < sz; i++ {
e := t.Get(types.Int(i)).Value()
re := reflect.ValueOf(e)
elements.Index(i).Set(re.Convert(elementType))
}
set := t.getSet()
for it := oSetList.Iterator(); it.HasNext() == types.True; {
e := it.Next().Value()
re := reflect.ValueOf(e)
if _, ok := set[e]; !ok {
set[e] = struct{}{}
elements = reflect.Append(elements, re.Convert(elementType))
}
}
return &typedSetList{
typedList: typedList{value: elements, itemsSchema: t.itemsSchema},
}
}
type typedMap struct {
value reflect.Value // Kind is required to be: reflect.Map
valuesSchema Schema
}
func (t *typedMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
switch typeDesc.Kind() {
case reflect.Map:
return t.value, nil
default:
return nil, fmt.Errorf("type conversion error from '%s' to '%s'", t.Type(), typeDesc)
}
}
func (t *typedMap) ConvertToType(typeValue ref.Type) ref.Val {
switch typeValue {
case types.MapType:
return t
case types.TypeType:
return types.MapType
}
return types.NewErr("type conversion error from '%s' to '%s'", t.Type(), typeValue.TypeName())
}
func (t *typedMap) Equal(other ref.Val) ref.Val {
oMap, isMap := other.(traits.Mapper)
if !isMap {
return types.MaybeNoSuchOverloadErr(other)
}
if types.Int(t.value.Len()) != oMap.Size() {
return types.False
}
for it := t.value.MapRange(); it.Next(); {
key := it.Key()
value := it.Value()
ov, found := oMap.Find(types.String(key.String()))
if !found {
return types.False
}
v := TypedToVal(value.Interface(), t.valuesSchema)
vEq := v.Equal(ov)
if vEq != types.True {
return vEq // either false or error
}
}
return types.True
}
func (t *typedMap) Type() ref.Type {
return types.MapType
}
func (t *typedMap) Value() interface{} {
return t.value
}
func (t *typedMap) Contains(key ref.Val) ref.Val {
v, found := t.Find(key)
if v != nil && types.IsUnknownOrError(v) {
return v
}
return types.Bool(found)
}
func (t *typedMap) Get(key ref.Val) ref.Val {
v, found := t.Find(key)
if found {
return v
}
return types.ValOrErr(key, "no such key: %v", key)
}
func (t *typedMap) Size() ref.Val {
return types.Int(t.value.Len())
}
func (t *typedMap) Find(key ref.Val) (ref.Val, bool) {
keyStr, ok := key.(types.String)
if !ok {
return types.MaybeNoSuchOverloadErr(key), true
}
k := keyStr.Value().(string)
if v := t.value.MapIndex(reflect.ValueOf(k)); v.IsValid() {
return TypedToVal(v.Interface(), t.valuesSchema), true
}
return nil, false
}
func (t *typedMap) Iterator() traits.Iterator {
keys := make([]ref.Val, t.value.Len())
for i, k := range t.value.MapKeys() {
keys[i] = types.String(k.String())
}
return &mapIter{typedMap: t, keys: keys}
}
type mapIter struct {
*typedMap
keys []ref.Val
idx int
}
func (it *mapIter) HasNext() ref.Val {
return types.Bool(it.idx < len(it.keys))
}
func (it *mapIter) Next() ref.Val {
key := it.keys[it.idx]
it.idx++
return key
}

View File

@ -33,7 +33,7 @@ import (
)
// UnstructuredToVal converts a Kubernetes unstructured data element to a CEL Val.
// The root schema of custom resource schema is expected contain type meta and object meta schemas.
// The root schema of custom resource schemas is expected to contain type meta and object meta schemas.
// If Embedded resources do not contain type meta and object meta schemas, they will be added automatically.
func UnstructuredToVal(unstructured interface{}, schema Schema) ref.Val {
if unstructured == nil {
@ -358,9 +358,8 @@ func escapeKeyProps(idents []string) []string {
// unstructuredSetList represents an unstructured data instance of an OpenAPI array with x-kubernetes-list-type=set.
type unstructuredSetList struct {
unstructuredList
escapedKeyProps []string
sync.Once // for for lazy load of setOfList since it is only needed if Equals is called
sync.Once // for lazy load of setOfList since it is only needed if Equals is called
set map[interface{}]struct{}
}
@ -415,7 +414,6 @@ func (t *unstructuredSetList) Add(other ref.Val) ref.Val {
}
return &unstructuredSetList{
unstructuredList: unstructuredList{elements: elements, itemsSchema: t.itemsSchema},
escapedKeyProps: t.escapedKeyProps,
}
}
@ -600,13 +598,17 @@ func (t *unstructuredMap) Equal(other ref.Val) ref.Val {
if t.Size() != oMap.Size() {
return types.False
}
for key, value := range t.value {
if propSchema, ok := t.propSchema(key); ok {
ov, found := oMap.Find(types.String(key))
if !found {
if _, ok := t.propSchema(key); ok {
v, found := t.Find(types.String(key))
ov, oFound := oMap.Find(types.String(key))
if found != oFound {
return types.False
}
v := UnstructuredToVal(value, propSchema)
if !found {
continue
}
vEq := v.Equal(ov)
if vEq != types.True {
return vEq // either false or error

View File

@ -32,9 +32,9 @@ import (
celconfig "k8s.io/apiserver/pkg/apis/cel"
"k8s.io/apiserver/pkg/cel/library"
genericfeatures "k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/util/compatibility"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/featuregate"
utilversion "k8s.io/component-base/version"
basecompatibility "k8s.io/component-base/compatibility"
)
// DefaultCompatibilityVersion returns a default compatibility version for use with EnvSet
@ -50,9 +50,9 @@ import (
// A default version number equal to the current Kubernetes major.minor version
// indicates fast forward CEL features that can be used when rollback is no longer needed.
func DefaultCompatibilityVersion() *version.Version {
effectiveVer := featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
effectiveVer := compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent)
if effectiveVer == nil {
effectiveVer = utilversion.DefaultKubeEffectiveVersion()
effectiveVer = compatibility.DefaultBuildEffectiveVersion()
}
return effectiveVer.MinCompatibilityVersion()
}
@ -173,7 +173,14 @@ var baseOptsWithoutStrictCost = []VersionedOptions{
{
IntroducedVersion: version.MajorMinor(1, 32),
EnvOptions: []cel.EnvOption{
UnversionedLib(ext.TwoVarComprehensions),
ext.TwoVarComprehensions(),
},
},
// Semver
{
IntroducedVersion: version.MajorMinor(1, 33),
EnvOptions: []cel.EnvOption{
library.SemverLib(library.SemverVersion(1)),
},
},
}

View File

@ -19,9 +19,10 @@ package cel
import (
"fmt"
"regexp"
"strings"
"testing"
fuzz "github.com/google/gofuzz"
"sigs.k8s.io/randfill"
)
// TestEscaping tests that property names are escaped as expected.
@ -142,10 +143,10 @@ func TestUnescapeMalformed(t *testing.T) {
}
func TestEscapingFuzz(t *testing.T) {
fuzzer := fuzz.New()
fuzzer := randfill.New()
for i := 0; i < 1000; i++ {
var unescaped string
fuzzer.Fuzz(&unescaped)
fuzzer.Fill(&unescaped)
t.Run(fmt.Sprintf("%d - '%s'", i, unescaped), func(t *testing.T) {
if len(unescaped) == 0 {
return
@ -204,3 +205,11 @@ func TestCanSkipRegex(t *testing.T) {
})
}
}
func TestCELReservedSymbolsNoDoubleUnderscore(t *testing.T) {
for symbol := range celReservedSymbols {
if strings.Contains(symbol, "__") {
t.Errorf("CEL reserved symbol '%s' contains '__', which is not allowed as it would interfere with escaping", symbol)
}
}
}

View File

@ -160,9 +160,7 @@ var cidrLibraryDecls = map[string][]cel.FunctionOpt{
}
func (*cidrs) CompileOptions() []cel.EnvOption {
options := []cel.EnvOption{cel.Types(apiservercel.CIDRType),
cel.Variable(apiservercel.CIDRType.TypeName(), types.NewTypeTypeWithParam(apiservercel.CIDRType)),
}
options := []cel.EnvOption{cel.Types(apiservercel.CIDRType)}
for name, overloads := range cidrLibraryDecls {
options = append(options, cel.Function(name, overloads...))
}
@ -231,8 +229,7 @@ func cidrContainsCIDR(arg ref.Val, other ref.Val) ref.Val {
return types.MaybeNoSuchOverloadErr(other)
}
equalMasked := cidr.Prefix.Masked() == netip.PrefixFrom(containsCIDR.Prefix.Addr(), cidr.Prefix.Bits())
return types.Bool(equalMasked && cidr.Prefix.Bits() <= containsCIDR.Prefix.Bits())
return types.Bool(cidr.Overlaps(containsCIDR.Prefix) && cidr.Prefix.Bits() <= containsCIDR.Prefix.Bits())
}
func prefixLength(arg ref.Val) ref.Val {

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