mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Merge pull request #1338 from wwadge/add-prometheus-bearer-auth
Allow access to Prometheus in OpenShift via SA token
This commit is contained in:
@@ -184,13 +184,25 @@ as the `MetricTemplate` with the basic-auth credentials:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: prom-basic-auth
|
||||
name: prom-auth
|
||||
namespace: flagger
|
||||
data:
|
||||
username: your-user
|
||||
password: your-password
|
||||
```
|
||||
|
||||
or if you require bearer token authentication (via a SA token):
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: prom-auth
|
||||
namespace: flagger
|
||||
data:
|
||||
token: ey1234...
|
||||
```
|
||||
|
||||
Then reference the secret in the `MetricTemplate`:
|
||||
|
||||
```yaml
|
||||
@@ -204,7 +216,7 @@ spec:
|
||||
type: prometheus
|
||||
address: http://prometheus.monitoring:9090
|
||||
secretRef:
|
||||
name: prom-basic-auth
|
||||
name: prom-auth
|
||||
```
|
||||
|
||||
## Datadog
|
||||
|
||||
@@ -41,6 +41,7 @@ type PrometheusProvider struct {
|
||||
url url.URL
|
||||
username string
|
||||
password string
|
||||
token string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ type prometheusResponse struct {
|
||||
}
|
||||
|
||||
// NewPrometheusProvider takes a provider spec and the credentials map,
|
||||
// validates the address, extracts the username and password values if provided and
|
||||
// validates the address, extracts the bearer token or username and password values if provided and
|
||||
// returns a Prometheus client ready to execute queries against the API
|
||||
func NewPrometheusProvider(provider flaggerv1.MetricTemplateProvider, credentials map[string][]byte) (*PrometheusProvider, error) {
|
||||
promURL, err := url.Parse(provider.Address)
|
||||
@@ -77,16 +78,21 @@ func NewPrometheusProvider(provider flaggerv1.MetricTemplateProvider, credential
|
||||
}
|
||||
|
||||
if provider.SecretRef != nil {
|
||||
if username, ok := credentials["username"]; ok {
|
||||
prom.username = string(username)
|
||||
if token, ok := credentials["token"]; ok {
|
||||
prom.token = string(token)
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s credentials does not contain a username", provider.Type)
|
||||
}
|
||||
|
||||
if password, ok := credentials["password"]; ok {
|
||||
prom.password = string(password)
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s credentials does not contain a password", provider.Type)
|
||||
if username, ok := credentials["username"]; ok {
|
||||
prom.username = string(username)
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s credentials does not contain a username", provider.Type)
|
||||
}
|
||||
|
||||
if password, ok := credentials["password"]; ok {
|
||||
prom.password = string(password)
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s credentials does not contain a password", provider.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +115,9 @@ func (p *PrometheusProvider) RunQuery(query string) (float64, error) {
|
||||
return 0, fmt.Errorf("http.NewRequest failed: %w", err)
|
||||
}
|
||||
|
||||
if p.username != "" && p.password != "" {
|
||||
if p.token != "" {
|
||||
req.Header.Add("Authorization", "Bearer "+p.token)
|
||||
} else if p.username != "" && p.password != "" {
|
||||
req.SetBasicAuth(p.username, p.password)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,19 @@ func prometheusFake() fakeClients {
|
||||
},
|
||||
}
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(secret)
|
||||
bearerTokenSecret := &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "prometheus-bearer",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"token": []byte("bearer_token"),
|
||||
},
|
||||
}
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(secret, bearerTokenSecret)
|
||||
|
||||
return fakeClients{
|
||||
kubeClient: kubeClient,
|
||||
@@ -170,6 +182,42 @@ func TestPrometheusProvider_RunQueryWithBasicAuth(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestPrometheusProvider_RunQueryWithBearerAuth(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
expected := `sum(envoy_cluster_upstream_rq)`
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
promql := r.URL.Query()["query"][0]
|
||||
assert.Equal(t, expected, promql)
|
||||
|
||||
header, ok := r.Header["Authorization"]
|
||||
if assert.True(t, ok, "Authorization header not found") {
|
||||
assert.True(t, strings.Contains(header[0], "Bearer"), "Bearer authorization header not found")
|
||||
}
|
||||
|
||||
json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1545905245.458,"100"]}]}}`
|
||||
w.Write([]byte(json))
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
clients := prometheusFake()
|
||||
|
||||
template, err := clients.flaggerClient.FlaggerV1beta1().MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
template.Spec.Provider.Address = ts.URL
|
||||
|
||||
secret, err := clients.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "prometheus-bearer", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
prom, err := NewPrometheusProvider(template.Spec.Provider, secret.Data)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err := prom.RunQuery(template.Spec.Query)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, float64(100), val)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrometheusProvider_IsOnline(t *testing.T) {
|
||||
t.Run("fail", func(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user