mirror of https://github.com/grafana/grafana
Cloudwatch: use shared library for aws auth (#29550)
* use sdk for handling auth * fix broken test * lint fixes Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>pull/31281/head
parent
8404d54277
commit
9dd1d5f553
@ -1,44 +0,0 @@ |
||||
package cloudwatch |
||||
|
||||
import ( |
||||
"sync" |
||||
"time" |
||||
|
||||
"github.com/aws/aws-sdk-go/aws" |
||||
"github.com/aws/aws-sdk-go/aws/credentials" |
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" |
||||
"github.com/aws/aws-sdk-go/aws/credentials/stscreds" |
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata" |
||||
"github.com/aws/aws-sdk-go/aws/session" |
||||
) |
||||
|
||||
type envelope struct { |
||||
session *session.Session |
||||
expiration time.Time |
||||
} |
||||
|
||||
var sessCache = map[string]envelope{} |
||||
var sessCacheLock sync.RWMutex |
||||
|
||||
// Session factory.
|
||||
// Stubbable by tests.
|
||||
//nolint:gocritic
|
||||
var newSession = func(cfgs ...*aws.Config) (*session.Session, error) { |
||||
return session.NewSession(cfgs...) |
||||
} |
||||
|
||||
// STS credentials factory.
|
||||
// Stubbable by tests.
|
||||
//nolint:gocritic
|
||||
var newSTSCredentials = stscreds.NewCredentials |
||||
|
||||
// EC2Metadata service factory.
|
||||
// Stubbable by tests.
|
||||
//nolint:gocritic
|
||||
var newEC2Metadata = ec2metadata.New |
||||
|
||||
// EC2 role credentials factory.
|
||||
// Stubbable by tests.
|
||||
var newEC2RoleCredentials = func(sess *session.Session) *credentials.Credentials { |
||||
return credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: stscreds.DefaultDuration}) |
||||
} |
||||
@ -1,188 +0,0 @@ |
||||
package cloudwatch |
||||
|
||||
import ( |
||||
"reflect" |
||||
"testing" |
||||
|
||||
"github.com/aws/aws-sdk-go/aws" |
||||
"github.com/aws/aws-sdk-go/aws/client" |
||||
"github.com/aws/aws-sdk-go/aws/credentials" |
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" |
||||
"github.com/aws/aws-sdk-go/aws/credentials/stscreds" |
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata" |
||||
"github.com/aws/aws-sdk-go/aws/session" |
||||
"github.com/google/go-cmp/cmp" |
||||
"github.com/google/go-cmp/cmp/cmpopts" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
"github.com/stretchr/testify/assert" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
// Test cloudWatchExecutor.newSession with assumption of IAM role.
|
||||
func TestNewSession_AssumeRole(t *testing.T) { |
||||
origNewSession := newSession |
||||
origNewSTSCredentials := newSTSCredentials |
||||
origNewEC2Metadata := newEC2Metadata |
||||
t.Cleanup(func() { |
||||
newSession = origNewSession |
||||
newSTSCredentials = origNewSTSCredentials |
||||
newEC2Metadata = origNewEC2Metadata |
||||
}) |
||||
newSession = func(cfgs ...*aws.Config) (*session.Session, error) { |
||||
cfg := aws.Config{} |
||||
cfg.MergeIn(cfgs...) |
||||
return &session.Session{ |
||||
Config: &cfg, |
||||
}, nil |
||||
} |
||||
newSTSCredentials = func(c client.ConfigProvider, roleARN string, |
||||
options ...func(*stscreds.AssumeRoleProvider)) *credentials.Credentials { |
||||
p := &stscreds.AssumeRoleProvider{ |
||||
RoleARN: roleARN, |
||||
} |
||||
for _, o := range options { |
||||
o(p) |
||||
} |
||||
|
||||
return credentials.NewCredentials(p) |
||||
} |
||||
newEC2Metadata = func(p client.ConfigProvider, cfgs ...*aws.Config) *ec2metadata.EC2Metadata { |
||||
return nil |
||||
} |
||||
|
||||
duration := stscreds.DefaultDuration |
||||
|
||||
t.Run("Without external ID", func(t *testing.T) { |
||||
t.Cleanup(func() { |
||||
sessCache = map[string]envelope{} |
||||
}) |
||||
|
||||
const roleARN = "test" |
||||
|
||||
e := newExecutor(nil, newTestConfig()) |
||||
e.DataSource = fakeDataSource(fakeDataSourceCfg{ |
||||
assumeRoleARN: roleARN, |
||||
}) |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, sess) |
||||
|
||||
expCreds := credentials.NewCredentials(&stscreds.AssumeRoleProvider{ |
||||
RoleARN: roleARN, |
||||
Duration: duration, |
||||
}) |
||||
diff := cmp.Diff(expCreds, sess.Config.Credentials, cmp.Exporter(func(_ reflect.Type) bool { |
||||
return true |
||||
}), cmpopts.IgnoreFields(stscreds.AssumeRoleProvider{}, "Expiry")) |
||||
assert.Empty(t, diff) |
||||
}) |
||||
|
||||
t.Run("With external ID", func(t *testing.T) { |
||||
t.Cleanup(func() { |
||||
sessCache = map[string]envelope{} |
||||
}) |
||||
|
||||
const roleARN = "test" |
||||
const externalID = "external" |
||||
|
||||
e := newExecutor(nil, newTestConfig()) |
||||
e.DataSource = fakeDataSource(fakeDataSourceCfg{ |
||||
assumeRoleARN: roleARN, |
||||
externalID: externalID, |
||||
}) |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, sess) |
||||
|
||||
expCreds := credentials.NewCredentials(&stscreds.AssumeRoleProvider{ |
||||
RoleARN: roleARN, |
||||
ExternalID: aws.String(externalID), |
||||
Duration: duration, |
||||
}) |
||||
diff := cmp.Diff(expCreds, sess.Config.Credentials, cmp.Exporter(func(_ reflect.Type) bool { |
||||
return true |
||||
}), cmpopts.IgnoreFields(stscreds.AssumeRoleProvider{}, "Expiry")) |
||||
assert.Empty(t, diff) |
||||
}) |
||||
|
||||
t.Run("Assume role not enabled", func(t *testing.T) { |
||||
t.Cleanup(func() { |
||||
sessCache = map[string]envelope{} |
||||
}) |
||||
|
||||
const roleARN = "test" |
||||
|
||||
e := newExecutor(nil, &setting.Cfg{AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: false}) |
||||
e.DataSource = fakeDataSource(fakeDataSourceCfg{ |
||||
assumeRoleARN: roleARN, |
||||
}) |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.Error(t, err) |
||||
require.Nil(t, sess) |
||||
|
||||
expectedError := "attempting to use assume role (ARN) which is disabled in grafana.ini" |
||||
assert.Equal(t, expectedError, err.Error()) |
||||
}) |
||||
} |
||||
|
||||
func TestNewSession_AllowedAuthProviders(t *testing.T) { |
||||
t.Run("Not allowed auth type is used", func(t *testing.T) { |
||||
e := newExecutor(nil, &setting.Cfg{AWSAllowedAuthProviders: []string{"keys"}}) |
||||
e.DataSource = fakeDataSource() |
||||
e.DataSource.JsonData.Set("authType", "default") |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.Error(t, err) |
||||
require.Nil(t, sess) |
||||
|
||||
assert.Equal(t, `attempting to use an auth type that is not allowed: "default"`, err.Error()) |
||||
}) |
||||
|
||||
t.Run("Allowed auth type is used", func(t *testing.T) { |
||||
e := newExecutor(nil, &setting.Cfg{AWSAllowedAuthProviders: []string{"keys"}}) |
||||
e.DataSource = fakeDataSource() |
||||
e.DataSource.JsonData.Set("authType", "keys") |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, sess) |
||||
}) |
||||
} |
||||
|
||||
func TestNewSession_EC2IAMRole(t *testing.T) { |
||||
newSession = func(cfgs ...*aws.Config) (*session.Session, error) { |
||||
cfg := aws.Config{} |
||||
cfg.MergeIn(cfgs...) |
||||
return &session.Session{ |
||||
Config: &cfg, |
||||
}, nil |
||||
} |
||||
newEC2Metadata = func(p client.ConfigProvider, cfgs ...*aws.Config) *ec2metadata.EC2Metadata { |
||||
return nil |
||||
} |
||||
newEC2RoleCredentials = func(sess *session.Session) *credentials.Credentials { |
||||
return credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{Client: newEC2Metadata(nil), ExpiryWindow: stscreds.DefaultDuration}) |
||||
} |
||||
|
||||
t.Run("Credentials are created", func(t *testing.T) { |
||||
e := newExecutor(nil, &setting.Cfg{AWSAllowedAuthProviders: []string{"ec2_iam_role"}, AWSAssumeRoleEnabled: true}) |
||||
e.DataSource = fakeDataSource() |
||||
e.DataSource.JsonData.Set("authType", "ec2_iam_role") |
||||
|
||||
sess, err := e.newSession(defaultRegion) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, sess) |
||||
|
||||
expCreds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{ |
||||
Client: newEC2Metadata(nil), ExpiryWindow: stscreds.DefaultDuration, |
||||
}) |
||||
|
||||
diff := cmp.Diff(expCreds, sess.Config.Credentials, cmp.Exporter(func(_ reflect.Type) bool { |
||||
return true |
||||
}), cmpopts.IgnoreFields(stscreds.AssumeRoleProvider{}, "Expiry")) |
||||
assert.Empty(t, diff) |
||||
}) |
||||
} |
||||
Loading…
Reference in new issue