Skip to content

Commit 75dc05e

Browse files
authored
Add support for aws-sdk-go-v2 authentication (#202)
1 parent 3785da9 commit 75dc05e

File tree

12 files changed

+746
-2
lines changed

12 files changed

+746
-2
lines changed

go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ toolchain go1.23.6
77
require (
88
github.com/aws/aws-sdk-go v1.55.6
99
github.com/aws/aws-sdk-go-v2 v1.36.1
10+
github.com/aws/aws-sdk-go-v2/config v1.29.4
11+
github.com/aws/aws-sdk-go-v2/credentials v1.17.57
12+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27
13+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.12
1014
github.com/google/go-cmp v0.6.0
1115
github.com/grafana/grafana-plugin-sdk-go v0.266.0
1216
github.com/grafana/sqlds/v4 v4.1.7
@@ -18,6 +22,13 @@ require (
1822
require (
1923
github.com/BurntSushi/toml v1.4.0 // indirect
2024
github.com/apache/arrow-go/v18 v18.0.1-0.20241212180703-82be143d7c30 // indirect
25+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 // indirect
26+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 // indirect
27+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
28+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
29+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 // indirect
30+
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 // indirect
31+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 // indirect
2132
github.com/aws/smithy-go v1.22.2 // indirect
2233
github.com/beorn7/perks v1.0.1 // indirect
2334
github.com/cenkalti/backoff/v4 v4.3.0 // indirect

go.sum

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,28 @@ github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk
1313
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
1414
github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E=
1515
github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
16+
github.com/aws/aws-sdk-go-v2/config v1.29.4 h1:ObNqKsDYFGr2WxnoXKOhCvTlf3HhwtoGgc+KmZ4H5yg=
17+
github.com/aws/aws-sdk-go-v2/config v1.29.4/go.mod h1:j2/AF7j/qxVmsNIChw1tWfsVKOayJoGRDjg1Tgq7NPk=
18+
github.com/aws/aws-sdk-go-v2/credentials v1.17.57 h1:kFQDsbdBAR3GZsB8xA+51ptEnq9TIj3tS4MuP5b+TcQ=
19+
github.com/aws/aws-sdk-go-v2/credentials v1.17.57/go.mod h1:2kerxPUUbTagAr/kkaHiqvj/bcYHzi2qiJS/ZinllU0=
20+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 h1:7lOW8NUwE9UZekS1DYoiPdVAqZ6A+LheHWb+mHbNOq8=
21+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27/go.mod h1:w1BASFIPOPUae7AgaH4SbjNbfdkxuggLyGfNFTn8ITY=
22+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 h1:lWm9ucLSRFiI4dQQafLrEOmEDGry3Swrz0BIRdiHJqQ=
23+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31/go.mod h1:Huu6GG0YTfbPphQkDSo4dEGmQRTKb9k9G7RdtyQWxuI=
24+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 h1:ACxDklUKKXb48+eg5ROZXi1vDgfMyfIA/WyvqHcHI0o=
25+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31/go.mod h1:yadnfsDwqXeVaohbGc/RaD287PuyRw2wugkh5ZL2J6k=
26+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk=
27+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
28+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA=
29+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY=
30+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 h1:O+8vD2rGjfihBewr5bT+QUfYUHIxCVgG61LHoT59shM=
31+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12/go.mod h1:usVdWJaosa66NMvmCrr08NcWDBRv4E6+YFG2pUdw1Lk=
32+
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 h1:c5WJ3iHz7rLIgArznb3JCSQT3uUMiz9DLZhIX+1G8ok=
33+
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14/go.mod h1:+JJQTxB6N4niArC14YNtxcQtwEqzS3o9Z32n7q33Rfs=
34+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 h1:f1L/JtUkVODD+k1+IiSJUUv8A++2qVr+Xvb3xWXETMU=
35+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13/go.mod h1:tvqlFoja8/s0o+UruA1Nrezo/df0PzdunMDDurUfg6U=
36+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.12 h1:fqg6c1KVrc3SYWma/egWue5rKI4G2+M4wMQN2JosNAA=
37+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.12/go.mod h1:7Yn+p66q/jt38qMoVfNvjbm3D89mGBnkwDcijgtih8w=
1638
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
1739
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
1840
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=

pkg/awsauth/api_client.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package awsauth
2+
3+
import (
4+
"context"
5+
"github.com/aws/aws-sdk-go-v2/aws"
6+
"github.com/aws/aws-sdk-go-v2/config"
7+
"github.com/aws/aws-sdk-go-v2/credentials"
8+
"github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds"
9+
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
10+
"github.com/aws/aws-sdk-go-v2/service/sts"
11+
)
12+
13+
type LoadOptionsFunc = func(*config.LoadOptions) error
14+
15+
// AWSAPIClient isolates most of our interactions with the AWS SDK to make it easier to mock in tests
16+
type AWSAPIClient interface {
17+
LoadDefaultConfig(ctx context.Context, options ...LoadOptionsFunc) (aws.Config, error)
18+
NewStaticCredentialsProvider(key, secret, session string) aws.CredentialsProvider
19+
NewSTSClientFromConfig(cfg aws.Config) stscreds.AssumeRoleAPIClient
20+
NewAssumeRoleProvider(client stscreds.AssumeRoleAPIClient, roleARN string, optFns ...func(*stscreds.AssumeRoleOptions)) aws.CredentialsProvider
21+
NewCredentialsCache(provider aws.CredentialsProvider, optFns ...func(options *aws.CredentialsCacheOptions)) aws.CredentialsProvider
22+
NewEC2RoleCreds() aws.CredentialsProvider
23+
}
24+
25+
type awsAPIClient struct{}
26+
27+
func (c awsAPIClient) NewStaticCredentialsProvider(key, secret, session string) aws.CredentialsProvider {
28+
return credentials.NewStaticCredentialsProvider(key, secret, session)
29+
}
30+
func (c awsAPIClient) LoadDefaultConfig(ctx context.Context, options ...LoadOptionsFunc) (aws.Config, error) {
31+
return config.LoadDefaultConfig(ctx, options...)
32+
}
33+
func (c awsAPIClient) NewSTSClientFromConfig(cfg aws.Config) stscreds.AssumeRoleAPIClient {
34+
return sts.NewFromConfig(cfg)
35+
}
36+
37+
func (c awsAPIClient) NewAssumeRoleProvider(client stscreds.AssumeRoleAPIClient, roleARN string, optFns ...func(*stscreds.AssumeRoleOptions)) aws.CredentialsProvider {
38+
return stscreds.NewAssumeRoleProvider(client, roleARN, optFns...)
39+
}
40+
41+
func (c awsAPIClient) NewCredentialsCache(provider aws.CredentialsProvider, optFns ...func(options *aws.CredentialsCacheOptions)) aws.CredentialsProvider {
42+
return aws.NewCredentialsCache(provider, optFns...)
43+
}
44+
func (c awsAPIClient) NewEC2RoleCreds() aws.CredentialsProvider {
45+
return ec2rolecreds.New()
46+
}

pkg/awsauth/auth.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package awsauth
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/aws/aws-sdk-go-v2/aws"
7+
"github.com/grafana/grafana-plugin-sdk-go/backend"
8+
)
9+
10+
type ConfigProvider interface {
11+
GetConfig(context.Context, Settings) (aws.Config, error)
12+
}
13+
14+
func NewConfigProvider() ConfigProvider {
15+
return newAWSConfigProviderWithClient(awsAPIClient{})
16+
}
17+
18+
func newAWSConfigProviderWithClient(client AWSAPIClient) *awsConfigProvider {
19+
return &awsConfigProvider{client, make(map[uint64]aws.Config)}
20+
}
21+
22+
type awsConfigProvider struct {
23+
client AWSAPIClient
24+
cache map[uint64]aws.Config
25+
}
26+
27+
func (rcp *awsConfigProvider) GetConfig(ctx context.Context, authSettings Settings) (aws.Config, error) {
28+
logger := backend.Logger.FromContext(ctx)
29+
30+
key := authSettings.Hash()
31+
cached, exists := rcp.cache[key]
32+
if exists {
33+
logger.Debug("returning config from cache")
34+
return cached, nil
35+
}
36+
logger.Debug("creating new config")
37+
38+
options := authSettings.BaseOptions()
39+
40+
authType := authSettings.GetAuthType()
41+
logger.Debug(fmt.Sprintf("Using auth type: %s", authType))
42+
switch authType {
43+
case AuthTypeDefault: // nothing else to do here
44+
case AuthTypeKeys:
45+
options = append(options, authSettings.WithStaticCredentials(rcp.client))
46+
case AuthTypeSharedCreds, AuthTypeGrafanaAssumeRole:
47+
options = append(options, authSettings.WithSharedCredentials())
48+
case AuthTypeEC2IAMRole:
49+
// TODO: test this
50+
options = append(options, authSettings.WithEC2RoleCredentials(rcp.client))
51+
default:
52+
return aws.Config{}, fmt.Errorf("unknown auth type: %s", authType)
53+
}
54+
55+
cfg, err := rcp.client.LoadDefaultConfig(ctx, options...)
56+
if err != nil {
57+
return aws.Config{}, err
58+
}
59+
60+
if authSettings.AssumeRoleARN != "" {
61+
options = append(authSettings.BaseOptions(), authSettings.WithAssumeRole(cfg, rcp.client))
62+
cfg, err = rcp.client.LoadDefaultConfig(ctx, options...)
63+
if err != nil {
64+
return aws.Config{}, err
65+
}
66+
}
67+
68+
_, err = cfg.Credentials.Retrieve(ctx)
69+
if err != nil {
70+
return aws.Config{}, fmt.Errorf("error retrieving credentials: %w", err)
71+
}
72+
73+
rcp.cache[key] = cfg
74+
return cfg, nil
75+
}

0 commit comments

Comments
 (0)