From d0ddde131ba546dcf319e2d43a7b635f44713caa Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Tue, 11 Aug 2020 02:12:34 -0400 Subject: [PATCH 1/3] add configurable user-agent information --- aws/config.go | 46 ++++++++++++++++++++++++++ aws/config_test.go | 55 ++++++++++++++++++++++++++++++++ website/docs/index.html.markdown | 13 ++++++++ 3 files changed, 114 insertions(+) diff --git a/aws/config.go b/aws/config.go index 458fcfc04c6..1ba741ee84d 100644 --- a/aws/config.go +++ b/aws/config.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "os" "strings" "github.com/aws/aws-sdk-go/aws" @@ -402,6 +403,13 @@ func (c *Config) Client() (interface{}, error) { }, } + if v := os.Getenv("TF_APPEND_USER_AGENT"); v != "" { + if customAgentInfo := parseTerraformAppendUserAgentEnvVar(v); len(customAgentInfo) > 0 { + log.Printf("[DEBUG] Using additional User-Agent Info: %s", v) + awsbaseConfig.UserAgentProducts = append(awsbaseConfig.UserAgentProducts, customAgentInfo...) + } + } + sess, accountID, partition, err := awsbase.GetSessionWithAccountIDAndPartition(awsbaseConfig) if err != nil { return nil, fmt.Errorf("error configuring Terraform AWS Provider: %w", err) @@ -796,3 +804,41 @@ func GetSupportedEC2Platforms(conn *ec2.EC2) ([]string, error) { return platforms, nil } + +// parseTerraformAppendUserAgentEnvVar determines User-Agent Information exported as TF_APPEND_USER_AGENT. +// To represent a User-Agent, the string must include the Name and optionally the Version and any Extra Information e.g. +// name +// name/version +// name/version/extra0 +// name/version/extra0,extra1... +// +// Multiple User-Agents can be provided when delimited by a " " e.g. +// name/version name2/version2/extra0 +func parseTerraformAppendUserAgentEnvVar(v string) []*awsbase.UserAgentProduct { + var products []*awsbase.UserAgentProduct + parts := strings.Split(v, " ") + if len(parts) > 0 { + for _, part := range parts { + infoParts := strings.SplitN(part, "/", 3) + ua := &awsbase.UserAgentProduct{} + if infoParts[0] != "" { + ua.Name = infoParts[0] + } + if len(infoParts) > 1 { + if infoParts[1] != "" { + ua.Version = infoParts[1] + } + } + if len(infoParts) > 2 { + if infoParts[2] != "" { + ua.Extra = strings.Split(infoParts[2], ",") + } + } + + if ua != nil { + products = append(products, ua) + } + } + } + return products +} diff --git a/aws/config_test.go b/aws/config_test.go index fd258cba839..b25233eb166 100644 --- a/aws/config_test.go +++ b/aws/config_test.go @@ -130,3 +130,58 @@ var test_ec2_describeAccountAttributes_response = ` ` + +func TestAWSConfigCustomUserAgentInfo(t *testing.T) { + testCases := []struct { + UserAgentInfo string + Expected []*awsbase.UserAgentProduct + }{ + { + UserAgentInfo: "Test", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test"}, + }, + }, + { + UserAgentInfo: "Test/1.0", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test", Version: "1.0"}, + }, + }, + { + UserAgentInfo: "Test,1.0", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test,1.0"}, + }, + }, + { + UserAgentInfo: "Test/1.0/extra0", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test", Version: "1.0", Extra: []string{"extra0"}}, + }, + }, + { + UserAgentInfo: "Test Test2", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test"}, + {Name: "Test2"}, + }, + }, + { + UserAgentInfo: "Test/1.0 Test2/2.0 Test3/3.0/extra0,extra1", + Expected: []*awsbase.UserAgentProduct{ + {Name: "Test", Version: "1.0"}, + {Name: "Test2", Version: "2.0"}, + {Name: "Test3", Version: "3.0", Extra: []string{"extra0", "extra1"}}, + }, + }, + } + + for _, testCase := range testCases { + got := parseTerraformAppendUserAgentEnvVar(testCase.UserAgentInfo) + + if !reflect.DeepEqual(got, testCase.Expected) { + t.Errorf("got %v, expected %v", got, testCase.Expected) + } + } +} diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 61856f987f8..8d0e6d2d10f 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -104,6 +104,19 @@ If you're running Terraform on CodeBuild or ECS and have configured an [IAM Task If you're running Terraform on EKS and have configured [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html), Terraform will use the pod's role. This support is based on the underlying `AWS_ROLE_ARN` and `AWS_WEB_IDENTITY_TOKEN_FILE` environment variables being automatically set by Kubernetes or manually for advanced usage. +### Custom User-Agent Information + +By default, the underlying AWS client used by the Terraform AWS Provider creates requests with User-Agent headers including information about +the requester i.e. HashiCorp and the Terraform Version and Homepage. To provide additional configuration information in the User-Agent headers, +the `TF_APPEND_USER_AGENT` environment variable can be set with the format: `name/version/extra0...`. +Multiple User-Agent configurations can be provided by including a space between each e.g. + +```sh +$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0" +$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0 JobID1234/1.0" +$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0 JobID1234/1.0/extra0,extra1" +``` + ### EC2 Instance Metadata Service If you're running Terraform from an EC2 instance with IAM Instance Profile From 6736c170484164792a85176c00e7c5daf4fefe08 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Fri, 14 Aug 2020 16:54:54 -0400 Subject: [PATCH 2/3] expect config additional opts to be set in aws-sdk-go-base --- aws/config.go | 46 -------------------------------------- aws/config_test.go | 55 ---------------------------------------------- 2 files changed, 101 deletions(-) diff --git a/aws/config.go b/aws/config.go index 1ba741ee84d..458fcfc04c6 100644 --- a/aws/config.go +++ b/aws/config.go @@ -3,7 +3,6 @@ package aws import ( "fmt" "log" - "os" "strings" "github.com/aws/aws-sdk-go/aws" @@ -403,13 +402,6 @@ func (c *Config) Client() (interface{}, error) { }, } - if v := os.Getenv("TF_APPEND_USER_AGENT"); v != "" { - if customAgentInfo := parseTerraformAppendUserAgentEnvVar(v); len(customAgentInfo) > 0 { - log.Printf("[DEBUG] Using additional User-Agent Info: %s", v) - awsbaseConfig.UserAgentProducts = append(awsbaseConfig.UserAgentProducts, customAgentInfo...) - } - } - sess, accountID, partition, err := awsbase.GetSessionWithAccountIDAndPartition(awsbaseConfig) if err != nil { return nil, fmt.Errorf("error configuring Terraform AWS Provider: %w", err) @@ -804,41 +796,3 @@ func GetSupportedEC2Platforms(conn *ec2.EC2) ([]string, error) { return platforms, nil } - -// parseTerraformAppendUserAgentEnvVar determines User-Agent Information exported as TF_APPEND_USER_AGENT. -// To represent a User-Agent, the string must include the Name and optionally the Version and any Extra Information e.g. -// name -// name/version -// name/version/extra0 -// name/version/extra0,extra1... -// -// Multiple User-Agents can be provided when delimited by a " " e.g. -// name/version name2/version2/extra0 -func parseTerraformAppendUserAgentEnvVar(v string) []*awsbase.UserAgentProduct { - var products []*awsbase.UserAgentProduct - parts := strings.Split(v, " ") - if len(parts) > 0 { - for _, part := range parts { - infoParts := strings.SplitN(part, "/", 3) - ua := &awsbase.UserAgentProduct{} - if infoParts[0] != "" { - ua.Name = infoParts[0] - } - if len(infoParts) > 1 { - if infoParts[1] != "" { - ua.Version = infoParts[1] - } - } - if len(infoParts) > 2 { - if infoParts[2] != "" { - ua.Extra = strings.Split(infoParts[2], ",") - } - } - - if ua != nil { - products = append(products, ua) - } - } - } - return products -} diff --git a/aws/config_test.go b/aws/config_test.go index b25233eb166..fd258cba839 100644 --- a/aws/config_test.go +++ b/aws/config_test.go @@ -130,58 +130,3 @@ var test_ec2_describeAccountAttributes_response = ` ` - -func TestAWSConfigCustomUserAgentInfo(t *testing.T) { - testCases := []struct { - UserAgentInfo string - Expected []*awsbase.UserAgentProduct - }{ - { - UserAgentInfo: "Test", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test"}, - }, - }, - { - UserAgentInfo: "Test/1.0", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test", Version: "1.0"}, - }, - }, - { - UserAgentInfo: "Test,1.0", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test,1.0"}, - }, - }, - { - UserAgentInfo: "Test/1.0/extra0", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test", Version: "1.0", Extra: []string{"extra0"}}, - }, - }, - { - UserAgentInfo: "Test Test2", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test"}, - {Name: "Test2"}, - }, - }, - { - UserAgentInfo: "Test/1.0 Test2/2.0 Test3/3.0/extra0,extra1", - Expected: []*awsbase.UserAgentProduct{ - {Name: "Test", Version: "1.0"}, - {Name: "Test2", Version: "2.0"}, - {Name: "Test3", Version: "3.0", Extra: []string{"extra0", "extra1"}}, - }, - }, - } - - for _, testCase := range testCases { - got := parseTerraformAppendUserAgentEnvVar(testCase.UserAgentInfo) - - if !reflect.DeepEqual(got, testCase.Expected) { - t.Errorf("got %v, expected %v", got, testCase.Expected) - } - } -} From 4a9736e16574e92f4d427de3321183fda9df2563 Mon Sep 17 00:00:00 2001 From: angie pinilla Date: Fri, 14 Aug 2020 16:55:22 -0400 Subject: [PATCH 3/3] Update website/docs/index.html.markdown Co-authored-by: Brian Flad --- website/docs/index.html.markdown | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 8d0e6d2d10f..e37cb2664f2 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -106,15 +106,10 @@ If you're running Terraform on EKS and have configured [IAM Roles for Service Ac ### Custom User-Agent Information -By default, the underlying AWS client used by the Terraform AWS Provider creates requests with User-Agent headers including information about -the requester i.e. HashiCorp and the Terraform Version and Homepage. To provide additional configuration information in the User-Agent headers, -the `TF_APPEND_USER_AGENT` environment variable can be set with the format: `name/version/extra0...`. -Multiple User-Agent configurations can be provided by including a space between each e.g. +By default, the underlying AWS client used by the Terraform AWS Provider creates requests with User-Agent headers including information about Terraform and AWS Go SDK versions. To provide additional information in the User-Agent headers, the `TF_APPEND_USER_AGENT` environment variable can be set and its value will be directly added to HTTP requests. e.g. ```sh -$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0" -$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0 JobID1234/1.0" -$ export TF_APPEND_USER_AGENT="JenkinsAgent1234/1.0 JobID1234/1.0/extra0,extra1" +$ export TF_APPEND_USER_AGENT="JenkinsAgent/i-12345678 BuildID/1234 (Optional Extra Information)" ``` ### EC2 Instance Metadata Service