From 70e28e0d10704b53f0b1d6803f34c1dd09b0f243 Mon Sep 17 00:00:00 2001 From: 9rnt <64017072+9rnt@users.noreply.github.com> Date: Mon, 24 Jul 2023 03:59:13 +0200 Subject: [PATCH] =?UTF-8?q?Allow=20provider=20to=20use=20the=20external=20?= =?UTF-8?q?ID=20when=20assuming=20the=20role=20in=20the=20p=E2=80=A6=20(#3?= =?UTF-8?q?57)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- docs/index.md | 7 +++++-- es/provider.go | 17 +++++++++++++++-- es/provider_test.go | 6 ++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/index.md b/docs/index.md index d9b7f271..bdbbdc41 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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. @@ -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" } ``` diff --git a/es/provider.go b/es/provider.go index 3d7c4f0d..ff30dd9a 100644 --- a/es/provider.go +++ b/es/provider.go @@ -57,6 +57,7 @@ type ProviderConf struct { pingTimeoutSeconds int awsRegion string awsAssumeRoleArn string + awsAssumeRoleExternalID string awsAssumeRoleSessionName string awsAccessKeyId string awsSecretAccessKey string @@ -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, @@ -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), @@ -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 @@ -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}) @@ -593,6 +602,7 @@ 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..) // @@ -600,7 +610,10 @@ func awsSession(region string, conf *ProviderConf) *awssession.Session { 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 } diff --git a/es/provider_test.go b/es/provider_test.go index 77239704..bd19dc77 100644 --- a/es/provider_test.go +++ b/es/provider_test.go @@ -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 {