mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Fix Azure authentication support (#44407)
Re-adding back Azure authentication support to Prometheus datasource after the datasource query logic was rewritten from plugin.json routes to Go backend. Ref #35857
This commit is contained in:
parent
6d931226d8
commit
85ea1a5d64
@ -4,8 +4,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/middleware"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/middleware"
|
||||||
|
"github.com/grafana/grafana/pkg/util/maputil"
|
||||||
|
|
||||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||||
@ -16,30 +16,28 @@ import (
|
|||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
settings backend.DataSourceInstanceSettings
|
settings backend.DataSourceInstanceSettings
|
||||||
jsonData JsonData
|
jsonData map[string]interface{}
|
||||||
|
httpMethod string
|
||||||
clientProvider httpclient.Provider
|
clientProvider httpclient.Provider
|
||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProvider(
|
func NewProvider(
|
||||||
settings backend.DataSourceInstanceSettings,
|
settings backend.DataSourceInstanceSettings,
|
||||||
jsonData JsonData,
|
jsonData map[string]interface{},
|
||||||
clientProvider httpclient.Provider,
|
clientProvider httpclient.Provider,
|
||||||
log log.Logger,
|
log log.Logger,
|
||||||
) *Provider {
|
) *Provider {
|
||||||
|
httpMethod, _ := maputil.GetStringOptional(jsonData, "httpMethod")
|
||||||
return &Provider{
|
return &Provider{
|
||||||
settings: settings,
|
settings: settings,
|
||||||
jsonData: jsonData,
|
jsonData: jsonData,
|
||||||
|
httpMethod: httpMethod,
|
||||||
clientProvider: clientProvider,
|
clientProvider: clientProvider,
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonData struct {
|
|
||||||
Method string `json:"httpMethod"`
|
|
||||||
TimeInterval string `json:"timeInterval"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) GetClient(headers map[string]string) (apiv1.API, error) {
|
func (p *Provider) GetClient(headers map[string]string) (apiv1.API, error) {
|
||||||
opts, err := p.settings.HTTPClientOptions()
|
opts, err := p.settings.HTTPClientOptions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,6 +52,12 @@ func (p *Provider) GetClient(headers map[string]string) (apiv1.API, error) {
|
|||||||
opts.SigV4.Service = "aps"
|
opts.SigV4.Service = "aps"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Azure authentication
|
||||||
|
err = p.configureAzureAuthentication(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
roundTripper, err := p.clientProvider.GetTransport(opts)
|
roundTripper, err := p.clientProvider.GetTransport(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -77,7 +81,7 @@ func (p *Provider) middlewares() []sdkhttpclient.Middleware {
|
|||||||
middleware.CustomQueryParameters(p.log),
|
middleware.CustomQueryParameters(p.log),
|
||||||
sdkhttpclient.CustomHeadersMiddleware(),
|
sdkhttpclient.CustomHeadersMiddleware(),
|
||||||
}
|
}
|
||||||
if strings.ToLower(p.jsonData.Method) == "get" {
|
if strings.ToLower(p.httpMethod) == "get" {
|
||||||
middlewares = append(middlewares, middleware.ForceHttpGet(p.log))
|
middlewares = append(middlewares, middleware.ForceHttpGet(p.log))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
pkg/tsdb/prometheus/promclient/provider_azure.go
Normal file
32
pkg/tsdb/prometheus/promclient/provider_azure.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package promclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||||
|
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/azcredentials"
|
||||||
|
"github.com/grafana/grafana/pkg/util/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Provider) configureAzureAuthentication(opts sdkhttpclient.Options) error {
|
||||||
|
credentials, err := azcredentials.FromDatasourceData(p.jsonData, p.settings.DecryptedSecureJSONData)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("invalid Azure credentials: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if credentials != nil {
|
||||||
|
opts.CustomOptions["_azureCredentials"] = credentials
|
||||||
|
|
||||||
|
resourceId, err := maputil.GetStringOptional(p.jsonData, "azureEndpointResourceId")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resourceId != "" {
|
||||||
|
opts.CustomOptions["azureEndpointResourceId"] = resourceId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -135,7 +135,7 @@ func setup(jsonData ...string) *testContext {
|
|||||||
rawData = []byte(jsonData[0])
|
rawData = []byte(jsonData[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var jd promclient.JsonData
|
var jd map[string]interface{}
|
||||||
_ = json.Unmarshal(rawData, &jd)
|
_ = json.Unmarshal(rawData, &jd)
|
||||||
|
|
||||||
settings := backend.DataSourceInstanceSettings{URL: "test-url", JSONData: rawData}
|
settings := backend.DataSourceInstanceSettings{URL: "test-url", JSONData: rawData}
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||||
|
"github.com/grafana/grafana/pkg/util/maputil"
|
||||||
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Trace
|
|||||||
|
|
||||||
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
|
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
|
||||||
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||||
var jsonData promclient.JsonData
|
var jsonData map[string]interface{}
|
||||||
err := json.Unmarshal(settings.JSONData, &jsonData)
|
err := json.Unmarshal(settings.JSONData, &jsonData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading settings: %w", err)
|
return nil, fmt.Errorf("error reading settings: %w", err)
|
||||||
@ -54,10 +55,15 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timeInterval, err := maputil.GetStringOptional(jsonData, "timeInterval")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
mdl := DatasourceInfo{
|
mdl := DatasourceInfo{
|
||||||
ID: settings.ID,
|
ID: settings.ID,
|
||||||
URL: settings.URL,
|
URL: settings.URL,
|
||||||
TimeInterval: jsonData.TimeInterval,
|
TimeInterval: timeInterval,
|
||||||
getClient: pc.GetClient,
|
getClient: pc.GetClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
pkg/util/maputil/maputil.go
Normal file
73
pkg/util/maputil/maputil.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package maputil
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func GetMap(obj map[string]interface{}, key string) (map[string]interface{}, error) {
|
||||||
|
if untypedValue, ok := obj[key]; ok {
|
||||||
|
if value, ok := untypedValue.(map[string]interface{}); ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be an object", key)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be set", key)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBool(obj map[string]interface{}, key string) (bool, error) {
|
||||||
|
if untypedValue, ok := obj[key]; ok {
|
||||||
|
if value, ok := untypedValue.(bool); ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be a bool", key)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be set", key)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBoolOptional(obj map[string]interface{}, key string) (bool, error) {
|
||||||
|
if untypedValue, ok := obj[key]; ok {
|
||||||
|
if value, ok := untypedValue.(bool); ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be a bool", key)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Value optional, not error
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetString(obj map[string]interface{}, key string) (string, error) {
|
||||||
|
if untypedValue, ok := obj[key]; ok {
|
||||||
|
if value, ok := untypedValue.(string); ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be a string", key)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be set", key)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStringOptional(obj map[string]interface{}, key string) (string, error) {
|
||||||
|
if untypedValue, ok := obj[key]; ok {
|
||||||
|
if value, ok := untypedValue.(string); ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("the field '%s' should be a string", key)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Value optional, not error
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user