support reading basic_auth password_file for HTTP basic auth (#4077)
Issue: https://github.com/prometheus/prometheus/issues/4076 Signed-off-by: Adam Shannon <adamkshannon@gmail.com>pull/4116/head
parent
91e470d733
commit
809881d7f5
@ -1,197 +0,0 @@ |
||||
// Copyright 2013 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" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/mwitkow/go-conntrack" |
||||
config_util "github.com/prometheus/common/config" |
||||
) |
||||
|
||||
// NewClient returns a http.Client using the specified http.RoundTripper.
|
||||
func newClient(rt http.RoundTripper) *http.Client { |
||||
return &http.Client{Transport: rt} |
||||
} |
||||
|
||||
// NewClientFromConfig returns a new HTTP client configured for the
|
||||
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
|
||||
func NewClientFromConfig(cfg config_util.HTTPClientConfig, name string) (*http.Client, error) { |
||||
rt, err := NewRoundTripperFromConfig(cfg, name) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return newClient(rt), nil |
||||
} |
||||
|
||||
// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
|
||||
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
|
||||
func NewRoundTripperFromConfig(cfg config_util.HTTPClientConfig, name string) (http.RoundTripper, error) { |
||||
tlsConfig, err := NewTLSConfig(cfg.TLSConfig) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
// The only timeout we care about is the configured scrape timeout.
|
||||
// It is applied on request. So we leave out any timings here.
|
||||
var rt http.RoundTripper = &http.Transport{ |
||||
Proxy: http.ProxyURL(cfg.ProxyURL.URL), |
||||
MaxIdleConns: 20000, |
||||
MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
|
||||
DisableKeepAlives: false, |
||||
TLSClientConfig: tlsConfig, |
||||
DisableCompression: true, |
||||
// 5 minutes is typically above the maximum sane scrape interval. So we can
|
||||
// use keepalive for all configurations.
|
||||
IdleConnTimeout: 5 * time.Minute, |
||||
DialContext: conntrack.NewDialContextFunc( |
||||
conntrack.DialWithTracing(), |
||||
conntrack.DialWithName(name), |
||||
), |
||||
} |
||||
|
||||
// If a bearer token is provided, create a round tripper that will set the
|
||||
// Authorization header correctly on each request.
|
||||
if len(cfg.BearerToken) > 0 { |
||||
rt = NewBearerAuthRoundTripper(string(cfg.BearerToken), rt) |
||||
} else if len(cfg.BearerTokenFile) > 0 { |
||||
rt = NewBearerAuthFileRoundTripper(cfg.BearerTokenFile, rt) |
||||
} |
||||
|
||||
if cfg.BasicAuth != nil { |
||||
rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, string(cfg.BasicAuth.Password), rt) |
||||
} |
||||
|
||||
// Return a new configured RoundTripper.
|
||||
return rt, nil |
||||
} |
||||
|
||||
type bearerAuthRoundTripper struct { |
||||
bearerToken string |
||||
rt http.RoundTripper |
||||
} |
||||
|
||||
// NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
|
||||
// header has already been set.
|
||||
func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper { |
||||
return &bearerAuthRoundTripper{bearer, rt} |
||||
} |
||||
|
||||
func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { |
||||
if len(req.Header.Get("Authorization")) == 0 { |
||||
req = cloneRequest(req) |
||||
req.Header.Set("Authorization", "Bearer "+rt.bearerToken) |
||||
} |
||||
|
||||
return rt.rt.RoundTrip(req) |
||||
} |
||||
|
||||
type bearerAuthFileRoundTripper struct { |
||||
bearerFile string |
||||
rt http.RoundTripper |
||||
} |
||||
|
||||
// NewBearerAuthFileRoundTripper adds the bearer token read from the provided file to a request unless
|
||||
// the authorization header has already been set. This file is read for every request.
|
||||
func NewBearerAuthFileRoundTripper(bearerFile string, rt http.RoundTripper) http.RoundTripper { |
||||
return &bearerAuthFileRoundTripper{bearerFile, rt} |
||||
} |
||||
|
||||
func (rt *bearerAuthFileRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { |
||||
if len(req.Header.Get("Authorization")) == 0 { |
||||
b, err := ioutil.ReadFile(rt.bearerFile) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("unable to read bearer token file %s: %s", rt.bearerFile, err) |
||||
} |
||||
bearerToken := strings.TrimSpace(string(b)) |
||||
|
||||
req = cloneRequest(req) |
||||
req.Header.Set("Authorization", "Bearer "+bearerToken) |
||||
} |
||||
|
||||
return rt.rt.RoundTrip(req) |
||||
} |
||||
|
||||
type basicAuthRoundTripper struct { |
||||
username string |
||||
password string |
||||
rt http.RoundTripper |
||||
} |
||||
|
||||
// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
|
||||
// already been set.
|
||||
func NewBasicAuthRoundTripper(username, password string, rt http.RoundTripper) http.RoundTripper { |
||||
return &basicAuthRoundTripper{username, password, rt} |
||||
} |
||||
|
||||
func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { |
||||
if len(req.Header.Get("Authorization")) != 0 { |
||||
return rt.rt.RoundTrip(req) |
||||
} |
||||
req = cloneRequest(req) |
||||
req.SetBasicAuth(rt.username, rt.password) |
||||
return rt.rt.RoundTrip(req) |
||||
} |
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request { |
||||
// Shallow copy of the struct.
|
||||
r2 := new(http.Request) |
||||
*r2 = *r |
||||
// Deep copy of the Header.
|
||||
r2.Header = make(http.Header) |
||||
for k, s := range r.Header { |
||||
r2.Header[k] = s |
||||
} |
||||
return r2 |
||||
} |
||||
|
||||
// NewTLSConfig creates a new tls.Config from the given config_util.TLSConfig.
|
||||
func NewTLSConfig(cfg config_util.TLSConfig) (*tls.Config, error) { |
||||
tlsConfig := &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify} |
||||
|
||||
// If a CA cert is provided then let's read it in so we can validate the
|
||||
// scrape target's certificate properly.
|
||||
if len(cfg.CAFile) > 0 { |
||||
caCertPool := x509.NewCertPool() |
||||
// Load CA cert.
|
||||
caCert, err := ioutil.ReadFile(cfg.CAFile) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("unable to use specified CA cert %s: %s", cfg.CAFile, err) |
||||
} |
||||
caCertPool.AppendCertsFromPEM(caCert) |
||||
tlsConfig.RootCAs = caCertPool |
||||
} |
||||
|
||||
if len(cfg.ServerName) > 0 { |
||||
tlsConfig.ServerName = cfg.ServerName |
||||
} |
||||
// If a client cert & key is provided then configure TLS config accordingly.
|
||||
if len(cfg.CertFile) > 0 && len(cfg.KeyFile) > 0 { |
||||
cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("unable to use specified client cert (%s) & key (%s): %s", cfg.CertFile, cfg.KeyFile, err) |
||||
} |
||||
tlsConfig.Certificates = []tls.Certificate{cert} |
||||
} |
||||
tlsConfig.BuildNameToCertificate() |
||||
|
||||
return tlsConfig, nil |
||||
} |
||||
@ -1,468 +0,0 @@ |
||||
// 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" |
||||
|
||||
config_util "github.com/prometheus/common/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_util.HTTPClientConfig |
||||
handler func(w http.ResponseWriter, r *http.Request) |
||||
}{ |
||||
{ |
||||
clientConfig: config_util.HTTPClientConfig{ |
||||
TLSConfig: config_util.TLSConfig{ |
||||
CAFile: "", |
||||
CertFile: BarneyCertificatePath, |
||||
KeyFile: BarneyKeyNoPassPath, |
||||
ServerName: "", |
||||
InsecureSkipVerify: true}, |
||||
}, |
||||
handler: func(w http.ResponseWriter, r *http.Request) { |
||||
fmt.Fprint(w, ExpectedMessage) |
||||
}, |
||||
}, { |
||||
clientConfig: config_util.HTTPClientConfig{ |
||||
TLSConfig: config_util.TLSConfig{ |
||||
CAFile: TLSCAChainPath, |
||||
CertFile: BarneyCertificatePath, |
||||
KeyFile: BarneyKeyNoPassPath, |
||||
ServerName: "", |
||||
InsecureSkipVerify: false}, |
||||
}, |
||||
handler: func(w http.ResponseWriter, r *http.Request) { |
||||
fmt.Fprint(w, ExpectedMessage) |
||||
}, |
||||
}, { |
||||
clientConfig: config_util.HTTPClientConfig{ |
||||
BearerToken: BearerToken, |
||||
TLSConfig: config_util.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_util.HTTPClientConfig{ |
||||
BearerTokenFile: BearerTokenFile, |
||||
TLSConfig: config_util.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_util.HTTPClientConfig{ |
||||
BasicAuth: &config_util.BasicAuth{ |
||||
Username: ExpectedUsername, |
||||
Password: ExpectedPassword, |
||||
}, |
||||
TLSConfig: config_util.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 { |
||||
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, "test") |
||||
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_util.HTTPClientConfig |
||||
errorMsg string |
||||
}{ |
||||
{ |
||||
clientConfig: config_util.HTTPClientConfig{ |
||||
TLSConfig: config_util.TLSConfig{ |
||||
CAFile: MissingCA, |
||||
CertFile: "", |
||||
KeyFile: "", |
||||
ServerName: "", |
||||
InsecureSkipVerify: true}, |
||||
}, |
||||
errorMsg: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA), |
||||
}, |
||||
} |
||||
|
||||
for _, invalidConfig := range newClientInvalidConfig { |
||||
client, err := NewClientFromConfig(invalidConfig.clientConfig, "test") |
||||
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 TestMissingBearerAuthFile(t *testing.T) { |
||||
cfg := config_util.HTTPClientConfig{ |
||||
BearerTokenFile: MissingBearerTokenFile, |
||||
TLSConfig: config_util.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) |
||||
} |
||||
} |
||||
|
||||
testServer, err := newTestServer(handler) |
||||
if err != nil { |
||||
t.Fatal(err.Error()) |
||||
} |
||||
defer testServer.Close() |
||||
|
||||
client, err := NewClientFromConfig(cfg, "test") |
||||
if err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
|
||||
_, err = client.Get(testServer.URL) |
||||
if err == nil { |
||||
t.Fatal("No error is returned here") |
||||
} |
||||
|
||||
if !strings.Contains(err.Error(), "unable to read bearer token file missing/bearer.token: open missing/bearer.token: no such file or directory") { |
||||
t.Fatal("wrong error message being returned") |
||||
} |
||||
} |
||||
|
||||
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 TestBearerAuthFileRoundTripper(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 := NewBearerAuthFileRoundTripper(BearerTokenFile, 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 := NewBearerAuthFileRoundTripper(MissingBearerTokenFile, 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 { |
||||
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_util.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_util.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_util.TLSConfig |
||||
errorMessage string |
||||
}{ |
||||
{ |
||||
configTLSConfig: config_util.TLSConfig{ |
||||
CAFile: MissingCA, |
||||
CertFile: "", |
||||
KeyFile: "", |
||||
ServerName: "", |
||||
InsecureSkipVerify: false}, |
||||
errorMessage: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA), |
||||
}, { |
||||
configTLSConfig: config_util.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_util.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) |
||||
} |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@ |
||||
-----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----- |
||||
@ -1,96 +0,0 @@ |
||||
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----- |
||||
@ -1 +0,0 @@ |
||||
theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo |
||||
@ -1,96 +0,0 @@ |
||||
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----- |
||||
@ -1,28 +0,0 @@ |
||||
-----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----- |
||||
@ -1,172 +0,0 @@ |
||||
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----- |
||||
Loading…
Reference in new issue