mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-26 06:04:05 -08:00
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>
This commit is contained in:
parent
91e470d733
commit
809881d7f5
|
@ -30,7 +30,6 @@ import (
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
"github.com/prometheus/prometheus/util/strutil"
|
"github.com/prometheus/prometheus/util/strutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ func NewDiscovery(conf *SDConfig, logger log.Logger) (*Discovery, error) {
|
||||||
logger = log.NewNopLogger()
|
logger = log.NewNopLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
tls, err := httputil.NewTLSConfig(conf.TLSConfig)
|
tls, err := config_util.NewTLSConfig(&conf.TLSConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import (
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
"github.com/prometheus/prometheus/util/strutil"
|
"github.com/prometheus/prometheus/util/strutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -138,7 +137,7 @@ func NewDiscovery(conf SDConfig, logger log.Logger) (*Discovery, error) {
|
||||||
logger = log.NewNopLogger()
|
logger = log.NewNopLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
rt, err := httputil.NewRoundTripperFromConfig(conf.HTTPClientConfig, "marathon_sd")
|
rt, err := config_util.NewRoundTripperFromConfig(conf.HTTPClientConfig, "marathon_sd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import (
|
||||||
|
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -126,7 +125,7 @@ func New(logger log.Logger, conf *SDConfig) (*Discovery, error) {
|
||||||
logger = log.NewNopLogger()
|
logger = log.NewNopLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
tls, err := httputil.NewTLSConfig(conf.TLSConfig)
|
tls, err := config_util.NewTLSConfig(&conf.TLSConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,9 +144,11 @@ params:
|
||||||
|
|
||||||
# Sets the `Authorization` header on every scrape request with the
|
# Sets the `Authorization` header on every scrape request with the
|
||||||
# configured username and password.
|
# configured username and password.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <secret> ]
|
[ password: <secret> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Sets the `Authorization` header on every scrape request with
|
# Sets the `Authorization` header on every scrape request with
|
||||||
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
||||||
|
@ -744,11 +746,13 @@ role: <role>
|
||||||
# Optional authentication information used to authenticate to the API server.
|
# Optional authentication information used to authenticate to the API server.
|
||||||
# Note that `basic_auth`, `bearer_token` and `bearer_token_file` options are
|
# Note that `basic_auth`, `bearer_token` and `bearer_token_file` options are
|
||||||
# mutually exclusive.
|
# mutually exclusive.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
|
|
||||||
# Optional HTTP basic authentication information.
|
# Optional HTTP basic authentication information.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <secret> ]
|
[ password: <secret> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Optional bearer token authentication information.
|
# Optional bearer token authentication information.
|
||||||
[ bearer_token: <secret> ]
|
[ bearer_token: <secret> ]
|
||||||
|
@ -816,9 +820,11 @@ servers:
|
||||||
# Sets the `Authorization` header on every request with the
|
# Sets the `Authorization` header on every request with the
|
||||||
# configured username and password.
|
# configured username and password.
|
||||||
# This is mutually exclusive with other authentication mechanisms.
|
# This is mutually exclusive with other authentication mechanisms.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <string> ]
|
[ password: <string> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Sets the `Authorization` header on every request with
|
# Sets the `Authorization` header on every request with
|
||||||
# the configured bearer token. It is mutually exclusive with `bearer_token_file` and other authentication mechanisms.
|
# the configured bearer token. It is mutually exclusive with `bearer_token_file` and other authentication mechanisms.
|
||||||
|
@ -1071,9 +1077,11 @@ through the `__alerts_path__` label.
|
||||||
|
|
||||||
# Sets the `Authorization` header on every request with the
|
# Sets the `Authorization` header on every request with the
|
||||||
# configured username and password.
|
# configured username and password.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <string> ]
|
[ password: <string> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Sets the `Authorization` header on every request with
|
# Sets the `Authorization` header on every request with
|
||||||
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
||||||
|
@ -1165,9 +1173,11 @@ write_relabel_configs:
|
||||||
|
|
||||||
# Sets the `Authorization` header on every remote write request with the
|
# Sets the `Authorization` header on every remote write request with the
|
||||||
# configured username and password.
|
# configured username and password.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <string> ]
|
[ password: <string> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Sets the `Authorization` header on every remote write request with
|
# Sets the `Authorization` header on every remote write request with
|
||||||
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
||||||
|
@ -1209,9 +1219,11 @@ required_matchers:
|
||||||
|
|
||||||
# Sets the `Authorization` header on every remote read request with the
|
# Sets the `Authorization` header on every remote read request with the
|
||||||
# configured username and password.
|
# configured username and password.
|
||||||
|
# password and password_file are mutually exclusive.
|
||||||
basic_auth:
|
basic_auth:
|
||||||
[ username: <string> ]
|
[ username: <string> ]
|
||||||
[ password: <string> ]
|
[ password: <string> ]
|
||||||
|
[ password_file: <string> ]
|
||||||
|
|
||||||
# Sets the `Authorization` header on every remote read request with
|
# Sets the `Authorization` header on every remote read request with
|
||||||
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
old_ctx "golang.org/x/net/context"
|
old_ctx "golang.org/x/net/context"
|
||||||
"golang.org/x/net/context/ctxhttp"
|
"golang.org/x/net/context/ctxhttp"
|
||||||
|
@ -39,7 +40,6 @@ import (
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/pkg/relabel"
|
"github.com/prometheus/prometheus/pkg/relabel"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -545,7 +545,7 @@ type alertmanagerSet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAlertmanagerSet(cfg *config.AlertmanagerConfig, logger log.Logger) (*alertmanagerSet, error) {
|
func newAlertmanagerSet(cfg *config.AlertmanagerConfig, logger log.Logger) (*alertmanagerSet, error) {
|
||||||
client, err := httputil.NewClientFromConfig(cfg.HTTPClientConfig, "alertmanager")
|
client, err := config_util.NewClientFromConfig(cfg.HTTPClientConfig, "alertmanager")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import (
|
||||||
"github.com/prometheus/prometheus/config"
|
"github.com/prometheus/prometheus/config"
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
"github.com/prometheus/prometheus/util/testutil"
|
"github.com/prometheus/prometheus/util/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -155,7 +154,7 @@ func TestHandlerSendAll(t *testing.T) {
|
||||||
|
|
||||||
h := NewManager(&Options{}, nil)
|
h := NewManager(&Options{}, nil)
|
||||||
|
|
||||||
authClient, _ := httputil.NewClientFromConfig(config_util.HTTPClientConfig{
|
authClient, _ := config_util.NewClientFromConfig(config_util.HTTPClientConfig{
|
||||||
BasicAuth: &config_util.BasicAuth{
|
BasicAuth: &config_util.BasicAuth{
|
||||||
Username: "prometheus",
|
Username: "prometheus",
|
||||||
Password: "testing_password",
|
Password: "testing_password",
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/common/version"
|
"github.com/prometheus/common/version"
|
||||||
"golang.org/x/net/context/ctxhttp"
|
"golang.org/x/net/context/ctxhttp"
|
||||||
|
@ -42,7 +43,6 @@ import (
|
||||||
"github.com/prometheus/prometheus/pkg/timestamp"
|
"github.com/prometheus/prometheus/pkg/timestamp"
|
||||||
"github.com/prometheus/prometheus/pkg/value"
|
"github.com/prometheus/prometheus/pkg/value"
|
||||||
"github.com/prometheus/prometheus/storage"
|
"github.com/prometheus/prometheus/storage"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -142,7 +142,7 @@ func newScrapePool(cfg *config.ScrapeConfig, app Appendable, logger log.Logger)
|
||||||
logger = log.NewNopLogger()
|
logger = log.NewNopLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := httputil.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName)
|
client, err := config_util.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Any errors that could occur here should be caught during config validation.
|
// Any errors that could occur here should be caught during config validation.
|
||||||
level.Error(logger).Log("msg", "Error creating HTTP client", "err", err)
|
level.Error(logger).Log("msg", "Error creating HTTP client", "err", err)
|
||||||
|
@ -212,7 +212,7 @@ func (sp *scrapePool) reload(cfg *config.ScrapeConfig) {
|
||||||
sp.mtx.Lock()
|
sp.mtx.Lock()
|
||||||
defer sp.mtx.Unlock()
|
defer sp.mtx.Unlock()
|
||||||
|
|
||||||
client, err := httputil.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName)
|
client, err := config_util.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Any errors that could occur here should be caught during config validation.
|
// Any errors that could occur here should be caught during config validation.
|
||||||
level.Error(sp.logger).Log("msg", "Error creating HTTP client", "err", err)
|
level.Error(sp.logger).Log("msg", "Error creating HTTP client", "err", err)
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
|
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -151,7 +150,7 @@ func TestNewHTTPBearerToken(t *testing.T) {
|
||||||
cfg := config_util.HTTPClientConfig{
|
cfg := config_util.HTTPClientConfig{
|
||||||
BearerToken: "1234",
|
BearerToken: "1234",
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -178,7 +177,7 @@ func TestNewHTTPBearerTokenFile(t *testing.T) {
|
||||||
cfg := config_util.HTTPClientConfig{
|
cfg := config_util.HTTPClientConfig{
|
||||||
BearerTokenFile: "testdata/bearertoken.txt",
|
BearerTokenFile: "testdata/bearertoken.txt",
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +206,7 @@ func TestNewHTTPBasicAuth(t *testing.T) {
|
||||||
Password: "password123",
|
Password: "password123",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -235,7 +234,7 @@ func TestNewHTTPCACert(t *testing.T) {
|
||||||
CAFile: caCertPath,
|
CAFile: caCertPath,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -269,7 +268,7 @@ func TestNewHTTPClientCert(t *testing.T) {
|
||||||
KeyFile: "testdata/client.key",
|
KeyFile: "testdata/client.key",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -298,7 +297,7 @@ func TestNewHTTPWithServerName(t *testing.T) {
|
||||||
ServerName: "prometheus.rocks",
|
ServerName: "prometheus.rocks",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -327,7 +326,7 @@ func TestNewHTTPWithBadServerName(t *testing.T) {
|
||||||
ServerName: "badname",
|
ServerName: "badname",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c, err := httputil.NewClientFromConfig(cfg, "test")
|
c, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -366,7 +365,7 @@ func TestNewClientWithBadTLSConfig(t *testing.T) {
|
||||||
KeyFile: "testdata/nonexistent_client.key",
|
KeyFile: "testdata/nonexistent_client.key",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := httputil.NewClientFromConfig(cfg, "test")
|
_, err := config_util.NewClientFromConfig(cfg, "test")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Expected error, got nil.")
|
t.Fatalf("Expected error, got nil.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
|
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/prometheus/prompb"
|
"github.com/prometheus/prometheus/prompb"
|
||||||
"github.com/prometheus/prometheus/util/httputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxErrMsgLen = 256
|
const maxErrMsgLen = 256
|
||||||
|
@ -52,7 +51,7 @@ type ClientConfig struct {
|
||||||
|
|
||||||
// NewClient creates a new Client.
|
// NewClient creates a new Client.
|
||||||
func NewClient(index int, conf *ClientConfig) (*Client, error) {
|
func NewClient(index int, conf *ClientConfig) (*Client, error) {
|
||||||
httpClient, err := httputil.NewClientFromConfig(conf.HTTPClientConfig, "remote_storage")
|
httpClient, err := config_util.NewClientFromConfig(conf.HTTPClientConfig, "remote_storage")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
27
util/httputil/testdata/barney-no-pass.key
vendored
27
util/httputil/testdata/barney-no-pass.key
vendored
|
@ -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-----
|
|
96
util/httputil/testdata/barney.crt
vendored
96
util/httputil/testdata/barney.crt
vendored
|
@ -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
util/httputil/testdata/bearer.token
vendored
1
util/httputil/testdata/bearer.token
vendored
|
@ -1 +0,0 @@
|
||||||
theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo
|
|
96
util/httputil/testdata/server.crt
vendored
96
util/httputil/testdata/server.crt
vendored
|
@ -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-----
|
|
28
util/httputil/testdata/server.key
vendored
28
util/httputil/testdata/server.key
vendored
|
@ -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-----
|
|
172
util/httputil/testdata/tls-ca-chain.pem
vendored
172
util/httputil/testdata/tls-ca-chain.pem
vendored
|
@ -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-----
|
|
140
vendor/github.com/prometheus/common/config/http_config.go
generated
vendored
140
vendor/github.com/prometheus/common/config/http_config.go
generated
vendored
|
@ -21,14 +21,17 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mwitkow/go-conntrack"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BasicAuth contains basic HTTP authentication credentials.
|
// BasicAuth contains basic HTTP authentication credentials.
|
||||||
type BasicAuth struct {
|
type BasicAuth struct {
|
||||||
Username string `yaml:"username"`
|
Username string `yaml:"username"`
|
||||||
Password Secret `yaml:"password"`
|
Password Secret `yaml:"password,omitempty"`
|
||||||
|
PasswordFile string `yaml:"password_file,omitempty"`
|
||||||
|
|
||||||
// Catches all undefined fields and must be empty after parsing.
|
// Catches all undefined fields and must be empty after parsing.
|
||||||
XXX map[string]interface{} `yaml:",inline"`
|
XXX map[string]interface{} `yaml:",inline"`
|
||||||
|
@ -88,6 +91,12 @@ func (c *HTTPClientConfig) Validate() error {
|
||||||
if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
|
if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
|
||||||
return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured")
|
return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured")
|
||||||
}
|
}
|
||||||
|
if c.BasicAuth != nil && c.BasicAuth.Username == "" {
|
||||||
|
return fmt.Errorf("basic_auth requires a username")
|
||||||
|
}
|
||||||
|
if c.BasicAuth != nil && (string(c.BasicAuth.Password) != "" && c.BasicAuth.PasswordFile != "") {
|
||||||
|
return fmt.Errorf("at most one of basic_auth password & password_file must be configured")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,42 +124,60 @@ func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
return checkOverflow(a.XXX, "basic_auth")
|
return checkOverflow(a.XXX, "basic_auth")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPClientFromConfig returns a new HTTP client configured for the
|
// NewClient returns a http.Client using the specified http.RoundTripper.
|
||||||
// given config.HTTPClientConfig.
|
func newClient(rt http.RoundTripper) *http.Client {
|
||||||
func NewHTTPClientFromConfig(cfg *HTTPClientConfig) (*http.Client, error) {
|
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 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 HTTPClientConfig, name string) (http.RoundTripper, error) {
|
||||||
tlsConfig, err := NewTLSConfig(&cfg.TLSConfig)
|
tlsConfig, err := NewTLSConfig(&cfg.TLSConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// The only timeout we care about is the configured scrape timeout.
|
||||||
// It's the caller's job to handle timeouts
|
// It is applied on request. So we leave out any timings here.
|
||||||
var rt http.RoundTripper = &http.Transport{
|
var rt http.RoundTripper = &http.Transport{
|
||||||
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
|
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
|
||||||
DisableKeepAlives: true,
|
MaxIdleConns: 20000,
|
||||||
|
MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
|
||||||
|
DisableKeepAlives: false,
|
||||||
TLSClientConfig: tlsConfig,
|
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
|
// If a bearer token is provided, create a round tripper that will set the
|
||||||
// Authorization header correctly on each request.
|
// Authorization header correctly on each request.
|
||||||
bearerToken := cfg.BearerToken
|
if len(cfg.BearerToken) > 0 {
|
||||||
if len(bearerToken) == 0 && len(cfg.BearerTokenFile) > 0 {
|
rt = NewBearerAuthRoundTripper(cfg.BearerToken, rt)
|
||||||
b, err := ioutil.ReadFile(cfg.BearerTokenFile)
|
} else if len(cfg.BearerTokenFile) > 0 {
|
||||||
if err != nil {
|
rt = NewBearerAuthFileRoundTripper(cfg.BearerTokenFile, rt)
|
||||||
return nil, fmt.Errorf("unable to read bearer token file %s: %s", cfg.BearerTokenFile, err)
|
|
||||||
}
|
|
||||||
bearerToken = Secret(strings.TrimSpace(string(b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(bearerToken) > 0 {
|
|
||||||
rt = NewBearerAuthRoundTripper(bearerToken, rt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.BasicAuth != nil {
|
if cfg.BasicAuth != nil {
|
||||||
rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, Secret(cfg.BasicAuth.Password), rt)
|
rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, cfg.BasicAuth.Password, cfg.BasicAuth.PasswordFile, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a new client with the configured round tripper.
|
// Return a new configured RoundTripper.
|
||||||
return &http.Client{Transport: rt}, nil
|
return rt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type bearerAuthRoundTripper struct {
|
type bearerAuthRoundTripper struct {
|
||||||
|
@ -158,39 +185,73 @@ type bearerAuthRoundTripper struct {
|
||||||
rt http.RoundTripper
|
rt http.RoundTripper
|
||||||
}
|
}
|
||||||
|
|
||||||
type basicAuthRoundTripper struct {
|
// NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
|
||||||
username string
|
// header has already been set.
|
||||||
password Secret
|
func NewBearerAuthRoundTripper(token Secret, rt http.RoundTripper) http.RoundTripper {
|
||||||
rt http.RoundTripper
|
return &bearerAuthRoundTripper{token, rt}
|
||||||
}
|
|
||||||
|
|
||||||
// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
|
|
||||||
// already been set.
|
|
||||||
func NewBasicAuthRoundTripper(username string, password Secret, rt http.RoundTripper) http.RoundTripper {
|
|
||||||
return &basicAuthRoundTripper{username, password, rt}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
if len(req.Header.Get("Authorization")) == 0 {
|
if len(req.Header.Get("Authorization")) == 0 {
|
||||||
req = cloneRequest(req)
|
req = cloneRequest(req)
|
||||||
req.Header.Set("Authorization", "Bearer "+string(rt.bearerToken))
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(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)
|
return rt.rt.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
|
type basicAuthRoundTripper struct {
|
||||||
// header has already been set.
|
username string
|
||||||
func NewBearerAuthRoundTripper(bearer Secret, rt http.RoundTripper) http.RoundTripper {
|
password Secret
|
||||||
return &bearerAuthRoundTripper{bearer, rt}
|
passwordFile string
|
||||||
|
rt http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
|
||||||
|
// already been set.
|
||||||
|
func NewBasicAuthRoundTripper(username string, password Secret, passwordFile string, rt http.RoundTripper) http.RoundTripper {
|
||||||
|
return &basicAuthRoundTripper{username, password, passwordFile, rt}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
if len(req.Header.Get("Authorization")) != 0 {
|
if len(req.Header.Get("Authorization")) != 0 {
|
||||||
return rt.RoundTrip(req)
|
return rt.rt.RoundTrip(req)
|
||||||
}
|
}
|
||||||
req = cloneRequest(req)
|
req = cloneRequest(req)
|
||||||
req.SetBasicAuth(rt.username, string(rt.password))
|
if rt.passwordFile != "" {
|
||||||
|
bs, err := ioutil.ReadFile(rt.passwordFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to read basic auth password file %s: %s", rt.passwordFile, err)
|
||||||
|
}
|
||||||
|
req.SetBasicAuth(rt.username, strings.TrimSpace(string(bs)))
|
||||||
|
} else {
|
||||||
|
req.SetBasicAuth(rt.username, strings.TrimSpace(string(rt.password)))
|
||||||
|
}
|
||||||
return rt.rt.RoundTrip(req)
|
return rt.rt.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +269,7 @@ func cloneRequest(r *http.Request) *http.Request {
|
||||||
return r2
|
return r2
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTLSConfig creates a new tls.Config from the given config.TLSConfig.
|
// NewTLSConfig creates a new tls.Config from the given TLSConfig.
|
||||||
func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
|
func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
|
||||||
tlsConfig := &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify}
|
tlsConfig := &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify}
|
||||||
|
|
||||||
|
@ -228,7 +289,6 @@ func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
|
||||||
if len(cfg.ServerName) > 0 {
|
if len(cfg.ServerName) > 0 {
|
||||||
tlsConfig.ServerName = cfg.ServerName
|
tlsConfig.ServerName = cfg.ServerName
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a client cert & key is provided then configure TLS config accordingly.
|
// If a client cert & key is provided then configure TLS config accordingly.
|
||||||
if len(cfg.CertFile) > 0 && len(cfg.KeyFile) == 0 {
|
if len(cfg.CertFile) > 0 && len(cfg.KeyFile) == 0 {
|
||||||
return nil, fmt.Errorf("client cert file %q specified without client key file", cfg.CertFile)
|
return nil, fmt.Errorf("client cert file %q specified without client key file", cfg.CertFile)
|
||||||
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -772,10 +772,10 @@
|
||||||
"revisionTime": "2015-02-12T10:17:44Z"
|
"revisionTime": "2015-02-12T10:17:44Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "i+0TxE6bOpJdPNOeNHpO0vMzFh4=",
|
"checksumSHA1": "bgmAaHIDapEUVLIWaqpxG9t4mYQ=",
|
||||||
"path": "github.com/prometheus/common/config",
|
"path": "github.com/prometheus/common/config",
|
||||||
"revision": "38c53a9f4bfcd932d1b00bfc65e256a7fba6b37a",
|
"revision": "e5b036cc37a466a0af27d604d1ee500211d16d6a",
|
||||||
"revisionTime": "2018-03-26T16:04:09Z"
|
"revisionTime": "2018-04-23T14:05:01Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "+wZ+Pa6NX+NOxUvayXBXGOcqFe8=",
|
"checksumSHA1": "+wZ+Pa6NX+NOxUvayXBXGOcqFe8=",
|
||||||
|
|
Loading…
Reference in a new issue