impersonator_test.go: small refactor of previous commit

This commit is contained in:
Ryan Richard 2021-03-11 17:24:52 -08:00
parent 6ddf4c04e6
commit 87f2899047

View File

@ -52,10 +52,6 @@ func TestImpersonator(t *testing.T) {
unrelatedCA, err := certauthority.New(pkix.Name{CommonName: "ca"}, time.Hour) unrelatedCA, err := certauthority.New(pkix.Name{CommonName: "ca"}, time.Hour)
require.NoError(t, err) require.NoError(t, err)
badClientCertPEM, badClientKeyPEM, err := unrelatedCA.IssuePEM(
pkix.Name{CommonName: "test-user", Organization: []string{"test-group1"}}, nil, nil, time.Hour,
)
require.NoError(t, err)
// Punch out just enough stuff to make New actually run without error. // Punch out just enough stuff to make New actually run without error.
recOpts := func(options *genericoptions.RecommendedOptions) { recOpts := func(options *genericoptions.RecommendedOptions) {
@ -68,10 +64,7 @@ func TestImpersonator(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
clientUsername string clientCert *clientCert
clientGroups []string
clientCertPEM string
clientKeyPEM string
clientImpersonateUser rest.ImpersonationConfig clientImpersonateUser rest.ImpersonationConfig
kubeAPIServerClientBearerTokenFile string kubeAPIServerClientBearerTokenFile string
kubeAPIServerStatusCode int kubeAPIServerStatusCode int
@ -81,8 +74,7 @@ func TestImpersonator(t *testing.T) {
}{ }{
{ {
name: "happy path", name: "happy path",
clientUsername: "test-username", clientCert: newClientCert(t, ca, "test-username", []string{"test-group1", "test-group2"}),
clientGroups: []string{"test-group1", "test-group2"},
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantKubeAPIServerRequestHeaders: http.Header{ wantKubeAPIServerRequestHeaders: http.Header{
"Impersonate-User": {"test-username"}, "Impersonate-User": {"test-username"},
@ -97,8 +89,7 @@ func TestImpersonator(t *testing.T) {
{ {
name: "user is authenticated but the kube API request returns an error", name: "user is authenticated but the kube API request returns an error",
kubeAPIServerStatusCode: http.StatusNotFound, kubeAPIServerStatusCode: http.StatusNotFound,
clientUsername: "test-username", clientCert: newClientCert(t, ca, "test-username", []string{"test-group1", "test-group2"}),
clientGroups: []string{"test-group1", "test-group2"},
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantError: `the server could not find the requested resource (get namespaces)`, wantError: `the server could not find the requested resource (get namespaces)`,
wantKubeAPIServerRequestHeaders: http.Header{ wantKubeAPIServerRequestHeaders: http.Header{
@ -113,8 +104,7 @@ func TestImpersonator(t *testing.T) {
}, },
{ {
name: "when there is no client cert on request, it is an anonymous request", name: "when there is no client cert on request, it is an anonymous request",
clientCertPEM: "present so we will use the empty keyPEM", clientCert: &clientCert{},
clientKeyPEM: "",
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantKubeAPIServerRequestHeaders: http.Header{ wantKubeAPIServerRequestHeaders: http.Header{
"Impersonate-User": {"system:anonymous"}, "Impersonate-User": {"system:anonymous"},
@ -128,15 +118,13 @@ func TestImpersonator(t *testing.T) {
}, },
{ {
name: "failed client cert authentication", name: "failed client cert authentication",
clientCertPEM: string(badClientCertPEM), clientCert: newClientCert(t, unrelatedCA, "test-username", []string{"test-group1"}),
clientKeyPEM: string(badClientKeyPEM),
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantError: "Unauthorized", wantError: "Unauthorized",
}, },
{ {
name: "double impersonation is not allowed by regular users", name: "double impersonation is not allowed by regular users",
clientUsername: "test-username", clientCert: newClientCert(t, ca, "test-username", []string{"test-group1", "test-group2"}),
clientGroups: []string{"test-group1", "test-group2"},
clientImpersonateUser: rest.ImpersonationConfig{UserName: "some-other-username"}, clientImpersonateUser: rest.ImpersonationConfig{UserName: "some-other-username"},
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantError: `users "some-other-username" is forbidden: User "test-username" ` + wantError: `users "some-other-username" is forbidden: User "test-username" ` +
@ -144,8 +132,7 @@ func TestImpersonator(t *testing.T) {
}, },
{ {
name: "double impersonation is not allowed by admin users", name: "double impersonation is not allowed by admin users",
clientUsername: "test-admin", clientCert: newClientCert(t, ca, "test-admin", []string{"system:masters", "test-group2"}),
clientGroups: []string{"system:masters", "test-group2"},
clientImpersonateUser: rest.ImpersonationConfig{UserName: "some-other-username"}, clientImpersonateUser: rest.ImpersonationConfig{UserName: "some-other-username"},
kubeAPIServerClientBearerTokenFile: "required-to-be-set", kubeAPIServerClientBearerTokenFile: "required-to-be-set",
wantError: `users "some-other-username" is forbidden: User "test-admin" ` + wantError: `users "some-other-username" is forbidden: User "test-admin" ` +
@ -230,25 +217,13 @@ func TestImpersonator(t *testing.T) {
errCh <- stopErr errCh <- stopErr
}() }()
// Create client certs for authentication to the impersonator.
var clientCertPEM, clientKeyPEM []byte
if len(tt.clientCertPEM) == 0 {
clientCertPEM, clientKeyPEM, err = ca.IssuePEM(
pkix.Name{CommonName: tt.clientUsername, Organization: tt.clientGroups}, nil, nil, time.Hour,
)
require.NoError(t, err)
} else {
clientCertPEM = []byte(tt.clientCertPEM)
clientKeyPEM = []byte(tt.clientKeyPEM)
}
// Create a kubeconfig to talk to the impersonator as a client. // Create a kubeconfig to talk to the impersonator as a client.
clientKubeconfig := &rest.Config{ clientKubeconfig := &rest.Config{
Host: "https://127.0.0.1:" + strconv.Itoa(port), Host: "https://127.0.0.1:" + strconv.Itoa(port),
TLSClientConfig: rest.TLSClientConfig{ TLSClientConfig: rest.TLSClientConfig{
CAData: ca.Bundle(), CAData: ca.Bundle(),
CertData: clientCertPEM, CertData: tt.clientCert.certPEM,
KeyData: clientKeyPEM, KeyData: tt.clientCert.keyPEM,
}, },
UserAgent: "test-agent", UserAgent: "test-agent",
// BearerToken should be ignored during auth when there are valid client certs, // BearerToken should be ignored during auth when there are valid client certs,
@ -292,12 +267,6 @@ func TestImpersonator(t *testing.T) {
} }
} }
func requireCanBindToPort(t *testing.T, port int) {
ln, _, listenErr := genericoptions.CreateListener("", "0.0.0.0:"+strconv.Itoa(port), net.ListenConfig{})
require.NoError(t, listenErr)
require.NoError(t, ln.Close())
}
func TestImpersonatorHTTPHandler(t *testing.T) { func TestImpersonatorHTTPHandler(t *testing.T) {
const testUser = "test-user" const testUser = "test-user"
@ -510,3 +479,24 @@ func TestImpersonatorHTTPHandler(t *testing.T) {
}) })
} }
} }
type clientCert struct {
certPEM, keyPEM []byte
}
func newClientCert(t *testing.T, ca *certauthority.CA, username string, groups []string) *clientCert {
certPEM, keyPEM, err := ca.IssuePEM(
pkix.Name{CommonName: username, Organization: groups}, nil, nil, time.Hour,
)
require.NoError(t, err)
return &clientCert{
certPEM: certPEM,
keyPEM: keyPEM,
}
}
func requireCanBindToPort(t *testing.T, port int) {
ln, _, listenErr := genericoptions.CreateListener("", "0.0.0.0:"+strconv.Itoa(port), net.ListenConfig{})
require.NoError(t, listenErr)
require.NoError(t, ln.Close())
}