Skip to content

Commit

Permalink
Allow provider to use the external ID when assuming the role in the p… (
Browse files Browse the repository at this point in the history
#357)

* Allow provider to use the external ID when assuming the role in the provider configuration set up

* Update the provider documentation

* copy pasta no good

---------

Co-authored-by: mannai2 <[email protected]>
  • Loading branch information
9rnt and hm-aircall authored Jul 24, 2023
1 parent c4ba861 commit 70e28e0
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 6 deletions.
7 changes: 5 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ The following arguments are supported:
* `username` (Optional) - Username to use to connect to elasticsearch using basic auth. Defaults to `ELASTICSEARCH_USERNAME` from the environment
* `password` (Optional) - Password to use to connect to elasticsearch using basic auth. Defaults to `ELASTICSEARCH_PASSWORD` from the environment
* `aws_assume_role_arn` (Optional) - ARN of role to assume when using AWS Elasticsearch Service domains.
* `aws_assume_role_external_id` (Optional) - External ID configured in the IAM policy of the IAM Role to assume prior to using AWS Elasticsearch Service domains.
* `aws_assume_role_session_name` - AWS IAM session name to use when assuming a role.
* `aws_access_key` (Optional) - The access key for use with AWS Elasticsearch Service domains. It can also be sourced from the `AWS_ACCESS_KEY_ID` environment variable.
* `aws_secret_key` (Optional) - The secret key for use with AWS Elasticsearch Service domains. It can also be sourced from the `AWS_SECRET_ACCESS_KEY` environment variable.
Expand Down Expand Up @@ -109,13 +110,15 @@ provider "elasticsearch" {
#### Assume role configuration

You can instruct the provider to assume a role in AWS before interacting with the cluster by setting the `aws_assume_role_arn` variable.
Optionnaly, you can configure the [External ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) of IAM role trust policy by setting the `aws_assume_role_external_id` variable.

Example usage:

```tf
provider "elasticsearch" {
url = "https://search-foo-bar-pqrhr4w3u4dzervg41frow4mmy.us-east-1.es.amazonaws.com"
aws_assume_role_arn = "arn:aws:iam::012345678901:role/rolename"
url = "https://search-foo-bar-pqrhr4w3u4dzervg41frow4mmy.us-east-1.es.amazonaws.com"
aws_assume_role_arn = "arn:aws:iam::012345678901:role/rolename"
aws_assume_role_external_id = "Unique ID"
}
```

Expand Down
17 changes: 15 additions & 2 deletions es/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type ProviderConf struct {
pingTimeoutSeconds int
awsRegion string
awsAssumeRoleArn string
awsAssumeRoleExternalID string
awsAssumeRoleSessionName string
awsAccessKeyId string
awsSecretAccessKey string
Expand Down Expand Up @@ -128,6 +129,12 @@ func Provider() *schema.Provider {
Default: "",
Description: "Amazon Resource Name of an IAM Role to assume prior to making AWS API calls.",
},
"aws_assume_role_external_id": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "External ID configured in the IAM policy of the IAM Role to assume prior to making AWS API calls.",
},
"aws_assume_role_session_name": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -299,6 +306,7 @@ func providerConfigure(c context.Context, d *schema.ResourceData) (interface{},
awsRegion: d.Get("aws_region").(string),

awsAssumeRoleArn: d.Get("aws_assume_role_arn").(string),
awsAssumeRoleExternalID: d.Get("aws_assume_role_external_id").(string),
awsAssumeRoleSessionName: d.Get("aws_assume_role_session_name").(string),
awsAccessKeyId: d.Get("aws_access_key").(string),
awsSecretAccessKey: d.Get("aws_secret_key").(string),
Expand Down Expand Up @@ -553,7 +561,7 @@ func getKibanaClient(conf *ProviderConf) (interface{}, error) {
}
}

func assumeRoleCredentials(region, roleARN, roleSessionName, profile string) *awscredentials.Credentials {
func assumeRoleCredentials(region, roleARN, roleExternalID, roleSessionName, profile string) *awscredentials.Credentials {
sessOpts := awsSessionOptions(region)
sessOpts.Profile = profile

Expand All @@ -563,6 +571,7 @@ func assumeRoleCredentials(region, roleARN, roleSessionName, profile string) *aw
Client: stsClient,
RoleARN: roleARN,
RoleSessionName: roleSessionName,
ExternalID: aws.String(roleExternalID),
}

return awscredentials.NewChainCredentials([]awscredentials.Provider{assumeRoleProvider})
Expand Down Expand Up @@ -593,14 +602,18 @@ func awsSession(region string, conf *ProviderConf) *awssession.Session {

// 1. access keys take priority
// 2. next is an assume role configuration
// 2.b check if the role external ID is set and use it
// 3. followed by a profile (for assume role)
// 4. let the default credentials provider figure out the rest (env, ec2, etc..)
//
// note: if #1 is chosen, then no further providers will be tested, since we've overridden the credentials with just a static provider
if conf.awsAccessKeyId != "" {
sessOpts.Config.Credentials = awscredentials.NewStaticCredentials(conf.awsAccessKeyId, conf.awsSecretAccessKey, conf.awsSessionToken)
} else if conf.awsAssumeRoleArn != "" {
sessOpts.Config.Credentials = assumeRoleCredentials(region, conf.awsAssumeRoleArn, conf.awsAssumeRoleSessionName, conf.awsProfile)
if conf.awsAssumeRoleExternalID == "" {
conf.awsAssumeRoleExternalID = ""
}
sessOpts.Config.Credentials = assumeRoleCredentials(region, conf.awsAssumeRoleArn, conf.awsAssumeRoleExternalID, conf.awsAssumeRoleSessionName, conf.awsProfile)
} else if conf.awsProfile != "" {
sessOpts.Profile = conf.awsProfile
}
Expand Down
6 changes: 4 additions & 2 deletions es/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,15 @@ func TestAWSCredsAssumeRole(t *testing.T) {
testRegion := "us-east-1"

testConfig := map[string]interface{}{
"aws_assume_role_arn": "test_arn",
"aws_assume_role_arn": "test_arn",
"aws_assume_role_external_id": "secret_id",
}

testConfigData := schema.TestResourceDataRaw(t, Provider().Schema, testConfig)

conf := &ProviderConf{
awsAssumeRoleArn: testConfigData.Get("aws_assume_role_arn").(string),
awsAssumeRoleArn: testConfigData.Get("aws_assume_role_arn").(string),
awsAssumeRoleExternalID: testConfigData.Get("aws_assume_role_external_id").(string),
}
s := awsSession(testRegion, conf)
if s == nil {
Expand Down

0 comments on commit 70e28e0

Please sign in to comment.