diff --git a/README.md b/README.md index db1591d7..7f5caade 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ instances: instance: rds-mysql57 aws_access_key: AKIAIOSFODNN7EXAMPLE aws_secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + aws_role_arn: arn:aws:iam::76784568345:role/my-role disable_basic_metrics: true disable_enhanced_metrics: false labels: @@ -31,7 +32,7 @@ instances: baz: qux ``` -If `aws_access_key` and `aws_secret_key` are present, they are used for that instance. +If `aws_role_arn` is present it will assume role otherwise if `aws_access_key` and `aws_secret_key` are present, they are used for that instance. Otherwise, [default credential provider chain](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials) is used, which includes `AWS_ACCESS_KEY_ID`/`AWS_ACCESS_KEY` and `AWS_SECRET_ACCESS_KEY`/`AWS_SECRET_KEY` environment variables, `~/.aws/credentials` file, and IAM role for EC2. diff --git a/config/config.go b/config/config.go index 2948ca31..538732a7 100644 --- a/config/config.go +++ b/config/config.go @@ -22,6 +22,7 @@ type Instance struct { Instance string `yaml:"instance"` AWSAccessKey string `yaml:"aws_access_key"` // may be empty AWSSecretKey string `yaml:"aws_secret_key"` // may be empty + AWSRoleArn string `yaml:"aws_role_arn"` // may be empty DisableBasicMetrics bool `yaml:"disable_basic_metrics"` DisableEnhancedMetrics bool `yaml:"disable_enhanced_metrics"` Labels map[string]string `yaml:"labels"` // may be empty diff --git a/sessions/sessions.go b/sessions/sessions.go index cf49e8c0..8c321b85 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/credentials/stscreds" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/rds" "github.com/prometheus/common/log" @@ -65,13 +66,11 @@ func New(instances []config.Instance, client *http.Client, trace bool) (*Session // use given credentials, or default credential chain var creds *credentials.Credentials - if instance.AWSAccessKey != "" || instance.AWSSecretKey != "" { - creds = credentials.NewCredentials(&credentials.StaticProvider{ - Value: credentials.Value{ - AccessKeyID: instance.AWSAccessKey, - SecretAccessKey: instance.AWSSecretKey, - }, - }) + + creds, err := buildCredentials(instance) + + if err != nil { + return nil, err } // make config with careful logging @@ -180,6 +179,29 @@ func (s *Sessions) GetSession(region, instance string) (*session.Session, *Insta return nil, nil } +func buildCredentials(instance config.Instance) (*credentials.Credentials, error) { + if instance.AWSRoleArn != "" { + stsSession, err := session.NewSession(&aws.Config{ + Region: aws.String(instance.Region), + Credentials: credentials.NewStaticCredentials(instance.AWSAccessKey, instance.AWSSecretKey, ""), + }) + if err != nil { + return nil, err + } + + return stscreds.NewCredentials(stsSession, instance.AWSRoleArn), nil + } + if instance.AWSAccessKey != "" || instance.AWSSecretKey != "" { + return credentials.NewCredentials(&credentials.StaticProvider{ + Value: credentials.Value{ + AccessKeyID: instance.AWSAccessKey, + SecretAccessKey: instance.AWSSecretKey, + }, + }), nil + } + return nil, nil +} + // AllSessions returns all sessions and instances. func (s *Sessions) AllSessions() map[*session.Session][]Instance { return s.sessions