Skip to content

Latest commit

 

History

History
202 lines (176 loc) · 13 KB

File metadata and controls

202 lines (176 loc) · 13 KB

terraform-aws-xray — SCOPE

Composite observability module for AWS X-Ray. It owns the X-Ray trace groups that segment traces by filter expression, the sampling rules that control which requests get instrumented, and the account/region encryption configuration that governs how trace data is encrypted at rest — so a single module call yields a fully configured, NPI/GLBA/FCA-aligned X-Ray tracing posture.

  • Module type: Composite (Phase 4 — Management & Observability Remainder)
  • Primary resource (keystone): aws_xray_group.this

⚠️ Verified correction to the starting brief: aws_xray_encryption_config is confirmed via the live hashicorp/aws provider schema (v6.53.0) to be a genuine account/Region singleton — its only exported attribute is id (the Region name), it has no arn attribute and no tags/tags_all support at all (the AWS API for PutEncryptionConfig has no tagging concept). This is unlike aws_xray_group and aws_xray_sampling_rule, which both support multiple instances, tags, and expose id + arn + tags_all. The module therefore renders aws_xray_encryption_config as a single optional resource (a for_each over a {} / { this = ... } map used purely as a create/skip toggle, never a caller-keyed collection), and it is the only resource in this module that does not participate in the universal tags pattern. The provider docs also note: "Removing this resource from Terraform has no effect to the encryption configuration within X-Ray" — destroying the Terraform resource does NOT revert the account to NONE; the setting is sticky at the AWS API level. This is documented under Provider gotchas below.

In-scope resources

The module manages the following (allow-list):

  • aws_xray_group — keystone; for_each over a caller-supplied map, one group per key, each with its own filter_expression and optional insights_configuration block
  • aws_xray_sampling_rule — child collection; for_each over a caller-supplied map, one sampling rule per key
  • aws_xray_encryption_configsingleton; rendered via a for_each toggle (0 or 1 instances), never a caller-keyed collection. Defaults to type = "KMS" with either a caller-supplied CMK or (if none supplied) no key_id — see Secure-by-default decisions for how the module still keeps the secure posture front-and-center even though AWS's own default is NONE.

Out-of-scope resources (consumed by reference)

