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_configis confirmed via the livehashicorp/awsprovider schema (v6.53.0) to be a genuine account/Region singleton — its only exported attribute isid(the Region name), it has noarnattribute and notags/tags_allsupport at all (the AWS API forPutEncryptionConfighas no tagging concept). This is unlikeaws_xray_groupandaws_xray_sampling_rule, which both support multiple instances,tags, and exposeid+arn+tags_all. The module therefore rendersaws_xray_encryption_configas a single optional resource (afor_eachover 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 universaltagspattern. 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 toNONE; the setting is sticky at the AWS API level. This is documented under Provider gotchas below.
The module manages the following (allow-list):
aws_xray_group— keystone;for_eachover a caller-supplied map, one group per key, each with its ownfilter_expressionand optionalinsights_configurationblockaws_xray_sampling_rule— child collection;for_eachover a caller-supplied map, one sampling rule per keyaws_xray_encryption_config— singleton; rendered via afor_eachtoggle (0 or 1 instances), never a caller-keyed collection. Defaults totype = "KMS"with either a caller-supplied CMK or (if none supplied) nokey_id— see Secure-by-default decisions for how the module still keeps the secure posture front-and-center even though AWS's own default isNONE.
Referenced by arn, never created here:
- KMS CMK for trace-data encryption — supplied by
terraform-aws-kmsviakms_key_arn; this module never creates a KMS key - IAM roles/policies granting
xray:PutTraceSegments/xray:GetSamplingRulesto instrumented workloads (Lambda execution roles, ECS task roles, EC2 instance profiles) — owned byterraform-aws-iam-roleand/orterraform-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)
| 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.
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:PassRoleis not required by this module — X-Ray does not assume a service role for group/sampling-rule/encryption-config management.
- No service-linked role is required for
aws_xray_group,aws_xray_sampling_rule, oraws_xray_encryption_config. - Account/Region singleton:
aws_xray_encryption_confighas 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 setencryption_configper 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, andkms:DescribeKey— otherwise trace ingestion fails silently at the API layer, not atterraform 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_arnmust be a symmetric key (the defaultcustomer_master_key_speconterraform-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_arnwildcard: most callers setresource_arn = "*"(all resources) unless narrowing to a specific ARN; this is an AWS modeling choice, not a Casey's restriction.
| 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 |
aws_xray_group.idand.arnare the same value. Unlike most AWS resources, the X-Ray group'sidattribute 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 expectidto be a bare name.aws_xray_sampling_rule.idis therule_name, not an ARN. Itsarnoutput 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_confighas noarn, notags, notags_all. Its only exported attribute isid(the Region name). It cannot be tagged — there is noTagResource-style API for this setting. Do not attempt to wirevar.tagsinto 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_configresource from aterraform destroyor state removal does not revert the account/Region back toNONEor to a previous key — the last-applied API call remains in effect until something else callsPutEncryptionConfigagain. Document this prominently so operators do not assumeterraform destroyrestores an encryption default. - All three resources support the v6
regionargument for multi-Region management from a single provider block, but this module does not expose aregionvariable per this module suite's region convention (provider inheritance only) — a caller needing multiple Regions passes a provider alias viaproviders = {}at the call site (out of this module's scope for Phase 4). - Sampling rule
versionis fixed at1— 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.
PutEncryptionConfigtransitions the settingUPDATING→ACTIVEat the AWS API layer; aterraform applyimmediately followed by a trace-ingestion smoke test can race the update. Groups and sampling rules do not exhibit this lag. tagsvstags_all.var.tagsflows toaws_xray_groupandaws_xray_sampling_ruleonly;tags_allon each reflects the merge with providerdefault_tags(resource tags win).aws_xray_encryption_configis excluded from both, as noted above.
| 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 |
- 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. Amanage_encryption_configbool + a singleencryption_configobject (nullable) accurately models "this module either owns the singleton or it doesn't," and avoids afor_eachkey 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 — nocount, caller-supplied stable string keys, so adding/removing one group or rule does not perturb others interraform 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 callxray: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 excluded —
terraform-aws-kmsowns CMK lifecycle; this module only consumes a keyarnby reference, consistent with every other Phase 1-4 module's KMS wiring pattern.