... | ... |
@@ -3,11 +3,14 @@ package x509request |
3 | 3 |
import ( |
4 | 4 |
"crypto/x509" |
5 | 5 |
"crypto/x509/pkix" |
6 |
+ "fmt" |
|
6 | 7 |
"net/http" |
7 | 8 |
|
9 |
+ "github.com/golang/glog" |
|
8 | 10 |
"github.com/openshift/origin/pkg/auth/authenticator" |
9 | 11 |
"k8s.io/kubernetes/pkg/auth/user" |
10 | 12 |
kerrors "k8s.io/kubernetes/pkg/util/errors" |
13 |
+ "k8s.io/kubernetes/pkg/util/sets" |
|
11 | 14 |
) |
12 | 15 |
|
13 | 16 |
// UserConversion defines an interface for extracting user info from a client certificate chain |
... | ... |
@@ -68,10 +71,14 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, |
68 | 68 |
type Verifier struct { |
69 | 69 |
opts x509.VerifyOptions |
70 | 70 |
auth authenticator.Request |
71 |
+ |
|
72 |
+ // allowedCommonNames contains the common names which a verified certificate is allowed to have. |
|
73 |
+ // If empty, all verified certificates are allowed. |
|
74 |
+ allowedCommonNames sets.String |
|
71 | 75 |
} |
72 | 76 |
|
73 |
-func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request) authenticator.Request { |
|
74 |
- return &Verifier{opts, auth} |
|
77 |
+func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request, allowedCommonNames sets.String) authenticator.Request { |
|
78 |
+ return &Verifier{opts, auth, allowedCommonNames} |
|
75 | 79 |
} |
76 | 80 |
|
77 | 81 |
// AuthenticateRequest verifies the presented client certificates, then delegates to the wrapped auth |
... | ... |
@@ -82,8 +89,11 @@ func (a *Verifier) AuthenticateRequest(req *http.Request) (user.Info, bool, erro |
82 | 82 |
|
83 | 83 |
var errlist []error |
84 | 84 |
for _, cert := range req.TLS.PeerCertificates { |
85 |
- _, err := cert.Verify(a.opts) |
|
86 |
- if err != nil { |
|
85 |
+ if _, err := cert.Verify(a.opts); err != nil { |
|
86 |
+ errlist = append(errlist, err) |
|
87 |
+ continue |
|
88 |
+ } |
|
89 |
+ if err := a.verifySubject(cert.Subject); err != nil { |
|
87 | 90 |
errlist = append(errlist, err) |
88 | 91 |
continue |
89 | 92 |
} |
... | ... |
@@ -92,6 +102,19 @@ func (a *Verifier) AuthenticateRequest(req *http.Request) (user.Info, bool, erro |
92 | 92 |
return nil, false, kerrors.NewAggregate(errlist) |
93 | 93 |
} |
94 | 94 |
|
95 |
+func (a *Verifier) verifySubject(subject pkix.Name) error { |
|
96 |
+ // No CN restrictions |
|
97 |
+ if len(a.allowedCommonNames) == 0 { |
|
98 |
+ return nil |
|
99 |
+ } |
|
100 |
+ // Enforce CN restrictions |
|
101 |
+ if a.allowedCommonNames.Has(subject.CommonName) { |
|
102 |
+ return nil |
|
103 |
+ } |
|
104 |
+ glog.Warningf("x509: subject with cn=%s is not in the allowed list: %v", subject.CommonName, a.allowedCommonNames.List()) |
|
105 |
+ return fmt.Errorf("x509: subject with cn=%s is not allowed", subject.CommonName) |
|
106 |
+} |
|
107 |
+ |
|
95 | 108 |
// DefaultVerifyOptions returns VerifyOptions that use the system root certificates, current time, |
96 | 109 |
// and requires certificates to be valid for client auth (x509.ExtKeyUsageClientAuth) |
97 | 110 |
func DefaultVerifyOptions() x509.VerifyOptions { |
... | ... |
@@ -11,6 +11,7 @@ import ( |
11 | 11 |
|
12 | 12 |
"github.com/openshift/origin/pkg/auth/authenticator" |
13 | 13 |
"k8s.io/kubernetes/pkg/auth/user" |
14 |
+ "k8s.io/kubernetes/pkg/util/sets" |
|
14 | 15 |
) |
15 | 16 |
|
16 | 17 |
const ( |
... | ... |
@@ -536,6 +537,8 @@ func TestX509Verifier(t *testing.T) { |
536 | 536 |
|
537 | 537 |
Opts x509.VerifyOptions |
538 | 538 |
|
539 |
+ AllowedCNs sets.String |
|
540 |
+ |
|
539 | 541 |
ExpectOK bool |
540 | 542 |
ExpectErr bool |
541 | 543 |
}{ |
... | ... |
@@ -579,6 +582,22 @@ func TestX509Verifier(t *testing.T) { |
579 | 579 |
ExpectOK: true, |
580 | 580 |
ExpectErr: false, |
581 | 581 |
}, |
582 |
+ "valid client cert with wrong CN": { |
|
583 |
+ Opts: getDefaultVerifyOptions(t), |
|
584 |
+ AllowedCNs: sets.NewString("foo", "bar"), |
|
585 |
+ Certs: getCerts(t, clientCNCert), |
|
586 |
+ |
|
587 |
+ ExpectOK: false, |
|
588 |
+ ExpectErr: true, |
|
589 |
+ }, |
|
590 |
+ "valid client cert with right CN": { |
|
591 |
+ Opts: getDefaultVerifyOptions(t), |
|
592 |
+ AllowedCNs: sets.NewString("client_cn"), |
|
593 |
+ Certs: getCerts(t, clientCNCert), |
|
594 |
+ |
|
595 |
+ ExpectOK: true, |
|
596 |
+ ExpectErr: false, |
|
597 |
+ }, |
|
582 | 598 |
|
583 | 599 |
"future cert": { |
584 | 600 |
Opts: x509.VerifyOptions{ |
... | ... |
@@ -614,7 +633,7 @@ func TestX509Verifier(t *testing.T) { |
614 | 614 |
return &user.DefaultInfo{Name: "innerauth"}, true, nil |
615 | 615 |
}) |
616 | 616 |
|
617 |
- a := NewVerifier(testCase.Opts, auth) |
|
617 |
+ a := NewVerifier(testCase.Opts, auth, testCase.AllowedCNs) |
|
618 | 618 |
|
619 | 619 |
user, ok, err := a.AuthenticateRequest(req) |
620 | 620 |
|
... | ... |
@@ -742,6 +742,9 @@ type RequestHeaderIdentityProvider struct { |
742 | 742 |
|
743 | 743 |
// ClientCA is a file with the trusted signer certs. If empty, no request verification is done, and any direct request to the OAuth server can impersonate any identity from this provider, merely by setting a request header. |
744 | 744 |
ClientCA string |
745 |
+ // ClientCommonNames is an optional list of common names to require a match from. If empty, any client certificate validated against the clientCA bundle is considered authoritative. |
|
746 |
+ ClientCommonNames []string |
|
747 |
+ |
|
745 | 748 |
// Headers is the set of headers to check for identity information |
746 | 749 |
Headers []string |
747 | 750 |
// PreferredUsernameHeaders is the set of headers to check for the preferred username |
... | ... |
@@ -617,6 +617,7 @@ var map_RequestHeaderIdentityProvider = map[string]string{ |
617 | 617 |
"loginURL": "LoginURL is a URL to redirect unauthenticated /authorize requests to Unauthenticated requests from OAuth clients which expect interactive logins will be redirected here ${url} is replaced with the current URL, escaped to be safe in a query parameter\n https://www.example.com/sso-login?then=${url}\n${query} is replaced with the current query string\n https://www.example.com/auth-proxy/oauth/authorize?${query}", |
618 | 618 |
"challengeURL": "ChallengeURL is a URL to redirect unauthenticated /authorize requests to Unauthenticated requests from OAuth clients which expect WWW-Authenticate challenges will be redirected here ${url} is replaced with the current URL, escaped to be safe in a query parameter\n https://www.example.com/sso-login?then=${url}\n${query} is replaced with the current query string\n https://www.example.com/auth-proxy/oauth/authorize?${query}", |
619 | 619 |
"clientCA": "ClientCA is a file with the trusted signer certs. If empty, no request verification is done, and any direct request to the OAuth server can impersonate any identity from this provider, merely by setting a request header.", |
620 |
+ "clientCommonNames": "ClientCommonNames is an optional list of common names to require a match from. If empty, any client certificate validated against the clientCA bundle is considered authoritative.", |
|
620 | 621 |
"headers": "Headers is the set of headers to check for identity information", |
621 | 622 |
"preferredUsernameHeaders": "PreferredUsernameHeaders is the set of headers to check for the preferred username", |
622 | 623 |
"nameHeaders": "NameHeaders is the set of headers to check for the display name", |
... | ... |
@@ -732,6 +732,9 @@ type RequestHeaderIdentityProvider struct { |
732 | 732 |
|
733 | 733 |
// ClientCA is a file with the trusted signer certs. If empty, no request verification is done, and any direct request to the OAuth server can impersonate any identity from this provider, merely by setting a request header. |
734 | 734 |
ClientCA string `json:"clientCA"` |
735 |
+ // ClientCommonNames is an optional list of common names to require a match from. If empty, any client certificate validated against the clientCA bundle is considered authoritative. |
|
736 |
+ ClientCommonNames []string `json:"clientCommonNames"` |
|
737 |
+ |
|
735 | 738 |
// Headers is the set of headers to check for identity information |
736 | 739 |
Headers []string `json:"headers"` |
737 | 740 |
// PreferredUsernameHeaders is the set of headers to check for the preferred username |
... | ... |
@@ -235,7 +235,10 @@ func ValidateRequestHeaderIdentityProvider(provider *api.RequestHeaderIdentityPr |
235 | 235 |
|
236 | 236 |
if len(provider.ClientCA) > 0 { |
237 | 237 |
validationResults.AddErrors(ValidateFile(provider.ClientCA, fieldPath.Child("provider", "clientCA"))...) |
238 |
+ } else if len(provider.ClientCommonNames) > 0 { |
|
239 |
+ validationResults.AddErrors(field.Invalid(fieldPath.Child("provider", "clientCommonNames"), provider.ClientCommonNames, "clientCA must be specified in order to use clientCommonNames")) |
|
238 | 240 |
} |
241 |
+ |
|
239 | 242 |
if len(provider.Headers) == 0 { |
240 | 243 |
validationResults.AddErrors(field.Required(fieldPath.Child("provider", "headers"), "")) |
241 | 244 |
} |
... | ... |
@@ -683,7 +683,7 @@ func (c *AuthConfig) getAuthenticationRequestHandler() (authenticator.Request, e |
683 | 683 |
return nil, fmt.Errorf("Error loading certs from %s: %v", provider.ClientCA, err) |
684 | 684 |
} |
685 | 685 |
|
686 |
- authRequestHandler = x509request.NewVerifier(opts, authRequestHandler) |
|
686 |
+ authRequestHandler = x509request.NewVerifier(opts, authRequestHandler, sets.NewString(provider.ClientCommonNames...)) |
|
687 | 687 |
} |
688 | 688 |
authRequestHandlers = append(authRequestHandlers, authRequestHandler) |
689 | 689 |
|
... | ... |
@@ -23,80 +23,9 @@ import ( |
23 | 23 |
testserver "github.com/openshift/origin/test/util/server" |
24 | 24 |
) |
25 | 25 |
|
26 |
-var ( |
|
27 |
- rootCACert = []byte(`-----BEGIN CERTIFICATE----- |
|
28 |
-MIIC7DCCAdagAwIBAgIBATALBgkqhkiG9w0BAQswKDEmMCQGA1UEAwwdMTAuMTMu |
|
29 |
-MTI5LjE0OTo4NDQzQDE0MjU2NzUyNzQwIBcNMTUwMzA2MjA1NDM0WhgPMjExNTAy |
|
30 |
-MTAyMDU0MzVaMCgxJjAkBgNVBAMMHTEwLjEzLjEyOS4xNDk6ODQ0M0AxNDI1Njc1 |
|
31 |
-Mjc0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOnLZ0PgeEKnbV7D |
|
32 |
-93g6fcllMh6ngCnQpEoaWSHTWjPbv/qDU/jRQU2l/KHOkMXKsbNiasRT6ZIWlUFc |
|
33 |
-W/Jgd1Tz7zjh+pgJHLEtKdWVPwP/8ruUhQotrb1E/q1g21wqczPxfb+Z9s6+AnkF |
|
34 |
-FLooBCCRa8wpC+TtcAaT7/yEJfN6IUhcT9XFmLzKTPz76UXBHMN+KDeK0k0u77a9 |
|
35 |
-vj+eAedB6Xg9lfpvIclvjgy6cvQ9oavYTJ8Q5mYZdIdspmSzFjAyZUylgpEIpPkN |
|
36 |
-e8dcqiA0hc2Mq/pwwn/F3i4va/NO7+Od9gRkAtvuvCUASXuCmon6pRYAZEImevRt |
|
37 |
-GbRlkQIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/BAUwAwEB/zAL |
|
38 |
-BgkqhkiG9w0BAQsDggEBAD30//8aJkPLtJ0G6/0oa+zjKBZH04PyWCjTsgaDCHVm |
|
39 |
-z/AntWxKR5fc+z/NXfnhV8M8/zb4ZGHp+jczozvcXZxUgftlUFNxV7sY8NXdJNrs |
|
40 |
-t+oFURLIibIjxN0vlz7py16RxXy693t6PzfQB/69ZB/AI3VfyOdJ1cvaV/kOce21 |
|
41 |
-Kp/jmVz5DUhQI60zcUOE4at81emo3uYK7Pz9iil2Wu2lK4+1uP4LdZRRLEUXWqNb |
|
42 |
-VmAB7OAhfJ2/x/BsPIvbI1aGp7DjjQgaeBwXD/mW8AUJHHbdvWUYz1yNyQ2XDWZm |
|
43 |
-X2kxcf0iGTwuqufTmw7EcDc/dWIdJ6bsB007/M9bz3g= |
|
44 |
-`) |
|
45 |
- |
|
46 |
- clientCert = []byte(`-----BEGIN CERTIFICATE----- |
|
47 |
-MIIC+DCCAeKgAwIBAgIBBTALBgkqhkiG9w0BAQswKDEmMCQGA1UEAwwdMTAuMTMu |
|
48 |
-MTI5LjE0OTo4NDQzQDE0MjU2NzUyNzQwIBcNMTUwMzA2MjA1NDM2WhgPMjExNTAy |
|
49 |
-MTAyMDU0MzdaMCIxIDAeBgNVBAMTF3N5c3RlbTpvcGVuc2hpZnQtY2xpZW50MIIB |
|
50 |
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwbkwwrV4j3xqmUhyKErAzfAI |
|
51 |
-UX5atGGJHt+oRmZ3BzeAl6CpGLGLSiYso4j5JmLo0qpvQroSw66oOoVMw2851nhI |
|
52 |
-OZHo7aGvJ9elgmwa7ghDg4DN3TUe8y9Ex+JUDnAAK5dY0DV8UK7Aa2SAxIlSMGIu |
|
53 |
-VuUcjwlC9w37D3VxDFoa6XO+SUBiRUJyjiDlLNUegyV60jimxVTZbTb8r90lbGc8 |
|
54 |
-iB5j6py5ZCF/UMRY5LEuIum/7dKvH2A03q2n3Y58qcAhWIp6lP9DeJe3CMvuK64C |
|
55 |
-BwvT9jm9TioRGZskqfV3mLYyhxp1q2FKK03umQ5KKNYqvppFUYVKdzXgFjxfMQID |
|
56 |
-AQABozUwMzAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYD |
|
57 |
-VR0TAQH/BAIwADALBgkqhkiG9w0BAQsDggEBACY2Lu5kl9a2cBi3+WB/oo7iG82S |
|
58 |
-9IdIaABDLFWCGp4e0PEGAfROlNcCrhmEizkhPXeDNrjmDKeShnu1E/8RgwBtDrym |
|
59 |
-v9WQBa/HI3ZbO3hDdR2pNo6c+y3MqDJHO8/4l7hV5DYY9ypfB85mZQ7uxKaFawqs |
|
60 |
-GqLZNJWjpG6T9yUDaj2fO+etXb5dPTZiSytw1Z4l2GDGElLRjVS4k2aP0Lo/BLXG |
|
61 |
-1nUatU3KcCEeb1ifghFjDLESo8mUwfBl9v1vO75rIFRDfoPFMqIHGhRmP+fbnCI8 |
|
62 |
-fWh90BcEhK0TheTyEHBPtpKKiYz5BWyNlkCuTmhygaRCa9SQWl2nRi2XVGY= |
|
63 |
-`) |
|
64 |
- |
|
65 |
- clientKey = []byte(`-----BEGIN RSA PRIVATE KEY----- |
|
66 |
-MIIEpAIBAAKCAQEAwbkwwrV4j3xqmUhyKErAzfAIUX5atGGJHt+oRmZ3BzeAl6Cp |
|
67 |
-GLGLSiYso4j5JmLo0qpvQroSw66oOoVMw2851nhIOZHo7aGvJ9elgmwa7ghDg4DN |
|
68 |
-3TUe8y9Ex+JUDnAAK5dY0DV8UK7Aa2SAxIlSMGIuVuUcjwlC9w37D3VxDFoa6XO+ |
|
69 |
-SUBiRUJyjiDlLNUegyV60jimxVTZbTb8r90lbGc8iB5j6py5ZCF/UMRY5LEuIum/ |
|
70 |
-7dKvH2A03q2n3Y58qcAhWIp6lP9DeJe3CMvuK64CBwvT9jm9TioRGZskqfV3mLYy |
|
71 |
-hxp1q2FKK03umQ5KKNYqvppFUYVKdzXgFjxfMQIDAQABAoIBADg/olXWxUO8V2Nc |
|
72 |
-crEaS3NAT9oBuyqG636IaF7Qn5z7052zK4Yc/xmvjeSJ//XSYFHS5O1WA97Hltcv |
|
73 |
-H0PbxspsMGRu5lghSy9hYRBGfWdCBQBo5N1m8C6iOfFj2Q48HQCLOGF0Nj1jEEHe |
|
74 |
-c7kdOj0MNPJMIgeyI7yCVbR+YC26dfxiaIfRtyzsScsNX/pP1AH9lEd9c6reMvms |
|
75 |
-UxjplUkYjk4gbngmKJjd2MD8dc8XqR5V+Oq1uwOQG/EZhSBlyxwRVMFwd5/opb2Q |
|
76 |
-JqMZvd458MQ2C2RSZALXDYYmCMbXU76Crg7N3+y34d+uwkIufUhFfTR7BuUkvlzt |
|
77 |
-5vb+WTECgYEAyVCSxvTbB9y3IQpsRlJeBwVnWNHclZft4g9PtqQgA6VaWqSoYvFz |
|
78 |
-t2m2/L3O39zEgalM6HesVT8EdiIWvp08eHYvFTb9jaqxHIbwdrzxtvBn5SJ6CjCX |
|
79 |
-xA+uWv3AbH+H2t/ZCiPAKebcOfefmce6/8cKrNKFXs5KojR6tpM2Lo0CgYEA9li3 |
|
80 |
-JDTRbCGLsuyVhDT3l4przzJC0DwU1j8zBJfUrBtuPMhDISHHvq9opSoTQsRXz9EH |
|
81 |
-ruQe3/XCvE/y988E3oVh+ikmBX01xCsIUB0jUhItVQ7GSacY0+UgZmH6Zw7xJjO5 |
|
82 |
-zwaYGnejOxHIs0XmeajbhYl+bAGEym+iV682rDUCgYEAn0ox2VtFNCNgg7RLmBj0 |
|
83 |
-bXnJHG5xq6xbfdO/rzSOYFQl+jLvSdrjRO1Q7QsC9f8pPa9IO2j14z3Jue+fL5Qa |
|
84 |
-lPZuqsqoNcAqA/iBrHI0kBwJGTT+e7GXZHtD6pt99luyk20rvuoq0vzopLVag8OW |
|
85 |
-I2zK9ZReE3YHd/EuZ+hzpsECgYBiTXSHliwboidE9vOTFi/W4P20aLIQtmj6Na3+ |
|
86 |
-HzhWlXuf9aoUBo7WoNh5UBjvg7omy5rtR0qqxD85Ng4WpR2kTkWStejeN+DErwda |
|
87 |
-MMZvcaF1V7f4nB1kMQKE2IQ7q9K/E9UJr+/yX9tbLvWP1EzsL12qI/u2zcRXo8R8 |
|
88 |
-iQagIQKBgQDA4Ag/ShDEb0x6rFFJwMaHUT/TT8Yv8Ul7paIcAX6c/1jwgEh9T20F |
|
89 |
-6UWl+OcIpJp7DYNNLB/hesYqs76QvZDd9nIiW1bzuC0LHuSzyEoe234gpAfrRfYs |
|
90 |
-qLwYJxjzwYTLvLYPU5vHmdg8v5wIXh0TaRTDTdKViISGD09aiXSYzw== |
|
91 |
-`) |
|
92 |
-) |
|
93 |
- |
|
94 | 26 |
// TestOAuthRequestHeader checks the following scenarios: |
95 | 27 |
// * request containing remote user header is ignored if it doesn't have client cert auth |
96 |
-// * request containing remote user header is honored if it has client cert auth |
|
28 |
+// * request containing remote user header is honored if it has valid client cert auth matching ClientCommonNames |
|
97 | 29 |
// * unauthenticated requests are redirected to an auth proxy |
98 | 30 |
// * login command succeeds against a request-header identity provider via redirection to an auth proxy |
99 | 31 |
func TestOAuthRequestHeader(t *testing.T) { |
... | ... |
@@ -169,10 +98,11 @@ func TestOAuthRequestHeader(t *testing.T) { |
169 | 169 |
UseAsLogin: true, |
170 | 170 |
MappingMethod: "claim", |
171 | 171 |
Provider: &configapi.RequestHeaderIdentityProvider{ |
172 |
- ChallengeURL: proxyServer.URL + "/oauth/authorize?${query}", |
|
173 |
- LoginURL: "http://www.example.com/login?then=${url}", |
|
174 |
- ClientCA: caFile.Name(), |
|
175 |
- Headers: []string{"My-Remote-User", "SSO-User"}, |
|
172 |
+ ChallengeURL: proxyServer.URL + "/oauth/authorize?${query}", |
|
173 |
+ LoginURL: "http://www.example.com/login?then=${url}", |
|
174 |
+ ClientCA: caFile.Name(), |
|
175 |
+ ClientCommonNames: []string{"proxy"}, |
|
176 |
+ Headers: []string{"My-Remote-User", "SSO-User"}, |
|
176 | 177 |
}, |
177 | 178 |
} |
178 | 179 |
|
... | ... |
@@ -199,77 +129,157 @@ func TestOAuthRequestHeader(t *testing.T) { |
199 | 199 |
|
200 | 200 |
// Use the server and CA info, with cert info |
201 | 201 |
proxyConfig := anonConfig |
202 |
- proxyConfig.CertData = clientCert |
|
203 |
- proxyConfig.KeyData = clientKey |
|
202 |
+ proxyConfig.CertData = proxyClientCert |
|
203 |
+ proxyConfig.KeyData = proxyClientKey |
|
204 | 204 |
proxyTransport, err = restclient.TransportFor(&proxyConfig) |
205 | 205 |
if err != nil { |
206 | 206 |
t.Fatalf("unexpected error: %v", err) |
207 | 207 |
} |
208 | 208 |
|
209 |
- // Build the authorize request, spoofing a remote user header |
|
210 |
- authorizeURL := clientConfig.Host + "/oauth/authorize?client_id=openshift-challenging-client&response_type=token" |
|
211 |
- req, err := http.NewRequest("GET", authorizeURL, nil) |
|
212 |
- req.Header.Set("My-Remote-User", "myuser") |
|
213 |
- |
|
214 |
- // Make the request without cert auth |
|
215 |
- resp, err := anonTransport.RoundTrip(req) |
|
209 |
+ // client cert that is valid, but not in the list of allowed common names |
|
210 |
+ otherCertConfig := anonConfig |
|
211 |
+ otherCertConfig.CertData = otherClientCert |
|
212 |
+ otherCertConfig.KeyData = otherClientKey |
|
213 |
+ otherCertTransport, err := restclient.TransportFor(&otherCertConfig) |
|
216 | 214 |
if err != nil { |
217 | 215 |
t.Fatalf("unexpected error: %v", err) |
218 | 216 |
} |
219 |
- proxyRedirect, err := resp.Location() |
|
220 |
- if err != nil { |
|
221 |
- t.Fatalf("expected spoofed remote user header to get 302 redirect, got error: %v", err) |
|
222 |
- } |
|
223 |
- if proxyRedirect.String() != proxyServer.URL+"/oauth/authorize?client_id=openshift-challenging-client&response_type=token" { |
|
224 |
- t.Fatalf("expected redirect to proxy endpoint, got redirected to %v", proxyRedirect.String()) |
|
225 |
- } |
|
226 |
- |
|
227 |
- // Request the redirected URL, which should cause the proxy to make the same request with cert auth |
|
228 |
- req, err = http.NewRequest("GET", proxyRedirect.String(), nil) |
|
229 |
- req.Header.Set("My-Remote-User", "myuser") |
|
230 |
- req.SetBasicAuth("myusername", "mypassword") |
|
231 | 217 |
|
232 |
- resp, err = proxyTransport.RoundTrip(req) |
|
218 |
+ // client cert that has the desired common name, but does not have a valid signature |
|
219 |
+ invalidCertConfig := anonConfig |
|
220 |
+ invalidCertConfig.CertData = invalidClientCert |
|
221 |
+ invalidCertConfig.KeyData = invalidClientKey |
|
222 |
+ invalidCertTransport, err := restclient.TransportFor(&invalidCertConfig) |
|
233 | 223 |
if err != nil { |
234 | 224 |
t.Fatalf("unexpected error: %v", err) |
235 | 225 |
} |
236 |
- tokenRedirect, err := resp.Location() |
|
237 |
- if err != nil { |
|
238 |
- t.Fatalf("expected 302 redirect, got error: %v", err) |
|
239 |
- } |
|
240 |
- if tokenRedirect.Query().Get("error") != "" { |
|
241 |
- t.Fatalf("expected successful token request, got error %v", tokenRedirect.String()) |
|
242 |
- } |
|
243 | 226 |
|
244 |
- // Extract the access_token |
|
227 |
+ authorizeURL := clientConfig.Host + "/oauth/authorize?client_id=openshift-challenging-client&response_type=token" |
|
228 |
+ proxyURL := proxyServer.URL + "/oauth/authorize?client_id=openshift-challenging-client&response_type=token" |
|
245 | 229 |
|
246 |
- // group #0 is everything. #1 #2 #3 |
|
247 |
- accessTokenRedirectRegex := regexp.MustCompile(`(^|&)access_token=([^&]+)($|&)`) |
|
248 |
- accessToken := "" |
|
249 |
- if matches := accessTokenRedirectRegex.FindStringSubmatch(tokenRedirect.Fragment); matches != nil { |
|
250 |
- accessToken = matches[2] |
|
251 |
- } |
|
252 |
- if accessToken == "" { |
|
253 |
- t.Fatalf("Expected access token, got %s", tokenRedirect.String()) |
|
230 |
+ testcases := map[string]struct { |
|
231 |
+ transport http.RoundTripper |
|
232 |
+ expectDirectRequestError bool |
|
233 |
+ }{ |
|
234 |
+ "anonymous": { |
|
235 |
+ transport: anonTransport, |
|
236 |
+ expectDirectRequestError: false, |
|
237 |
+ }, |
|
238 |
+ "valid signature, invalid cn": { |
|
239 |
+ transport: otherCertTransport, |
|
240 |
+ // TODO: this should redirect once we add support for client-cert logins |
|
241 |
+ expectDirectRequestError: true, |
|
242 |
+ }, |
|
243 |
+ "invalid signature, valid cn": { |
|
244 |
+ transport: invalidCertTransport, |
|
245 |
+ // TODO: this should redirect once we add support for client-cert logins |
|
246 |
+ expectDirectRequestError: true, |
|
247 |
+ }, |
|
254 | 248 |
} |
255 | 249 |
|
256 |
- // Make sure we can use the token, and it represents who we expect |
|
257 |
- userConfig := anonConfig |
|
258 |
- userConfig.BearerToken = accessToken |
|
259 |
- userClient, err := client.New(&userConfig) |
|
260 |
- if err != nil { |
|
261 |
- t.Fatalf("Unexpected error: %v", err) |
|
262 |
- } |
|
263 |
- user, err := userClient.Users().Get("~") |
|
264 |
- if err != nil { |
|
265 |
- t.Fatalf("Unexpected error: %v", err) |
|
266 |
- } |
|
267 |
- if user.Name != "myusername" { |
|
268 |
- t.Fatalf("Expected myusername as the user, got %v", user) |
|
250 |
+ for k, tc := range testcases { |
|
251 |
+ // Build the authorize request, spoofing a remote user header |
|
252 |
+ directRequest, err := http.NewRequest("GET", authorizeURL, nil) |
|
253 |
+ directRequest.Header.Set("My-Remote-User", "myuser") |
|
254 |
+ |
|
255 |
+ // direct request against authorizeURL should redirect to proxy |
|
256 |
+ directResponse, err := tc.transport.RoundTrip(directRequest) |
|
257 |
+ if err != nil { |
|
258 |
+ t.Errorf("%s: unexpected error: %v", k, err) |
|
259 |
+ continue |
|
260 |
+ } |
|
261 |
+ |
|
262 |
+ if tc.expectDirectRequestError { |
|
263 |
+ if directResponse.StatusCode != 500 { |
|
264 |
+ body, _ := ioutil.ReadAll(directResponse.Body) |
|
265 |
+ t.Logf("%s: Status: %#v", k, directResponse.StatusCode) |
|
266 |
+ t.Logf("%s: Headers: %#v", k, directResponse.Header) |
|
267 |
+ t.Logf("%s: Body: %s", k, string(body)) |
|
268 |
+ t.Errorf("%s: Expected spoofed header to get 500 status code, got %d", k, directResponse.StatusCode) |
|
269 |
+ continue |
|
270 |
+ } |
|
271 |
+ } else { |
|
272 |
+ proxyRedirect, err := directResponse.Location() |
|
273 |
+ if err != nil { |
|
274 |
+ body, _ := ioutil.ReadAll(directResponse.Body) |
|
275 |
+ t.Logf("%s: Status: %#v", k, directResponse.StatusCode) |
|
276 |
+ t.Logf("%s: Headers: %#v", k, directResponse.Header) |
|
277 |
+ t.Logf("%s: Body: %s", k, string(body)) |
|
278 |
+ t.Errorf("%s: expected spoofed remote user header to get 302 redirect, got error: %v", k, err) |
|
279 |
+ continue |
|
280 |
+ } |
|
281 |
+ if proxyRedirect.String() != proxyURL { |
|
282 |
+ t.Errorf("%s: expected redirect to proxy endpoint, got redirected to %v", k, proxyRedirect.String()) |
|
283 |
+ continue |
|
284 |
+ } |
|
285 |
+ } |
|
286 |
+ |
|
287 |
+ // request to proxy without credentials should return 401 |
|
288 |
+ proxyRequest, err := http.NewRequest("GET", proxyURL, nil) |
|
289 |
+ proxyRequest.Header.Set("My-Remote-User", "myuser") |
|
290 |
+ |
|
291 |
+ unauthenticatedProxyResponse, err := tc.transport.RoundTrip(proxyRequest) |
|
292 |
+ if err != nil { |
|
293 |
+ t.Errorf("%s: unexpected error: %v", k, err) |
|
294 |
+ continue |
|
295 |
+ } |
|
296 |
+ if unauthenticatedProxyResponse.StatusCode != 401 { |
|
297 |
+ t.Errorf("%s: expected 401 status, got: %v", k, unauthenticatedProxyResponse.StatusCode) |
|
298 |
+ continue |
|
299 |
+ } |
|
300 |
+ |
|
301 |
+ // request to proxy with credentials should succeed with given credentials, not with passed Remote-User header |
|
302 |
+ proxyRequest.SetBasicAuth("myusername", "mypassword") |
|
303 |
+ |
|
304 |
+ authenticatedProxyResponse, err := tc.transport.RoundTrip(proxyRequest) |
|
305 |
+ if err != nil { |
|
306 |
+ t.Errorf("%s: unexpected error: %v", k, err) |
|
307 |
+ continue |
|
308 |
+ } |
|
309 |
+ tokenRedirect, err := authenticatedProxyResponse.Location() |
|
310 |
+ if err != nil { |
|
311 |
+ t.Errorf("%s: expected 302 redirect, got error: %v", k, err) |
|
312 |
+ continue |
|
313 |
+ } |
|
314 |
+ if tokenRedirect.Query().Get("error") != "" { |
|
315 |
+ t.Errorf("%s: expected successful token request, got error %v", k, tokenRedirect.String()) |
|
316 |
+ continue |
|
317 |
+ } |
|
318 |
+ |
|
319 |
+ // Extract the access_token |
|
320 |
+ |
|
321 |
+ // group #0 is everything. #1 #2 #3 |
|
322 |
+ accessTokenRedirectRegex := regexp.MustCompile(`(^|&)access_token=([^&]+)($|&)`) |
|
323 |
+ accessToken := "" |
|
324 |
+ if matches := accessTokenRedirectRegex.FindStringSubmatch(tokenRedirect.Fragment); matches != nil { |
|
325 |
+ accessToken = matches[2] |
|
326 |
+ } |
|
327 |
+ if accessToken == "" { |
|
328 |
+ t.Errorf("%s: Expected access token, got %s", k, tokenRedirect.String()) |
|
329 |
+ continue |
|
330 |
+ } |
|
331 |
+ |
|
332 |
+ // Make sure we can use the token, and it represents who we expect |
|
333 |
+ userConfig := anonConfig |
|
334 |
+ userConfig.BearerToken = accessToken |
|
335 |
+ userClient, err := client.New(&userConfig) |
|
336 |
+ if err != nil { |
|
337 |
+ t.Errorf("%s: Unexpected error: %v", k, err) |
|
338 |
+ continue |
|
339 |
+ } |
|
340 |
+ user, err := userClient.Users().Get("~") |
|
341 |
+ if err != nil { |
|
342 |
+ t.Errorf("%s: Unexpected error: %v", k, err) |
|
343 |
+ continue |
|
344 |
+ } |
|
345 |
+ if user.Name != "myusername" { |
|
346 |
+ t.Errorf("%s: Expected myusername as the user, got %v", k, user) |
|
347 |
+ continue |
|
348 |
+ } |
|
269 | 349 |
} |
270 | 350 |
|
271 | 351 |
// Get the master CA data for the login command |
272 |
- masterCAFile := userConfig.CAFile |
|
352 |
+ masterCAFile := anonConfig.CAFile |
|
273 | 353 |
if masterCAFile == "" { |
274 | 354 |
// Write master ca data |
275 | 355 |
tmpFile, err := ioutil.TempFile("", "ca.crt") |
... | ... |
@@ -277,7 +287,7 @@ func TestOAuthRequestHeader(t *testing.T) { |
277 | 277 |
t.Fatalf("unexpected error: %v", err) |
278 | 278 |
} |
279 | 279 |
defer os.Remove(tmpFile.Name()) |
280 |
- if err := ioutil.WriteFile(tmpFile.Name(), userConfig.CAData, os.FileMode(0600)); err != nil { |
|
280 |
+ if err := ioutil.WriteFile(tmpFile.Name(), anonConfig.CAData, os.FileMode(0600)); err != nil { |
|
281 | 281 |
t.Fatalf("unexpected error: %v", err) |
282 | 282 |
} |
283 | 283 |
masterCAFile = tmpFile.Name() |
... | ... |
@@ -302,3 +312,403 @@ func TestOAuthRequestHeader(t *testing.T) { |
302 | 302 |
t.Fatalf("Expected token after authentication: %#v", loginOptions.Config) |
303 | 303 |
} |
304 | 304 |
} |
305 |
+ |
|
306 |
+var ( |
|
307 |
+ // oadm ca create-signer-cert --name=test-ca --overwrite=true |
|
308 |
+ rootCACert = []byte(` |
|
309 |
+Certificate: |
|
310 |
+ Data: |
|
311 |
+ Version: 3 (0x2) |
|
312 |
+ Serial Number: 1 (0x1) |
|
313 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
314 |
+ Issuer: CN=test-ca |
|
315 |
+ Validity |
|
316 |
+ Not Before: Apr 11 18:11:23 2016 GMT |
|
317 |
+ Not After : Mar 18 18:11:24 2116 GMT |
|
318 |
+ Subject: CN=test-ca |
|
319 |
+ Subject Public Key Info: |
|
320 |
+ Public Key Algorithm: rsaEncryption |
|
321 |
+ RSA Public Key: (2048 bit) |
|
322 |
+ Modulus (2048 bit): |
|
323 |
+ 00:b8:e7:dd:d5:05:90:93:bf:21:58:06:bd:00:b2: |
|
324 |
+ 02:a3:5f:4b:e8:6c:22:26:87:76:22:ff:0a:69:4a: |
|
325 |
+ 90:c1:b5:2f:b9:09:7d:3e:73:75:04:b9:52:9f:43: |
|
326 |
+ 44:e8:67:2b:2f:25:06:03:b2:f8:2d:a1:10:8c:de: |
|
327 |
+ f7:bf:61:7f:82:bc:4c:aa:c2:af:ea:b3:e3:81:9b: |
|
328 |
+ e4:58:c2:99:7e:e3:81:b5:26:57:3b:98:fa:c1:59: |
|
329 |
+ 90:24:f5:98:6a:e5:c8:1d:6a:31:f0:05:15:b6:c1: |
|
330 |
+ 17:35:0d:03:eb:c8:bd:19:28:8d:33:b0:40:8b:63: |
|
331 |
+ 95:3a:80:bb:6c:5f:d7:1e:7b:e4:27:fd:89:6b:52: |
|
332 |
+ 46:1b:7d:2d:48:b0:3e:42:d3:28:32:ce:2a:7c:d7: |
|
333 |
+ 66:d1:ec:59:a5:1c:2e:62:78:56:c6:d5:0c:64:5d: |
|
334 |
+ 2e:51:8e:7c:6e:6c:6b:71:4d:a4:54:55:cb:fc:a5: |
|
335 |
+ 29:ea:e5:df:36:2f:c6:2b:cf:86:84:54:cf:4e:2b: |
|
336 |
+ b1:3f:e2:ea:51:60:72:eb:2c:fc:67:d0:1b:01:21: |
|
337 |
+ 1c:4a:45:78:fa:d7:7f:87:92:d7:3c:21:4c:8f:0c: |
|
338 |
+ 90:f0:bc:df:56:1b:c6:2c:9b:cf:fa:38:88:95:53: |
|
339 |
+ 3a:2d:08:76:d0:2b:67:4c:15:fd:da:ed:83:67:d0: |
|
340 |
+ d2:2f |
|
341 |
+ Exponent: 65537 (0x10001) |
|
342 |
+ X509v3 extensions: |
|
343 |
+ X509v3 Key Usage: critical |
|
344 |
+ Digital Signature, Key Encipherment, Certificate Sign |
|
345 |
+ X509v3 Basic Constraints: critical |
|
346 |
+ CA:TRUE |
|
347 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
348 |
+ 45:44:e3:86:5a:0b:a4:75:57:f4:75:51:cf:19:1c:b8:af:a6: |
|
349 |
+ 4e:80:1f:47:93:26:a4:32:ab:35:f2:e7:67:17:ab:96:8d:9f: |
|
350 |
+ 82:10:d8:f1:e1:9f:3f:93:6d:ba:5d:22:d1:72:4e:d4:d1:f6: |
|
351 |
+ 24:06:00:ee:ac:d4:e4:61:b8:a6:52:04:32:f9:a1:cb:8f:53: |
|
352 |
+ 73:4d:cc:b5:35:32:b9:01:77:bf:db:00:b1:79:62:95:fd:da: |
|
353 |
+ 1e:b6:43:5f:48:05:bb:99:66:49:05:db:14:c3:65:82:77:6d: |
|
354 |
+ d7:ec:b9:6e:0d:7d:8f:79:72:64:fc:e1:ee:15:0e:45:62:ec: |
|
355 |
+ ac:3b:b2:dd:bc:84:89:6d:d1:ac:c5:04:79:d4:f6:e0:ee:b3: |
|
356 |
+ 1a:45:db:24:89:38:12:4a:3a:9d:4c:32:7b:cf:ba:a7:5b:44: |
|
357 |
+ be:3d:44:ca:63:59:3e:19:4e:d2:0c:c8:36:0b:87:22:fd:8e: |
|
358 |
+ 34:ba:60:3c:d7:81:0f:5c:35:7f:6c:64:ae:cd:18:49:a7:07: |
|
359 |
+ 54:cf:7d:94:92:f3:13:a4:f1:6c:2b:aa:4a:5b:30:f9:23:d0: |
|
360 |
+ 1c:e2:56:6d:4d:c5:b9:19:2e:bd:9d:bf:43:2b:e9:8e:ef:e7: |
|
361 |
+ b6:dd:ea:22:52:ae:e6:94:48:1a:c4:1e:e6:04:b5:c1:86:de: |
|
362 |
+ 49:03:ab:3a |
|
363 |
+-----BEGIN CERTIFICATE----- |
|
364 |
+MIICxDCCAaygAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 |
|
365 |
+LWNhMCAXDTE2MDQxMTE4MTEyM1oYDzIxMTYwMzE4MTgxMTI0WjASMRAwDgYDVQQD |
|
366 |
+Ewd0ZXN0LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOfd1QWQ |
|
367 |
+k78hWAa9ALICo19L6GwiJod2Iv8KaUqQwbUvuQl9PnN1BLlSn0NE6GcrLyUGA7L4 |
|
368 |
+LaEQjN73v2F/grxMqsKv6rPjgZvkWMKZfuOBtSZXO5j6wVmQJPWYauXIHWox8AUV |
|
369 |
+tsEXNQ0D68i9GSiNM7BAi2OVOoC7bF/XHnvkJ/2Ja1JGG30tSLA+QtMoMs4qfNdm |
|
370 |
+0exZpRwuYnhWxtUMZF0uUY58bmxrcU2kVFXL/KUp6uXfNi/GK8+GhFTPTiuxP+Lq |
|
371 |
+UWBy6yz8Z9AbASEcSkV4+td/h5LXPCFMjwyQ8LzfVhvGLJvP+jiIlVM6LQh20Ctn |
|
372 |
+TBX92u2DZ9DSLwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAqQwDwYDVR0TAQH/BAUw |
|
373 |
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEARUTjhloLpHVX9HVRzxkcuK+mToAfR5Mm |
|
374 |
+pDKrNfLnZxerlo2fghDY8eGfP5Ntul0i0XJO1NH2JAYA7qzU5GG4plIEMvmhy49T |
|
375 |
+c03MtTUyuQF3v9sAsXlilf3aHrZDX0gFu5lmSQXbFMNlgndt1+y5bg19j3lyZPzh |
|
376 |
+7hUORWLsrDuy3byEiW3RrMUEedT24O6zGkXbJIk4Eko6nUwye8+6p1tEvj1EymNZ |
|
377 |
+PhlO0gzINguHIv2ONLpgPNeBD1w1f2xkrs0YSacHVM99lJLzE6TxbCuqSlsw+SPQ |
|
378 |
+HOJWbU3FuRkuvZ2/Qyvpju/ntt3qIlKu5pRIGsQe5gS1wYbeSQOrOg== |
|
379 |
+-----END CERTIFICATE----- |
|
380 |
+`) |
|
381 |
+ |
|
382 |
+ // oadm create-api-client-config --basename=proxy --client-dir=. --user=proxy |
|
383 |
+ proxyClientCert = []byte(` |
|
384 |
+Certificate: |
|
385 |
+ Data: |
|
386 |
+ Version: 3 (0x2) |
|
387 |
+ Serial Number: 2 (0x2) |
|
388 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
389 |
+ Issuer: CN=test-ca |
|
390 |
+ Validity |
|
391 |
+ Not Before: Apr 11 18:12:17 2016 GMT |
|
392 |
+ Not After : Mar 18 18:12:18 2116 GMT |
|
393 |
+ Subject: CN=proxy |
|
394 |
+ Subject Public Key Info: |
|
395 |
+ Public Key Algorithm: rsaEncryption |
|
396 |
+ RSA Public Key: (2048 bit) |
|
397 |
+ Modulus (2048 bit): |
|
398 |
+ 00:db:09:79:3d:37:2d:69:2a:2d:57:cf:87:27:a7: |
|
399 |
+ 6e:07:00:a6:af:71:19:18:1e:f3:04:00:09:54:52: |
|
400 |
+ 26:67:03:f1:a6:ef:35:e6:73:cb:ee:46:75:11:5f: |
|
401 |
+ 30:46:dc:d1:fb:2c:68:bb:a8:e0:60:0f:fa:59:f2: |
|
402 |
+ d1:40:a1:79:29:83:8e:a6:b6:2c:22:c1:0a:3c:04: |
|
403 |
+ 74:ae:5d:a1:3d:db:9b:61:ea:bb:d1:77:20:26:fb: |
|
404 |
+ c1:ec:e6:9a:0d:ef:df:8c:02:35:27:8b:69:9c:01: |
|
405 |
+ a2:f6:bd:f2:a0:43:15:42:05:b2:77:1c:b4:21:58: |
|
406 |
+ fd:23:65:e7:bb:e1:3b:9b:ab:0e:fd:5e:15:da:97: |
|
407 |
+ 3f:23:50:53:67:c9:2c:77:f9:fb:62:ee:4c:df:6b: |
|
408 |
+ e1:4e:40:ef:f7:de:ba:6d:fe:32:be:f7:e5:4a:a5: |
|
409 |
+ 33:5e:ca:84:8c:d4:3e:24:18:9e:a4:b4:a8:02:3d: |
|
410 |
+ 45:5b:ac:66:06:72:70:ea:14:9b:14:9a:b6:50:29: |
|
411 |
+ 78:bf:49:80:43:ba:da:8d:03:dc:52:6d:4a:be:2f: |
|
412 |
+ 5c:1d:2a:27:65:4c:2a:bc:45:69:80:ec:2e:fe:55: |
|
413 |
+ 81:24:09:b4:2f:b8:5b:77:e3:cc:56:3e:b9:3d:57: |
|
414 |
+ 91:de:17:08:b2:c6:77:5d:9f:f4:b2:8f:d8:8d:a9: |
|
415 |
+ 2e:81 |
|
416 |
+ Exponent: 65537 (0x10001) |
|
417 |
+ X509v3 extensions: |
|
418 |
+ X509v3 Key Usage: critical |
|
419 |
+ Digital Signature, Key Encipherment |
|
420 |
+ X509v3 Extended Key Usage: |
|
421 |
+ TLS Web Client Authentication |
|
422 |
+ X509v3 Basic Constraints: critical |
|
423 |
+ CA:FALSE |
|
424 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
425 |
+ 0e:bb:6c:d9:7a:f4:b8:57:a3:ea:d3:36:2b:83:31:3d:ed:48: |
|
426 |
+ c5:7f:b2:ba:20:33:82:03:22:a4:3e:4c:54:60:66:74:17:be: |
|
427 |
+ ac:a6:28:86:0f:eb:b0:33:f7:5c:ba:d4:52:97:da:5d:00:04: |
|
428 |
+ bc:90:61:76:2c:d6:51:37:b9:8a:ea:c3:63:b7:77:01:d1:4a: |
|
429 |
+ 56:98:fb:61:e1:94:b2:fb:c2:da:19:a1:8b:f3:33:fa:4c:b5: |
|
430 |
+ 0f:7f:2b:3b:83:63:48:28:bc:d4:ff:e6:93:ee:a7:3f:b5:47: |
|
431 |
+ 4b:9b:47:96:cb:b5:cc:e7:df:27:24:54:b7:3e:ec:e6:67:52: |
|
432 |
+ 40:78:03:bd:7f:ec:3b:90:56:f1:bb:63:04:f0:6e:43:07:13: |
|
433 |
+ 23:e9:b2:9d:84:25:13:5f:a1:76:3b:d9:72:cf:05:8e:2e:a6: |
|
434 |
+ 9d:9b:68:d4:36:76:95:76:68:4e:1c:90:bb:22:c4:6d:3c:bd: |
|
435 |
+ 16:bf:57:06:de:f6:76:1a:2a:10:dc:f5:d9:8f:23:a6:39:49: |
|
436 |
+ 34:66:6d:74:2c:81:2d:0f:49:a4:d2:f3:8c:a9:dc:72:8b:7b: |
|
437 |
+ 2b:95:37:9a:f5:b4:7f:9d:61:fe:04:c1:53:48:bc:26:8e:f8: |
|
438 |
+ 01:8f:ac:24:4d:44:ac:7d:4d:fd:5b:a2:ff:b9:33:33:2e:83: |
|
439 |
+ 81:d2:66:54 |
|
440 |
+-----BEGIN CERTIFICATE----- |
|
441 |
+MIIC1DCCAbygAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 |
|
442 |
+LWNhMCAXDTE2MDQxMTE4MTIxN1oYDzIxMTYwMzE4MTgxMjE4WjAQMQ4wDAYDVQQD |
|
443 |
+EwVwcm94eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANsJeT03LWkq |
|
444 |
+LVfPhyenbgcApq9xGRge8wQACVRSJmcD8abvNeZzy+5GdRFfMEbc0fssaLuo4GAP |
|
445 |
++lny0UCheSmDjqa2LCLBCjwEdK5doT3bm2Hqu9F3ICb7wezmmg3v34wCNSeLaZwB |
|
446 |
+ova98qBDFUIFsncctCFY/SNl57vhO5urDv1eFdqXPyNQU2fJLHf5+2LuTN9r4U5A |
|
447 |
+7/feum3+Mr735UqlM17KhIzUPiQYnqS0qAI9RVusZgZycOoUmxSatlApeL9JgEO6 |
|
448 |
+2o0D3FJtSr4vXB0qJ2VMKrxFaYDsLv5VgSQJtC+4W3fjzFY+uT1Xkd4XCLLGd12f |
|
449 |
+9LKP2I2pLoECAwEAAaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG |
|
450 |
+AQUFBwMCMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAA67bNl69LhX |
|
451 |
+o+rTNiuDMT3tSMV/srogM4IDIqQ+TFRgZnQXvqymKIYP67Az91y61FKX2l0ABLyQ |
|
452 |
+YXYs1lE3uYrqw2O3dwHRSlaY+2HhlLL7wtoZoYvzM/pMtQ9/KzuDY0govNT/5pPu |
|
453 |
+pz+1R0ubR5bLtczn3yckVLc+7OZnUkB4A71/7DuQVvG7YwTwbkMHEyPpsp2EJRNf |
|
454 |
+oXY72XLPBY4upp2baNQ2dpV2aE4ckLsixG08vRa/Vwbe9nYaKhDc9dmPI6Y5STRm |
|
455 |
+bXQsgS0PSaTS84yp3HKLeyuVN5r1tH+dYf4EwVNIvCaO+AGPrCRNRKx9Tf1bov+5 |
|
456 |
+MzMug4HSZlQ= |
|
457 |
+-----END CERTIFICATE-----`) |
|
458 |
+ |
|
459 |
+ proxyClientKey = []byte(` |
|
460 |
+-----BEGIN RSA PRIVATE KEY----- |
|
461 |
+MIIEowIBAAKCAQEA2wl5PTctaSotV8+HJ6duBwCmr3EZGB7zBAAJVFImZwPxpu81 |
|
462 |
+5nPL7kZ1EV8wRtzR+yxou6jgYA/6WfLRQKF5KYOOprYsIsEKPAR0rl2hPdubYeq7 |
|
463 |
+0XcgJvvB7OaaDe/fjAI1J4tpnAGi9r3yoEMVQgWydxy0IVj9I2Xnu+E7m6sO/V4V |
|
464 |
+2pc/I1BTZ8ksd/n7Yu5M32vhTkDv9966bf4yvvflSqUzXsqEjNQ+JBiepLSoAj1F |
|
465 |
+W6xmBnJw6hSbFJq2UCl4v0mAQ7rajQPcUm1Kvi9cHSonZUwqvEVpgOwu/lWBJAm0 |
|
466 |
+L7hbd+PMVj65PVeR3hcIssZ3XZ/0so/YjakugQIDAQABAoIBAEenNrkW1s0jVgf2 |
|
467 |
+xLDtLaouxVh5OAtS/I6fcG3cHeHvQVspv8kuslS1SdCwAfv8etie83gIS7ZBI9XP |
|
468 |
+ADMTX6578euJhrCr06xEjOMJkBjLQW5ruptQS/1UuGDGIzlR8iA8DKVuDtNRGb17 |
|
469 |
+7+YLa+XYNUSP6EFMeirdSEyG5tgKJ32j1SQAtIedhnrMRtdIfjLmus0c2efIXvgz |
|
470 |
+f26d3OclRy50X+P61jns/5ya+aocYKfzQ3Gp8ZKeIGZ6vw3tgID18eQ8vrjUJJWk |
|
471 |
+43UQg+axShqJTm/+unLpS3dJcXSSMu1OCzdCOnyiYiqL0KhJy8YC7doTQTQTq7VJ |
|
472 |
+SBkoQtECgYEA8S1I4FtSwU+Wv0Wa8b7QticOGOxDzfnEgkLQHC1I0hVnATKGKpvN |
|
473 |
+luOT8UBblwZssozFJ0UzpKWbPWYS7l+4G634A7qxu7+Byv9BwZITyg36LlGEbJXU |
|
474 |
+god22G6+Z6HeSQIFPElp8nY+UtpuzXmdvijlm3/RzViDiJx2PcS5A4UCgYEA6H/W |
|
475 |
+IMge3Alc0imTK3TIrNP6sPjztvKv6JVxrxN5GAzHx3mlwj8m+0naXeXqo/6krq52 |
|
476 |
+wGaUCZPzehpN6R6H/d5VfANa9x1wCBHCPBEhPN+rnFiUlT2q5uNcg9uDwYisxJ96 |
|
477 |
++aInjsPaoCxAIHJFmxxFJH26Y7JBQydRoGRR+c0CgYEA8ILEhlkMMhN4tc5oMmSk |
|
478 |
+JsLT4C7df29xdKXEfBT85eTKD/ueqKcvYyYYxyHzNK0HgRe5FOyCD9PG+HfusSFr |
|
479 |
+rM7U4oMv85eLjDD6FlviuEEwGTjZ4p+YiYMmFbh60UYvMod9SR29NjqM9Hs4vFhn |
|
480 |
+4tdOAsB5LVrz8Sx3Dio8hzECgYBWe8bw5r/j5W+rlV9zGLvU3f0we0pc0SVyBLUH |
|
481 |
+BN1UftyJbMyl1svvSWd66h0/52bmu2rc4stKTMiSsNouTvcTDfMKcE0UAtU7iy+P |
|
482 |
+HGgatrClNaX/ZbL+s7AkNDFseiSZ9yDNXu4MAvp9/jfUWe1eZ0Oo8UO19gakrimE |
|
483 |
+2gxMOQKBgGYuj4I5TmtROJDTRxrRRzQVnoTV3GesequaW/y5UM4xr2ThLevnPCMI |
|
484 |
+dSmVatvGsqYsQbPKOAp3ZcMQiqTIPUFeYSuzs3TuTs/tZ1cwfseN4M2bs258ynsT |
|
485 |
+51PHf9W7BDmvHZn8JMg688SSklatAUj4h3nnGWco1de9YL1bBLPg |
|
486 |
+-----END RSA PRIVATE KEY----- |
|
487 |
+`) |
|
488 |
+ |
|
489 |
+ // oadm create-api-client-config --basename=other --client-dir=. --user=other |
|
490 |
+ otherClientCert = []byte(` |
|
491 |
+Certificate: |
|
492 |
+ Data: |
|
493 |
+ Version: 3 (0x2) |
|
494 |
+ Serial Number: 3 (0x3) |
|
495 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
496 |
+ Issuer: CN=test-ca |
|
497 |
+ Validity |
|
498 |
+ Not Before: Apr 11 18:12:25 2016 GMT |
|
499 |
+ Not After : Mar 18 18:12:26 2116 GMT |
|
500 |
+ Subject: CN=other |
|
501 |
+ Subject Public Key Info: |
|
502 |
+ Public Key Algorithm: rsaEncryption |
|
503 |
+ RSA Public Key: (2048 bit) |
|
504 |
+ Modulus (2048 bit): |
|
505 |
+ 00:d8:6d:9e:41:51:d3:e9:99:b9:6d:37:4d:72:32: |
|
506 |
+ 6d:e8:3e:01:38:15:30:cd:5c:fb:0e:e1:76:01:32: |
|
507 |
+ 38:cf:1b:0e:8c:ec:21:5b:87:25:aa:6b:ac:6d:4b: |
|
508 |
+ a9:a5:c4:5e:aa:43:32:70:96:9f:30:dd:c7:ba:0f: |
|
509 |
+ a8:de:73:72:b5:10:9f:55:0a:80:bf:10:cc:c7:e3: |
|
510 |
+ 55:9b:6d:e1:13:6b:c2:d7:be:1c:c4:29:7b:db:06: |
|
511 |
+ bd:7e:22:a9:be:1a:af:cb:59:98:cf:0d:a5:e7:f7: |
|
512 |
+ cc:cd:92:05:3e:c8:a6:1e:cf:a3:05:90:b8:a8:76: |
|
513 |
+ 7a:a4:44:78:82:e4:7d:ba:1b:6e:4b:6f:1b:39:96: |
|
514 |
+ 04:c3:ec:28:1f:ac:c5:36:09:2e:71:23:00:35:44: |
|
515 |
+ 6e:ac:73:7b:5a:ad:c9:5c:35:4e:0c:5f:d6:09:9c: |
|
516 |
+ a0:a5:2c:ce:d7:5e:d6:93:e1:9c:b4:ec:61:bb:9f: |
|
517 |
+ ff:32:dc:64:9a:d5:bf:7f:20:84:a9:e7:5d:69:b6: |
|
518 |
+ 87:42:e6:a2:31:1c:32:50:6a:20:18:3e:f6:f8:c7: |
|
519 |
+ b8:63:eb:a2:35:da:4f:eb:34:f3:e5:e8:da:06:fd: |
|
520 |
+ c9:19:4e:45:b3:5d:e8:be:ed:18:e8:b5:30:42:eb: |
|
521 |
+ 70:64:72:76:03:30:04:81:38:f3:7c:09:98:5b:1d: |
|
522 |
+ 0f:dd |
|
523 |
+ Exponent: 65537 (0x10001) |
|
524 |
+ X509v3 extensions: |
|
525 |
+ X509v3 Key Usage: critical |
|
526 |
+ Digital Signature, Key Encipherment |
|
527 |
+ X509v3 Extended Key Usage: |
|
528 |
+ TLS Web Client Authentication |
|
529 |
+ X509v3 Basic Constraints: critical |
|
530 |
+ CA:FALSE |
|
531 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
532 |
+ 61:bf:f3:81:d2:c9:46:e3:bb:68:0d:ae:b3:ce:56:1f:bf:3b: |
|
533 |
+ 93:ba:65:54:04:37:25:5e:bf:2a:b6:79:2f:bd:17:3f:eb:85: |
|
534 |
+ 9a:ce:78:ff:f8:b5:5a:3d:f9:99:1d:24:41:2c:0d:d1:c9:63: |
|
535 |
+ 19:19:75:b2:a6:65:da:d6:a5:ae:31:57:ec:8f:d6:0d:d9:86: |
|
536 |
+ 5e:b8:f1:98:a7:43:12:1c:d0:71:d2:5c:2f:a3:bb:5f:89:fc: |
|
537 |
+ dd:9a:fc:fb:8a:9b:ed:73:3b:6d:25:90:c9:70:96:88:d0:67: |
|
538 |
+ d7:10:17:35:e9:6e:d4:2b:61:f6:d0:4d:02:75:73:7a:cf:03: |
|
539 |
+ ed:d2:e2:3b:6f:cf:58:2e:92:e8:b6:c2:e1:1b:5d:33:46:3f: |
|
540 |
+ 95:53:67:7a:69:92:be:2d:e8:59:cd:71:16:a4:a4:89:80:ee: |
|
541 |
+ 67:97:47:84:a8:0e:f7:fe:7c:2e:97:b1:f5:11:84:30:90:1d: |
|
542 |
+ a7:44:55:15:93:c9:fc:16:16:28:2c:cd:8c:1d:82:a0:ff:35: |
|
543 |
+ 61:ec:8e:ae:59:88:bf:87:55:85:79:cd:20:58:79:c3:6b:4d: |
|
544 |
+ 78:43:c0:48:44:6d:78:24:e2:26:24:99:97:81:b9:43:a4:6d: |
|
545 |
+ 1e:dd:31:53:5b:36:49:cc:df:58:e8:f2:a8:25:30:cd:69:a8: |
|
546 |
+ c1:0d:c7:84 |
|
547 |
+-----BEGIN CERTIFICATE----- |
|
548 |
+MIIC1DCCAbygAwIBAgIBAzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 |
|
549 |
+LWNhMCAXDTE2MDQxMTE4MTIyNVoYDzIxMTYwMzE4MTgxMjI2WjAQMQ4wDAYDVQQD |
|
550 |
+EwVvdGhlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANhtnkFR0+mZ |
|
551 |
+uW03TXIybeg+ATgVMM1c+w7hdgEyOM8bDozsIVuHJaprrG1LqaXEXqpDMnCWnzDd |
|
552 |
+x7oPqN5zcrUQn1UKgL8QzMfjVZtt4RNrwte+HMQpe9sGvX4iqb4ar8tZmM8Npef3 |
|
553 |
+zM2SBT7Iph7PowWQuKh2eqREeILkfbobbktvGzmWBMPsKB+sxTYJLnEjADVEbqxz |
|
554 |
+e1qtyVw1Tgxf1gmcoKUsztde1pPhnLTsYbuf/zLcZJrVv38ghKnnXWm2h0LmojEc |
|
555 |
+MlBqIBg+9vjHuGProjXaT+s08+Xo2gb9yRlORbNd6L7tGOi1MELrcGRydgMwBIE4 |
|
556 |
+83wJmFsdD90CAwEAAaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG |
|
557 |
+AQUFBwMCMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAGG/84HSyUbj |
|
558 |
+u2gNrrPOVh+/O5O6ZVQENyVevyq2eS+9Fz/rhZrOeP/4tVo9+ZkdJEEsDdHJYxkZ |
|
559 |
+dbKmZdrWpa4xV+yP1g3Zhl648ZinQxIc0HHSXC+ju1+J/N2a/PuKm+1zO20lkMlw |
|
560 |
+lojQZ9cQFzXpbtQrYfbQTQJ1c3rPA+3S4jtvz1gukui2wuEbXTNGP5VTZ3ppkr4t |
|
561 |
+6FnNcRakpImA7meXR4SoDvf+fC6XsfURhDCQHadEVRWTyfwWFigszYwdgqD/NWHs |
|
562 |
+jq5ZiL+HVYV5zSBYecNrTXhDwEhEbXgk4iYkmZeBuUOkbR7dMVNbNknM31jo8qgl |
|
563 |
+MM1pqMENx4Q= |
|
564 |
+-----END CERTIFICATE-----`) |
|
565 |
+ |
|
566 |
+ otherClientKey = []byte(` |
|
567 |
+-----BEGIN RSA PRIVATE KEY----- |
|
568 |
+MIIEpAIBAAKCAQEA2G2eQVHT6Zm5bTdNcjJt6D4BOBUwzVz7DuF2ATI4zxsOjOwh |
|
569 |
+W4clqmusbUuppcReqkMycJafMN3Hug+o3nNytRCfVQqAvxDMx+NVm23hE2vC174c |
|
570 |
+xCl72wa9fiKpvhqvy1mYzw2l5/fMzZIFPsimHs+jBZC4qHZ6pER4guR9uhtuS28b |
|
571 |
+OZYEw+woH6zFNgkucSMANURurHN7Wq3JXDVODF/WCZygpSzO117Wk+GctOxhu5// |
|
572 |
+MtxkmtW/fyCEqeddabaHQuaiMRwyUGogGD72+Me4Y+uiNdpP6zTz5ejaBv3JGU5F |
|
573 |
+s13ovu0Y6LUwQutwZHJ2AzAEgTjzfAmYWx0P3QIDAQABAoIBAQCQF8Nid8lf4NIc |
|
574 |
+jdJJMpwMIKQNI8afI8We7ar0NuytrrTsTBYVaxA/u3pMNjDXxbrFHwIJBa8tCKt+ |
|
575 |
+DAkBOdnoBQ4fv2NiUhwVBR0s42YT2Q4bN17Nl1T3yTAGN6vNftUFzTw4tjx8CXZY |
|
576 |
+c1x8pXg8UT+XZ/gZaPBUR6X4d4nhikGqSiILNh6uDjuYUxxMgea0qrAnx4HvBcBF |
|
577 |
+I1X5zg+turWcuTXoR39Ijn3UNnNZrp8XUqjA850dzQQnZqrcDnD0lqV1HOcF5V2H |
|
578 |
+VABBIVL8Jzm7mn+k6+NTVC3eWFK+EPwY8/OwHGa3O9LsA0l3knsG8x4FvaRFXTSY |
|
579 |
+fYSkExudAoGBANwE79pvjGE9kJ5MgJVg7klNv5XWIoaZnmiaPovM5LX7Fylw6vV3 |
|
580 |
+QGEj8x3VO3EqBB66g70SrqoNgCmVNx3oe8+KVX1+8XVhX4DIQLbLJBFfvaNZV7sh |
|
581 |
+IOM00hhwdKZk+szb2CS3yRo2rsmD1yEr7djsnC1l7UiLn4TJ9bA6oK+nAoGBAPvS |
|
582 |
+V07KwKKFQUv7cLwPDy1b8G7JbFOmYuc8Zber3S9YtrpFKjX2lR9bXk6iPSa2k485 |
|
583 |
+cqs1RM2/Mrw0uXKpW3jrwVE6dy2IyKLuMBcvKWlUVY02cGA0hV7A2CJKGcPxsFEP |
|
584 |
+txj5R+VN/FDcm7RzE0jmJNay+5PmDfchom4WXFTbAoGAWhHXUvfpYwF+C5/L39sf |
|
585 |
+kXi3npJb7fhDZhUG19pYIruYvslQFo7sFxhNdYAOZoRJzX6TYbqdMFZ4ig1g0+iR |
|
586 |
+juPVnZtzI5dqLmFMRMiiik5EZvOzO5MTUJAWFhUrW9bo6SZytI1cUVPjd/F2B0lh |
|
587 |
+hDVQtjEM0279LbIz1yIZF+8CgYEArRMlRJcfjNPPTBy1n9st0DwXZN11YYzC/zDI |
|
588 |
+rFMoAymS9TUiTNJ8LYALsjnZk6j6g/607C0Ba/OUODx4lPEHWHWYeW6YiKgxVaIl |
|
589 |
+VVnpuWXoItUeqVCPtc8O/Yo2aTDMwPnvGvAB1P0jhKQLNBu/TmQ3P4TmWgFM6eSp |
|
590 |
+Eca2kO8CgYAstEpSdnMQAHE92HsTSBA+aFm5jfYE/2papDcVE/Q2AqMN+ZjZvfnj |
|
591 |
+vWyX2MBY8yccNwUyNiwbEfiy9A+XLtNpsuVvNGzOp5CQAs/wIPTCfRD7zVUtIhUN |
|
592 |
+PVEo4cjWU2JK68lSTyW3UWdoPwcKIdDlnure/al7NpIG2g6weBubpQ== |
|
593 |
+-----END RSA PRIVATE KEY----- |
|
594 |
+`) |
|
595 |
+ |
|
596 |
+ // 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 |
|
597 |
+ // oadm ca create-signer-cert --name=test-ca --overwrite=true |
|
598 |
+ // oadm create-api-client-config --basename=invalid --client-dir=. --user=invalid |
|
599 |
+ invalidClientCert = []byte(` |
|
600 |
+Certificate: |
|
601 |
+ Data: |
|
602 |
+ Version: 3 (0x2) |
|
603 |
+ Serial Number: 2 (0x2) |
|
604 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
605 |
+ Issuer: CN=test-ca |
|
606 |
+ Validity |
|
607 |
+ Not Before: Apr 11 18:17:29 2016 GMT |
|
608 |
+ Not After : Mar 18 18:17:30 2116 GMT |
|
609 |
+ Subject: CN=invalid |
|
610 |
+ Subject Public Key Info: |
|
611 |
+ Public Key Algorithm: rsaEncryption |
|
612 |
+ RSA Public Key: (2048 bit) |
|
613 |
+ Modulus (2048 bit): |
|
614 |
+ 00:ac:87:5e:71:36:39:6d:2b:33:40:0e:ff:d6:3d: |
|
615 |
+ 67:a5:8b:3d:7e:56:c5:3f:49:a9:42:7d:6f:da:30: |
|
616 |
+ cc:0f:cd:64:cc:20:91:e4:41:b2:9c:54:f8:9a:fe: |
|
617 |
+ ba:7d:e6:2b:2f:ff:fc:c8:7b:4f:bf:3d:61:5c:18: |
|
618 |
+ 6e:10:6f:a8:33:9e:54:8f:f7:ac:34:57:f4:ff:00: |
|
619 |
+ c7:24:07:dd:df:47:e1:bc:0f:d6:41:b5:e4:5c:c0: |
|
620 |
+ 36:90:4b:2e:b2:97:a9:2c:7f:c4:f7:7a:2b:96:1b: |
|
621 |
+ a4:20:ba:db:df:4b:72:ff:e2:ae:46:79:5b:5d:72: |
|
622 |
+ 41:16:3d:a4:c5:31:cf:12:0c:ca:59:d5:72:c9:fe: |
|
623 |
+ 87:51:b4:54:0f:eb:46:79:95:8b:2b:ba:a3:51:71: |
|
624 |
+ 87:06:c2:5b:80:59:74:c4:d8:bd:c6:7f:56:e9:8f: |
|
625 |
+ 95:d1:85:1f:67:39:20:33:1f:3a:ba:9a:81:c6:32: |
|
626 |
+ b6:a6:e3:1d:15:97:19:c9:71:9e:95:ec:d3:38:3b: |
|
627 |
+ 2a:28:37:f8:cf:ea:c3:3c:af:84:b9:d6:64:8f:e1: |
|
628 |
+ cd:29:d3:9a:ba:48:82:50:85:0f:07:d2:d4:e9:83: |
|
629 |
+ 42:9f:22:25:4d:55:9d:38:32:9c:f1:07:17:14:bf: |
|
630 |
+ 80:7b:c5:88:6e:f7:60:50:ab:95:32:a3:0f:98:74: |
|
631 |
+ 49:21 |
|
632 |
+ Exponent: 65537 (0x10001) |
|
633 |
+ X509v3 extensions: |
|
634 |
+ X509v3 Key Usage: critical |
|
635 |
+ Digital Signature, Key Encipherment |
|
636 |
+ X509v3 Extended Key Usage: |
|
637 |
+ TLS Web Client Authentication |
|
638 |
+ X509v3 Basic Constraints: critical |
|
639 |
+ CA:FALSE |
|
640 |
+ Signature Algorithm: sha256WithRSAEncryption |
|
641 |
+ 92:5d:46:49:82:df:80:84:8c:7a:4d:4a:4c:ab:13:20:70:ee: |
|
642 |
+ 36:42:84:3c:30:67:51:a6:b4:c8:e2:0f:13:c4:2b:51:9f:2d: |
|
643 |
+ 7a:0d:be:77:3e:90:67:81:55:f8:3d:b5:c6:00:a1:ca:86:d1: |
|
644 |
+ 83:67:d6:7d:4c:e9:c0:af:53:3b:23:5d:17:1f:8b:c0:c5:ae: |
|
645 |
+ a3:f2:7c:b5:7b:9a:fc:1b:09:a8:78:ed:12:13:fd:ed:97:0c: |
|
646 |
+ e4:eb:f8:b2:63:d1:bf:89:db:84:1e:45:f8:5b:5b:d2:93:c2: |
|
647 |
+ 26:5c:61:b4:a9:05:30:45:5e:f5:c4:95:8e:98:83:4d:41:61: |
|
648 |
+ 5d:cb:83:a6:72:b6:af:70:64:8a:72:5a:1f:20:cb:8b:7c:82: |
|
649 |
+ 52:26:45:9d:58:da:c8:0b:e0:ac:00:f0:d4:12:85:2c:2b:a5: |
|
650 |
+ 29:db:54:e6:83:e3:48:d2:61:65:e6:13:31:09:cd:c8:ba:39: |
|
651 |
+ 3c:f7:ca:ab:93:ea:21:12:5f:49:0d:46:17:15:cc:ae:72:a8: |
|
652 |
+ 66:97:56:f3:2f:39:75:b5:f9:3e:ff:5a:4f:3b:8c:16:4d:bf: |
|
653 |
+ 70:55:c5:b7:ee:74:d7:39:4b:da:f9:da:39:84:25:62:24:a8: |
|
654 |
+ b8:f3:2d:6b:e5:71:60:26:cb:71:ad:bc:25:2a:f9:3a:ec:25: |
|
655 |
+ b9:c3:5c:e4 |
|
656 |
+-----BEGIN CERTIFICATE----- |
|
657 |
+MIIC1jCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0 |
|
658 |
+LWNhMCAXDTE2MDQxMTE4MTcyOVoYDzIxMTYwMzE4MTgxNzMwWjASMRAwDgYDVQQD |
|
659 |
+EwdpbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArIdecTY5 |
|
660 |
+bSszQA7/1j1npYs9flbFP0mpQn1v2jDMD81kzCCR5EGynFT4mv66feYrL//8yHtP |
|
661 |
+vz1hXBhuEG+oM55Uj/esNFf0/wDHJAfd30fhvA/WQbXkXMA2kEsuspepLH/E93or |
|
662 |
+lhukILrb30ty/+KuRnlbXXJBFj2kxTHPEgzKWdVyyf6HUbRUD+tGeZWLK7qjUXGH |
|
663 |
+BsJbgFl0xNi9xn9W6Y+V0YUfZzkgMx86upqBxjK2puMdFZcZyXGelezTODsqKDf4 |
|
664 |
+z+rDPK+EudZkj+HNKdOaukiCUIUPB9LU6YNCnyIlTVWdODKc8QcXFL+Ae8WIbvdg |
|
665 |
+UKuVMqMPmHRJIQIDAQABozUwMzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI |
|
666 |
+KwYBBQUHAwIwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAkl1GSYLf |
|
667 |
+gISMek1KTKsTIHDuNkKEPDBnUaa0yOIPE8QrUZ8teg2+dz6QZ4FV+D21xgChyobR |
|
668 |
+g2fWfUzpwK9TOyNdFx+LwMWuo/J8tXua/BsJqHjtEhP97ZcM5Ov4smPRv4nbhB5F |
|
669 |
++Ftb0pPCJlxhtKkFMEVe9cSVjpiDTUFhXcuDpnK2r3BkinJaHyDLi3yCUiZFnVja |
|
670 |
+yAvgrADw1BKFLCulKdtU5oPjSNJhZeYTMQnNyLo5PPfKq5PqIRJfSQ1GFxXMrnKo |
|
671 |
+ZpdW8y85dbX5Pv9aTzuMFk2/cFXFt+501zlL2vnaOYQlYiSouPMta+VxYCbLca28 |
|
672 |
+JSr5OuwlucNc5A== |
|
673 |
+-----END CERTIFICATE-----`) |
|
674 |
+ |
|
675 |
+ invalidClientKey = []byte(` |
|
676 |
+-----BEGIN RSA PRIVATE KEY----- |
|
677 |
+MIIEowIBAAKCAQEArIdecTY5bSszQA7/1j1npYs9flbFP0mpQn1v2jDMD81kzCCR |
|
678 |
+5EGynFT4mv66feYrL//8yHtPvz1hXBhuEG+oM55Uj/esNFf0/wDHJAfd30fhvA/W |
|
679 |
+QbXkXMA2kEsuspepLH/E93orlhukILrb30ty/+KuRnlbXXJBFj2kxTHPEgzKWdVy |
|
680 |
+yf6HUbRUD+tGeZWLK7qjUXGHBsJbgFl0xNi9xn9W6Y+V0YUfZzkgMx86upqBxjK2 |
|
681 |
+puMdFZcZyXGelezTODsqKDf4z+rDPK+EudZkj+HNKdOaukiCUIUPB9LU6YNCnyIl |
|
682 |
+TVWdODKc8QcXFL+Ae8WIbvdgUKuVMqMPmHRJIQIDAQABAoIBAE7weTPPnaLnm0F6 |
|
683 |
+G3DJE71Y4kAGL6XvbDRx9FWe8h9g2PfVByurK6//6OfyGR41zBjgRabtVOWpjfx3 |
|
684 |
+aRS4IfvMO+DLb81bWUu77WH8/3WEDDLiBCR4tw4BHHYVED7CybMEmviou3ypFQWs |
|
685 |
+uaGHggy2iQrRyA4Pktw8REG9soMM+s+T0zlfexbeXgz7OJYd5QStBslI5ZJhHa1I |
|
686 |
+LW94hrU0Yj1ONP2hCfMc5H808zOkMUSZMgRMTXXZQzo2XdujLelRxQ1oaZTU4aQM |
|
687 |
+SwZG1vzdDjjFhXW1sjD7G2DoyTxbDVOIfqYOmO/t7witXo2g52hIXhb4RFoxD0eZ |
|
688 |
+dFDRyakCgYEA0mU9X2rc1GU4OlKUOd4phsQfLmRk4ya7i2Zica3n4PFvaz+XoIZ0 |
|
689 |
+NZf2xwZlY5MX21tBadIFW8C4GilDscgLrP8P2gW15hP6bKpHuB2nkJcGdNi6Tg8f |
|
690 |
+0Vvf7L4RHamolN7yk39zJoC9KUDaPAtqGB4niUDCsjc6LdJTqW/oCHMCgYEA0ezs |
|
691 |
+Dxe8j9l34BEqZxu71NjUKovUQJv+0kz301W5gVCFAY5oBDfFf42IHl5q+B7TFLaP |
|
692 |
+6xEEdyh0K6GrGTt9YtWB3HYPEStzBf0fXAg7fJHPn12mn8/B0UFMkJKyuRnPOW7t |
|
693 |
+3WOROzChSpWWKVUMFJIBCyfMvEjUgm8SzUluxxsCgYBe8g8DK09ijhcUwsVfY/Fr |
|
694 |
+fr/viKC6nXUPEHImiOtWaL32MSl06Jgyw1Q7Npi0meGvPPxFC+EdKdgq/iotZXBX |
|
695 |
+bncx1Vfj72oYdbON09wVdQIV4uQYa9zY9tQTmyZQM4r/O6lOhLprSreSkVCqvh/v |
|
696 |
+qFQBLXdvQ1r+6KaWlQiqHwKBgG7s6FeZTVQdr5BAwc02BGyWHpZUyNVTGLV7YkDT |
|
697 |
+vXAtYfrOivwflEawPMr/TTrK3vLE/QtTNK7aO3iKtuRgYQMGmtYptBB4ixERDa8N |
|
698 |
+0pEiYzlsvQ0ZNOsjvBdwzOuuTaeljB8965IBQlks7entPLLp648/epnLSi+aDa9Y |
|
699 |
+LCcdAoGBAL1qU+P+8+8Lfdj+/8GfaZdZQnqeOzLkxzGDcuVDNYACIVGmGJqL01Gx |
|
700 |
+RUVzUCnG68qdoai960Yo0w41U90hsCpBny50SShYu3kL67Gqn03UcEYDw5pmUPwn |
|
701 |
+NykkJ6u51LArDs6E8hA0aoMrQbZGZiod93dPHlbFhR3+4t4l8wDJ |
|
702 |
+-----END RSA PRIVATE KEY----- |
|
703 |
+`) |
|
704 |
+) |