Auth: Add Sigv4 auth option to datasources (#27552)

* create transport chain

* add frontend

* remove log

* inline field updates

* allow ARN, Credentials + Keys auth in frontend

* configure credentials

* add tests and refactor

* update frontend json field names

* fix tests

* fix comment

* add app config flag

* refactor tests

* add return field for tests

* add flag for UI display

* update comment

* move logic

* fix config

* pass config through props

* update docs

* pr feedback and add docs coverage

* shorten settings filename

* fix imports

* revert docs changes

* remove log line

* wrap up next as round tripper

* only propagate required config

* remove unused import

* remove ARN option and replace with default chain

* make ARN role assume as supplemental

* update docs

* refactor flow

* sign body when necessary

* remove unnecessary wrapper

* remove newline

* Apply suggestions from code review

* PR fixes

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Will Browne
2020-10-08 10:03:20 +02:00
committed by GitHub
parent ab33e46789
commit 7d63b2c473
17 changed files with 517 additions and 11 deletions

View File

@@ -69,6 +69,7 @@ type dataSourceTransport struct {
datasourceName string
headers map[string]string
transport *http.Transport
next http.RoundTripper
}
func instrumentRoundtrip(datasourceName string, next http.RoundTripper) promhttp.RoundTripperFunc {
@@ -108,7 +109,7 @@ func (d *dataSourceTransport) RoundTrip(req *http.Request) (*http.Response, erro
req.Header.Set(key, value)
}
return instrumentRoundtrip(d.datasourceName, d.transport).RoundTrip(req)
return instrumentRoundtrip(d.datasourceName, d.next).RoundTrip(req)
}
type cachedTransport struct {
@@ -133,6 +134,7 @@ func (ds *DataSource) GetHttpClient() (*http.Client, error) {
}, nil
}
// Creates a HTTP Transport middleware chain
func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) {
ptc.Lock()
defer ptc.Unlock()
@@ -163,10 +165,19 @@ func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) {
IdleConnTimeout: 90 * time.Second,
}
// Set default next round tripper to the default transport
next := http.RoundTripper(transport)
// Add SigV4 middleware if enabled, which will then defer to the default transport
if ds.JsonData != nil && ds.JsonData.Get("sigV4Auth").MustBool() && setting.SigV4AuthEnabled {
next = ds.sigV4Middleware(transport)
}
dsTransport := &dataSourceTransport{
datasourceName: ds.Name,
headers: customHeaders,
transport: transport,
datasourceName: ds.Name,
next: next,
}
ptc.cache[ds.Id] = cachedTransport{
@@ -177,6 +188,23 @@ func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) {
return dsTransport, nil
}
func (ds *DataSource) sigV4Middleware(next http.RoundTripper) http.RoundTripper {
decrypted := ds.DecryptedValues()
return &SigV4Middleware{
Config: &Config{
AccessKey: decrypted["accessKey"],
SecretKey: decrypted["secretKey"],
Region: ds.JsonData.Get("region").MustString(),
AssumeRoleARN: ds.JsonData.Get("assumeRoleArn").MustString(),
AuthType: ds.JsonData.Get("authType").MustString(),
ExternalID: ds.JsonData.Get("externalId").MustString(),
Profile: ds.JsonData.Get("profile").MustString(),
},
Next: next,
}
}
func (ds *DataSource) GetTLSConfig() (*tls.Config, error) {
var tlsSkipVerify, tlsClientAuth, tlsAuthWithCACert bool
if ds.JsonData != nil {