mirror of
https://github.com/grafana/grafana.git
synced 2025-09-27 08:14:11 +08:00

* 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>
111 lines
2.3 KiB
Go
111 lines
2.3 KiB
Go
package models
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/defaults"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
|
|
)
|
|
|
|
type AuthType string
|
|
|
|
const (
|
|
Default AuthType = "default"
|
|
Keys AuthType = "keys"
|
|
Credentials AuthType = "credentials"
|
|
)
|
|
|
|
type SigV4Middleware struct {
|
|
Config *Config
|
|
Next http.RoundTripper
|
|
}
|
|
|
|
type Config struct {
|
|
AuthType string
|
|
|
|
Profile string
|
|
|
|
AccessKey string
|
|
SecretKey string
|
|
|
|
AssumeRoleARN string
|
|
ExternalID string
|
|
Region string
|
|
}
|
|
|
|
func (m *SigV4Middleware) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
_, err := m.signRequest(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if m.Next == nil {
|
|
return http.DefaultTransport.RoundTrip(req)
|
|
}
|
|
|
|
return m.Next.RoundTrip(req)
|
|
}
|
|
|
|
func (m *SigV4Middleware) signRequest(req *http.Request) (http.Header, error) {
|
|
signer, err := m.signer()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if req.Body != nil {
|
|
// consume entire request body so that the signer can generate a hash from the contents
|
|
body, err := ioutil.ReadAll(req.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return signer.Sign(req, bytes.NewReader(body), "grafana", m.Config.Region, time.Now().UTC())
|
|
}
|
|
return signer.Sign(req, nil, "grafana", m.Config.Region, time.Now().UTC())
|
|
}
|
|
|
|
func (m *SigV4Middleware) signer() (*v4.Signer, error) {
|
|
c, err := m.credentials()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if m.Config.AssumeRoleARN != "" {
|
|
s, err := session.NewSession(&aws.Config{
|
|
Region: aws.String(m.Config.Region),
|
|
Credentials: c},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return v4.NewSigner(stscreds.NewCredentials(s, m.Config.AssumeRoleARN)), nil
|
|
}
|
|
|
|
return v4.NewSigner(c), nil
|
|
}
|
|
|
|
func (m *SigV4Middleware) credentials() (*credentials.Credentials, error) {
|
|
authType := AuthType(m.Config.AuthType)
|
|
|
|
switch authType {
|
|
case Default:
|
|
return defaults.CredChain(defaults.Config(), defaults.Handlers()), nil
|
|
case Keys:
|
|
return credentials.NewStaticCredentials(m.Config.AccessKey, m.Config.SecretKey, ""), nil
|
|
case Credentials:
|
|
return credentials.NewSharedCredentials("", m.Config.Profile), nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("unrecognized authType: %s", authType)
|
|
}
|