Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow role_arn work with access keys for AWS #25446

Merged
merged 5 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Fix 'make setup' instructions for a new beat {pull}24944[24944]
- Fix discovery of short-living and failing pods in Kubernetes autodiscover {issue}22718[22718] {pull}24742[24742]
- Fix panic when overwriting metadata {pull}24741[24741]
- Fix role_arn to work with access keys for AWS. {pull}25446[25446]

*Auditbeat*

Expand Down
2 changes: 0 additions & 2 deletions x-pack/libbeat/autodiscover/providers/aws/elb/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ func AutodiscoverBuilder(

// Construct MetricSet with a full regions list if there is no region specified.
if config.Regions == nil {
// set default region to make initial aws api call
awsCfg.Region = "us-west-1"
svcEC2 := ec2.New(awscommon.EnrichAWSConfigWithEndpoint(
config.AWSConfig.Endpoint, "ec2", awsCfg.Region, awsCfg))

Expand Down
72 changes: 48 additions & 24 deletions x-pack/libbeat/common/aws/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,53 @@ type ConfigAWS struct {
}

// GetAWSCredentials function gets aws credentials from the config.
// If access_key_id and secret_access_key are given, then use them as credentials.
// If role_arn is given, assume the IAM role instead.
// If none of the above is given, then load from aws config file. If credential_profile_name is not
// given, then load default profile from the aws config file.
// If access keys given, use them as credentials.
// If access keys are not given, then load from AWS config file. If credential_profile_name is not
// given, default profile will be used.
// If role_arn is given, assume the IAM role either with access keys or default profile.
func GetAWSCredentials(config ConfigAWS) (awssdk.Config, error) {
logger := logp.NewLogger("get_aws_credentials")

// Check if accessKeyID or secretAccessKey or sessionToken is given from configuration
if config.AccessKeyID != "" || config.SecretAccessKey != "" || config.SessionToken != "" {
logger.Debug("Using access_key_id, secret_access_key and/or session_token for AWS credential")
awsConfig := defaults.Config()
awsCredentials := awssdk.Credentials{
AccessKeyID: config.AccessKeyID,
SecretAccessKey: config.SecretAccessKey,
}
return getAccessKeys(config), nil
}
return getSharedCredentialProfile(config)
}

if config.SessionToken != "" {
awsCredentials.SessionToken = config.SessionToken
}
func getAccessKeys(config ConfigAWS) awssdk.Config {
logger := logp.NewLogger("getAccessKeys")
awsConfig := defaults.Config()
awsCredentials := awssdk.Credentials{
AccessKeyID: config.AccessKeyID,
SecretAccessKey: config.SecretAccessKey,
}

awsConfig.Credentials = awssdk.StaticCredentialsProvider{
Value: awsCredentials,
}
return awsConfig, nil
if config.SessionToken != "" {
awsCredentials.SessionToken = config.SessionToken
}

awsConfig.Credentials = awssdk.StaticCredentialsProvider{
Value: awsCredentials,
}

// Set default region to make initial aws api call
awsConfig.Region = "us-east-1"

// Assume IAM role if iam_role config parameter is given
if config.RoleArn != "" {
logger.Debug("Using role arn and access keys for AWS credential")
return getRoleArn(config, awsConfig)
} else {
kaiyan-sheng marked this conversation as resolved.
Show resolved Hide resolved
logger.Debug("Using access keys for AWS credential")
return awsConfig
}
}

func getSharedCredentialProfile(config ConfigAWS) (awssdk.Config, error) {
// If accessKeyID, secretAccessKey or sessionToken is not given, iam_role is not given, then load from default config
// Please see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
// with more details.
// If credential_profile_name is empty, then default profile is used.
logger.Debug("Using shared credential profile for AWS credential")
logger := logp.NewLogger("getSharedCredentialProfile")
var options []external.Config
if config.ProfileName != "" {
options = append(options, external.WithSharedConfigProfile(config.ProfileName))
Expand All @@ -78,16 +94,24 @@ func GetAWSCredentials(config ConfigAWS) (awssdk.Config, error) {
return awsConfig, errors.Wrap(err, "external.LoadDefaultAWSConfig failed with shared credential profile given")
}

if config.RoleArn == "" {
// Set default region to make initial aws api call
awsConfig.Region = "us-east-1"

// Assume IAM role if iam_role config parameter is given
if config.RoleArn != "" {
logger.Debug("Using role arn and shared credential profile for AWS credential")
return getRoleArn(config, awsConfig), nil
} else {
kaiyan-sheng marked this conversation as resolved.
Show resolved Hide resolved
logger.Debug("Using shared credential profile for AWS credential")
return awsConfig, nil
}
}

// Assume IAM role if iam_role config parameter is given
logger.Debug("Using role_arn for AWS credential")
func getRoleArn(config ConfigAWS, awsConfig awssdk.Config) awssdk.Config {
stsSvc := sts.New(awsConfig)
stsCredProvider := stscreds.NewAssumeRoleProvider(stsSvc, config.RoleArn)
awsConfig.Credentials = stsCredProvider
return awsConfig, nil
return awsConfig
}

// EnrichAWSConfigWithEndpoint function enabled endpoint resolver for AWS
Expand Down
15 changes: 5 additions & 10 deletions x-pack/libbeat/docs/aws-credentials-config.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,6 @@ AWS_SECRET_ACCESS_KEY=abcd
$ docker run --env-file env.list -d --name=metricbeat --user=root --volume="$(pwd)/metricbeat.aws.yml:/usr/share/metricbeat/metricbeat.yml:ro" docker.elastic.co/beats/metricbeat:7.11.1 metricbeat -e -E cloud.auth=elastic:1234 -E cloud.id=test-aws:1234
----

* Use `role_arn`

If `access_key_id` and `secret_access_key` are not given, then {beatname_lc} will
check for `role_arn`. `role_arn` is used to specify which AWS IAM role to assume
for generating temporary credentials.

* Use `credential_profile_name` and/or `shared_credential_file`

If `access_key_id`, `secret_access_key` and `role_arn` are all not given, then
Expand All @@ -80,10 +74,11 @@ for more details.

* Use `role_arn`

If `access_key_id` and `secret_access_key`, `credential_profile_name` and/or
`shared_credential_file` are not given, then {beatname_lc} will check for
`role_arn`. `role_arn` is used to specify which AWS IAM role to assume
for generating temporary credentials.
`role_arn` is used to specify which AWS IAM role to assume for generating
temporary credentials. If `role_arn` is given, {beatname_lc} will check if
access keys are given. If not, {beatname_lc} will check for credential profile
name. If neither is given, default credential profile will be used. Please make
sure credentials are given under either a credential profile or access keys.

If running on Docker, the credential file needs to be provided via a volume
mount. For example, with Metricbeat:
Expand Down