diff --git a/hack/make-rules/test-cmd.sh b/hack/make-rules/test-cmd.sh index f6edd1dee92..052c51ceca5 100755 --- a/hack/make-rules/test-cmd.sh +++ b/hack/make-rules/test-cmd.sh @@ -80,7 +80,7 @@ function run_kube_apiserver() { --storage-media-type="${KUBE_TEST_API_STORAGE_TYPE-}" \ --cert-dir="${TMPDIR:-/tmp/}" \ --service-cluster-ip-range="10.0.0.0/24" \ - --client-ca-file=hack/testdata/ca.crt \ + --client-ca-file=hack/testdata/ca/ca.crt \ --token-auth-file=hack/testdata/auth-tokens.csv 1>&2 & export APISERVER_PID=$! @@ -121,6 +121,8 @@ EOF kube::log::status "Starting controller-manager" "${KUBE_OUTPUT_HOSTBIN}/kube-controller-manager" \ --kube-api-content-type="${KUBE_TEST_API_TYPE-}" \ + --cluster-signing-cert-file=hack/testdata/ca/ca.crt \ + --cluster-signing-key-file=hack/testdata/ca/ca.key \ --kubeconfig="${config}" 1>&2 & export CTLRMGR_PID=$! diff --git a/hack/testdata/auth/testuser.csr b/hack/testdata/auth/testuser.csr new file mode 100644 index 00000000000..1e5c736fc10 --- /dev/null +++ b/hack/testdata/auth/testuser.csr @@ -0,0 +1,19 @@ +# this is a test-only certificate request that is used in integration +# tests to test certificate based auth. +# generated with 'openssl req -out testuser.csr -key testuser.key -new -sha256' +# then skipping all the options except for setting CN to testuser +-----BEGIN CERTIFICATE REQUEST----- +MIICWDCCAUACAQAwEzERMA8GA1UEAwwIdGVzdHVzZXIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC0MWVzF3QC92dQSzA/tBla3okdNkSNyd+SbnzFNxIG +mnm/5vSg1T2b8yx6s0IXLzUK2laY9cB12nS96m3YV+71YFVnXhGpgcxUlQgcr/yk +mcMl545HYBRs5d2m/v7cfYjqtmuvFwEeQeVyI3DpWLEu3DFCas1TpABnDggOcLDe +1YEjBgo5hNlojnKuOqKzJfIWjjbh/wevvxRMZ+5fdi4ilaSh3J13kmvmvrhD2nn6 +WqUdjhSsC8oOTmnzbm1RNbpgO6w7SCbTp/Exb3YIvq1T6mzio/N0N4VQgS2uQ+66 +ERiVB1iGH+J5jSphcm8sYAtwXQyd+A3d61wo08BaezBVAgMBAAGgADANBgkqhkiG +9w0BAQsFAAOCAQEACQia6OUAsEw0zC6K7fxdI1jnPYqcx8QGqbFQ0yWWKwAlW7rY +PitodCU+0d/88a9ig32Yj01bfOwgU1GPL5NXJmXNtNw1Lu5nQzgiZWzFLjZe3+Ni +bUr8+HhaxHMMV2//SPILtr0aYZIkHPSK3+rcGmo6Mvlr8ANP0G9pwZzb8q2NO3mQ +iXGpFyLq00BEZZyZ3mCGyYGNBpO/pSIxL5eK0gJgT5UJWHZxepi2gsyz+prLjwGo +d5M2z9W6l3/ACHltjEz9t9b1gTZ/fUlNUWRk2frE/NwJDKzL9lhh5qaIKtSsROQ1 +OQHcijbY6cSTmgqyAqrGoXMyfJJJvJ4gvludcQ== +-----END CERTIFICATE REQUEST----- diff --git a/hack/testdata/auth/testuser.key b/hack/testdata/auth/testuser.key new file mode 100644 index 00000000000..5e6ac5b4c4e --- /dev/null +++ b/hack/testdata/auth/testuser.key @@ -0,0 +1,30 @@ +# this is a test-only private key that is used in integration +# tests to test certificate based auth. +# generated with 'openssl genrsa 2048 > testuser.key' +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtDFlcxd0AvdnUEswP7QZWt6JHTZEjcnfkm58xTcSBpp5v+b0 +oNU9m/MserNCFy81CtpWmPXAddp0vept2Ffu9WBVZ14RqYHMVJUIHK/8pJnDJeeO +R2AUbOXdpv7+3H2I6rZrrxcBHkHlciNw6VixLtwxQmrNU6QAZw4IDnCw3tWBIwYK +OYTZaI5yrjqisyXyFo424f8Hr78UTGfuX3YuIpWkodydd5Jr5r64Q9p5+lqlHY4U +rAvKDk5p825tUTW6YDusO0gm06fxMW92CL6tU+ps4qPzdDeFUIEtrkPuuhEYlQdY +hh/ieY0qYXJvLGALcF0MnfgN3etcKNPAWnswVQIDAQABAoIBABRHBsKX3g9DZhXs +ECbrDntiVY27AKXwFL+2vUW4N8gUdCT7SYYb2Q4GpHe+Wm6felmZTmtyJFFe3wpM +KkZRRuvIBnRWaqhnmeXey4Xm7Ahd4U8PqrwvfLzwdSwIwAdx/Qlks+OFNDQCeF6K +zHcF6xJ55vUxbZ++8eim9JMjbVP2BFcm7a1JjohhstLuWDXo40wk9jozUQu6Tlea +E2YZ52NrUcB9oZq6Q0iW5GXSkGsq/Cc2eSif3TVP9oEnRYL/8vOInuz3sXmHoRTQ +Iz6WHjtq/1OW9OHmqb6MeVL9kUoJx2LLIm6WdZEtSRoDCfi/c3AqK60WnJ/8x3OY +ZT/62AECgYEA5pSsXyD5h89f0PjbnJJWj7Z3eUrw9qMfUGc+FW2LkOFTfDx3M0EM +mdKMFssvn1HUlt+O0KUUE2vGBt/3zlHAfh9XyI01KmPkumarPq+keBCA0KDa3X8i +T2LqTTzBA80CeC3k/+/o7DKXbQCqqDbanNpDTPJUK6WvsRyTA80GhlUCgYEAyA60 +lavRjA4nMjoRnI+AuFIgK1flKt+XMF95O8N2I5QgNCKhxoi5nD706dsB5zLWH/A4 +hwSJeW6HSFgG7g/lN7CA8dJuQ096FvIoJlBpbUUJOXJWaoU46CGmSw/nx9iTJEm/ +9vyVcT0+5xdlBcKec+kcOAHsgsakTycORVbIAgECgYBs44bnQaY1OXwxLmRfc0gH +hA61q+tRPcVa7faGnf3LxGztfYx5Gt39gk1/siJiJX20ZgyGgX6SkVGqC3h16Wty +5BBLeEvEIfpxAG0cJEwSGxEJ9PyGnzQvszGcmfU4e0cQQ/Qh3UTszhNueWMeHxFs +AzLHEqUnG451oF3Y7KiJJQKBgFspmFC7wvk3WdUhcPUOz3Euu0oE+4DV8mcwmmYJ +Y8RCs4oOXfnCRBJW/fOywONB3yEeriOYhay4GR12P3Ir/B+sZpXLdkNl7BSYtIMB +EYmhc9qhp49StePRsZ1y2gPPRP28PaWm49J+PjPADWDalqnrB9jdx5CwRB9thKtE +KFABAoGAcvbPiKOb0/CjkdRE3ysoZlHi9Z2EN9NLiV6EjFSR6H62SsSLBjNvd2Hh +Ii9imj/5jD2qgFXX80+sBoTBqz0WEUt9opxQ5JJ4jXnDWCxZg4sLlLmw+EnjanEl +KMcyXsWn5YOWaY6/e2D8MqNd7vWFZxokFTuhRcJKIHcovKBLJcQ= +-----END RSA PRIVATE KEY----- diff --git a/hack/testdata/ca.crt b/hack/testdata/ca.crt deleted file mode 100644 index 6060bec2bda..00000000000 --- a/hack/testdata/ca.crt +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICpjCCAY4CCQCZBiNB23olFzANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAkx -MjcuMC4wLjEwIBcNMjAwNjE0MTk0OTM4WhgPMjI5NDAzMzAxOTQ5MzhaMBQxEjAQ -BgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMxIjMd58IhiiyK4VjmuCWBUZksSs1CcQuo5HSpOqogVZ+vR5mdJDZ56Pw/NSM5c -RqOB3cvjGrxYQe/lKvo9D3UmWLcRKtxdlWxCfPekioJ25/dhGOxtBQcjtp/TSqTM -txprwT4fvsVwiwaURFoCOivF4xjQFG0K1i3/m7CiMHODy67M1EfJDrM7Vv5XPIuJ -VF8HhWBH2HiM25ak34XhxVTX8K97k6wO9OZ5GMqbYuVobTZrSRdiv8s95rkmik6P -jn0ePKqSz6cXNXgXqTl11WtsuoGgjOdB8j/noqTF3m3z17sSBqqG/xBFuSFoNceA -yBDb9ohbs8oY3NIZzyMrt8MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFgcaqRgv -qylx4ogL5iUr0K2e/8YzsvH7zLHG6xnr7HxpR/p0lQt3dPlppECZMGDKElbCgU8f -xVDdZ3FOxHTJ51Vnq/U5xJo+UOMJ4sS8fEH8cfNliSsvmSKzjxpPKqbCJ7VTnkW8 -lonedCPRksnhlD1U8CF21rEjKsXcLoX5PsxlS4DX3PtO0+e8aUh9F4XyZagpejq8 -0ttXkWd3IyYrpFRGDlFDxIiKx7pf+mG6JZ/ms6jloBSwwcz/Nkn5FMxiq75bQuOH -EV+99S2du/X2bRmD1JxCiMDw8cMacIFBr6BYXsvKOlivwfHBWk8U0f+lVi60jWje -PpKFRd1mYuEZgw== ------END CERTIFICATE----- diff --git a/hack/testdata/ca/ca.crt b/hack/testdata/ca/ca.crt new file mode 100644 index 00000000000..ad8c78c6723 --- /dev/null +++ b/hack/testdata/ca/ca.crt @@ -0,0 +1,21 @@ +# this is a test-only public key that is used in integration +# tests as the kube controller manager's signing certificate +# and the api server's client ca file. +# generated with 'openssl req -new -x509 -nodes -days 365000 -key ca.key -out ca.crt', set the CN to 127.0.0.1 +-----BEGIN CERTIFICATE----- +MIICpjCCAY4CCQCP7S9OEzUZmDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAkx +MjcuMC4wLjEwIBcNMjIwMTA0MjMzNDMyWhgPMzAyMTA1MDcyMzM0MzJaMBQxEjAQ +BgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMI22ieHLxXpWc58JyCdYG9QmahHfdtDN6R9EwI674gmm81iUq0+bQBoyh4oASos +Xuc3i6Fc7S+rvEeReaYCYQOXk/KotajY3sSCNAGI9oHsdJmrtuLTcPX9vIgcqBU5 +BiFaSQEkFtlSGKECI5l/mH+5uMsBkmx7YKj6LyvM/YAPv1WsWrM2IZVPj2eWMljh +uhaDOiQOhrSjmWZuOcRKPTui2IVqTjszuZ7A1r+sKHFSNgTFqEcVSCH8Jcja/35H +LvTpOLdfntVSvklCO20sDGXnNkxcLYz2i2Jm7ixksTeGFPbzfT9q7q3Vyi5FfVvQ +31cGieUwifk3toheQ63WdZMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAXF6NCEdP +LMqgmtrfP5bl4F2QLRkVhmqoS88gsQHEUSb1ljz0Jwov4V4/m56Of+jHpQeFbsO7 +dXfR4kN3J7cW3UZ8HddIiQvFHW8NPEQvmvVpWfEnNl8aXS9NilowMVDOGwvhQFFS +xsz+1OWXxrF+RpgYB+b0orjy7K1jYER+baXKeLU8JGPKXQGSR+0YomeC/xc2LznD +KfS8t/7D9jbKhFGvTC5x15MSy8rGcdCsFVxtkCmbuq1KwP5CYAyowZ/zCKPtBoKK +5F9TmayjX3AUvh4KVdeh8zrMhFdWmOihKlrj/bJyY0l/hbnROG+ipMPdcepCmfFA +r+6CBEIWxsxJTQ== +-----END CERTIFICATE----- diff --git a/hack/testdata/ca/ca.key b/hack/testdata/ca/ca.key new file mode 100644 index 00000000000..7d41a7d857e --- /dev/null +++ b/hack/testdata/ca/ca.key @@ -0,0 +1,30 @@ +# this is a test-only private key that is used in integration +# tests as the kube controller manager's signing key. +# generated with 'openssl genrsa 2048 > ca.key' +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwjbaJ4cvFelZznwnIJ1gb1CZqEd920M3pH0TAjrviCabzWJS +rT5tAGjKHigBKixe5zeLoVztL6u8R5F5pgJhA5eT8qi1qNjexII0AYj2gex0mau2 +4tNw9f28iByoFTkGIVpJASQW2VIYoQIjmX+Yf7m4ywGSbHtgqPovK8z9gA+/Vaxa +szYhlU+PZ5YyWOG6FoM6JA6GtKOZZm45xEo9O6LYhWpOOzO5nsDWv6wocVI2BMWo +RxVIIfwlyNr/fkcu9Ok4t1+e1VK+SUI7bSwMZec2TFwtjPaLYmbuLGSxN4YU9vN9 +P2rurdXKLkV9W9DfVwaJ5TCJ+Te2iF5DrdZ1kwIDAQABAoIBAEpzQo+yl887hAzO +tSUgj048xJqoxUtfah4pQDczpo0317QVBAKbkqd8hDapOUEUf1D9jw5NlDMZD3UU +BGEqOkxpN/Lmz7SpZkRIcW1BNtY5cb1TASnUylHScgpvidOQ55Ozi5bfYc7vVLes +HT+DlU8pP/i6YoophbVhKuIMlAUZ2NkyoFdW+fFUj4r695JIrKIyct+uH+igem6G +OqiTMkAYPwaKHai/yl7UdLRek6xXn1IafTBfvYAL0mdQlOMgTpt/u1oa4EPoxytX +RbsulC6D2cmNlqvc0sQurbwfPeO+eCCwLeFs9aOPy7eWsujoj+lMFdB7oYQdqAEi +VK/p4JECgYEA8JSQMucMr81BZjNldCyLOKb1SHQzyyhrQxnFVEvbVHHCN18VDKf9 +p4kjnR8GOqLx/j+gSIUS7nHG+KCLCiwFoK/y+xcf++6yyrv6L8qZq48F+RqoXgGU +H0rxAmdnxRuRVo7Qd2bXbcrvoqS7XVV4YQ1o9pYTEfiGzyxTSRFkyrkCgYEAzqmD +/rEimA/Jbn1MKH3f7U6W49uj6lJeRfxGfbBLqhPCVXOPgnSONjYchYs3TBAwbknm +yPBk6HNUhqnyrZ5Co3n57lSBRpKb4oNh7+n6rZQLT1aTX8Rpf26UVqxjzyuNlTe9 +9DYcT9uJm3QI4cdl567KbhmdIJ3zELjri4dlbKsCgYEAhHBkiYEkPMtzyz1UBoZX +BhLzSLWfpaFUmxXeya8QyQXu8uiG//ai7s3SKzbfCPyW125TYFjRuS4taMWIhUsC +thjmXE+4rcoT5wNgkVqpCgasNRv1v/qCfk+VKcufFqU8dzgbjv+wbKKhFRo2gwUA +Rf1J4SVwzh3QqNAv8TOAFxECgYAimhVkponxRetnGYmP2guNMzRmcFcQm7v3Idc3 +ojX5AxftsMydfiB1iTfbUETw8mD5hlwi1sU+eljzty7PzQjBUGH9ep6uj0uUcIUM +Y3O6bmg6X3eLeFploMErhe+sN1GcY1nlss2ovUxb/+Cg1P8F/KkeKCG73VZePWgK +05+ywwKBgQDbVh4uufob8ia/1xQxTgao90YeerihmwkdpUEIIU5a22GBOeIUr4jF +ciT4Nm8Rb3noFVzLj36N1LfzrZzmsLmdXzYLx3q2eXlGi3zay0n6mmS7yaRjGmQX +XNc/BzOWHfjPQakxzTsJJaCAPTlQ7+JXNlrLblYrSI5EjBWD1OUG6A== +-----END RSA PRIVATE KEY----- diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go index e405e3dc129..9747d507463 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go @@ -290,8 +290,8 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { // also configured to allow client certificates for authentication. For requests // like "kubectl get --token (token) pods" we should assume the intention is to // use the provided token for authentication. The same can be said for when the - // user specifies basic auth. - if c.HasTokenAuth() || c.HasBasicAuth() { + // user specifies basic auth or cert auth. + if c.HasTokenAuth() || c.HasBasicAuth() || c.HasCertAuth() { return nil } @@ -299,7 +299,7 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { return &roundTripper{a, rt} }) - if c.TLS.GetCert != nil { + if c.HasCertCallback() { return errors.New("can't add TLS certificate callback: transport.Config.TLS.GetCert already set") } c.TLS.GetCert = a.cert diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go index 6698fb4e836..b1fa9f4d913 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go @@ -1206,6 +1206,13 @@ func TestAuthorizationHeaderPresentCancelsExecAction(t *testing.T) { config.Password = "zelda" }, }, + { + name: "cert auth", + setTransportConfig: func(config *transport.Config) { + config.TLS.CertData = []byte("some-cert-data") + config.TLS.KeyData = []byte("some-key-data") + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/test/cmd/authentication.sh b/test/cmd/authentication.sh index 155ae914637..3e1c9d5d6e3 100644 --- a/test/cmd/authentication.sh +++ b/test/cmd/authentication.sh @@ -82,7 +82,7 @@ EOF fi # Post-condition: None - cat > "${TMPDIR:-/tmp}"/valid_exec_plugin.yaml << EOF + cat >"${TMPDIR:-/tmp}"/valid_exec_plugin.yaml < "${TMPDIR:-/tmp}"/testuser.crt + + output5=$(kubectl "${kube_flags_without_token[@]:?}" --client-certificate="${TMPDIR:-/tmp}"/testuser.crt --client-key="hack/testdata/auth/testuser.key" --kubeconfig="${TMPDIR:-/tmp}"/invalid_exec_plugin.yaml get namespace kube-system -o name) + if [[ "${output5}" =~ "Unauthorized" ]]; then + kube::log::status "Unexpected output when providing --client-certificate/--client-key for authentication - exec credential plugin likely triggered. Output: ${output5}" + exit 1 + else + kube::log::status "exec credential plugin not triggered since kubectl was called with provided --client-certificate/--client-key" + fi + + ### Provided --client-certificate/--client-key should take precedence in the kubeconfig, thus not triggering the (invalid) exec credential plugin. + cat >"${TMPDIR:-/tmp}"/invalid_execcredential.sh < "${TMPDIR:-/tmp}"/always_interactive_exec_plugin.yaml << EOF + cat >"${TMPDIR:-/tmp}"/always_interactive_exec_plugin.yaml < "${TMPDIR:-/tmp}"/missing_interactive_exec_plugin.yaml << EOF + cat >"${TMPDIR:-/tmp}"/missing_interactive_exec_plugin.yaml <