From 5ff1058f302b09d707f6c43d2cd5ebed43607159 Mon Sep 17 00:00:00 2001 From: "blinkagent[bot]" <237617714+blinkagent[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 10:33:24 -0500 Subject: [PATCH] feat: add AWS PRM user-agent attribution for partner revenue tracking (#23138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sets `AWS_SDK_UA_APP_ID` in the Terraform provisioner environment so that all AWS API calls made during workspace builds include Coder's AWS Partner Revenue Measurement (PRM) attribution in the user-agent header. This enables AWS to attribute resource usage driven by Coder back to us as an AWS partner across all deployments. ## How it works - `provisionEnv()` now unconditionally sets `AWS_SDK_UA_APP_ID=APN_1.1/pc_cdfmjwn8i6u8l9fwz8h82e4w3$` in the environment passed to `terraform plan` and `terraform apply` - The Terraform AWS provider picks this up and appends it to the user-agent header on every AWS API call - If a customer has already set `AWS_SDK_UA_APP_ID` in their environment (e.g. via `coder.env`), we don't override it - Templates that don't use the AWS provider are unaffected — the env var is simply ignored ## Notes - The product code is hardcoded in the source. It may be worth obfuscating this value (e.g. via `-ldflags -X` at build time) to keep it out of the public repo, though it is technically a public identifier. - This covers user-agent attribution only. Resource-level `aws-apn-id` tags for cost allocation are a separate effort that requires template changes. ## References - [AWS SDK Application ID docs](https://docs.aws.amazon.com/sdkref/latest/guide/feature-appid.html) - [AWS PRM Automated User Agent](https://prm.partner.aws.dev/automated-user-agent.html) (partner login required) --------- Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: DevCats --- provisioner/terraform/provision.go | 1 + provisioner/terraform/provision_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index 3dd0adbb83..592bc3c9cc 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -381,6 +381,7 @@ func provisionEnv( "CODER_WORKSPACE_BUILD_ID="+metadata.GetWorkspaceBuildId(), "CODER_TASK_ID="+metadata.GetTaskId(), "CODER_TASK_PROMPT="+metadata.GetTaskPrompt(), + "AWS_SDK_UA_APP_ID=APN_1.1/pc_cdfmjwn8i6u8l9fwz8h82e4w3$", ) if metadata.GetPrebuiltWorkspaceBuildStage().IsPrebuild() { env = append(env, provider.IsPrebuildEnvironmentVariable()+"=true") diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index 46c1c980b2..d32fb1f599 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -1298,6 +1298,7 @@ func TestProvision_SafeEnv(t *testing.T) { require.Contains(t, log, passedValue) require.NotContains(t, log, secretValue) require.Contains(t, log, "CODER_") + require.Contains(t, log, "AWS_SDK_UA_APP_ID=APN_1.1/pc_cdfmjwn8i6u8l9fwz8h82e4w3$") apply := applyComplete.Type.(*proto.Response_Apply) require.NotEmpty(t, apply.Apply.State, "state exists")