Referenced by arn, never created here:

  • KMS CMK for trace-data encryption — supplied by terraform-aws-kms via kms_key_arn; this module never creates a KMS key
  • IAM roles/policies granting xray:PutTraceSegments / xray:GetSamplingRules to instrumented workloads (Lambda execution roles, ECS task roles, EC2 instance profiles) — owned by terraform-aws-iam-role and/or terraform-aws-iam-policy, referenced by the caller's own wiring, not by this module
  • CloudWatch Log Groups / dashboards consuming X-Ray service-graph metrics — owned by terraform-aws-cloudwatch-log-group / terraform-aws-cloudwatch-alarm
  • SNS topics for sampling/insights notifications — owned by terraform-aws-sns (X-Ray insights notifications are delivered via EventBridge/Chatbot integrations configured outside this module's scope)

Consumes

Input Type Source module
kms_key_arn string (ARN, optional) terraform-aws-kms (arn output) — customer-managed key for aws_xray_encryption_config

No VPC/subnet/security-group wiring is required — X-Ray is a regional control- plane/API service with no network footprint of its own to manage.

Required IAM permissions

Least-privilege actions the Terraform identity needs:

Action Required for
xray:CreateGroup, xray:UpdateGroup, xray:DeleteGroup, xray:GetGroup, xray:GetGroups X-Ray group lifecycle
xray:CreateSamplingRule, xray:UpdateSamplingRule, xray:DeleteSamplingRule, xray:GetSamplingRules Sampling rule lifecycle
xray:PutEncryptionConfig, xray:GetEncryptionConfig Encryption config (account/Region singleton)
xray:TagResource, xray:UntagResource, xray:ListTagsForResource Tagging groups and sampling rules (encryption config is not taggable)
kms:DescribeKey, kms:CreateGrant Only when a customer-managed KMS key is supplied to aws_xray_encryption_config; the CMK's own key policy must also allow X-Ray (xray.amazonaws.com) to use the grant

iam:PassRole is not required by this module — X-Ray does not assume a service role for group/sampling-rule/encryption-config management.

AWS Prerequisites

  • No service-linked role is required for aws_xray_group, aws_xray_sampling_rule, or aws_xray_encryption_config.
  • Account/Region singleton: aws_xray_encryption_config has exactly one live value per account per Region. If more than one Terraform configuration (or a manual console change) manages it for the same account/Region, the last write wins and state will drift. Only one instance of this module should set encryption_config per account/Region.
  • KMS key policy: when type = "KMS" with a customer-managed key, the key's policy must grant the calling principal (and X-Ray itself) kms:Decrypt, kms:GenerateDataKey, and kms:DescribeKey — otherwise trace ingestion fails silently at the API layer, not at terraform apply.
  • No asymmetric KMS keys. Confirmed via AWS X-Ray documentation: X-Ray does not support asymmetric KMS keys for trace encryption. The CMK supplied via kms_key_arn must be a symmetric key (the default customer_master_key_spec on terraform-aws-kms).
  • Region constraint: none beyond standard regional availability — X-Ray is available in all commercial Regions where the provider is configured. No us-east-1 global-service requirement (unlike CloudFront/WAFv2/ACM).
  • Quotas: 500 groups per account (soft), 2,000 sampling rules per account (soft), 1 encryption configuration per account per Region (hard, by design).
  • Sampling rule resource_arn wildcard: most callers set resource_arn = "*" (all resources) unless narrowing to a specific ARN; this is an AWS modeling choice, not a Casey's restriction.

Emits

Output Description Consumed by
group_ids Map (key → id) of X-Ray group ARNs — aws_xray_group.id is the group ARN Reference / drift audit
group_arns Map (key → arn) of X-Ray group ARNs (identical value to id; both surfaced per the primary-outputs convention) IAM policy Resource elements scoping xray:PutTraceSegments to a group
group_names Map (key → group_name) Dashboards, CLI/SDK trace filtering, CloudWatch metric filters
sampling_rule_ids Map (key → id, the rule_name) Reference / drift audit
sampling_rule_arns Map (key → arn) Reference in IAM conditions, cross-account sharing
encryption_config_id The encryption config id (the Region name), or null when not managed by this module instance Reference / audit only — no known consumer wires this further
encryption_config_type The effective encryption type (KMS or NONE), or null when not managed Compliance reporting / audit
tags_all Map (key → tags_all) for groups and sampling rules (the only two taggable resource types in this module) Governance/audit

Provider gotchas

  • aws_xray_group.id and .arn are the same value. Unlike most AWS resources, the X-Ray group's id attribute IS the ARN string (arn:aws:xray:<region>:<account>:group/<name>/<hash>), not a short identifier. Both outputs are still surfaced per the primary-outputs convention, but callers should not expect id to be a bare name.
  • aws_xray_sampling_rule.id is the rule_name, not an ARN. Its arn output IS a full ARN (arn:aws:xray:<region>:<account>:sampling-rule/<rule_name>). This is the inverse of the group's id/arn relationship — document both directions clearly so callers wire the correct value.
  • aws_xray_encryption_config has no arn, no tags, no tags_all. Its only exported attribute is id (the Region name). It cannot be tagged — there is no TagResource-style API for this setting. Do not attempt to wire var.tags into this resource.
  • Encryption config is sticky at the API layer. Per the provider docs: "Removing this resource from Terraform has no effect to the encryption configuration within X-Ray." Destroying/removing the aws_xray_encryption_config resource from a terraform destroy or state removal does not revert the account/Region back to NONE or to a previous key — the last-applied API call remains in effect until something else calls PutEncryptionConfig again. Document this prominently so operators do not assume terraform destroy restores an encryption default.
  • All three resources support the v6 region argument for multi-Region management from a single provider block, but this module does not expose a region variable per this module suite's region convention (provider inheritance only) — a caller needing multiple Regions passes a provider alias via providers = {} at the call site (out of this module's scope for Phase 4).
  • Sampling rule version is fixed at 1 — it is the only sampling rule format AWS currently supports, but the argument is still (Required) in the provider schema, so the module hardcodes it via a default rather than leaving it as a true free-form input.
  • No destroy-ordering hazard. None of the three resources in this module have ENI, NAT, or cross-resource attachment dependencies — they are pure control-plane API objects with no VPC footprint, so destroy order between groups / sampling rules / encryption config is irrelevant.
  • Encryption config apply is asynchronous. PutEncryptionConfig transitions the setting UPDATINGACTIVE at the AWS API layer; a terraform apply immediately followed by a trace-ingestion smoke test can race the update. Groups and sampling rules do not exhibit this lag.
  • tags vs tags_all. var.tags flows to aws_xray_group and aws_xray_sampling_rule only; tags_all on each reflects the merge with provider default_tags (resource tags win). aws_xray_encryption_config is excluded from both, as noted above.

Secure-by-default decisions

Posture Default Opt-out
Encryption config type KMS (customer-managed key when kms_key_arn is supplied; AWS-managed key material under type = "KMS" with key_id = null otherwise) — never left at AWS's own out-of-the-box NONE default encryption_config.type = "NONE" explicitly, or set manage_encryption_config = false to skip managing the singleton entirely (e.g. when another module instance already owns it)
Encryption config management The module manages the account/Region singleton by default (manage_encryption_config = true) so a fresh account does not silently ship with NONE manage_encryption_config = false — the module then emits null for both encryption outputs and leaves whatever is already configured untouched
Sampling rule insights insights_configuration.insights_enabled defaults to false per group (matches AWS default; enabling costs additional CloudWatch/X-Ray charges) set insights_configuration.insights_enabled = true per group where anomaly detection is wanted
Tags tags = optional(map(string), {}) on both taggable resources (groups, sampling rules) not opt-out — tagging is a governance invariant, not a security control here

Design decisions

  • The encryption config is a singleton, modeled as an optional block, not a collection. Making it a map(object(...)) like groups/sampling rules would imply multiple encryption configs are meaningful, which is false at the AWS API level — there is exactly one per account per Region. A manage_encryption_config bool + a single encryption_config object (nullable) accurately models "this module either owns the singleton or it doesn't," and avoids a for_each key namespace that has no real-world counterpart.
  • Groups and sampling rules are both modeled as map(object(...)) per this module suite's composite child-collection rule — no count, caller-supplied stable string keys, so adding/removing one group or rule does not perturb others in terraform plan.
  • No VPC/networking inputs. X-Ray's group/sampling-rule/encryption-config APIs are pure control-plane resources; the workloads that emit trace segments (Lambda, ECS, EC2, EKS) are configured by their own modules (terraform-aws-lambda, terraform-aws-ecs-service, etc.) to call xray:PutTraceSegments — that wiring is deliberately out of scope here to keep this module's blast radius limited to the X-Ray control plane itself.
  • KMS key creation is deliberately excludedterraform-aws-kms owns CMK lifecycle; this module only consumes a key arn by reference, consistent with every other Phase 1-4 module's KMS wiring pattern.