package integration import ( "bytes" "io" "io/ioutil" "net/http" "net/http/httptest" "net/url" "os" "strings" "testing" "k8s.io/kubernetes/pkg/client/restclient" clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" "github.com/openshift/origin/pkg/client" "github.com/openshift/origin/pkg/cmd/cli/cmd/login" configapi "github.com/openshift/origin/pkg/cmd/server/api" testutil "github.com/openshift/origin/test/util" testserver "github.com/openshift/origin/test/util/server" ) // TestOAuthRequestHeader checks the following scenarios: // * request containing remote user header is ignored if it doesn't have client cert auth // * request containing remote user header is honored if it has valid client cert auth matching ClientCommonNames // * unauthenticated requests are redirected to an auth proxy // * login command succeeds against a request-header identity provider via redirection to an auth proxy func TestOAuthRequestHeader(t *testing.T) { // Test data used by auth proxy users := map[string]string{ "myusername": "mypassword", } // Write cert we're going to use to verify OAuth requestheader requests caFile, err := ioutil.TempFile("", "test.crt") if err != nil { t.Fatalf("unexpected error: %v", err) } defer os.Remove(caFile.Name()) if err := ioutil.WriteFile(caFile.Name(), rootCACert, os.FileMode(0600)); err != nil { t.Fatalf("unexpected error: %v", err) } // Get master config testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) masterOptions, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("unexpected error: %v", err) } masterURL, _ := url.Parse(masterOptions.OAuthConfig.MasterPublicURL) // Set up an auth proxy var proxyTransport http.RoundTripper proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Decide whether to challenge username, password, hasBasicAuth := r.BasicAuth() if correctPassword, hasUser := users[username]; !hasBasicAuth || !hasUser || password != correctPassword { w.Header().Set("WWW-Authenticate", "Basic realm=Protected Area") w.WriteHeader(401) return } // Swap the scheme and host to the master, keeping path and params the same proxyURL := r.URL proxyURL.Scheme = masterURL.Scheme proxyURL.Host = masterURL.Host // Build a request, copying the original method, body, and headers, overriding the remote user headers proxyRequest, _ := http.NewRequest(r.Method, proxyURL.String(), r.Body) proxyRequest.Header = r.Header proxyRequest.Header.Set("My-Remote-User", username) proxyRequest.Header.Set("SSO-User", "") // Round trip to the back end response, err := proxyTransport.RoundTrip(r) if err != nil { t.Fatalf("Unexpected error: %v", err) } defer response.Body.Close() // Copy response back to originator for k, v := range response.Header { w.Header()[k] = v } w.WriteHeader(response.StatusCode) if _, err := io.Copy(w, response.Body); err != nil { t.Fatalf("Unexpected error: %v", err) } })) defer proxyServer.Close() masterOptions.OAuthConfig.IdentityProviders[0] = configapi.IdentityProvider{ Name: "requestheader", UseAsChallenger: true, UseAsLogin: true, MappingMethod: "claim", Provider: &configapi.RequestHeaderIdentityProvider{ ChallengeURL: proxyServer.URL + "/oauth/authorize?${query}", LoginURL: "http://www.example.com/login?then=${url}", ClientCA: caFile.Name(), ClientCommonNames: []string{"proxy"}, Headers: []string{"My-Remote-User", "SSO-User"}, }, } // Start server clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterOptions) if err != nil { t.Fatalf("unexpected error: %v", err) } clientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // Use the server and CA info, but no client cert info anonConfig := restclient.Config{} anonConfig.Host = clientConfig.Host anonConfig.CAFile = clientConfig.CAFile anonConfig.CAData = clientConfig.CAData anonTransport, err := restclient.TransportFor(&anonConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // Use the server and CA info, with cert info proxyConfig := anonConfig proxyConfig.CertData = proxyClientCert proxyConfig.KeyData = proxyClientKey proxyTransport, err = restclient.TransportFor(&proxyConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // client cert that is valid, but not in the list of allowed common names otherCertConfig := anonConfig otherCertConfig.CertData = otherClientCert otherCertConfig.KeyData = otherClientKey otherCertTransport, err := restclient.TransportFor(&otherCertConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // client cert that has the desired common name, but does not have a valid signature invalidCertConfig := anonConfig invalidCertConfig.CertData = invalidClientCert invalidCertConfig.KeyData = invalidClientKey invalidCertTransport, err := restclient.TransportFor(&invalidCertConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } state := `{"then": "/index.html?a=1&b=2&c=%2F"}` encodedState := (url.Values{"state": []string{state}}).Encode() authorizeURL := clientConfig.Host + "/oauth/authorize?client_id=openshift-challenging-client&response_type=token&" + encodedState proxyURL := proxyServer.URL + "/oauth/authorize?client_id=openshift-challenging-client&response_type=token&" + encodedState testcases := map[string]struct { transport http.RoundTripper expectDirectRequestError bool }{ "anonymous": { transport: anonTransport, expectDirectRequestError: false, }, "valid signature, invalid cn": { transport: otherCertTransport, // TODO: this should redirect once we add support for client-cert logins expectDirectRequestError: true, }, "invalid signature, valid cn": { transport: invalidCertTransport, // TODO: this should redirect once we add support for client-cert logins expectDirectRequestError: true, }, } for k, tc := range testcases { // Build the authorize request, spoofing a remote user header directRequest, err := http.NewRequest("GET", authorizeURL, nil) directRequest.Header.Set("My-Remote-User", "myuser") // direct request against authorizeURL should redirect to proxy directResponse, err := tc.transport.RoundTrip(directRequest) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if tc.expectDirectRequestError { if directResponse.StatusCode != 500 { body, _ := ioutil.ReadAll(directResponse.Body) t.Logf("%s: Status: %#v", k, directResponse.StatusCode) t.Logf("%s: Headers: %#v", k, directResponse.Header) t.Logf("%s: Body: %s", k, string(body)) t.Errorf("%s: Expected spoofed header to get 500 status code, got %d", k, directResponse.StatusCode) continue } } else { proxyRedirect, err := directResponse.Location() if err != nil { body, _ := ioutil.ReadAll(directResponse.Body) t.Logf("%s: Status: %#v", k, directResponse.StatusCode) t.Logf("%s: Headers: %#v", k, directResponse.Header) t.Logf("%s: Body: %s", k, string(body)) t.Errorf("%s: expected spoofed remote user header to get 302 redirect, got error: %v", k, err) continue } if proxyRedirect.String() != proxyURL { t.Errorf("%s: expected redirect to proxy endpoint, got redirected to %v", k, proxyRedirect.String()) continue } } // request to proxy without credentials should return 401 proxyRequest, err := http.NewRequest("GET", proxyURL, nil) proxyRequest.Header.Set("My-Remote-User", "myuser") unauthenticatedProxyResponse, err := tc.transport.RoundTrip(proxyRequest) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if unauthenticatedProxyResponse.StatusCode != 401 { t.Errorf("%s: expected 401 status, got: %v", k, unauthenticatedProxyResponse.StatusCode) continue } // request to proxy with credentials should succeed with given credentials, not with passed Remote-User header proxyRequest.SetBasicAuth("myusername", "mypassword") authenticatedProxyResponse, err := tc.transport.RoundTrip(proxyRequest) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } tokenRedirect, err := authenticatedProxyResponse.Location() if err != nil { t.Errorf("%s: expected 302 redirect, got error: %v", k, err) continue } if tokenRedirect.Query().Get("error") != "" { t.Errorf("%s: expected successful token request, got error %v", k, tokenRedirect.String()) continue } // Grab the raw fragment ourselves, since the stdlib URL parsing decodes parts of it fragment := "" if parts := strings.SplitN(authenticatedProxyResponse.Header.Get("Location"), "#", 2); len(parts) == 2 { fragment = parts[1] } // Extract query-encoded values from the fragment fragmentValues, err := url.ParseQuery(fragment) if err != nil { t.Errorf("%s: %v", k, err) continue } // Ensure the state was retrieved correctly returnedState := fragmentValues.Get("state") if returnedState != state { t.Errorf("%s: Expected state\n\t%v\ngot\n\t%v", k, state, returnedState) continue } // Ensure the access_token was retrieved correctly accessToken := fragmentValues.Get("access_token") if accessToken == "" { t.Errorf("%s: Expected access token, got %s", k, tokenRedirect.String()) continue } // Make sure we can use the token, and it represents who we expect userConfig := anonConfig userConfig.BearerToken = accessToken userClient, err := client.New(&userConfig) if err != nil { t.Errorf("%s: Unexpected error: %v", k, err) continue } user, err := userClient.Users().Get("~") if err != nil { t.Errorf("%s: Unexpected error: %v", k, err) continue } if user.Name != "myusername" { t.Errorf("%s: Expected myusername as the user, got %v", k, user) continue } } // Get the master CA data for the login command masterCAFile := anonConfig.CAFile if masterCAFile == "" { // Write master ca data tmpFile, err := ioutil.TempFile("", "ca.crt") if err != nil { t.Fatalf("unexpected error: %v", err) } defer os.Remove(tmpFile.Name()) if err := ioutil.WriteFile(tmpFile.Name(), anonConfig.CAData, os.FileMode(0600)); err != nil { t.Fatalf("unexpected error: %v", err) } masterCAFile = tmpFile.Name() } // Attempt a login using a redirecting auth proxy loginOutput := &bytes.Buffer{} loginOptions := &login.LoginOptions{ Server: anonConfig.Host, CAFile: masterCAFile, StartingKubeConfig: &clientcmdapi.Config{}, Reader: bytes.NewBufferString("myusername\nmypassword\n"), Out: loginOutput, } if err := loginOptions.GatherInfo(); err != nil { t.Fatalf("Error trying to determine server info: %v\n%v", err, loginOutput.String()) } if loginOptions.Username != "myusername" { t.Fatalf("Unexpected user after authentication: %#v", loginOptions) } if len(loginOptions.Config.BearerToken) == 0 { t.Fatalf("Expected token after authentication: %#v", loginOptions.Config) } } var ( // oadm ca create-signer-cert --name=test-ca --overwrite=true rootCACert = []byte(` Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=test-ca Validity Not Before: Apr 11 18:11:23 2016 GMT Not After : Mar 18 18:11:24 2116 GMT Subject: CN=test-ca Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (2048 bit) Modulus (2048 bit): 00:b8:e7:dd:d5:05:90:93:bf:21:58:06:bd:00:b2: 02:a3:5f:4b:e8:6c:22:26:87:76:22:ff:0a:69:4a: 90:c1:b5:2f:b9:09:7d:3e:73:75:04:b9:52:9f:43: 44:e8:67:2b:2f:25:06:03:b2:f8:2d:a1:10:8c:de: f7:bf:61:7f:82:bc:4c:aa:c2:af:ea:b3:e3:81:9b: e4:58:c2:99:7e:e3:81:b5:26:57:3b:98:fa:c1:59: 90:24:f5:98:6a:e5:c8:1d:6a:31:f0:05:15:b6:c1: 17:35:0d:03:eb:c8:bd:19:28:8d:33:b0:40:8b:63: 95:3a:80:bb:6c:5f:d7:1e:7b:e4:27:fd:89:6b:52: 46:1b:7d:2d:48:b0:3e:42:d3:28:32:ce:2a:7c:d7: 66:d1:ec:59:a5:1c:2e:62:78:56:c6:d5:0c:64:5d: 2e:51:8e:7c:6e:6c:6b:71:4d:a4:54:55:cb:fc:a5: 29:ea:e5:df:36:2f:c6:2b:cf:86:84:54:cf:4e:2b: b1:3f:e2:ea:51:60:72:eb:2c:fc:67:d0:1b:01:21: 1c:4a:45:78:fa:d7:7f:87:92:d7:3c:21:4c:8f:0c: 90:f0:bc:df:56:1b:c6:2c:9b:cf:fa:38:88:95:53: 3a:2d:08:76:d0:2b:67:4c:15:fd:da:ed:83:67:d0: d2:2f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment, Certificate Sign X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: sha256WithRSAEncryption 45:44:e3:86:5a:0b:a4:75:57:f4:75:51:cf:19:1c:b8:af:a6: 4e:80:1f:47:93:26:a4:32:ab:35:f2:e7:67:17:ab:96:8d:9f: 82:10:d8:f1:e1:9f:3f:93:6d:ba:5d:22:d1:72:4e:d4:d1:f6: 24:06:00:ee:ac:d4:e4:61:b8:a6:52:04:32:f9:a1:cb:8f:53: 73:4d:cc:b5:35:32:b9:01:77:bf:db:00:b1:79:62:95:fd:da: 1e:b6:43:5f:48:05:bb:99:66:49:05:db:14:c3:65:82:77:6d: d7:ec:b9:6e:0d:7d:8f:79:72:64:fc:e1:ee:15:0e:45:62:ec: ac:3b:b2:dd:bc:84:89:6d:d1:ac:c5:04:79:d4:f6:e0:ee:b3: 1a:45:db:24:89:38:12:4a:3a:9d:4c:32:7b:cf:ba:a7:5b:44: be:3d:44:ca:63:59:3e:19:4e:d2:0c:c8:36:0b:87:22:fd:8e: 34:ba:60:3c:d7:81:0f:5c:35:7f:6c:64:ae:cd:18:49:a7:07: 54:cf:7d:94:92:f3:13:a4:f1:6c:2b:aa:4a:5b:30:f9:23:d0: 1c:e2:56:6d:4d:c5:b9:19:2e:bd:9d:bf:43:2b:e9:8e:ef:e7: b6:dd:ea:22:52:ae:e6:94:48:1a:c4:1e:e6:04:b5:c1:86:de: 49:03:ab:3a -----BEGIN CERTIFICATE----- MIICxDCCAaygAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 LWNhMCAXDTE2MDQxMTE4MTEyM1oYDzIxMTYwMzE4MTgxMTI0WjASMRAwDgYDVQQD Ewd0ZXN0LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOfd1QWQ k78hWAa9ALICo19L6GwiJod2Iv8KaUqQwbUvuQl9PnN1BLlSn0NE6GcrLyUGA7L4 LaEQjN73v2F/grxMqsKv6rPjgZvkWMKZfuOBtSZXO5j6wVmQJPWYauXIHWox8AUV tsEXNQ0D68i9GSiNM7BAi2OVOoC7bF/XHnvkJ/2Ja1JGG30tSLA+QtMoMs4qfNdm 0exZpRwuYnhWxtUMZF0uUY58bmxrcU2kVFXL/KUp6uXfNi/GK8+GhFTPTiuxP+Lq UWBy6yz8Z9AbASEcSkV4+td/h5LXPCFMjwyQ8LzfVhvGLJvP+jiIlVM6LQh20Ctn TBX92u2DZ9DSLwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAqQwDwYDVR0TAQH/BAUw AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEARUTjhloLpHVX9HVRzxkcuK+mToAfR5Mm pDKrNfLnZxerlo2fghDY8eGfP5Ntul0i0XJO1NH2JAYA7qzU5GG4plIEMvmhy49T c03MtTUyuQF3v9sAsXlilf3aHrZDX0gFu5lmSQXbFMNlgndt1+y5bg19j3lyZPzh 7hUORWLsrDuy3byEiW3RrMUEedT24O6zGkXbJIk4Eko6nUwye8+6p1tEvj1EymNZ PhlO0gzINguHIv2ONLpgPNeBD1w1f2xkrs0YSacHVM99lJLzE6TxbCuqSlsw+SPQ HOJWbU3FuRkuvZ2/Qyvpju/ntt3qIlKu5pRIGsQe5gS1wYbeSQOrOg== -----END CERTIFICATE----- `) // oadm create-api-client-config --basename=proxy --client-dir=. --user=proxy proxyClientCert = []byte(` Certificate: Data: Version: 3 (0x2) Serial Number: 2 (0x2) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=test-ca Validity Not Before: Apr 11 18:12:17 2016 GMT Not After : Mar 18 18:12:18 2116 GMT Subject: CN=proxy Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (2048 bit) Modulus (2048 bit): 00:db:09:79:3d:37:2d:69:2a:2d:57:cf:87:27:a7: 6e:07:00:a6:af:71:19:18:1e:f3:04:00:09:54:52: 26:67:03:f1:a6:ef:35:e6:73:cb:ee:46:75:11:5f: 30:46:dc:d1:fb:2c:68:bb:a8:e0:60:0f:fa:59:f2: d1:40:a1:79:29:83:8e:a6:b6:2c:22:c1:0a:3c:04: 74:ae:5d:a1:3d:db:9b:61:ea:bb:d1:77:20:26:fb: c1:ec:e6:9a:0d:ef:df:8c:02:35:27:8b:69:9c:01: a2:f6:bd:f2:a0:43:15:42:05:b2:77:1c:b4:21:58: fd:23:65:e7:bb:e1:3b:9b:ab:0e:fd:5e:15:da:97: 3f:23:50:53:67:c9:2c:77:f9:fb:62:ee:4c:df:6b: e1:4e:40:ef:f7:de:ba:6d:fe:32:be:f7:e5:4a:a5: 33:5e:ca:84:8c:d4:3e:24:18:9e:a4:b4:a8:02:3d: 45:5b:ac:66:06:72:70:ea:14:9b:14:9a:b6:50:29: 78:bf:49:80:43:ba:da:8d:03:dc:52:6d:4a:be:2f: 5c:1d:2a:27:65:4c:2a:bc:45:69:80:ec:2e:fe:55: 81:24:09:b4:2f:b8:5b:77:e3:cc:56:3e:b9:3d:57: 91:de:17:08:b2:c6:77:5d:9f:f4:b2:8f:d8:8d:a9: 2e:81 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE Signature Algorithm: sha256WithRSAEncryption 0e:bb:6c:d9:7a:f4:b8:57:a3:ea:d3:36:2b:83:31:3d:ed:48: c5:7f:b2:ba:20:33:82:03:22:a4:3e:4c:54:60:66:74:17:be: ac:a6:28:86:0f:eb:b0:33:f7:5c:ba:d4:52:97:da:5d:00:04: bc:90:61:76:2c:d6:51:37:b9:8a:ea:c3:63:b7:77:01:d1:4a: 56:98:fb:61:e1:94:b2:fb:c2:da:19:a1:8b:f3:33:fa:4c:b5: 0f:7f:2b:3b:83:63:48:28:bc:d4:ff:e6:93:ee:a7:3f:b5:47: 4b:9b:47:96:cb:b5:cc:e7:df:27:24:54:b7:3e:ec:e6:67:52: 40:78:03:bd:7f:ec:3b:90:56:f1:bb:63:04:f0:6e:43:07:13: 23:e9:b2:9d:84:25:13:5f:a1:76:3b:d9:72:cf:05:8e:2e:a6: 9d:9b:68:d4:36:76:95:76:68:4e:1c:90:bb:22:c4:6d:3c:bd: 16:bf:57:06:de:f6:76:1a:2a:10:dc:f5:d9:8f:23:a6:39:49: 34:66:6d:74:2c:81:2d:0f:49:a4:d2:f3:8c:a9:dc:72:8b:7b: 2b:95:37:9a:f5:b4:7f:9d:61:fe:04:c1:53:48:bc:26:8e:f8: 01:8f:ac:24:4d:44:ac:7d:4d:fd:5b:a2:ff:b9:33:33:2e:83: 81:d2:66:54 -----BEGIN CERTIFICATE----- MIIC1DCCAbygAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 LWNhMCAXDTE2MDQxMTE4MTIxN1oYDzIxMTYwMzE4MTgxMjE4WjAQMQ4wDAYDVQQD EwVwcm94eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANsJeT03LWkq LVfPhyenbgcApq9xGRge8wQACVRSJmcD8abvNeZzy+5GdRFfMEbc0fssaLuo4GAP +lny0UCheSmDjqa2LCLBCjwEdK5doT3bm2Hqu9F3ICb7wezmmg3v34wCNSeLaZwB ova98qBDFUIFsncctCFY/SNl57vhO5urDv1eFdqXPyNQU2fJLHf5+2LuTN9r4U5A 7/feum3+Mr735UqlM17KhIzUPiQYnqS0qAI9RVusZgZycOoUmxSatlApeL9JgEO6 2o0D3FJtSr4vXB0qJ2VMKrxFaYDsLv5VgSQJtC+4W3fjzFY+uT1Xkd4XCLLGd12f 9LKP2I2pLoECAwEAAaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG AQUFBwMCMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAA67bNl69LhX o+rTNiuDMT3tSMV/srogM4IDIqQ+TFRgZnQXvqymKIYP67Az91y61FKX2l0ABLyQ YXYs1lE3uYrqw2O3dwHRSlaY+2HhlLL7wtoZoYvzM/pMtQ9/KzuDY0govNT/5pPu pz+1R0ubR5bLtczn3yckVLc+7OZnUkB4A71/7DuQVvG7YwTwbkMHEyPpsp2EJRNf oXY72XLPBY4upp2baNQ2dpV2aE4ckLsixG08vRa/Vwbe9nYaKhDc9dmPI6Y5STRm bXQsgS0PSaTS84yp3HKLeyuVN5r1tH+dYf4EwVNIvCaO+AGPrCRNRKx9Tf1bov+5 MzMug4HSZlQ= -----END CERTIFICATE-----`) proxyClientKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA2wl5PTctaSotV8+HJ6duBwCmr3EZGB7zBAAJVFImZwPxpu81 5nPL7kZ1EV8wRtzR+yxou6jgYA/6WfLRQKF5KYOOprYsIsEKPAR0rl2hPdubYeq7 0XcgJvvB7OaaDe/fjAI1J4tpnAGi9r3yoEMVQgWydxy0IVj9I2Xnu+E7m6sO/V4V 2pc/I1BTZ8ksd/n7Yu5M32vhTkDv9966bf4yvvflSqUzXsqEjNQ+JBiepLSoAj1F W6xmBnJw6hSbFJq2UCl4v0mAQ7rajQPcUm1Kvi9cHSonZUwqvEVpgOwu/lWBJAm0 L7hbd+PMVj65PVeR3hcIssZ3XZ/0so/YjakugQIDAQABAoIBAEenNrkW1s0jVgf2 xLDtLaouxVh5OAtS/I6fcG3cHeHvQVspv8kuslS1SdCwAfv8etie83gIS7ZBI9XP ADMTX6578euJhrCr06xEjOMJkBjLQW5ruptQS/1UuGDGIzlR8iA8DKVuDtNRGb17 7+YLa+XYNUSP6EFMeirdSEyG5tgKJ32j1SQAtIedhnrMRtdIfjLmus0c2efIXvgz f26d3OclRy50X+P61jns/5ya+aocYKfzQ3Gp8ZKeIGZ6vw3tgID18eQ8vrjUJJWk 43UQg+axShqJTm/+unLpS3dJcXSSMu1OCzdCOnyiYiqL0KhJy8YC7doTQTQTq7VJ SBkoQtECgYEA8S1I4FtSwU+Wv0Wa8b7QticOGOxDzfnEgkLQHC1I0hVnATKGKpvN luOT8UBblwZssozFJ0UzpKWbPWYS7l+4G634A7qxu7+Byv9BwZITyg36LlGEbJXU god22G6+Z6HeSQIFPElp8nY+UtpuzXmdvijlm3/RzViDiJx2PcS5A4UCgYEA6H/W IMge3Alc0imTK3TIrNP6sPjztvKv6JVxrxN5GAzHx3mlwj8m+0naXeXqo/6krq52 wGaUCZPzehpN6R6H/d5VfANa9x1wCBHCPBEhPN+rnFiUlT2q5uNcg9uDwYisxJ96 +aInjsPaoCxAIHJFmxxFJH26Y7JBQydRoGRR+c0CgYEA8ILEhlkMMhN4tc5oMmSk JsLT4C7df29xdKXEfBT85eTKD/ueqKcvYyYYxyHzNK0HgRe5FOyCD9PG+HfusSFr rM7U4oMv85eLjDD6FlviuEEwGTjZ4p+YiYMmFbh60UYvMod9SR29NjqM9Hs4vFhn 4tdOAsB5LVrz8Sx3Dio8hzECgYBWe8bw5r/j5W+rlV9zGLvU3f0we0pc0SVyBLUH BN1UftyJbMyl1svvSWd66h0/52bmu2rc4stKTMiSsNouTvcTDfMKcE0UAtU7iy+P HGgatrClNaX/ZbL+s7AkNDFseiSZ9yDNXu4MAvp9/jfUWe1eZ0Oo8UO19gakrimE 2gxMOQKBgGYuj4I5TmtROJDTRxrRRzQVnoTV3GesequaW/y5UM4xr2ThLevnPCMI dSmVatvGsqYsQbPKOAp3ZcMQiqTIPUFeYSuzs3TuTs/tZ1cwfseN4M2bs258ynsT 51PHf9W7BDmvHZn8JMg688SSklatAUj4h3nnGWco1de9YL1bBLPg -----END RSA PRIVATE KEY----- `) // oadm create-api-client-config --basename=other --client-dir=. --user=other otherClientCert = []byte(` Certificate: Data: Version: 3 (0x2) Serial Number: 3 (0x3) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=test-ca Validity Not Before: Apr 11 18:12:25 2016 GMT Not After : Mar 18 18:12:26 2116 GMT Subject: CN=other Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (2048 bit) Modulus (2048 bit): 00:d8:6d:9e:41:51:d3:e9:99:b9:6d:37:4d:72:32: 6d:e8:3e:01:38:15:30:cd:5c:fb:0e:e1:76:01:32: 38:cf:1b:0e:8c:ec:21:5b:87:25:aa:6b:ac:6d:4b: a9:a5:c4:5e:aa:43:32:70:96:9f:30:dd:c7:ba:0f: a8:de:73:72:b5:10:9f:55:0a:80:bf:10:cc:c7:e3: 55:9b:6d:e1:13:6b:c2:d7:be:1c:c4:29:7b:db:06: bd:7e:22:a9:be:1a:af:cb:59:98:cf:0d:a5:e7:f7: cc:cd:92:05:3e:c8:a6:1e:cf:a3:05:90:b8:a8:76: 7a:a4:44:78:82:e4:7d:ba:1b:6e:4b:6f:1b:39:96: 04:c3:ec:28:1f:ac:c5:36:09:2e:71:23:00:35:44: 6e:ac:73:7b:5a:ad:c9:5c:35:4e:0c:5f:d6:09:9c: a0:a5:2c:ce:d7:5e:d6:93:e1:9c:b4:ec:61:bb:9f: ff:32:dc:64:9a:d5:bf:7f:20:84:a9:e7:5d:69:b6: 87:42:e6:a2:31:1c:32:50:6a:20:18:3e:f6:f8:c7: b8:63:eb:a2:35:da:4f:eb:34:f3:e5:e8:da:06:fd: c9:19:4e:45:b3:5d:e8:be:ed:18:e8:b5:30:42:eb: 70:64:72:76:03:30:04:81:38:f3:7c:09:98:5b:1d: 0f:dd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE Signature Algorithm: sha256WithRSAEncryption 61:bf:f3:81:d2:c9:46:e3:bb:68:0d:ae:b3:ce:56:1f:bf:3b: 93:ba:65:54:04:37:25:5e:bf:2a:b6:79:2f:bd:17:3f:eb:85: 9a:ce:78:ff:f8:b5:5a:3d:f9:99:1d:24:41:2c:0d:d1:c9:63: 19:19:75:b2:a6:65:da:d6:a5:ae:31:57:ec:8f:d6:0d:d9:86: 5e:b8:f1:98:a7:43:12:1c:d0:71:d2:5c:2f:a3:bb:5f:89:fc: dd:9a:fc:fb:8a:9b:ed:73:3b:6d:25:90:c9:70:96:88:d0:67: d7:10:17:35:e9:6e:d4:2b:61:f6:d0:4d:02:75:73:7a:cf:03: ed:d2:e2:3b:6f:cf:58:2e:92:e8:b6:c2:e1:1b:5d:33:46:3f: 95:53:67:7a:69:92:be:2d:e8:59:cd:71:16:a4:a4:89:80:ee: 67:97:47:84:a8:0e:f7:fe:7c:2e:97:b1:f5:11:84:30:90:1d: a7:44:55:15:93:c9:fc:16:16:28:2c:cd:8c:1d:82:a0:ff:35: 61:ec:8e:ae:59:88:bf:87:55:85:79:cd:20:58:79:c3:6b:4d: 78:43:c0:48:44:6d:78:24:e2:26:24:99:97:81:b9:43:a4:6d: 1e:dd:31:53:5b:36:49:cc:df:58:e8:f2:a8:25:30:cd:69:a8: c1:0d:c7:84 -----BEGIN CERTIFICATE----- MIIC1DCCAbygAwIBAgIBAzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 LWNhMCAXDTE2MDQxMTE4MTIyNVoYDzIxMTYwMzE4MTgxMjI2WjAQMQ4wDAYDVQQD EwVvdGhlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANhtnkFR0+mZ uW03TXIybeg+ATgVMM1c+w7hdgEyOM8bDozsIVuHJaprrG1LqaXEXqpDMnCWnzDd x7oPqN5zcrUQn1UKgL8QzMfjVZtt4RNrwte+HMQpe9sGvX4iqb4ar8tZmM8Npef3 zM2SBT7Iph7PowWQuKh2eqREeILkfbobbktvGzmWBMPsKB+sxTYJLnEjADVEbqxz e1qtyVw1Tgxf1gmcoKUsztde1pPhnLTsYbuf/zLcZJrVv38ghKnnXWm2h0LmojEc MlBqIBg+9vjHuGProjXaT+s08+Xo2gb9yRlORbNd6L7tGOi1MELrcGRydgMwBIE4 83wJmFsdD90CAwEAAaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG AQUFBwMCMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAGG/84HSyUbj u2gNrrPOVh+/O5O6ZVQENyVevyq2eS+9Fz/rhZrOeP/4tVo9+ZkdJEEsDdHJYxkZ dbKmZdrWpa4xV+yP1g3Zhl648ZinQxIc0HHSXC+ju1+J/N2a/PuKm+1zO20lkMlw lojQZ9cQFzXpbtQrYfbQTQJ1c3rPA+3S4jtvz1gukui2wuEbXTNGP5VTZ3ppkr4t 6FnNcRakpImA7meXR4SoDvf+fC6XsfURhDCQHadEVRWTyfwWFigszYwdgqD/NWHs jq5ZiL+HVYV5zSBYecNrTXhDwEhEbXgk4iYkmZeBuUOkbR7dMVNbNknM31jo8qgl MM1pqMENx4Q= -----END CERTIFICATE-----`) otherClientKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA2G2eQVHT6Zm5bTdNcjJt6D4BOBUwzVz7DuF2ATI4zxsOjOwh W4clqmusbUuppcReqkMycJafMN3Hug+o3nNytRCfVQqAvxDMx+NVm23hE2vC174c xCl72wa9fiKpvhqvy1mYzw2l5/fMzZIFPsimHs+jBZC4qHZ6pER4guR9uhtuS28b OZYEw+woH6zFNgkucSMANURurHN7Wq3JXDVODF/WCZygpSzO117Wk+GctOxhu5// MtxkmtW/fyCEqeddabaHQuaiMRwyUGogGD72+Me4Y+uiNdpP6zTz5ejaBv3JGU5F s13ovu0Y6LUwQutwZHJ2AzAEgTjzfAmYWx0P3QIDAQABAoIBAQCQF8Nid8lf4NIc jdJJMpwMIKQNI8afI8We7ar0NuytrrTsTBYVaxA/u3pMNjDXxbrFHwIJBa8tCKt+ DAkBOdnoBQ4fv2NiUhwVBR0s42YT2Q4bN17Nl1T3yTAGN6vNftUFzTw4tjx8CXZY c1x8pXg8UT+XZ/gZaPBUR6X4d4nhikGqSiILNh6uDjuYUxxMgea0qrAnx4HvBcBF I1X5zg+turWcuTXoR39Ijn3UNnNZrp8XUqjA850dzQQnZqrcDnD0lqV1HOcF5V2H VABBIVL8Jzm7mn+k6+NTVC3eWFK+EPwY8/OwHGa3O9LsA0l3knsG8x4FvaRFXTSY fYSkExudAoGBANwE79pvjGE9kJ5MgJVg7klNv5XWIoaZnmiaPovM5LX7Fylw6vV3 QGEj8x3VO3EqBB66g70SrqoNgCmVNx3oe8+KVX1+8XVhX4DIQLbLJBFfvaNZV7sh IOM00hhwdKZk+szb2CS3yRo2rsmD1yEr7djsnC1l7UiLn4TJ9bA6oK+nAoGBAPvS V07KwKKFQUv7cLwPDy1b8G7JbFOmYuc8Zber3S9YtrpFKjX2lR9bXk6iPSa2k485 cqs1RM2/Mrw0uXKpW3jrwVE6dy2IyKLuMBcvKWlUVY02cGA0hV7A2CJKGcPxsFEP txj5R+VN/FDcm7RzE0jmJNay+5PmDfchom4WXFTbAoGAWhHXUvfpYwF+C5/L39sf kXi3npJb7fhDZhUG19pYIruYvslQFo7sFxhNdYAOZoRJzX6TYbqdMFZ4ig1g0+iR juPVnZtzI5dqLmFMRMiiik5EZvOzO5MTUJAWFhUrW9bo6SZytI1cUVPjd/F2B0lh hDVQtjEM0279LbIz1yIZF+8CgYEArRMlRJcfjNPPTBy1n9st0DwXZN11YYzC/zDI rFMoAymS9TUiTNJ8LYALsjnZk6j6g/607C0Ba/OUODx4lPEHWHWYeW6YiKgxVaIl VVnpuWXoItUeqVCPtc8O/Yo2aTDMwPnvGvAB1P0jhKQLNBu/TmQ3P4TmWgFM6eSp Eca2kO8CgYAstEpSdnMQAHE92HsTSBA+aFm5jfYE/2papDcVE/Q2AqMN+ZjZvfnj vWyX2MBY8yccNwUyNiwbEfiy9A+XLtNpsuVvNGzOp5CQAs/wIPTCfRD7zVUtIhUN PVEo4cjWU2JK68lSTyW3UWdoPwcKIdDlnure/al7NpIG2g6weBubpQ== -----END RSA PRIVATE KEY----- `) // invalidClientCert is a client cert with the desired name which is NOT signed by the root CA crt, but by another signer with the same name // oadm ca create-signer-cert --name=test-ca --overwrite=true // oadm create-api-client-config --basename=invalid --client-dir=. --user=invalid invalidClientCert = []byte(` Certificate: Data: Version: 3 (0x2) Serial Number: 2 (0x2) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=test-ca Validity Not Before: Apr 11 18:17:29 2016 GMT Not After : Mar 18 18:17:30 2116 GMT Subject: CN=invalid Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (2048 bit) Modulus (2048 bit): 00:ac:87:5e:71:36:39:6d:2b:33:40:0e:ff:d6:3d: 67:a5:8b:3d:7e:56:c5:3f:49:a9:42:7d:6f:da:30: cc:0f:cd:64:cc:20:91:e4:41:b2:9c:54:f8:9a:fe: ba:7d:e6:2b:2f:ff:fc:c8:7b:4f:bf:3d:61:5c:18: 6e:10:6f:a8:33:9e:54:8f:f7:ac:34:57:f4:ff:00: c7:24:07:dd:df:47:e1:bc:0f:d6:41:b5:e4:5c:c0: 36:90:4b:2e:b2:97:a9:2c:7f:c4:f7:7a:2b:96:1b: a4:20:ba:db:df:4b:72:ff:e2:ae:46:79:5b:5d:72: 41:16:3d:a4:c5:31:cf:12:0c:ca:59:d5:72:c9:fe: 87:51:b4:54:0f:eb:46:79:95:8b:2b:ba:a3:51:71: 87:06:c2:5b:80:59:74:c4:d8:bd:c6:7f:56:e9:8f: 95:d1:85:1f:67:39:20:33:1f:3a:ba:9a:81:c6:32: b6:a6:e3:1d:15:97:19:c9:71:9e:95:ec:d3:38:3b: 2a:28:37:f8:cf:ea:c3:3c:af:84:b9:d6:64:8f:e1: cd:29:d3:9a:ba:48:82:50:85:0f:07:d2:d4:e9:83: 42:9f:22:25:4d:55:9d:38:32:9c:f1:07:17:14:bf: 80:7b:c5:88:6e:f7:60:50:ab:95:32:a3:0f:98:74: 49:21 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE Signature Algorithm: sha256WithRSAEncryption 92:5d:46:49:82:df:80:84:8c:7a:4d:4a:4c:ab:13:20:70:ee: 36:42:84:3c:30:67:51:a6:b4:c8:e2:0f:13:c4:2b:51:9f:2d: 7a:0d:be:77:3e:90:67:81:55:f8:3d:b5:c6:00:a1:ca:86:d1: 83:67:d6:7d:4c:e9:c0:af:53:3b:23:5d:17:1f:8b:c0:c5:ae: a3:f2:7c:b5:7b:9a:fc:1b:09:a8:78:ed:12:13:fd:ed:97:0c: e4:eb:f8:b2:63:d1:bf:89:db:84:1e:45:f8:5b:5b:d2:93:c2: 26:5c:61:b4:a9:05:30:45:5e:f5:c4:95:8e:98:83:4d:41:61: 5d:cb:83:a6:72:b6:af:70:64:8a:72:5a:1f:20:cb:8b:7c:82: 52:26:45:9d:58:da:c8:0b:e0:ac:00:f0:d4:12:85:2c:2b:a5: 29:db:54:e6:83:e3:48:d2:61:65:e6:13:31:09:cd:c8:ba:39: 3c:f7:ca:ab:93:ea:21:12:5f:49:0d:46:17:15:cc:ae:72:a8: 66:97:56:f3:2f:39:75:b5:f9:3e:ff:5a:4f:3b:8c:16:4d:bf: 70:55:c5:b7:ee:74:d7:39:4b:da:f9:da:39:84:25:62:24:a8: b8:f3:2d:6b:e5:71:60:26:cb:71:ad:bc:25:2a:f9:3a:ec:25: b9:c3:5c:e4 -----BEGIN CERTIFICATE----- MIIC1jCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 LWNhMCAXDTE2MDQxMTE4MTcyOVoYDzIxMTYwMzE4MTgxNzMwWjASMRAwDgYDVQQD EwdpbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArIdecTY5 bSszQA7/1j1npYs9flbFP0mpQn1v2jDMD81kzCCR5EGynFT4mv66feYrL//8yHtP vz1hXBhuEG+oM55Uj/esNFf0/wDHJAfd30fhvA/WQbXkXMA2kEsuspepLH/E93or lhukILrb30ty/+KuRnlbXXJBFj2kxTHPEgzKWdVyyf6HUbRUD+tGeZWLK7qjUXGH BsJbgFl0xNi9xn9W6Y+V0YUfZzkgMx86upqBxjK2puMdFZcZyXGelezTODsqKDf4 z+rDPK+EudZkj+HNKdOaukiCUIUPB9LU6YNCnyIlTVWdODKc8QcXFL+Ae8WIbvdg UKuVMqMPmHRJIQIDAQABozUwMzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI KwYBBQUHAwIwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAkl1GSYLf gISMek1KTKsTIHDuNkKEPDBnUaa0yOIPE8QrUZ8teg2+dz6QZ4FV+D21xgChyobR g2fWfUzpwK9TOyNdFx+LwMWuo/J8tXua/BsJqHjtEhP97ZcM5Ov4smPRv4nbhB5F +Ftb0pPCJlxhtKkFMEVe9cSVjpiDTUFhXcuDpnK2r3BkinJaHyDLi3yCUiZFnVja yAvgrADw1BKFLCulKdtU5oPjSNJhZeYTMQnNyLo5PPfKq5PqIRJfSQ1GFxXMrnKo ZpdW8y85dbX5Pv9aTzuMFk2/cFXFt+501zlL2vnaOYQlYiSouPMta+VxYCbLca28 JSr5OuwlucNc5A== -----END CERTIFICATE-----`) invalidClientKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEArIdecTY5bSszQA7/1j1npYs9flbFP0mpQn1v2jDMD81kzCCR 5EGynFT4mv66feYrL//8yHtPvz1hXBhuEG+oM55Uj/esNFf0/wDHJAfd30fhvA/W QbXkXMA2kEsuspepLH/E93orlhukILrb30ty/+KuRnlbXXJBFj2kxTHPEgzKWdVy yf6HUbRUD+tGeZWLK7qjUXGHBsJbgFl0xNi9xn9W6Y+V0YUfZzkgMx86upqBxjK2 puMdFZcZyXGelezTODsqKDf4z+rDPK+EudZkj+HNKdOaukiCUIUPB9LU6YNCnyIl TVWdODKc8QcXFL+Ae8WIbvdgUKuVMqMPmHRJIQIDAQABAoIBAE7weTPPnaLnm0F6 G3DJE71Y4kAGL6XvbDRx9FWe8h9g2PfVByurK6//6OfyGR41zBjgRabtVOWpjfx3 aRS4IfvMO+DLb81bWUu77WH8/3WEDDLiBCR4tw4BHHYVED7CybMEmviou3ypFQWs uaGHggy2iQrRyA4Pktw8REG9soMM+s+T0zlfexbeXgz7OJYd5QStBslI5ZJhHa1I LW94hrU0Yj1ONP2hCfMc5H808zOkMUSZMgRMTXXZQzo2XdujLelRxQ1oaZTU4aQM SwZG1vzdDjjFhXW1sjD7G2DoyTxbDVOIfqYOmO/t7witXo2g52hIXhb4RFoxD0eZ dFDRyakCgYEA0mU9X2rc1GU4OlKUOd4phsQfLmRk4ya7i2Zica3n4PFvaz+XoIZ0 NZf2xwZlY5MX21tBadIFW8C4GilDscgLrP8P2gW15hP6bKpHuB2nkJcGdNi6Tg8f 0Vvf7L4RHamolN7yk39zJoC9KUDaPAtqGB4niUDCsjc6LdJTqW/oCHMCgYEA0ezs Dxe8j9l34BEqZxu71NjUKovUQJv+0kz301W5gVCFAY5oBDfFf42IHl5q+B7TFLaP 6xEEdyh0K6GrGTt9YtWB3HYPEStzBf0fXAg7fJHPn12mn8/B0UFMkJKyuRnPOW7t 3WOROzChSpWWKVUMFJIBCyfMvEjUgm8SzUluxxsCgYBe8g8DK09ijhcUwsVfY/Fr fr/viKC6nXUPEHImiOtWaL32MSl06Jgyw1Q7Npi0meGvPPxFC+EdKdgq/iotZXBX bncx1Vfj72oYdbON09wVdQIV4uQYa9zY9tQTmyZQM4r/O6lOhLprSreSkVCqvh/v qFQBLXdvQ1r+6KaWlQiqHwKBgG7s6FeZTVQdr5BAwc02BGyWHpZUyNVTGLV7YkDT vXAtYfrOivwflEawPMr/TTrK3vLE/QtTNK7aO3iKtuRgYQMGmtYptBB4ixERDa8N 0pEiYzlsvQ0ZNOsjvBdwzOuuTaeljB8965IBQlks7entPLLp648/epnLSi+aDa9Y LCcdAoGBAL1qU+P+8+8Lfdj+/8GfaZdZQnqeOzLkxzGDcuVDNYACIVGmGJqL01Gx RUVzUCnG68qdoai960Yo0w41U90hsCpBny50SShYu3kL67Gqn03UcEYDw5pmUPwn NykkJ6u51LArDs6E8hA0aoMrQbZGZiod93dPHlbFhR3+4t4l8wDJ -----END RSA PRIVATE KEY----- `) )