Merge pull request #3709 from krasi-georgiev/bearer-token

read bearer token on every request + some http and scrape tests
pull/3766/head
Frederic Branczyk 2018-01-30 18:17:54 +01:00 committed by GitHub
commit af547ce862
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 29 deletions

View File

@ -56,8 +56,6 @@ type ScrapeManager struct {
// Run starts background processing to handle target updates and reload the scraping loops. // Run starts background processing to handle target updates and reload the scraping loops.
func (m *ScrapeManager) Run(tsets <-chan map[string][]*targetgroup.Group) error { func (m *ScrapeManager) Run(tsets <-chan map[string][]*targetgroup.Group) error {
level.Info(m.logger).Log("msg", "Starting scrape manager...")
for { for {
select { select {
case ts := <-tsets: case ts := <-tsets:

View File

@ -17,9 +17,11 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
"time"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
) )
@ -230,3 +232,44 @@ func TestPopulateLabels(t *testing.T) {
} }
} }
} }
// TestScrapeManagerReloadNoChange tests that no scrape reload happens when there is no config change.
func TestManagerReloadNoChange(t *testing.T) {
tsetName := "test"
reloadCfg := &config.Config{
ScrapeConfigs: []*config.ScrapeConfig{
&config.ScrapeConfig{
ScrapeInterval: model.Duration(3 * time.Second),
ScrapeTimeout: model.Duration(2 * time.Second),
},
},
}
scrapeManager := NewScrapeManager(nil, nil)
scrapeManager.scrapeConfigs[tsetName] = reloadCfg.ScrapeConfigs[0]
// As reload never happens, new loop should never be called.
newLoop := func(_ *Target, s scraper) loop {
t.Fatal("reload happened")
return nil
}
sp := &scrapePool{
appendable: &nopAppendable{},
targets: map[uint64]*Target{},
loops: map[uint64]loop{
1: &scrapeLoop{},
},
newLoop: newLoop,
logger: nil,
config: reloadCfg.ScrapeConfigs[0],
}
scrapeManager.scrapePools = map[string]*scrapePool{
tsetName: sp,
}
targets := map[string][]*targetgroup.Group{
tsetName: []*targetgroup.Group{},
}
scrapeManager.reload(targets)
}

View File

@ -699,7 +699,7 @@ func TestScrapeLoopAppendSampleLimit(t *testing.T) {
} }
value := metric.GetCounter().GetValue() value := metric.GetCounter().GetValue()
if (value - beforeMetricValue) != 1 { if (value - beforeMetricValue) != 1 {
t.Fatal("Unexpected change of sample limit metric: %f", (value - beforeMetricValue)) t.Fatalf("Unexpected change of sample limit metric: %f", (value - beforeMetricValue))
} }
// And verify that we got the samples that fit under the limit. // And verify that we got the samples that fit under the limit.

View File

@ -58,17 +58,10 @@ func NewClientFromConfig(cfg config_util.HTTPClientConfig, name string) (*http.C
// 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 := string(cfg.BearerToken) if len(cfg.BearerToken) > 0 {
if len(bearerToken) == 0 && len(cfg.BearerTokenFile) > 0 { rt = NewBearerAuthRoundTripper(string(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 = strings.TrimSpace(string(b))
}
if len(bearerToken) > 0 {
rt = NewBearerAuthRoundTripper(bearerToken, rt)
} }
if cfg.BasicAuth != nil { if cfg.BasicAuth != nil {
@ -99,6 +92,32 @@ func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response,
return rt.rt.RoundTrip(req) 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 { type basicAuthRoundTripper struct {
username string username string
password string password string

View File

@ -218,17 +218,6 @@ func TestNewClientFromInvalidConfig(t *testing.T) {
InsecureSkipVerify: true}, InsecureSkipVerify: true},
}, },
errorMsg: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA), errorMsg: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA),
}, {
clientConfig: config_util.HTTPClientConfig{
BearerTokenFile: MissingBearerTokenFile,
TLSConfig: config_util.TLSConfig{
CAFile: TLSCAChainPath,
CertFile: BarneyCertificatePath,
KeyFile: BarneyKeyNoPassPath,
ServerName: "",
InsecureSkipVerify: false},
},
errorMsg: fmt.Sprintf("unable to read bearer token file %s:", MissingBearerTokenFile),
}, },
} }
@ -246,6 +235,47 @@ func TestNewClientFromInvalidConfig(t *testing.T) {
} }
} }
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) { func TestBearerAuthRoundTripper(t *testing.T) {
const ( const (
newBearerToken = "goodbyeandthankyouforthefish" newBearerToken = "goodbyeandthankyouforthefish"
@ -259,19 +289,45 @@ func TestBearerAuthRoundTripper(t *testing.T) {
} }
}, nil, nil) }, nil, nil)
//Normal flow // Normal flow.
bearerAuthRoundTripper := NewBearerAuthRoundTripper(BearerToken, fakeRoundTripper) bearerAuthRoundTripper := NewBearerAuthRoundTripper(BearerToken, fakeRoundTripper)
request, _ := http.NewRequest("GET", "/hitchhiker", nil) request, _ := http.NewRequest("GET", "/hitchhiker", nil)
request.Header.Set("User-Agent", "Douglas Adams mind") request.Header.Set("User-Agent", "Douglas Adams mind")
bearerAuthRoundTripper.RoundTrip(request) bearerAuthRoundTripper.RoundTrip(request)
//Should honor already Authorization header set // Should honor already Authorization header set.
bearerAuthRoundTripperShouldNotModifyExistingAuthorization := NewBearerAuthRoundTripper(newBearerToken, fakeRoundTripper) bearerAuthRoundTripperShouldNotModifyExistingAuthorization := NewBearerAuthRoundTripper(newBearerToken, fakeRoundTripper)
request, _ = http.NewRequest("GET", "/hitchhiker", nil) request, _ = http.NewRequest("GET", "/hitchhiker", nil)
request.Header.Set("Authorization", ExpectedBearer) request.Header.Set("Authorization", ExpectedBearer)
bearerAuthRoundTripperShouldNotModifyExistingAuthorization.RoundTrip(request) 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) { func TestBasicAuthRoundTripper(t *testing.T) {
const ( const (
newUsername = "fordprefect" newUsername = "fordprefect"
@ -291,14 +347,14 @@ func TestBasicAuthRoundTripper(t *testing.T) {
} }
}, nil, nil) }, nil, nil)
//Normal flow // Normal flow.
basicAuthRoundTripper := NewBasicAuthRoundTripper(ExpectedUsername, basicAuthRoundTripper := NewBasicAuthRoundTripper(ExpectedUsername,
ExpectedPassword, fakeRoundTripper) ExpectedPassword, fakeRoundTripper)
request, _ := http.NewRequest("GET", "/hitchhiker", nil) request, _ := http.NewRequest("GET", "/hitchhiker", nil)
request.Header.Set("User-Agent", "Douglas Adams mind") request.Header.Set("User-Agent", "Douglas Adams mind")
basicAuthRoundTripper.RoundTrip(request) basicAuthRoundTripper.RoundTrip(request)
//Should honor already Authorization header set // Should honor already Authorization header set.
basicAuthRoundTripperShouldNotModifyExistingAuthorization := NewBasicAuthRoundTripper(newUsername, basicAuthRoundTripperShouldNotModifyExistingAuthorization := NewBasicAuthRoundTripper(newUsername,
newPassword, fakeRoundTripper) newPassword, fakeRoundTripper)
request, _ = http.NewRequest("GET", "/hitchhiker", nil) request, _ = http.NewRequest("GET", "/hitchhiker", nil)