diff --git a/util/httputil/client.go b/util/httputil/client.go index bbe5fe596..f89ea688e 100644 --- a/util/httputil/client.go +++ b/util/httputil/client.go @@ -18,11 +18,8 @@ import ( "crypto/x509" "fmt" "io/ioutil" - "net" "net/http" - "net/url" "strings" - "time" "github.com/prometheus/prometheus/config" ) @@ -70,33 +67,6 @@ func NewClientFromConfig(cfg config.HTTPClientConfig) (*http.Client, error) { return NewClient(rt), nil } -// NewDeadlineRoundTripper returns a new http.RoundTripper which will time out -// long running requests. -func NewDeadlineRoundTripper(timeout time.Duration, proxyURL *url.URL) http.RoundTripper { - return &http.Transport{ - // Set proxy (if null, then becomes a direct connection) - Proxy: http.ProxyURL(proxyURL), - // We need to disable keepalive, because we set a deadline on the - // underlying connection. - DisableKeepAlives: true, - Dial: func(netw, addr string) (c net.Conn, err error) { - start := time.Now() - - c, err = net.DialTimeout(netw, addr, timeout) - if err != nil { - return nil, err - } - - if err = c.SetDeadline(start.Add(timeout)); err != nil { - c.Close() - return nil, err - } - - return c, nil - }, - } -} - type bearerAuthRoundTripper struct { bearerToken string rt http.RoundTripper diff --git a/util/httputil/client_test.go b/util/httputil/client_test.go new file mode 100644 index 000000000..10e65e863 --- /dev/null +++ b/util/httputil/client_test.go @@ -0,0 +1,412 @@ +// Copyright 2017 The Prometheus 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 httputil + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + + "github.com/prometheus/prometheus/config" + "github.com/prometheus/prometheus/util/testutil" +) + +const ( + TLSCAChainPath = "testdata/tls-ca-chain.pem" + ServerCertificatePath = "testdata/server.crt" + ServerKeyPath = "testdata/server.key" + BarneyCertificatePath = "testdata/barney.crt" + BarneyKeyNoPassPath = "testdata/barney-no-pass.key" + MissingCA = "missing/ca.crt" + MissingCert = "missing/cert.crt" + MissingKey = "missing/secret.key" + + ExpectedMessage = "I'm here to serve you!!!" + BearerToken = "theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo" + BearerTokenFile = "testdata/bearer.token" + MissingBearerTokenFile = "missing/bearer.token" + ExpectedBearer = "Bearer " + BearerToken + ExpectedUsername = "arthurdent" + ExpectedPassword = "42" +) + +func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, error) { + testServer := httptest.NewUnstartedServer(http.HandlerFunc(handler)) + + tlsCAChain, err := ioutil.ReadFile(TLSCAChainPath) + if err != nil { + return nil, fmt.Errorf("Can't read %s", TLSCAChainPath) + } + serverCertificate, err := tls.LoadX509KeyPair(ServerCertificatePath, ServerKeyPath) + if err != nil { + return nil, fmt.Errorf("Can't load X509 key pair %s - %s", ServerCertificatePath, ServerKeyPath) + } + + rootCAs := x509.NewCertPool() + rootCAs.AppendCertsFromPEM(tlsCAChain) + + testServer.TLS = &tls.Config{ + Certificates: make([]tls.Certificate, 1), + RootCAs: rootCAs, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: rootCAs} + testServer.TLS.Certificates[0] = serverCertificate + testServer.TLS.BuildNameToCertificate() + + testServer.StartTLS() + + return testServer, nil +} + +func TestNewClientFromConfig(t *testing.T) { + var newClientValidConfig = []struct { + clientConfig config.HTTPClientConfig + handler func(w http.ResponseWriter, r *http.Request) + }{ + { + clientConfig: config.HTTPClientConfig{ + TLSConfig: config.TLSConfig{ + CAFile: "", + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: true}, + }, + handler: func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, ExpectedMessage) + }, + }, { + clientConfig: config.HTTPClientConfig{ + TLSConfig: config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + }, + handler: func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, ExpectedMessage) + }, + }, { + clientConfig: config.HTTPClientConfig{ + BearerToken: BearerToken, + TLSConfig: config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + }, + handler: func(w http.ResponseWriter, r *http.Request) { + bearer := r.Header.Get("Authorization") + if bearer != ExpectedBearer { + fmt.Fprintf(w, "The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)", + ExpectedBearer, bearer) + } else { + fmt.Fprint(w, ExpectedMessage) + } + }, + }, { + clientConfig: config.HTTPClientConfig{ + BearerTokenFile: BearerTokenFile, + TLSConfig: config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + }, + handler: func(w http.ResponseWriter, r *http.Request) { + bearer := r.Header.Get("Authorization") + if bearer != ExpectedBearer { + fmt.Fprintf(w, "The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)", + ExpectedBearer, bearer) + } else { + fmt.Fprint(w, ExpectedMessage) + } + }, + }, { + clientConfig: config.HTTPClientConfig{ + BasicAuth: &config.BasicAuth{ + Username: ExpectedUsername, + Password: ExpectedPassword, + }, + TLSConfig: config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + }, + handler: func(w http.ResponseWriter, r *http.Request) { + username, password, ok := r.BasicAuth() + if ok == false { + fmt.Fprintf(w, "The Authorization header wasn't set") + } else if ExpectedUsername != username { + fmt.Fprintf(w, "The expected username (%s) differs from the obtained username (%s).", ExpectedUsername, username) + } else if ExpectedPassword != password { + fmt.Fprintf(w, "The expected password (%s) differs from the obtained password (%s).", ExpectedPassword, password) + } else { + fmt.Fprint(w, ExpectedMessage) + } + }, + }, + } + + for _, validConfig := range newClientValidConfig { + testServer, err := newTestServer(validConfig.handler) + if err != nil { + t.Fatal(err.Error()) + } + defer testServer.Close() + + client, err := NewClientFromConfig(validConfig.clientConfig) + if err != nil { + t.Errorf("Can't create a client from this config: %+v", validConfig.clientConfig) + continue + } + response, err := client.Get(testServer.URL) + if err != nil { + t.Errorf("Can't connect to the test server using this config: %+v", validConfig.clientConfig) + continue + } + + message, err := ioutil.ReadAll(response.Body) + response.Body.Close() + if err != nil { + t.Errorf("Can't read the server response body using this config: %+v", validConfig.clientConfig) + continue + } + + trimMessage := strings.TrimSpace(string(message)) + if ExpectedMessage != trimMessage { + t.Errorf("The expected message (%s) differs from the obtained message (%s) using this config: %+v", + ExpectedMessage, trimMessage, validConfig.clientConfig) + } + } +} + +func TestNewClientFromInvalidConfig(t *testing.T) { + var newClientInvalidConfig = []struct { + clientConfig config.HTTPClientConfig + errorMsg string + }{ + { + clientConfig: config.HTTPClientConfig{ + TLSConfig: config.TLSConfig{ + CAFile: MissingCA, + CertFile: "", + KeyFile: "", + ServerName: "", + InsecureSkipVerify: true}, + }, + errorMsg: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA), + }, { + clientConfig: config.HTTPClientConfig{ + BearerTokenFile: MissingBearerTokenFile, + TLSConfig: config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + }, + errorMsg: fmt.Sprintf("unable to read bearer token file %s:", MissingBearerTokenFile), + }, + } + + for _, invalidConfig := range newClientInvalidConfig { + client, err := NewClientFromConfig(invalidConfig.clientConfig) + if client != nil { + t.Errorf("A client instance was returned instead of nil using this config: %+v", invalidConfig.clientConfig) + } + if err == nil { + t.Errorf("No error was returned using this config: %+v", invalidConfig.clientConfig) + } + if !strings.Contains(err.Error(), invalidConfig.errorMsg) { + t.Errorf("Expected error %s does not contain %s", err.Error(), invalidConfig.errorMsg) + } + } +} + +func TestBearerAuthRoundTripper(t *testing.T) { + const ( + newBearerToken = "goodbyeandthankyouforthefish" + ) + + fakeRoundTripper := testutil.NewRoundTripCheckRequest(func(req *http.Request) { + bearer := req.Header.Get("Authorization") + if bearer != ExpectedBearer { + t.Errorf("The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)", + ExpectedBearer, bearer) + } + }, nil, nil) + + //Normal flow + bearerAuthRoundTripper := NewBearerAuthRoundTripper(BearerToken, fakeRoundTripper) + request, _ := http.NewRequest("GET", "/hitchhiker", nil) + request.Header.Set("User-Agent", "Douglas Adams mind") + bearerAuthRoundTripper.RoundTrip(request) + + //Should honor already Authorization header set + bearerAuthRoundTripperShouldNotModifyExistingAuthorization := NewBearerAuthRoundTripper(newBearerToken, fakeRoundTripper) + request, _ = http.NewRequest("GET", "/hitchhiker", nil) + request.Header.Set("Authorization", ExpectedBearer) + bearerAuthRoundTripperShouldNotModifyExistingAuthorization.RoundTrip(request) +} + +func TestBasicAuthRoundTripper(t *testing.T) { + const ( + newUsername = "fordprefect" + newPassword = "towel" + ) + + fakeRoundTripper := testutil.NewRoundTripCheckRequest(func(req *http.Request) { + username, password, ok := req.BasicAuth() + if ok == false { + t.Errorf("The Authorization header wasn't set") + } + if ExpectedUsername != username { + t.Errorf("The expected username (%s) differs from the obtained username (%s).", ExpectedUsername, username) + } + if ExpectedPassword != password { + t.Errorf("The expected password (%s) differs from the obtained password (%s).", ExpectedPassword, password) + } + }, nil, nil) + + //Normal flow + basicAuthRoundTripper := NewBasicAuthRoundTripper(ExpectedUsername, + ExpectedPassword, fakeRoundTripper) + request, _ := http.NewRequest("GET", "/hitchhiker", nil) + request.Header.Set("User-Agent", "Douglas Adams mind") + basicAuthRoundTripper.RoundTrip(request) + + //Should honor already Authorization header set + basicAuthRoundTripperShouldNotModifyExistingAuthorization := NewBasicAuthRoundTripper(newUsername, + newPassword, fakeRoundTripper) + request, _ = http.NewRequest("GET", "/hitchhiker", nil) + request.SetBasicAuth(ExpectedUsername, ExpectedPassword) + basicAuthRoundTripperShouldNotModifyExistingAuthorization.RoundTrip(request) +} + +func TestTLSConfig(t *testing.T) { + configTLSConfig := config.TLSConfig{ + CAFile: TLSCAChainPath, + CertFile: BarneyCertificatePath, + KeyFile: BarneyKeyNoPassPath, + ServerName: "localhost", + InsecureSkipVerify: false} + + tlsCAChain, err := ioutil.ReadFile(TLSCAChainPath) + if err != nil { + t.Fatalf("Can't read the CA certificate chain (%s)", + TLSCAChainPath) + } + rootCAs := x509.NewCertPool() + rootCAs.AppendCertsFromPEM(tlsCAChain) + + barneyCertificate, err := tls.LoadX509KeyPair(BarneyCertificatePath, BarneyKeyNoPassPath) + if err != nil { + t.Fatalf("Can't load the client key pair ('%s' and '%s'). Reason: %s", + BarneyCertificatePath, BarneyKeyNoPassPath, err) + } + + expectedTLSConfig := &tls.Config{ + RootCAs: rootCAs, + Certificates: []tls.Certificate{barneyCertificate}, + ServerName: configTLSConfig.ServerName, + InsecureSkipVerify: configTLSConfig.InsecureSkipVerify} + expectedTLSConfig.BuildNameToCertificate() + + tlsConfig, err := NewTLSConfig(configTLSConfig) + if err != nil { + t.Fatalf("Can't create a new TLS Config from a configuration (%s).", err) + } + + if !reflect.DeepEqual(tlsConfig, expectedTLSConfig) { + t.Fatalf("Unexpected TLS Config result: \n\n%+v\n expected\n\n%+v", tlsConfig, expectedTLSConfig) + } +} + +func TestTLSConfigEmpty(t *testing.T) { + configTLSConfig := config.TLSConfig{ + CAFile: "", + CertFile: "", + KeyFile: "", + ServerName: "", + InsecureSkipVerify: true} + + expectedTLSConfig := &tls.Config{ + InsecureSkipVerify: configTLSConfig.InsecureSkipVerify} + expectedTLSConfig.BuildNameToCertificate() + + tlsConfig, err := NewTLSConfig(configTLSConfig) + if err != nil { + t.Fatalf("Can't create a new TLS Config from a configuration (%s).", err) + } + + if !reflect.DeepEqual(tlsConfig, expectedTLSConfig) { + t.Fatalf("Unexpected TLS Config result: \n\n%+v\n expected\n\n%+v", tlsConfig, expectedTLSConfig) + } +} + +func TestTLSConfigInvalidCA(t *testing.T) { + var invalidTLSConfig = []struct { + configTLSConfig config.TLSConfig + errorMessage string + }{ + { + configTLSConfig: config.TLSConfig{ + CAFile: MissingCA, + CertFile: "", + KeyFile: "", + ServerName: "", + InsecureSkipVerify: false}, + errorMessage: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA), + }, { + configTLSConfig: config.TLSConfig{ + CAFile: "", + CertFile: MissingCert, + KeyFile: BarneyKeyNoPassPath, + ServerName: "", + InsecureSkipVerify: false}, + errorMessage: fmt.Sprintf("unable to use specified client cert (%s) & key (%s):", MissingCert, BarneyKeyNoPassPath), + }, { + configTLSConfig: config.TLSConfig{ + CAFile: "", + CertFile: BarneyCertificatePath, + KeyFile: MissingKey, + ServerName: "", + InsecureSkipVerify: false}, + errorMessage: fmt.Sprintf("unable to use specified client cert (%s) & key (%s):", BarneyCertificatePath, MissingKey), + }, + } + + for _, anInvalididTLSConfig := range invalidTLSConfig { + tlsConfig, err := NewTLSConfig(anInvalididTLSConfig.configTLSConfig) + if tlsConfig != nil && err == nil { + t.Errorf("The TLS Config could be created even with this %+v", anInvalididTLSConfig.configTLSConfig) + continue + } + if !strings.Contains(err.Error(), anInvalididTLSConfig.errorMessage) { + t.Errorf("The expected error should contain %s, but got %s", anInvalididTLSConfig.errorMessage, err) + } + } +} diff --git a/util/httputil/testdata/barney-no-pass.key b/util/httputil/testdata/barney-no-pass.key new file mode 100644 index 000000000..b8e44f552 --- /dev/null +++ b/util/httputil/testdata/barney-no-pass.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAxmYjfBZhZbAup9uSULehoqPCv/U+77ETxUNyS2nviWEHDAb/ +pFS8Btx4oCQ1ECVSyxcUmXSlrvDjMY4sisOHvndNRlGi274M5a8Q5yD1BUqvxq3u +XB/+SYNVShBzaswrSjpzMe89AlOPxPjnE14OXh00j2hHunOG4jhlWgJnY0YyvUQQ +YWO6KrmKMiZ4MgmY0SWh/ZhlkDJPtkp3aUVM2sheCru/70E9viLGfdlhc2pIMshy +wNp4/5IkHBZwbqXFFGX4sRtSXI/auZNvcHOBse+3e3BonWvBWS2lIYbzpX3vLB7B +E9BGIxWn1fgNQr14yFPaccSszBvgtmEUONolnwIDAQABAoIBAQC7nBhQHgXKGBl2 +Z97rb0pstrjRtsLl/Cg68LWi9LEr0tHMIM4bgnkvb8qtfK+k7fZl0BSNrE2EqYvd +75jVO2MgzEYJieccLpKZm7u7JGIut9qSYSU2fpaCw6uiVv4dbqY9EhqejKG/km8w +j0JMATRK8Qkj1zOE7/wL7dKBlCZaK3u+OT17spuA/21PG/cLiPaSGSA3CU/eqbkU +BD6JeBxp33XNTytwWoOvarsigpL0dGqQ7+qhGq6t69qFfWoe9rimV7Ya+tB9zF/U +HzOIEspOYvzxe+C7VJjlVFr4haMYmsrO9qRUJ2ofp49OLVdfEANsdVISSvS63BEp +gBZN8Ko5AoGBAO1z8y8YCsI+2vBG6nxZ1eMba0KHi3bS8db1TaenJBV22w6WQATh +hEaU6VLMFcMvrOUjXN/7HJfnEMyvFT6gb9obPDVEMZw88s9lVN6njgGLZR/jodyN +7N7utLopN043Ra0WfEILAXPSz8esT1yn05OZV6AFHxJEWMrX3/4+spCLAoGBANXl +RomieVY4u3FF/uzhbzKNNb9ETxrQuexfbangKp5eLniwnr2SQWIbyPzeurwp15J8 +HvxB2vpNvs1khSwNx9dQfMdiUVPGLWj7MimAHTHsnQ9LVV9W28ghuSWbjQDGTUt1 +WCCu1MkKIOzupbi+zgsNlI33yilRQKAb9SRxdy29AoGBAOKpvyZiPcrkMxwPpb/k +BU7QGpgcSR25CQ+Xg3QZEVHH7h1DgYLnPtwdQ4g8tj1mohTsp7hKvSWndRrdulrY +zUyWmOeD3BN2/pTI9rW/nceNp49EPHsLo2O+2xelRlzMWB98ikqEtPM59gt1SSB6 +N3X6d3GR0fIe+d9PKEtK0Cs3AoGAZ9r8ReXSvm+ra5ON9Nx8znHMEAON2TpRnBi1 +uY7zgpO+QrGXUfqKrqVJEKbgym4SkribnuYm+fP32eid1McYKk6VV4ZAcMm/0MJv +F8Fx64S0ufFdEX6uFl1xdXYyn5apfyMJ2EyrWrYFSKWTZ8GVb753S/tteGRQWa1Z +eQly0Y0CgYEAnI6G9KFvXI+MLu5y2LPYAwsesDFzaWwyDl96ioQTA9hNSrjR33Vw +xwpiEe0T/WKF8NQ0QWnrQDbTvuCvZUK37TVxscYWuItL6vnBrYqr4Ck0j1BcGwV5 +jT581A/Vw8JJiR/vfcxgmrFYqoUmkMKDmCN1oImfz09GtQ4jQ1rlxz8= +-----END RSA PRIVATE KEY----- diff --git a/util/httputil/testdata/barney.crt b/util/httputil/testdata/barney.crt new file mode 100644 index 000000000..e2f950483 --- /dev/null +++ b/util/httputil/testdata/barney.crt @@ -0,0 +1,96 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA + Validity + Not Before: Jul 13 04:02:47 2017 GMT + Not After : Jul 13 04:02:47 2019 GMT + Subject: C=NO, O=Telenor AS, OU=Support, CN=Barney Rubble + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c6:66:23:7c:16:61:65:b0:2e:a7:db:92:50:b7: + a1:a2:a3:c2:bf:f5:3e:ef:b1:13:c5:43:72:4b:69: + ef:89:61:07:0c:06:ff:a4:54:bc:06:dc:78:a0:24: + 35:10:25:52:cb:17:14:99:74:a5:ae:f0:e3:31:8e: + 2c:8a:c3:87:be:77:4d:46:51:a2:db:be:0c:e5:af: + 10:e7:20:f5:05:4a:af:c6:ad:ee:5c:1f:fe:49:83: + 55:4a:10:73:6a:cc:2b:4a:3a:73:31:ef:3d:02:53: + 8f:c4:f8:e7:13:5e:0e:5e:1d:34:8f:68:47:ba:73: + 86:e2:38:65:5a:02:67:63:46:32:bd:44:10:61:63: + ba:2a:b9:8a:32:26:78:32:09:98:d1:25:a1:fd:98: + 65:90:32:4f:b6:4a:77:69:45:4c:da:c8:5e:0a:bb: + bf:ef:41:3d:be:22:c6:7d:d9:61:73:6a:48:32:c8: + 72:c0:da:78:ff:92:24:1c:16:70:6e:a5:c5:14:65: + f8:b1:1b:52:5c:8f:da:b9:93:6f:70:73:81:b1:ef: + b7:7b:70:68:9d:6b:c1:59:2d:a5:21:86:f3:a5:7d: + ef:2c:1e:c1:13:d0:46:23:15:a7:d5:f8:0d:42:bd: + 78:c8:53:da:71:c4:ac:cc:1b:e0:b6:61:14:38:da: + 25:9f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature + X509v3 Basic Constraints: + CA:FALSE + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Subject Key Identifier: + F4:17:02:DD:1B:01:AB:C5:BC:17:A4:5C:4B:75:8E:EC:B1:E0:C8:F1 + X509v3 Authority Key Identifier: + keyid:AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71 + + Authority Information Access: + CA Issuers - URI:http://green.no/ca/tls-ca.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://green.no/ca/tls-ca.crl + + X509v3 Subject Alternative Name: + email:barney@telenor.no + Signature Algorithm: sha1WithRSAEncryption + 96:9a:c5:41:8a:2f:4a:c4:80:d9:2b:1a:cf:07:85:e9:b6:18: + 01:20:41:b9:c3:d4:ca:d3:2d:66:c3:1d:52:7f:25:d7:92:0c: + e9:a9:ae:e6:2e:fa:9d:0a:cf:84:b9:03:f2:63:e3:d3:c9:70: + 6a:ac:04:5e:a9:2d:a2:43:7a:34:60:f7:a9:32:e1:48:ec:c6: + 03:ac:b3:06:2e:48:6e:d0:35:11:31:3d:0c:04:66:41:e6:b2: + ec:8c:68:f8:e4:bc:47:85:39:60:69:a9:8a:ee:2f:56:88:8a: + 19:45:d0:84:8e:c2:27:2c:82:9c:07:6c:34:ae:41:61:63:f9: + 32:cb:8b:33:ea:2c:15:5f:f9:35:b0:3c:51:4d:5f:30:de:0b: + 88:28:94:79:f3:bd:69:37:ad:12:20:e1:6b:1d:b6:77:d9:83: + db:81:a4:53:6c:0f:6a:17:5e:2b:c1:94:c6:42:e3:73:cd:9e: + 79:1b:8c:89:cd:da:ce:b0:f4:21:c5:32:25:04:6e:68:9f:a7: + ca:f4:c5:86:e5:4e:d9:fd:69:73:e6:15:50:6e:76:0f:73:5e: + 7a:a3:f4:dc:15:4a:ab:bb:3c:9a:fa:9f:01:7a:5c:47:a9:a3: + 68:1c:49:e0:37:37:77:af:87:07:16:e4:e1:d7:98:39:15:a6: + 51:5d:4c:db +-----BEGIN CERTIFICATE----- +MIIEITCCAwmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJOTzER +MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1 +dGhvcml0eTEVMBMGA1UEAwwMR3JlZW4gVExTIENBMB4XDTE3MDcxMzA0MDI0N1oX +DTE5MDcxMzA0MDI0N1owTDELMAkGA1UEBhMCTk8xEzARBgNVBAoMClRlbGVub3Ig +QVMxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDUJhcm5leSBSdWJibGUwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGZiN8FmFlsC6n25JQt6Gio8K/ +9T7vsRPFQ3JLae+JYQcMBv+kVLwG3HigJDUQJVLLFxSZdKWu8OMxjiyKw4e+d01G +UaLbvgzlrxDnIPUFSq/Gre5cH/5Jg1VKEHNqzCtKOnMx7z0CU4/E+OcTXg5eHTSP +aEe6c4biOGVaAmdjRjK9RBBhY7oquYoyJngyCZjRJaH9mGWQMk+2SndpRUzayF4K +u7/vQT2+IsZ92WFzakgyyHLA2nj/kiQcFnBupcUUZfixG1Jcj9q5k29wc4Gx77d7 +cGida8FZLaUhhvOlfe8sHsET0EYjFafV+A1CvXjIU9pxxKzMG+C2YRQ42iWfAgMB +AAGjgfwwgfkwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYI +KwYBBQUHAwIwHQYDVR0OBBYEFPQXAt0bAavFvBekXEt1juyx4MjxMB8GA1UdIwQY +MBaAFK5CiHXdBaaOSH9Qafm3NCNJuLRxMDkGCCsGAQUFBwEBBC0wKzApBggrBgEF +BQcwAoYdaHR0cDovL2dyZWVuLm5vL2NhL3Rscy1jYS5jZXIwLgYDVR0fBCcwJTAj +oCGgH4YdaHR0cDovL2dyZWVuLm5vL2NhL3Rscy1jYS5jcmwwHAYDVR0RBBUwE4ER +YmFybmV5QHRlbGVub3Iubm8wDQYJKoZIhvcNAQEFBQADggEBAJaaxUGKL0rEgNkr +Gs8Hhem2GAEgQbnD1MrTLWbDHVJ/JdeSDOmpruYu+p0Kz4S5A/Jj49PJcGqsBF6p +LaJDejRg96ky4UjsxgOsswYuSG7QNRExPQwEZkHmsuyMaPjkvEeFOWBpqYruL1aI +ihlF0ISOwicsgpwHbDSuQWFj+TLLizPqLBVf+TWwPFFNXzDeC4golHnzvWk3rRIg +4WsdtnfZg9uBpFNsD2oXXivBlMZC43PNnnkbjInN2s6w9CHFMiUEbmifp8r0xYbl +Ttn9aXPmFVBudg9zXnqj9NwVSqu7PJr6nwF6XEepo2gcSeA3N3evhwcW5OHXmDkV +plFdTNs= +-----END CERTIFICATE----- diff --git a/util/httputil/testdata/bearer.token b/util/httputil/testdata/bearer.token new file mode 100644 index 000000000..3367abffd --- /dev/null +++ b/util/httputil/testdata/bearer.token @@ -0,0 +1 @@ +theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo diff --git a/util/httputil/testdata/server.crt b/util/httputil/testdata/server.crt new file mode 100644 index 000000000..87ad202fe --- /dev/null +++ b/util/httputil/testdata/server.crt @@ -0,0 +1,96 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA + Validity + Not Before: Jul 26 12:47:08 2017 GMT + Not After : Jul 26 12:47:08 2019 GMT + Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:97:43:c5:f6:24:b8:ce:30:12:70:ea:17:9c:c0: + ce:f2:ef:58:8b:12:7d:46:5e:01:f1:1a:93:b2:3e: + d8:cf:99:bc:10:32:f1:12:b0:ef:00:6c:d6:c4:45: + 85:a8:33:7b:cd:ec:8f:4a:92:d0:5a:4a:41:69:7f: + e3:dd:7e:71:d2:21:9c:df:43:b5:6c:60:bb:2a:12: + a8:08:cf:c5:ee:08:7d:48:ea:4b:54:e4:82:d9:88: + b0:b8:5e:02:12:cb:0e:09:99:b7:5f:42:b6:d7:26: + 34:0f:4a:e7:fc:ac:9c:59:cd:a1:50:4c:88:5f:f1: + d2:7e:5b:21:41:f0:37:50:80:48:71:50:26:61:26: + 79:64:4b:7e:91:8d:0e:f4:27:fe:19:80:bf:39:55: + b7:f3:d0:cd:61:6c:d8:c1:c7:d3:26:77:92:1a:14: + 42:56:cb:bc:fd:1a:4a:eb:17:d8:8d:af:d1:c0:46: + 9f:f0:40:5e:0e:34:2f:e7:db:be:66:fd:89:0b:6b: + 8c:71:c1:0b:0a:c5:c4:c4:eb:7f:44:c1:75:36:23: + fd:ed:b6:ee:87:d9:88:47:e1:4b:7c:60:53:e7:85: + 1c:2f:82:4b:2b:5e:63:1a:49:17:36:2c:fc:39:23: + 49:22:4d:43:b5:51:22:12:24:9e:31:44:d8:16:4e: + a8:eb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Basic Constraints: + CA:FALSE + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Subject Key Identifier: + 70:A9:FB:44:66:3C:63:96:E6:05:B2:74:47:C8:18:7E:43:6D:EE:8B + X509v3 Authority Key Identifier: + keyid:AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71 + + Authority Information Access: + CA Issuers - URI:http://green.no/ca/tls-ca.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://green.no/ca/tls-ca.crl + + X509v3 Subject Alternative Name: + IP Address:127.0.0.1, IP Address:127.0.0.0, DNS:localhost + Signature Algorithm: sha1WithRSAEncryption + 56:1e:b8:52:ba:f5:72:42:ad:15:71:c1:5e:00:63:c9:4d:56: + f2:8d:a3:a9:91:db:d0:b5:1b:88:80:93:80:28:48:b2:d0:a9: + d0:ea:de:40:78:cc:57:8c:00:b8:65:99:68:95:98:9b:fb:a2: + 43:21:ea:00:37:01:77:c7:3b:1a:ec:58:2d:25:9c:ad:23:41: + 5e:ae:fd:ac:2f:26:81:b8:a7:49:9b:5a:10:fe:ad:c3:86:ab: + 59:67:b0:c7:81:72:95:60:b5:cb:fc:9f:ad:27:16:50:85:76: + 33:16:20:2c:1f:c6:14:09:0c:48:9f:c0:19:16:c9:fa:b0:d8: + bf:b7:8d:a7:aa:eb:fe:f8:6f:dd:2b:83:ee:c7:8a:df:c8:59: + e6:2e:13:1f:57:cc:6f:31:db:f7:b7:5c:3f:78:ad:22:2c:48: + bb:6d:c4:ab:dc:c1:76:34:29:d9:1e:67:e0:ac:37:2b:90:f9: + 71:bd:cf:a1:01:b9:eb:0b:0b:79:2e:8b:52:3d:8e:13:97:c8: + 05:a3:ef:68:82:49:12:2a:25:1a:48:49:b8:7c:3c:66:0d:74: + f9:00:8c:5b:57:d7:76:b1:26:95:86:b2:2e:a3:b2:9c:e0:eb: + 2d:fc:77:03:8f:cd:56:46:3a:c9:6a:fa:72:e3:19:d8:ef:de: + 4b:36:95:79 +-----BEGIN CERTIFICATE----- +MIIEQjCCAyqgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJOTzER +MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1 +dGhvcml0eTEVMBMGA1UEAwwMR3JlZW4gVExTIENBMB4XDTE3MDcyNjEyNDcwOFoX +DTE5MDcyNjEyNDcwOFowXTELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEdyZWVuIEFT +MSQwIgYDVQQLDBtHcmVlbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFTATBgNVBAMM +DEdyZWVuIFRMUyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJdD +xfYkuM4wEnDqF5zAzvLvWIsSfUZeAfEak7I+2M+ZvBAy8RKw7wBs1sRFhagze83s +j0qS0FpKQWl/491+cdIhnN9DtWxguyoSqAjPxe4IfUjqS1TkgtmIsLheAhLLDgmZ +t19CttcmNA9K5/ysnFnNoVBMiF/x0n5bIUHwN1CASHFQJmEmeWRLfpGNDvQn/hmA +vzlVt/PQzWFs2MHH0yZ3khoUQlbLvP0aSusX2I2v0cBGn/BAXg40L+fbvmb9iQtr +jHHBCwrFxMTrf0TBdTYj/e227ofZiEfhS3xgU+eFHC+CSyteYxpJFzYs/DkjSSJN +Q7VRIhIknjFE2BZOqOsCAwEAAaOCAQswggEHMA4GA1UdDwEB/wQEAwIFoDAJBgNV +HRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU +cKn7RGY8Y5bmBbJ0R8gYfkNt7oswHwYDVR0jBBgwFoAUrkKIdd0Fpo5If1Bp+bc0 +I0m4tHEwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzAChh1odHRwOi8vZ3JlZW4u +bm8vY2EvdGxzLWNhLmNlcjAuBgNVHR8EJzAlMCOgIaAfhh1odHRwOi8vZ3JlZW4u +bm8vY2EvdGxzLWNhLmNybDAgBgNVHREEGTAXhwR/AAABhwR/AAAAgglsb2NhbGhv +c3QwDQYJKoZIhvcNAQEFBQADggEBAFYeuFK69XJCrRVxwV4AY8lNVvKNo6mR29C1 +G4iAk4AoSLLQqdDq3kB4zFeMALhlmWiVmJv7okMh6gA3AXfHOxrsWC0lnK0jQV6u +/awvJoG4p0mbWhD+rcOGq1lnsMeBcpVgtcv8n60nFlCFdjMWICwfxhQJDEifwBkW +yfqw2L+3jaeq6/74b90rg+7Hit/IWeYuEx9XzG8x2/e3XD94rSIsSLttxKvcwXY0 +KdkeZ+CsNyuQ+XG9z6EBuesLC3kui1I9jhOXyAWj72iCSRIqJRpISbh8PGYNdPkA +jFtX13axJpWGsi6jspzg6y38dwOPzVZGOslq+nLjGdjv3ks2lXk= +-----END CERTIFICATE----- diff --git a/util/httputil/testdata/server.key b/util/httputil/testdata/server.key new file mode 100644 index 000000000..126c1b5d0 --- /dev/null +++ b/util/httputil/testdata/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXQ8X2JLjOMBJw +6hecwM7y71iLEn1GXgHxGpOyPtjPmbwQMvESsO8AbNbERYWoM3vN7I9KktBaSkFp +f+PdfnHSIZzfQ7VsYLsqEqgIz8XuCH1I6ktU5ILZiLC4XgISyw4JmbdfQrbXJjQP +Suf8rJxZzaFQTIhf8dJ+WyFB8DdQgEhxUCZhJnlkS36RjQ70J/4ZgL85Vbfz0M1h +bNjBx9Mmd5IaFEJWy7z9GkrrF9iNr9HARp/wQF4ONC/n275m/YkLa4xxwQsKxcTE +639EwXU2I/3ttu6H2YhH4Ut8YFPnhRwvgksrXmMaSRc2LPw5I0kiTUO1USISJJ4x +RNgWTqjrAgMBAAECggEAVurwo4FyV7gzwIIi00XPJLT3ceJL7dUy1HHrEG8gchnq +gHxlHdJhYyMnPVydcosyxp75r2YxJtCoSZDdRHbVvGLoGzpy0zW6FnDl8TpCh4aF +RxKp+rvbnFf5A9ew5U+cX1PelHRnT7V6EJeAOiaNKOUJnnR7oHX59/UxZQw9HJnX +3H4xUdRDmSS3BGKXEswbd7beQjqJtEIkbConfaw32yEod0w2MC0LI4miZ87/6Hsk +pyvfpeYxXp4z3BTvFBbf/GEBFuozu63VWHayB9PDmEN/TlphoQpJQihdR2r1lz/H +I5QwVlFTDvUSFitNLu+FoaHOfgLprQndbojBXb+tcQKBgQDHCPyM4V7k97RvJgmB +ELgZiDYufDrjRLXvFzrrZ7ySU3N+nx3Gz/EhtgbHicDjnRVagHBIwi/QAfBJksCd +xcioY5k2OW+8PSTsfFZTAA6XwJp/LGfJik/JjvAVv5CnxBu9lYG4WiSBJFp59ojC +zTmfEuB4GPwrjQvzjlqaSpij9QKBgQDCjriwAB2UJIdlgK+DkryLqgim5I4cteB3 ++juVKz+S8ufFmVvmIXkyDcpyy/26VLC6esy8dV0JoWc4EeitoJvQD1JVZ5+CBTY+ +r9umx18oe2A/ZgcEf/A3Zd94jM1MwriF6YC+eIOhwhpi7T1xTLf3hc9B0OJ5B1mA +vob9rGDtXwKBgD4rkW+UCictNIAvenKFPWxEPuBgT6ij0sx/DhlwCtgOFxprK0rp +syFbkVyMq+KtM3lUez5O4c5wfJUOsPnXSOlISxhD8qHy23C/GdvNPcGrGNc2kKjE +ek20R0wTzWSJ/jxG0gE6rwJjz5sfJfLrVd9ZbyI0c7hK03vdcHGXcXxtAoGAeGHl +BwnbQ3niyTx53VijD2wTVGjhQgSLstEDowYSnTNtk8eTpG6b1gvQc32jLnMOsyQe +oJGiEr5q5re2GBDjuDZyxGOMv9/Hs7wOlkCQsbS9Vh0kRHWBRlXjk2zT7yYhFMLp +pXFeSW2X9BRFS2CkCCUkm93K9AZHLDE3x6ishNMCgYEAsDsUCzGhI49Aqe+CMP2l +WPZl7SEMYS5AtdC5sLtbLYBl8+rMXVGL2opKXqVFYBYkqMJiHGdX3Ub6XSVKLYkN +vm4PWmlQS24ZT+jlUl4jk6JU6SAlM/o6ixZl5KNR7yQm6zN2O/RHDeYm0urUQ9tF +9dux7LbIFeOoJmoDTWG2+fI= +-----END PRIVATE KEY----- diff --git a/util/httputil/testdata/tls-ca-chain.pem b/util/httputil/testdata/tls-ca-chain.pem new file mode 100644 index 000000000..03e4189e6 --- /dev/null +++ b/util/httputil/testdata/tls-ca-chain.pem @@ -0,0 +1,172 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA + Validity + Not Before: Jul 13 03:47:20 2017 GMT + Not After : Jul 13 03:47:20 2027 GMT + Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b5:5a:b3:7a:7f:6a:5b:e9:ee:62:ee:4f:61:42: + 79:93:06:bf:81:fc:9a:1f:b5:80:83:7c:b3:a6:94: + 54:58:8a:b1:74:cb:c3:b8:3c:23:a8:69:1f:ca:2b: + af:be:97:ba:31:73:b5:b8:ce:d9:bf:bf:9a:7a:cf: + 3a:64:51:83:c9:36:d2:f7:3b:3a:0e:4c:c7:66:2e: + bf:1a:df:ce:10:aa:3d:0f:19:74:03:7e:b5:10:bb: + e8:37:bd:62:f0:42:2d:df:3d:ca:70:50:10:17:ce: + a9:ec:55:8e:87:6f:ce:9a:04:36:14:96:cb:d1:a5: + 48:d5:d2:87:02:62:93:4e:21:4a:ff:be:44:f1:d2: + 7e:ed:74:da:c2:51:26:8e:03:a0:c2:bd:bd:5f:b0: + 50:11:78:fd:ab:1d:04:86:6c:c1:8d:20:bd:05:5f: + 51:67:c6:d3:07:95:92:2d:92:90:00:c6:9f:2d:dd: + 36:5c:dc:78:10:7c:f6:68:39:1d:2c:e0:e1:26:64: + 4f:36:34:66:a7:84:6a:90:15:3a:94:b7:79:b1:47: + f5:d2:51:95:54:bf:92:76:9a:b9:88:ee:63:f9:6c: + 0d:38:c6:b6:1c:06:43:ed:24:1d:bb:6c:72:48:cc: + 8c:f4:35:bc:43:fe:a6:96:4c:31:5f:82:0d:0d:20: + 2a:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71 + X509v3 Authority Key Identifier: + keyid:60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5 + + Authority Information Access: + CA Issuers - URI:http://green.no/ca/root-ca.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://green.no/ca/root-ca.crl + + Signature Algorithm: sha1WithRSAEncryption + 15:a7:ac:d7:25:9e:2a:d4:d1:14:b4:99:38:3d:2f:73:61:2a: + d9:b6:8b:13:ea:fe:db:78:d9:0a:6c:df:26:6e:c1:d5:4a:97: + 42:19:dd:97:05:03:e4:2b:fc:1e:1f:38:3c:4e:b0:3b:8c:38: + ad:2b:65:fa:35:2d:81:8e:e0:f6:0a:89:4c:38:97:01:4b:9c: + ac:4e:e1:55:17:ef:0a:ad:a7:eb:1e:4b:86:23:12:f1:52:69: + cb:a3:8a:ce:fb:14:8b:86:d7:bb:81:5e:bd:2a:c7:a7:79:58: + 00:10:c0:db:ff:d4:a5:b9:19:74:b3:23:19:4a:1f:78:4b:a8: + b6:f6:20:26:c1:69:f9:89:7f:b8:1c:3b:a2:f9:37:31:80:2c: + b0:b6:2b:d2:84:44:d7:42:e4:e6:44:51:04:35:d9:1c:a4:48: + c6:b7:35:de:f2:ae:da:4b:ba:c8:09:42:8d:ed:7a:81:dc:ed: + 9d:f0:de:6e:21:b9:01:1c:ad:64:3d:25:4c:91:94:f1:13:18: + bb:89:e9:48:ac:05:73:07:c8:db:bd:69:8e:6f:02:9d:b0:18: + c0:b9:e1:a8:b1:17:50:3d:ac:05:6e:6f:63:4f:b1:73:33:60: + 9a:77:d2:81:8a:01:38:43:e9:4c:3c:90:63:a4:99:4b:d2:1b: + f9:1b:ec:ee +-----BEGIN CERTIFICATE----- +MIIECzCCAvOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJOTzER +MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1 +dGhvcml0eTEWMBQGA1UEAwwNR3JlZW4gUm9vdCBDQTAeFw0xNzA3MTMwMzQ3MjBa +Fw0yNzA3MTMwMzQ3MjBaMF0xCzAJBgNVBAYTAk5PMREwDwYDVQQKDAhHcmVlbiBB +UzEkMCIGA1UECwwbR3JlZW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRUwEwYDVQQD +DAxHcmVlbiBUTFMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1 +WrN6f2pb6e5i7k9hQnmTBr+B/JoftYCDfLOmlFRYirF0y8O4PCOoaR/KK6++l7ox +c7W4ztm/v5p6zzpkUYPJNtL3OzoOTMdmLr8a384Qqj0PGXQDfrUQu+g3vWLwQi3f +PcpwUBAXzqnsVY6Hb86aBDYUlsvRpUjV0ocCYpNOIUr/vkTx0n7tdNrCUSaOA6DC +vb1fsFAReP2rHQSGbMGNIL0FX1FnxtMHlZItkpAAxp8t3TZc3HgQfPZoOR0s4OEm +ZE82NGanhGqQFTqUt3mxR/XSUZVUv5J2mrmI7mP5bA04xrYcBkPtJB27bHJIzIz0 +NbxD/qaWTDFfgg0NICo9AgMBAAGjgdQwgdEwDgYDVR0PAQH/BAQDAgEGMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFK5CiHXdBaaOSH9Qafm3NCNJuLRxMB8G +A1UdIwQYMBaAFGCTUy/HzyrX8wko9jyunFDsk2PlMDoGCCsGAQUFBwEBBC4wLDAq +BggrBgEFBQcwAoYeaHR0cDovL2dyZWVuLm5vL2NhL3Jvb3QtY2EuY2VyMC8GA1Ud +HwQoMCYwJKAioCCGHmh0dHA6Ly9ncmVlbi5uby9jYS9yb290LWNhLmNybDANBgkq +hkiG9w0BAQUFAAOCAQEAFaes1yWeKtTRFLSZOD0vc2Eq2baLE+r+23jZCmzfJm7B +1UqXQhndlwUD5Cv8Hh84PE6wO4w4rStl+jUtgY7g9gqJTDiXAUucrE7hVRfvCq2n +6x5LhiMS8VJpy6OKzvsUi4bXu4FevSrHp3lYABDA2//UpbkZdLMjGUofeEuotvYg +JsFp+Yl/uBw7ovk3MYAssLYr0oRE10Lk5kRRBDXZHKRIxrc13vKu2ku6yAlCje16 +gdztnfDebiG5ARytZD0lTJGU8RMYu4npSKwFcwfI271pjm8CnbAYwLnhqLEXUD2s +BW5vY0+xczNgmnfSgYoBOEPpTDyQY6SZS9Ib+Rvs7g== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA + Validity + Not Before: Jul 13 03:44:39 2017 GMT + Not After : Dec 31 23:59:59 2030 GMT + Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a7:e8:ed:de:d4:54:08:41:07:40:d5:c0:43:d6: + ab:d3:9e:21:87:c6:13:bf:a7:cf:3d:08:4f:c1:fe: + 8f:e5:6c:c5:89:97:e5:27:75:26:c3:2a:73:2d:34: + 7c:6f:35:8d:40:66:61:05:c0:eb:e9:b3:38:47:f8: + 8b:26:35:2c:df:dc:24:31:fe:72:e3:87:10:d1:f7: + a0:57:b7:f3:b1:1a:fe:c7:4b:f8:7b:14:6d:73:08: + 54:eb:63:3c:0c:ce:22:95:5f:3f:f2:6f:89:ae:63: + da:80:74:36:21:13:e8:91:01:58:77:cc:c2:f2:42: + bf:eb:b3:60:a7:21:ed:88:24:7f:eb:ff:07:41:9b: + 93:c8:5f:6a:8e:a6:1a:15:3c:bc:e7:0d:fd:05:fd: + 3c:c1:1c:1d:1f:57:2b:40:27:62:a1:7c:48:63:c1: + 45:e7:2f:20:ed:92:1c:42:94:e4:58:70:7a:b6:d2: + 85:c5:61:d8:cd:c6:37:6b:72:3b:7f:af:55:81:d6: + 9d:dc:10:c9:d8:0e:81:e4:5e:40:13:2f:20:e8:6b: + 46:81:ce:88:47:dd:38:71:3d:ef:21:cc:c0:67:cf: + 0a:f4:e9:3f:a8:9d:26:25:2e:23:1e:a3:11:18:cb: + d1:70:1c:9e:7d:09:b1:a4:20:dc:95:15:1d:49:cf: + 1b:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5 + X509v3 Authority Key Identifier: + keyid:60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5 + + Signature Algorithm: sha1WithRSAEncryption + a7:77:71:8b:1a:e5:5a:5b:87:54:08:bf:07:3e:cb:99:2f:dc: + 0e:8d:63:94:95:83:19:c9:92:82:d5:cb:5b:8f:1f:86:55:bc: + 70:01:1d:33:46:ec:99:de:6b:1f:c3:c2:7a:dd:ef:69:ab:96: + 58:ec:6c:6f:6c:70:82:71:8a:7f:f0:3b:80:90:d5:64:fa:80: + 27:b8:7b:50:69:98:4b:37:99:ad:bf:a2:5b:93:22:5e:96:44: + 3c:5a:cf:0c:f4:62:63:4a:6f:72:a7:f6:89:1d:09:26:3d:8f: + a8:86:d4:b4:bc:dd:b3:38:ca:c0:59:16:8c:20:1f:89:35:12: + b4:2d:c0:e9:de:93:e0:39:76:32:fc:80:db:da:44:26:fd:01: + 32:74:97:f8:44:ae:fe:05:b1:34:96:13:34:56:73:b4:93:a5: + 55:56:d1:01:51:9d:9c:55:e7:38:53:28:12:4e:38:72:0c:8f: + bd:91:4c:45:48:3b:e1:0d:03:5f:58:40:c9:d3:a0:ac:b3:89: + ce:af:27:8a:0f:ab:ec:72:4d:40:77:30:6b:36:fd:32:46:9f: + ee:f9:c4:f5:17:06:0f:4b:d3:88:f5:a4:2f:3d:87:9e:f5:26: + 74:f0:c9:dc:cb:ad:d9:a7:8a:d3:71:15:00:d3:5d:9f:4c:59: + 3e:24:63:f5 +-----BEGIN CERTIFICATE----- +MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJOTzER +MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1 +dGhvcml0eTEWMBQGA1UEAwwNR3JlZW4gUm9vdCBDQTAgFw0xNzA3MTMwMzQ0Mzla +GA8yMDMwMTIzMTIzNTk1OVowXjELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEdyZWVu +IEFTMSQwIgYDVQQLDBtHcmVlbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFjAUBgNV +BAMMDUdyZWVuIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCn6O3e1FQIQQdA1cBD1qvTniGHxhO/p889CE/B/o/lbMWJl+UndSbDKnMtNHxv +NY1AZmEFwOvpszhH+IsmNSzf3CQx/nLjhxDR96BXt/OxGv7HS/h7FG1zCFTrYzwM +ziKVXz/yb4muY9qAdDYhE+iRAVh3zMLyQr/rs2CnIe2IJH/r/wdBm5PIX2qOphoV +PLznDf0F/TzBHB0fVytAJ2KhfEhjwUXnLyDtkhxClORYcHq20oXFYdjNxjdrcjt/ +r1WB1p3cEMnYDoHkXkATLyDoa0aBzohH3ThxPe8hzMBnzwr06T+onSYlLiMeoxEY +y9FwHJ59CbGkINyVFR1JzxutAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRgk1Mvx88q1/MJKPY8rpxQ7JNj5TAfBgNV +HSMEGDAWgBRgk1Mvx88q1/MJKPY8rpxQ7JNj5TANBgkqhkiG9w0BAQUFAAOCAQEA +p3dxixrlWluHVAi/Bz7LmS/cDo1jlJWDGcmSgtXLW48fhlW8cAEdM0bsmd5rH8PC +et3vaauWWOxsb2xwgnGKf/A7gJDVZPqAJ7h7UGmYSzeZrb+iW5MiXpZEPFrPDPRi +Y0pvcqf2iR0JJj2PqIbUtLzdszjKwFkWjCAfiTUStC3A6d6T4Dl2MvyA29pEJv0B +MnSX+ESu/gWxNJYTNFZztJOlVVbRAVGdnFXnOFMoEk44cgyPvZFMRUg74Q0DX1hA +ydOgrLOJzq8nig+r7HJNQHcwazb9Mkaf7vnE9RcGD0vTiPWkLz2HnvUmdPDJ3Mut +2aeK03EVANNdn0xZPiRj9Q== +-----END CERTIFICATE----- diff --git a/util/testutil/roundtrip.go b/util/testutil/roundtrip.go new file mode 100644 index 000000000..42c109527 --- /dev/null +++ b/util/testutil/roundtrip.go @@ -0,0 +1,47 @@ +// Copyright 2017 The Prometheus 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 testutil + +import ( + "net/http" +) + +type roundTrip struct { + theResponse *http.Response + theError error +} + +func (rt *roundTrip) RoundTrip(r *http.Request) (*http.Response, error) { + return rt.theResponse, rt.theError +} + +type roundTripCheckRequest struct { + checkRequest func(*http.Request) + roundTrip +} + +func (rt *roundTripCheckRequest) RoundTrip(r *http.Request) (*http.Response, error) { + rt.checkRequest(r) + return rt.theResponse, rt.theError +} + +// NewRoundTripCheckRequest creates a new instance of a type that implements http.RoundTripper, +// wich before returning theResponse and theError, executes checkRequest against a http.Request. +func NewRoundTripCheckRequest(checkRequest func(*http.Request), theResponse *http.Response, theError error) http.RoundTripper { + return &roundTripCheckRequest{ + checkRequest: checkRequest, + roundTrip: roundTrip{ + theResponse: theResponse, + theError: theError}} +}