/* Copyright 2019 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 podlogs import ( "crypto/tls" "io/ioutil" "net/url" "strings" "testing" "time" "k8s.io/apiserver/pkg/server/dynamiccertificates" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/test/integration/framework" ) func TestClientCA(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) // I have no idea what this cert is, but it doesn't matter, we just want something that always fails validation differentClientCA := []byte(`-----BEGIN CERTIFICATE----- MIIDQDCCAiigAwIBAgIJANWw74P5KJk2MA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX DTE3MTExNjAwMDUzOVoYDzIyOTEwOTAxMDAwNTM5WjAjMSEwHwYDVQQDExh3ZWJo b29rLXRlc3QuZGVmYXVsdC5zdmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQDXd/nQ89a5H8ifEsigmMd01Ib6NVR3bkJjtkvYnTbdfYEBj7UzqOQtHoLa dIVmefny5uIHvj93WD8WDVPB3jX2JHrXkDTXd/6o6jIXHcsUfFTVLp6/bZ+Anqe0 r/7hAPkzA2A7APyTWM3ZbEeo1afXogXhOJ1u/wz0DflgcB21gNho4kKTONXO3NHD XLpspFqSkxfEfKVDJaYAoMnYZJtFNsa2OvsmLnhYF8bjeT3i07lfwrhUZvP+7Gsp 7UgUwc06WuNHjfx1s5e6ySzH0QioMD1rjYneqOvk0pKrMIhuAEWXqq7jlXcDtx1E j+wnYbVqqVYheHZ8BCJoVAAQGs9/AgMBAAGjZDBiMAkGA1UdEwQCMAAwCwYDVR0P BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATApBgNVHREEIjAg hwR/AAABghh3ZWJob29rLXRlc3QuZGVmYXVsdC5zdmMwDQYJKoZIhvcNAQELBQAD ggEBAD/GKSPNyQuAOw/jsYZesb+RMedbkzs18sSwlxAJQMUrrXwlVdHrA8q5WhE6 ABLqU1b8lQ8AWun07R8k5tqTmNvCARrAPRUqls/ryER+3Y9YEcxEaTc3jKNZFLbc T6YtcnkdhxsiO136wtiuatpYL91RgCmuSpR8+7jEHhuFU01iaASu7ypFrUzrKHTF bKwiLRQi1cMzVcLErq5CDEKiKhUkoDucyARFszrGt9vNIl/YCcBOkcNvM3c05Hn3 M++C29JwS3Hwbubg6WO3wjFjoEhpCwU6qRYUz3MRp4tHO4kxKXx+oQnUiFnR7vW0 YkNtGc1RUDHwecCTFpJtPb7Yu/E= -----END CERTIFICATE----- `) differentFrontProxyCA := []byte(`-----BEGIN CERTIFICATE----- MIIBqDCCAU2gAwIBAgIUfbqeieihh/oERbfvRm38XvS/xHAwCgYIKoZIzj0EAwIw GjEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlLUNBMCAXDTE2MTAxMTA1MDYwMFoYDzIx MTYwOTE3MDUwNjAwWjAUMRIwEAYDVQQDEwlNeSBDbGllbnQwWTATBgcqhkjOPQIB BggqhkjOPQMBBwNCAARv6N4R/sjMR65iMFGNLN1GC/vd7WhDW6J4X/iAjkRLLnNb KbRG/AtOUZ+7upJ3BWIRKYbOabbQGQe2BbKFiap4o3UwczAOBgNVHQ8BAf8EBAMC BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU K/pZOWpNcYai6eHFpmJEeFpeQlEwHwYDVR0jBBgwFoAUX6nQlxjfWnP6aM1meO/Q a6b3a9kwCgYIKoZIzj0EAwIDSQAwRgIhAIWTKw/sjJITqeuNzJDAKU4xo1zL+xJ5 MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps= -----END CERTIFICATE----- `) clientCAFilename := "" frontProxyCAFilename := "" _, kubeconfig := framework.StartTestServer(t, stopCh, framework.TestServerSetup{ ModifyServerRunOptions: func(opts *options.ServerRunOptions) { opts.GenericServerRunOptions.MaxRequestBodyBytes = 1024 * 1024 clientCAFilename = opts.Authentication.ClientCert.ClientCA frontProxyCAFilename = opts.Authentication.RequestHeader.ClientCAFile dynamiccertificates.FileRefreshDuration = 1 * time.Second }, }) apiserverURL, err := url.Parse(kubeconfig.Host) if err != nil { t.Fatal(err) } // when we run this the second time, we know which one we are expecting acceptableCAs := []string{} tlsConfig := &tls.Config{ InsecureSkipVerify: true, GetClientCertificate: func(hello *tls.CertificateRequestInfo) (*tls.Certificate, error) { acceptableCAs = []string{} for _, curr := range hello.AcceptableCAs { acceptableCAs = append(acceptableCAs, string(curr)) } return &tls.Certificate{}, nil }, } conn, err := tls.Dial("tcp", apiserverURL.Host, tlsConfig) if err != nil { t.Fatal(err) } defer conn.Close() if err := ioutil.WriteFile(clientCAFilename, differentClientCA, 0644); err != nil { t.Fatal(err) } if err := ioutil.WriteFile(frontProxyCAFilename, differentFrontProxyCA, 0644); err != nil { t.Fatal(err) } time.Sleep(4 * time.Second) conn2, err := tls.Dial("tcp", apiserverURL.Host, tlsConfig) if err != nil { t.Fatal(err) } defer conn2.Close() expectedCAs := []string{"webhook-test.default.svc", "My Client"} if len(expectedCAs) != len(acceptableCAs) { t.Fatal(strings.Join(acceptableCAs, ":")) } for i := range expectedCAs { if !strings.Contains(acceptableCAs[i], expectedCAs[i]) { t.Errorf("expected %q, got %q", expectedCAs[i], acceptableCAs[i]) } } }