diff --git a/pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller_test.go b/pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller_test.go index d9e3a217dd6..0dfe2cbca13 100644 --- a/pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller_test.go +++ b/pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller_test.go @@ -30,11 +30,14 @@ import ( "k8s.io/apimachinery/pkg/util/dump" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/authentication/request/headerrequest" + "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/server/dynamiccertificates" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" corev1listers "k8s.io/client-go/listers/core/v1" clienttesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" + featuregatetesting "k8s.io/component-base/featuregate/testing" ) var ( @@ -95,6 +98,7 @@ func TestWriteClientCAs(t *testing.T) { preexistingObjs []runtime.Object expectedConfigMaps map[string]*corev1.ConfigMap expectCreate bool + uidGate bool }{ { name: "basic", @@ -107,6 +111,32 @@ func TestWriteClientCAs(t *testing.T) { RequestHeaderCA: anotherRandomCAProvider, RequestHeaderAllowedNames: headerrequest.StaticStringSlice{"first", "second"}, }, + expectedConfigMaps: map[string]*corev1.ConfigMap{ + "extension-apiserver-authentication": { + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "client-ca-file": string(someRandomCA), + "requestheader-username-headers": `["alfa","bravo","charlie"]`, + "requestheader-group-headers": `["delta"]`, + "requestheader-extra-headers-prefix": `["echo","foxtrot"]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `["first","second"]`, + }, + }, + }, + expectCreate: true, + }, + { + name: "basic with feature gate", + clusterAuthInfo: ClusterAuthenticationInfo{ + ClientCA: someRandomCAProvider, + RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{"alfa", "bravo", "charlie"}, + RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{"golf", "hotel", "india"}, + RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{"delta"}, + RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{"echo", "foxtrot"}, + RequestHeaderCA: anotherRandomCAProvider, + RequestHeaderAllowedNames: headerrequest.StaticStringSlice{"first", "second"}, + }, expectedConfigMaps: map[string]*corev1.ConfigMap{ "extension-apiserver-authentication": { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, @@ -122,6 +152,7 @@ func TestWriteClientCAs(t *testing.T) { }, }, expectCreate: true, + uidGate: true, }, { name: "skip extension-apiserver-authentication", @@ -134,7 +165,6 @@ func TestWriteClientCAs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(anotherRandomCA), @@ -169,7 +199,6 @@ func TestWriteClientCAs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(anotherRandomCA), @@ -205,7 +234,6 @@ func TestWriteClientCAs(t *testing.T) { name: "overwrite extension-apiserver-authentication requestheader", clusterAuthInfo: ClusterAuthenticationInfo{ RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{}, - RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{}, RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{}, RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{}, RequestHeaderCA: anotherRandomCAProvider, @@ -216,7 +244,6 @@ func TestWriteClientCAs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(someRandomCA), @@ -229,7 +256,6 @@ func TestWriteClientCAs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(someRandomCA) + string(anotherRandomCA), @@ -260,7 +286,6 @@ func TestWriteClientCAs(t *testing.T) { name: "skip on no change", clusterAuthInfo: ClusterAuthenticationInfo{ RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{}, - RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{}, RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{}, RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{}, RequestHeaderCA: anotherRandomCAProvider, @@ -271,7 +296,6 @@ func TestWriteClientCAs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(anotherRandomCA), @@ -282,10 +306,126 @@ func TestWriteClientCAs(t *testing.T) { expectedConfigMaps: map[string]*corev1.ConfigMap{}, expectCreate: false, }, + { + name: "drop uid without feature gate", + clusterAuthInfo: ClusterAuthenticationInfo{ + RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{"panda"}, + RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{}, + RequestHeaderCA: anotherRandomCAProvider, + RequestHeaderAllowedNames: headerrequest.StaticStringSlice{}, + }, + preexistingObjs: []runtime.Object{ + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-uid-headers": `["snorlax"]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectedConfigMaps: map[string]*corev1.ConfigMap{ + "extension-apiserver-authentication": { + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectCreate: false, + }, + { + name: "add uid with feature gate", + clusterAuthInfo: ClusterAuthenticationInfo{ + RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{"panda"}, + RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{}, + RequestHeaderCA: anotherRandomCAProvider, + RequestHeaderAllowedNames: headerrequest.StaticStringSlice{}, + }, + preexistingObjs: []runtime.Object{ + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectedConfigMaps: map[string]*corev1.ConfigMap{ + "extension-apiserver-authentication": { + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-uid-headers": `["panda"]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectCreate: false, + uidGate: true, + }, + { + name: "append uid with feature gate", + clusterAuthInfo: ClusterAuthenticationInfo{ + RequestHeaderUsernameHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderUIDHeaders: headerrequest.StaticStringSlice{"panda"}, + RequestHeaderGroupHeaders: headerrequest.StaticStringSlice{}, + RequestHeaderExtraHeaderPrefixes: headerrequest.StaticStringSlice{}, + RequestHeaderCA: anotherRandomCAProvider, + RequestHeaderAllowedNames: headerrequest.StaticStringSlice{}, + }, + preexistingObjs: []runtime.Object{ + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-uid-headers": `["snorlax"]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectedConfigMaps: map[string]*corev1.ConfigMap{ + "extension-apiserver-authentication": { + ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, + Data: map[string]string{ + "requestheader-username-headers": `[]`, + "requestheader-uid-headers": `["snorlax","panda"]`, + "requestheader-group-headers": `[]`, + "requestheader-extra-headers-prefix": `[]`, + "requestheader-client-ca-file": string(anotherRandomCA), + "requestheader-allowed-names": `[]`, + }, + }, + }, + expectCreate: false, + uidGate: true, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RemoteRequestHeaderUID, test.uidGate) + client := fake.NewSimpleClientset(test.preexistingObjs...) configMapIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) for _, obj := range test.preexistingObjs { @@ -341,7 +481,6 @@ func TestWriteConfigMapDeleted(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"}, Data: map[string]string{ "requestheader-username-headers": `[]`, - "requestheader-uid-headers": `[]`, "requestheader-group-headers": `[]`, "requestheader-extra-headers-prefix": `[]`, "requestheader-client-ca-file": string(anotherRandomCA), diff --git a/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go b/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go index eb28217aff5..e9d452fb8cb 100644 --- a/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go +++ b/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go @@ -99,7 +99,7 @@ func SetFeatureGateEmulationVersionDuringTest(tb TB, gate featuregate.FeatureGat detectParallelOverrideCleanup := detectParallelOverrideEmulationVersion(tb, ver) originalEmuVer := gate.(featuregate.MutableVersionedFeatureGate).EmulationVersion() if err := gate.(featuregate.MutableVersionedFeatureGate).SetEmulationVersion(ver); err != nil { - tb.Fatalf("failed to set emulation version to %s during test", ver.String()) + tb.Fatalf("failed to set emulation version to %s during test: %v", ver.String(), err) } tb.Cleanup(func() { tb.Helper() diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go index ecc85c7e198..a19cdd22fad 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go @@ -35,35 +35,33 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "k8s.io/apiserver/pkg/audit" - "k8s.io/apiserver/pkg/features" - "k8s.io/apiserver/pkg/server/dynamiccertificates" - "k8s.io/client-go/transport" - - "golang.org/x/net/websocket" - "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" + "golang.org/x/net/websocket" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/proxy" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/endpoints/filters" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/features" + "k8s.io/apiserver/pkg/server/dynamiccertificates" "k8s.io/apiserver/pkg/server/egressselector" utilfeature "k8s.io/apiserver/pkg/util/feature" utilflowcontrol "k8s.io/apiserver/pkg/util/flowcontrol" apiserverproxyutil "k8s.io/apiserver/pkg/util/proxy" + "k8s.io/client-go/transport" "k8s.io/component-base/featuregate" featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/component-base/metrics" "k8s.io/component-base/metrics/legacyregistry" apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" - "k8s.io/utils/pointer" "k8s.io/utils/ptr" ) @@ -145,7 +143,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", }, @@ -168,7 +166,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", InsecureSkipTLSVerify: true, @@ -201,7 +199,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", InsecureSkipTLSVerify: true, @@ -236,7 +234,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: testCACrt, @@ -269,7 +267,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: testCACrt, @@ -304,7 +302,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: testCACrt, @@ -328,7 +326,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "bad-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "bad-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: testCACrt, @@ -351,7 +349,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", }, @@ -373,7 +371,7 @@ func TestProxyHandler(t *testing.T) { apiService: &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: testCACrt, @@ -511,6 +509,8 @@ func newBrokenDialerAndSelector() (*mockEgressDialer, *egressselector.EgressSele } func TestProxyUpgrade(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RemoteRequestHeaderUID, true) + upgradeUser := "upgradeUser" upgradeUID := "upgradeUser-UID" testcases := map[string]struct { @@ -525,7 +525,7 @@ func TestProxyUpgrade(t *testing.T) { CABundle: testCACrt, Group: "mygroup", Version: "v1", - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, }, Status: apiregistration.APIServiceStatus{ Conditions: []apiregistration.APIServiceCondition{ @@ -542,7 +542,7 @@ func TestProxyUpgrade(t *testing.T) { InsecureSkipTLSVerify: true, Group: "mygroup", Version: "v1", - Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: ptr.To[int32](443)}, }, Status: apiregistration.APIServiceStatus{ Conditions: []apiregistration.APIServiceCondition{ @@ -559,7 +559,7 @@ func TestProxyUpgrade(t *testing.T) { CABundle: testCACrt, Group: "mygroup", Version: "v1", - Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: ptr.To[int32](443)}, }, Status: apiregistration.APIServiceStatus{ Conditions: []apiregistration.APIServiceCondition{ @@ -576,7 +576,7 @@ func TestProxyUpgrade(t *testing.T) { CABundle: testCACrt, Group: "mygroup", Version: "v1", - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, }, Status: apiregistration.APIServiceStatus{ Conditions: []apiregistration.APIServiceCondition{ @@ -594,7 +594,7 @@ func TestProxyUpgrade(t *testing.T) { CABundle: testCACrt, Group: "mygroup", Version: "v1", - Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: ptr.To[int32](443)}, }, Status: apiregistration.APIServiceStatus{ Conditions: []apiregistration.APIServiceCondition{ @@ -1075,7 +1075,7 @@ func TestProxyCertReload(t *testing.T) { apiService := &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, Spec: apiregistration.APIServiceSpec{ - Service: &apiregistration.ServiceReference{Name: "test-service2", Namespace: "test-ns", Port: pointer.Int32Ptr(443)}, + Service: &apiregistration.ServiceReference{Name: "test-service2", Namespace: "test-ns", Port: ptr.To[int32](443)}, Group: "foo", Version: "v1", CABundle: backendCaCertificate(), // used to validate backendCertificate() diff --git a/staging/src/k8s.io/sample-apiserver/main.go b/staging/src/k8s.io/sample-apiserver/main.go index 7dd8718c804..6550efa560e 100644 --- a/staging/src/k8s.io/sample-apiserver/main.go +++ b/staging/src/k8s.io/sample-apiserver/main.go @@ -27,7 +27,7 @@ import ( func main() { ctx := genericapiserver.SetupSignalContext() options := server.NewWardleServerOptions(os.Stdout, os.Stderr) - cmd := server.NewCommandStartWardleServer(ctx, options) + cmd := server.NewCommandStartWardleServer(ctx, options, false) code := cli.Run(cmd) os.Exit(code) } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go index 79df51f015b..852252dbb0d 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go @@ -90,12 +90,15 @@ func NewWardleServerOptions(out, errOut io.Writer) *WardleServerOptions { // NewCommandStartWardleServer provides a CLI handler for 'start master' command // with a default WardleServerOptions. -func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOptions) *cobra.Command { +func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOptions, skipDefaultComponentGlobalsRegistrySet bool) *cobra.Command { o := *defaults cmd := &cobra.Command{ Short: "Launch a wardle API server", Long: "Launch a wardle API server", PersistentPreRunE: func(*cobra.Command, []string) error { + if skipDefaultComponentGlobalsRegistrySet { + return nil + } return featuregate.DefaultComponentGlobalsRegistry.Set() }, RunE: func(c *cobra.Command, args []string) error { diff --git a/test/featuregates_linter/test_data/versioned_feature_list.yaml b/test/featuregates_linter/test_data/versioned_feature_list.yaml index 3e355898dd7..a25a113071a 100644 --- a/test/featuregates_linter/test_data/versioned_feature_list.yaml +++ b/test/featuregates_linter/test_data/versioned_feature_list.yaml @@ -1058,6 +1058,12 @@ lockToDefault: true preRelease: GA version: "1.29" +- name: RemoteRequestHeaderUID + versionedSpecs: + - default: false + lockToDefault: false + preRelease: Alpha + version: "1.32" - name: ResilientWatchCacheInitialization versionedSpecs: - default: true diff --git a/test/integration/auth/requestheader_test.go b/test/integration/auth/requestheader_test.go index 65198f2bc54..4654a795091 100644 --- a/test/integration/auth/requestheader_test.go +++ b/test/integration/auth/requestheader_test.go @@ -27,11 +27,14 @@ import ( authnv1 "k8s.io/api/authentication/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/features" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" certutil "k8s.io/client-go/util/cert" "k8s.io/client-go/util/keyutil" + featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/test/integration/framework" testutils "k8s.io/kubernetes/test/utils" @@ -39,6 +42,8 @@ import ( ) func TestAuthnToKAS(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RemoteRequestHeaderUID, true) + tCtx := ktesting.Init(t) frontProxyCA, frontProxyClient, frontProxyKey, err := newTestCAWithClient( diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index 36e3f7721d0..a50a8a846a5 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -45,8 +45,10 @@ import ( "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authentication/user" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/server/dynamiccertificates" genericapiserveroptions "k8s.io/apiserver/pkg/server/options" + utilfeature "k8s.io/apiserver/pkg/util/feature" client "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -54,6 +56,7 @@ import ( "k8s.io/client-go/transport" "k8s.io/client-go/util/cert" "k8s.io/component-base/featuregate" + featuregatetesting "k8s.io/component-base/featuregate/testing" utilversion "k8s.io/component-base/version" apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" @@ -260,6 +263,7 @@ func TestFrontProxyConfig(t *testing.T) { testFrontProxyConfig(t, false) }) t.Run("WithUID", func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RemoteRequestHeaderUID, true) testFrontProxyConfig(t, true) }) } @@ -282,7 +286,7 @@ func testFrontProxyConfig(t *testing.T, withUID bool) { kubeBinaryVersion := sampleserver.WardleVersionToKubeVersion(version.MustParse(wardleBinaryVersion)).String() // start up the KAS and prepare the options for the wardle API server - testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, extraKASFlags) + testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, extraKASFlags, withUID) kubeConfig := getKubeConfig(testKAS) // create the SA that we will use to query the aggregated API @@ -337,12 +341,12 @@ func testFrontProxyConfig(t *testing.T, withUID bool) { transport.WrapperFunc(func(rt http.RoundTripper) http.RoundTripper { return roundTripperFunc(func(req *http.Request) (*http.Response, error) { gotUser, ok := genericapirequest.UserFrom(req.Context()) - if !ok || gotUser.GetName() == "system:anonymous" { + if !ok { return nil, fmt.Errorf("got an unauthenticated request") } // this is likely the KAS checking the OpenAPI endpoints - if gotUser.GetName() == "system:anonymous" || gotUser.GetName() == "system:aggregator" { + if gotUser.GetName() == "system:anonymous" || gotUser.GetName() == "system:aggregator" || gotUser.GetName() == "system:kube-aggregator" { return rt.RoundTrip(req) } @@ -368,7 +372,7 @@ func testFrontProxyConfig(t *testing.T, withUID bool) { wardleCertDir, _ := os.MkdirTemp("", "test-integration-wardle-server") defer os.RemoveAll(wardleCertDir) - runPreparedWardleServer(ctx, t, wardleOptions, wardleCertDir, wardlePort, false, true, wardleBinaryVersion, kubeConfig) + runPreparedWardleServer(ctx, t, wardleOptions, wardleCertDir, wardlePort, false, true, wardleBinaryVersion, kubeConfig, withUID) waitForWardleAPIServiceReady(ctx, t, kubeConfig, wardleCertDir, testNamespace) // get the wardle API client using our SA token @@ -401,13 +405,13 @@ func testAggregatedAPIServer(t *testing.T, setWardleFeatureGate, banFlunder bool // each wardle binary is bundled with a specific kube binary. kubeBinaryVersion := sampleserver.WardleVersionToKubeVersion(version.MustParse(wardleBinaryVersion)).String() - testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, nil) + testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, nil, false) kubeClientConfig := getKubeConfig(testKAS) wardleCertDir, _ := os.MkdirTemp("", "test-integration-wardle-server") defer os.RemoveAll(wardleCertDir) - directWardleClientConfig := runPreparedWardleServer(ctx, t, wardleOptions, wardleCertDir, wardlePort, setWardleFeatureGate, banFlunder, wardleEmulationVersion, kubeClientConfig) + directWardleClientConfig := runPreparedWardleServer(ctx, t, wardleOptions, wardleCertDir, wardlePort, setWardleFeatureGate, banFlunder, wardleEmulationVersion, kubeClientConfig, false) // now we're finally ready to test. These are what's run by default now wardleDirectClient := client.NewForConfigOrDie(directWardleClientConfig) @@ -681,7 +685,7 @@ func TestAggregatedAPIServerRejectRedirectResponse(t *testing.T) { } } -func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, kubebinaryVersion, wardleBinaryVersion string, kubeAPIServerFlags []string) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) { +func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, kubebinaryVersion, wardleBinaryVersion string, kubeAPIServerFlags []string, withUID bool) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) { // makes the kube-apiserver very responsive. it's normally a minute dynamiccertificates.FileRefreshDuration = 1 * time.Second @@ -693,6 +697,11 @@ func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespa // endpoints cannot have loopback IPs so we need to override the resolver itself t.Cleanup(app.SetServiceResolverForTests(staticURLServiceResolver(fmt.Sprintf("https://127.0.0.1:%d", wardlePort)))) + // TODO figure out how to actually make BinaryVersion/EmulationVersion work with Wardle and KAS at the same time when Alpha FG are being set + if withUID { + kubebinaryVersion = "" + } + testServer := kastesting.StartTestServerOrDie(t, &kastesting.TestServerInstanceOptions{ EnableCertAuth: true, @@ -751,6 +760,7 @@ func runPreparedWardleServer( banFlunder bool, emulationVersion string, kubeConfig *rest.Config, + withUID bool, ) *rest.Config { // start the wardle server to prove we can aggregate it @@ -769,7 +779,8 @@ func runPreparedWardleServer( if flunderBanningFeatureGate { args = append(args, "--feature-gates", fmt.Sprintf("wardle:BanFlunder=%v", banFlunder)) } - wardleCmd := sampleserver.NewCommandStartWardleServer(ctx, wardleOptions) + // TODO figure out how to actually make BinaryVersion/EmulationVersion work with Wardle and KAS at the same time when Alpha FG are being set + wardleCmd := sampleserver.NewCommandStartWardleServer(ctx, wardleOptions, withUID) wardleCmd.SetArgs(args) if err := wardleCmd.Execute(); err != nil { t.Error(err)