delegate authn: don't default the ReqHeaders UID header

This commit is contained in:
Stanislav Láznička 2024-05-20 13:43:22 +02:00
parent dcc6cf9280
commit 26902de531
5 changed files with 42 additions and 12 deletions

View File

@ -214,6 +214,7 @@ func StartTestServer(t ktesting.TB, instanceOptions *TestServerInstanceOptions,
}
s.SecureServing.ServerCert.CertDirectory = result.TmpDir
reqHeaderFromFlags := s.Authentication.RequestHeader
if instanceOptions.EnableCertAuth {
// set up default headers for request header auth
reqHeaders := serveroptions.NewDelegatingAuthenticationOptions()
@ -347,6 +348,23 @@ func StartTestServer(t ktesting.TB, instanceOptions *TestServerInstanceOptions,
return result, err
}
// the RequestHeader options pointer gets replaced in the case of EnableCertAuth override
// and so flags are connected to a struct that no longer appears in the ServerOptions struct
// we're using.
// We still want to make it possible to configure the headers config for the RequestHeader authenticator.
if usernameHeaders := reqHeaderFromFlags.UsernameHeaders; len(usernameHeaders) > 0 {
s.Authentication.RequestHeader.UsernameHeaders = usernameHeaders
}
if uidHeaders := reqHeaderFromFlags.UIDHeaders; len(uidHeaders) > 0 {
s.Authentication.RequestHeader.UIDHeaders = uidHeaders
}
if groupHeaders := reqHeaderFromFlags.GroupHeaders; len(groupHeaders) > 0 {
s.Authentication.RequestHeader.GroupHeaders = groupHeaders
}
if extraHeaders := reqHeaderFromFlags.ExtraHeaderPrefixes; len(extraHeaders) > 0 {
s.Authentication.RequestHeader.ExtraHeaderPrefixes = extraHeaders
}
if err := utilversion.DefaultComponentGlobalsRegistry.Set(); err != nil {
return result, err
}

View File

@ -430,7 +430,7 @@ func TestAddFlags(t *testing.T) {
ClientCert: apiserveroptions.ClientCertAuthenticationOptions{},
RequestHeader: apiserveroptions.RequestHeaderAuthenticationOptions{
UsernameHeaders: []string{"x-remote-user"},
UIDHeaders: []string{"x-remote-uid"},
UIDHeaders: nil,
GroupHeaders: []string{"x-remote-group"},
ExtraHeaderPrefixes: []string{"x-remote-extra-"},
},

View File

@ -245,8 +245,13 @@ func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
CacheTTL: 10 * time.Second,
ClientCert: ClientCertAuthenticationOptions{},
RequestHeader: RequestHeaderAuthenticationOptions{
UsernameHeaders: []string{"x-remote-user"},
UIDHeaders: []string{"x-remote-uid"},
UsernameHeaders: []string{"x-remote-user"},
// we specifically don't default UID headers as these were introduced
// later (kube 1.32) and we don't want 3rd parties to be trusting the default headers
// before we can safely say that all KAS instances know they should
// remove them from an incoming request in its WithAuthentication handler.
// The defaulting will be enabled in a future (1.33+) version.
UIDHeaders: nil,
GroupHeaders: []string{"x-remote-group"},
ExtraHeaderPrefixes: []string{"x-remote-extra-"},
},

View File

@ -133,7 +133,7 @@ func TestDefaultFlags(t *testing.T) {
ClientCert: apiserveroptions.ClientCertAuthenticationOptions{},
RequestHeader: apiserveroptions.RequestHeaderAuthenticationOptions{
UsernameHeaders: []string{"x-remote-user"},
UIDHeaders: []string{"x-remote-uid"},
UIDHeaders: nil,
GroupHeaders: []string{"x-remote-group"},
ExtraHeaderPrefixes: []string{"x-remote-extra-"},
},
@ -294,7 +294,7 @@ func TestAddFlags(t *testing.T) {
ClientCert: apiserveroptions.ClientCertAuthenticationOptions{},
RequestHeader: apiserveroptions.RequestHeaderAuthenticationOptions{
UsernameHeaders: []string{"x-remote-user"},
UIDHeaders: []string{"x-remote-uid"},
UIDHeaders: nil,
GroupHeaders: []string{"x-remote-group"},
ExtraHeaderPrefixes: []string{"x-remote-extra-"},
},

View File

@ -268,7 +268,7 @@ func TestFrontProxyConfig(t *testing.T) {
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)
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, []string{"--requestheader-uid-headers=x-remote-uid"})
kubeConfig := getKubeConfig(testKAS)
// create the SA that we will use to query the aggregated API
@ -281,8 +281,6 @@ func TestFrontProxyConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
expectedSAUserInfo := serviceaccount.UserInfo(expectedSA.Namespace, expectedSA.Name, string(expectedSA.UID))
expectedRealSAGroups := append(expectedSAUserInfo.GetGroups(), user.AllAuthenticated)
saTokenReq, err := kubeClient.CoreV1().ServiceAccounts(testNamespace).CreateToken(ctx, "wardle-client-sa", &v1.TokenRequest{}, metav1.CreateOptions{})
if err != nil {
@ -301,6 +299,9 @@ func TestFrontProxyConfig(t *testing.T) {
if err != nil {
t.Fatalf("failed to retrieve details about the SA: %v", err)
}
expectedSAUserInfo := serviceaccount.UserInfo(expectedSA.Namespace, expectedSA.Name, string(expectedSA.UID))
expectedRealSAGroups := append(expectedSAUserInfo.GetGroups(), user.AllAuthenticated)
expectedExtra := expectedSAUserInfo.GetExtra()
if expectedExtra == nil {
expectedExtra = map[string][]string{}
@ -315,7 +316,7 @@ func TestFrontProxyConfig(t *testing.T) {
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 {
if !ok || gotUser.GetName() == "system:anonymous" {
return nil, fmt.Errorf("got an unauthenticated request")
}
@ -382,7 +383,7 @@ 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)
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, nil)
kubeClientConfig := getKubeConfig(testKAS)
wardleCertDir, _ := os.MkdirTemp("", "test-integration-wardle-server")
@ -662,7 +663,7 @@ func TestAggregatedAPIServerRejectRedirectResponse(t *testing.T) {
}
}
func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, kubebinaryVersion, wardleBinaryVersion string) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) {
func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, kubebinaryVersion, wardleBinaryVersion string, kubeAPIServerFlags []string) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) {
// makes the kube-apiserver very responsive. it's normally a minute
dynamiccertificates.FileRefreshDuration = 1 * time.Second
@ -674,7 +675,13 @@ 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))))
testServer := kastesting.StartTestServerOrDie(t, &kastesting.TestServerInstanceOptions{EnableCertAuth: true, BinaryVersion: kubebinaryVersion}, nil, framework.SharedEtcd())
testServer := kastesting.StartTestServerOrDie(t,
&kastesting.TestServerInstanceOptions{
EnableCertAuth: true,
BinaryVersion: kubebinaryVersion,
},
kubeAPIServerFlags,
framework.SharedEtcd())
t.Cleanup(func() { testServer.TearDownFn() })
_, _ = utilversion.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(