Skip to content

microsoftexpert/tf-mod-aws-payment-cryptography

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🟧 AWS Payment Cryptography Terraform Module

A secure-by-default AWS Payment Cryptography HSM-backed key for card and payment cryptographic workflows — non-exportable by default, TR-31-scoped key usage, friendly aliases. Built for the AWS provider v6.x.

Terraform aws module type resources


🧩 Overview

  • 🔐 Creates an HSM-backed AWS Payment Cryptography key (aws_paymentcryptography_key) — a purpose-built key for PCI-scoped payment cryptographic workflows (PIN translation/verification, card verification values, TR-31/TR-34/ECDH key exchange, EMV master-key derivation, MAC generation/verification).
  • 🚫 Non-exportable by default posture recommendedexportable has no baked-in default and must be stated explicitly; the recommended value is false so key material never leaves the HSM boundary.
  • 🎯 Least-privilege key_modes_of_use — every cryptographic-operation flag (encrypt, decrypt, sign, wrap, etc.) defaults to false; the caller enumerates only the operations the key actually needs.
  • 🏷️ Builds any number of friendly aliases (aws_paymentcryptography_key_alias) pointing at the same key, keyed by a stable logical name.
  • 🔍 Emits key metadata only — algorithm, class, usage, state, and key check value (KCV). No key material is ever read back or output, by design and by API limitation.
  • ⚠️ A different service from KMS. This is not a general-purpose encryption key — use tf-mod-aws-kms for at-rest encryption; use this module only for payment/card cryptographic key material.

💡 Why it matters: payment cryptography sits at the center of PCI compliance and card-fraud blast radius. This module makes the non-exportable, narrowly-scoped, HSM-bound posture the path of least resistance, so PIN-translation and card-verification keys default to the safest configuration a regulated FI can operate.


❤️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


🗺️ Where this fits in the family

flowchart LR
 iam["tf-mod-aws-iam-role"]
 pc["tf-mod-aws-payment-cryptography"]
 policy["Caller IAM policies\n(Resource = key arn)"]
 data["Payment Cryptography\nData Plane (app runtime)"]

 iam -->|principal arn referenced in policy| policy
 policy -->|scoped access to| pc
 pc -->|key arn / KeyIdentifier| data

 style pc fill:#FF9900,color:#fff
Loading

This module is not a foundation module in the usual sense — it consumes nothing from other infrastructure modules. It sits alongside tf-mod-aws-iam-role (whose role ARNs are referenced in caller-authored IAM policies scoped to this key's arn) and is consumed at runtime by application code making AWS Payment Cryptography Data Plane API calls (EncryptData, TranslatePinData, GenerateCardValidationData, etc.) — those calls are outside Terraform's scope entirely.


🧬 What this module builds

flowchart TD
 subgraph module["tf-mod-aws-payment-cryptography"]
 key["aws_paymentcryptography_key.this<br/>(keystone HSM-backed key)"]
 alias["aws_paymentcryptography_key_alias.this<br/>(for_each, optional)"]
 end

 key -->|key_arn| alias

 style key fill:#FF9900,color:#fff
Loading
Resource Role Created when
aws_paymentcryptography_key.this Keystone HSM-backed payment key Always
aws_paymentcryptography_key_alias.this Friendly alias(es) pointing at the key (for_each) aliases non-empty

ℹ️ This is a deliberately small composite — two resources, no key policy resource (AWS Payment Cryptography has no Terraform-managed resource-policy analog to aws_kms_key_policy; access control is expressed entirely through IAM identity/resource policies the caller authors against the key arn).


✅ Provider / Versions

Requirement Version
Terraform >= 1.12.0
hashicorp/aws >= 6.0, < 7.0

No provider {} block, no configuration_aliases — this module inherits the caller's single provider configuration (standard region model; no region variable).


🔑 Required IAM Permissions

The Terraform identity needs the following actions. CreateKey cannot be resource-scoped (no ARN exists yet); everything else can be scoped to the key arn once known.

Action Required for Notes
payment-cryptography:CreateKey Key creation Cannot be resource-scoped — no ARN yet
payment-cryptography:GetKey, payment-cryptography:ListKeys Read-back / plan refresh
payment-cryptography:StartKeyUsage, payment-cryptography:StopKeyUsage enabled lifecycle toggling
payment-cryptography:DeleteKey, payment-cryptography:RestoreKey Destroy / recovery Deletion is scheduled with a recovery window, mirroring KMS
payment-cryptography:TagResource, payment-cryptography:UntagResource, payment-cryptography:ListTagsForResource Tagging
payment-cryptography:CreateAlias, payment-cryptography:DeleteAlias, payment-cryptography:UpdateAlias, payment-cryptography:GetAlias, payment-cryptography:ListAliases Alias lifecycle
payment-cryptography:ExportKey Only if a key is exportable = true and later exported Not called by this module — needed by the runtime identity performing the export, not Terraform

ℹ️ No iam:PassRole is required. This module creates no IAM role and assumes nothing.

⚠️ No service-linked role is auto-created for standard key management. An SLR is only relevant for Multi-Party Approval (MPA) or Multi-Region replication features, both configured outside this module.


📋 AWS Prerequisites

  • Different action namespace from KMS. Ensure the executing IAM principal is permissioned for payment-cryptography:*, not kms:* — these are entirely separate services despite superficial similarity.
  • No service-linked role required for the resources this module manages.
  • Region availability. AWS Payment Cryptography is available only in a subset of AWS Regions — confirm the target Region supports the service before relying on it; no region variable is exposed (standard provider-inheritance model).
  • HSM / PCI boundary. Keys are generated and held inside PCI PTS HSM-listed hardware security modules. exportable = false keys can never have their material read out via any API.
  • Quotas. Control-plane request-rate limits apply per account/Region (CreateKey, GetKey, alias operations) — see the AWS Payment Cryptography service quotas page before provisioning large batches of keys (e.g. per-merchant BDKs) via for_each.

📁 Module Structure

tf-mod-aws-payment-cryptography/
├── providers.tf # required_providers only — no provider {} block
├── variables.tf # key_attributes, exportable, enabled, key_check_value_algorithm, aliases, tags, timeouts
├── main.tf # aws_paymentcryptography_key.this + aws_paymentcryptography_key_alias.this (for_each)
├── outputs.tf # id, arn, key_check_value, key_origin, key_state, alias_names, tags_all
├── README.md # this file
└── SCOPE.md # in/out-of-scope, IAM, prerequisites, gotchas, design decisions

⚙️ Quick Start

Smallest working call — a non-exportable PIN encryption key (TR31_P0), the recommended posture:

module "pin_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false # RECOMMENDED — key material never leaves the HSM boundary

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }

  aliases = {
    primary = "pin-encryption-prod"
  }

  tags = {
    Environment = "prod"
    DataClass   = "PCI"
  }
}

# Wire the key ARN into an IAM policy Resource element or a Data Plane KeyIdentifier:
# key_arn = module.pin_key.arn

⚠️ Always pin the source with ?ref=v1.0.0 — never a branch.


🔌 Cross-Module Contract

Consumes

Input Type Source module
(none)

This module consumes nothing from other infrastructure modules — it is typically wired standalone, with IAM policies (authored by the caller, not generated here) referencing its arn.

Emits

Output Description Consumed by
id Key id (identical to arn) AWS Payment Cryptography API references
arn Key ARN — the canonical cross-resource reference IAM policy Resource elements, aws_paymentcryptography_key_alias.key_arn, Data Plane KeyIdentifier
key_check_value KCV — non-secret checksum confirming key identity Counterparty key-exchange verification
key_origin Source of key material Audit
key_state Lifecycle state Operational monitoring
alias_names Map of logical alias key → normalized alias/<name> Application config referencing the key by friendly name
tags_all All tags incl. provider default_tags Governance / audit

📚 Example Library

1 · Minimal — non-exportable PIN encryption key
module "pin_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }
}
2 · With tags (merges with provider default_tags)
# Provider-level default_tags are the CALLER's concern, set once:
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      ManagedBy = "Terraform"
      Owner     = "payments-platform-team"
    }
  }
}

module "pin_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }

  # Resource tags MERGE with default_tags; resource tags win on key conflict.
  tags = {
    Environment = "prod"
    DataClass   = "PCI" # overrides any default_tags DataClass
  }
}

# module.pin_key.tags_all == { ManagedBy, Owner, Environment, DataClass }
3 · Card verification key (CVV/CVV2) — TR31_C0
module "cvv_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_2KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_C0_CARD_VERIFICATION_KEY"
    key_modes_of_use = {
      generate = true
      verify   = true
    }
  }

  aliases = {
    cvv2 = "cvv2-issuer-prod"
  }

  tags = { KEY_PURPOSE = "CVV2", CARD_BIN = "12345678" }
}
4 · AES-256 symmetric data encryption key — TR31_D0
module "data_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "AES_256"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_D0_SYMMETRIC_DATA_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }
}
5 · HMAC key for MAC generation/verification — TR31_M7
module "mac_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "HMAC_SHA256"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_M7_HMAC_KEY"
    key_modes_of_use = {
      generate = true
      verify   = true
    }
  }

  tags = { KEY_PURPOSE = "SPA2_AAV", CARD_BIN = "12345678" }
}
6 · Key-block protection key (KEK) for TR-31 key exchange
module "kek" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "AES_256"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_K1_KEY_BLOCK_PROTECTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }

  aliases = { kek = "tr31-kek-prod" }
}
7 · EMV master key for application cryptogram derivation — TR31_E0
module "emv_mkey" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_E0_EMV_MKEY_APP_CRYPTOGRAMS"
    key_modes_of_use = {
      derive_key = true
    }
  }
}
8 · Asymmetric key for digital signature — TR31_S0 (RSA)
module "signing_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "RSA_2048"
    key_class     = "PRIVATE_KEY"
    key_usage     = "TR31_S0_ASYMMETRIC_KEY_FOR_DIGITAL_SIGNATURE"
    key_modes_of_use = {
      sign = true
    }
  }
}
9 · Explicit key check value algorithm (counterparty KCV convention)
module "legacy_kek" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable                = false
  key_check_value_algorithm = "ANSI_X9_24" # match a TDES-era counterparty's KCV convention

  key_attributes = {
    key_algorithm = "TDES_2KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_K0_KEY_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }
}
10 · Multiple aliases pointing at one key
module "shared_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "AES_256"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_D0_SYMMETRIC_DATA_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }

  # "alias/" prefix optional — the module normalizes it.
  aliases = {
    primary   = "shared-data-key"
    reporting = "alias/shared-reporting-key"
  }
}
11 · for_each pattern — a batch of per-merchant BDKs
locals {
  merchants = toset(["merchant-a", "merchant-b", "merchant-c"])
}

module "merchant_bdk" {
  for_each = local.merchants
  source   = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "AES_128"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_B0_BASE_DERIVATION_KEY"
    key_modes_of_use = {
      derive_key = true
    }
  }

  aliases = { bdk = "dukpt-bdk-${each.key}" }

  tags = { Merchant = each.key }
}

# Stay under the account/Region CreateKey request-rate quota for large batches.
12 · Import an existing key (by ARN)
import {
  to = module.pin_key.aws_paymentcryptography_key.this
  id = "arn:aws:payment-cryptography:us-east-1:111122223333:key/qtbojf64yshyvyzf"
}

module "pin_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }
}
13 · Secure-by-default opt-out — exportable = true (EXCEPTION, review required)
# ⚠️ Weakens the baseline. Document the exception and get security sign-off
# before enabling — this permits ExportKey (e.g. TR-34/RSA-wrap to a legacy HSM).
module "legacy_interop_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = true # OPT-OUT: key material CAN be exported (wrapped) — documented exception only

  key_attributes = {
    key_algorithm = "TDES_2KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_K2_TR34_ASYMMETRIC_KEY"
    key_modes_of_use = {
      encrypt = true
      wrap    = true
    }
  }

  tags = { Exception = "legacy-hsm-interop-2026-07", ApprovedBy = "security-review" }
}
14 · Disabled key (retained, not usable)
module "retired_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false
  enabled    = false # OPT-OUT: disables cryptographic operations without deleting the key

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }
}
15 · End-to-end composition — IAM policy scoped to a PIN key (mandatory finale)
# 1) The non-exportable, HSM-bound PIN encryption key
module "pin_key" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-payment-cryptography?ref=v1.0.0"

  exportable = false

  key_attributes = {
    key_algorithm = "TDES_3KEY"
    key_class     = "SYMMETRIC_KEY"
    key_usage     = "TR31_P0_PIN_ENCRYPTION_KEY"
    key_modes_of_use = {
      encrypt = true
      decrypt = true
      wrap    = true
      unwrap  = true
    }
  }

  aliases = { primary = "pin-encryption-prod" }
  tags    = { Environment = "prod", DataClass = "PCI" }
}

# 2) An IAM policy scoped to exactly the actions the payment-processing
# service needs, authored by the caller (out of this module's scope).
data "aws_iam_policy_document" "pin_translation_data_plane" {
  statement {
    sid    = "AllowPinTranslateDataPlane"
    effect = "Allow"
    actions = [
      "payment-cryptography-data:TranslatePinData",
      "payment-cryptography-data:DecryptData",
    ]
    resources = [module.pin_key.arn]
  }
}

module "pin_translation_policy" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-iam-policy?ref=v1.0.0"
  name   = "pin-translation-data-plane"
  policy = data.aws_iam_policy_document.pin_translation_data_plane.json
}

# 3) The role assumed by the payment-processing service, with the policy attached
module "pin_translation_role" {
  source              = "git::https://github.com/microsoftexpert/tf-mod-aws-iam-role?ref=v1.0.0"
  name                = "pin-translation-service"
  assume_role_policy  = data.aws_iam_policy_document.service_trust.json
  managed_policy_arns = [module.pin_translation_policy.arn]
}

📥 Inputs

ℹ️ High-level grouping below.

  • Core (FORCE-NEW): key_attributeskey_algorithm, key_class, key_usage, key_modes_of_use (all immutable; changing any recreates the key).
  • Security (FORCE-NEW, no default): exportable — the caller must state true/false explicitly; -recommended value is false.
  • Lifecycle: enabled (default true).
  • Key exchange: key_check_value_algorithm (default null — service picks the conventional algorithm for the key type).
  • Aliases: aliasesmap(string) keyed by a stable logical name, values normalized to alias/<name>.
  • Universal: tags, timeouts.

🧾 Outputs

  • id / arn — identical values; the key ARN (arn:aws:payment-cryptography:<region>:<account>:key/<key-id>) is the canonical cross-resource reference.
  • key_check_value — the KCV checksum (non-secret).
  • key_origin — source of the key material.
  • key_state — lifecycle state (e.g. CREATE_COMPLETE, DELETE_PENDING).
  • alias_names — map of logical alias key → normalized alias name (empty when aliases = {}).
  • tags_all — merged resource + provider default_tags.
  • No key-material output exists. There is nothing to emit — exportable = false keys have no read-back API at all, and this module never wires up the separate ExportKey Data Plane call even for exportable = true keys.

🧠 Architecture Notes

  • ARN / id formats. Key ARN: arn:aws:payment-cryptography:<region>:<account>:key/<key-id>. This resource's id and arn are identical (confirmed by the provider's import identity schema, which requires only arn).
  • Force-new / immutable fields. exportable and every field under key_attributes (key_algorithm, key_class, key_usage, key_modes_of_use) are FORCE-NEW — AWS Payment Cryptography has no UpdateKey API for these. Changing any of them destroys and recreates the key with a new ARN and new key material; treat it as a deliberate key-rotation event (issue new key, re-point aliases, retire the old key), not an in-place edit.
  • tagstags_alldefault_tags. var.tags flows only to aws_paymentcryptography_key — the alias resource is not taggable. tags_all is the computed merge of resource tags over the provider's default_tags; resource tags win on key conflict. default_tags is the caller's provider-block concern, never set in the module.
  • Eventual consistency. As with most AWS control-plane services, a freshly created key may briefly be unresolvable by the alias resource or by IAM policy evaluation immediately after creation; Terraform's dependency graph (key_arn = aws_paymentcryptography_key.this.arn) orders the alias after the key, but downstream IAM propagation is outside Terraform's control.
  • Destroy ordering. Deletion is scheduled (mirroring KMS behavior) rather than immediate; the key is recoverable via RestoreKey within the waiting window. Aliases are destroyed ahead of the key in Terraform's graph since they depend on key_arn.
  • No us-east-1 global-resource requirement. AWS Payment Cryptography keys are regional; this module has no CloudFront/WAFv2/ACM-style Region coupling.

🧱 Design Principles

Secure-by-default posture — each hardened default (or, where the module intentionally has none, the reasoning) and the exact variable that relaxes it:

Posture Hardened default Opt-out (variable)
Key exportability No baked-in default — the caller must state intent; -recommended value is exportable = false (non-exportable, HSM-bound) exportable = true, with a documented legacy-interop exception and security sign-off
Key-material exposure No Terraform-managed export path exists at all n/a — by design, not configurable
Scope of cryptographic operations Every key_modes_of_use flag defaults to false — least-privilege, caller enumerates only needed operations no_restrictions = true removes this floor — discouraged
Key enablement enabled = true enabled = false (disable without deleting)
Secret exposure No output ever carries key material, exportable or not n/a

Additional principles:

  • Small composite, two resources. The key and its alias(es) are inseparable in practice — one module call produces both.
  • exportable deliberately has no default value. Unlike most secure-by-default booleans (which quietly default to the secure posture), payment-key exportability is consequential enough that the module forces an explicit, reviewable decision rather than letting either posture happen silently.
  • No key-policy resource in scope, unlike tf-mod-aws-kms — access control is expressed entirely through caller-authored IAM identity/resource policies scoped to the key arn.

🚀 Runbook

terraform init -backend=false
terraform validate
terraform fmt -check

# plan/apply require valid AWS credentials (profile / SSO / OIDC) and a region:
terraform plan
terraform apply
terraform output

⚠️ Pin the module source with ?ref=v1.0.0 — never a branch.


🧪 Testing

  • terraform init -backend=false && terraform validate — offline schema validation.
  • terraform fmt -check — formatting gate.
  • terraform plan against a sandbox account — confirm key_attributes renders the expected key_algorithm/key_class/key_usage/key_modes_of_use combination and that it matches a valid combination per the AWS Payment Cryptography "key attributes" reference table (the service rejects invalid combinations at apply time even though Terraform's own validation {} blocks only check membership in the known enums, not cross-field combinations).
  • Verify key_state shows CREATE_COMPLETE and key_check_value is populated after apply.
  • For batches created via for_each, confirm the request rate stays under the account/Region CreateKey quota.

💬 Example Output

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

alias_names = {
 "primary" = "alias/pin-encryption-prod"
}
arn = "arn:aws:payment-cryptography:us-east-1:111122223333:key/qtbojf64yshyvyzf"
id = "arn:aws:payment-cryptography:us-east-1:111122223333:key/qtbojf64yshyvyzf"
key_check_value = "8B3F2A"
key_origin = "AWS_PAYMENT_CRYPTOGRAPHY"
key_state = "CREATE_COMPLETE"
tags_all = {
 "DataClass" = "PCI"
 "Environment" = "prod"
 "ManagedBy" = "Terraform"
}

🔍 Troubleshooting

  • Tag drift from default_tags overlap. A key set in both var.tags and provider default_tags shows the resource value in tags_all (resource wins). If a plan keeps re-adding a tag, it is defined in both places with different values — remove the duplicate.
  • Credential-chain failures. NoCredentialProviders / ExpiredToken on plan/apply means no valid AWS credentials — set AWS_PROFILE, refresh SSO, or confirm the OIDC role assumption succeeded in CI.
  • Region errors. AWS Payment Cryptography is not available in every Region — a ResourceNotFoundException/UnknownOperationException-style error on apply often means the caller's provider Region does not support the service. There is no us-east-1 global-resource requirement here (unlike CloudFront/WAFv2/ACM) — check the AWS Payment Cryptography Region-availability table instead.
  • IAM permission denials. A payment-cryptography:CreateKey/payment-cryptography:CreateAlias denial means the Terraform identity lacks the action — see Required IAM Permissions. Remember this is a distinct action namespace from kms:*.
  • ValidationException on key_attributes. The combination of key_algorithm + key_usage + key_modes_of_use is invalid per the service's valid-attribute-combination table (e.g. sign/verify modes are only valid with TR31_S0_ASYMMETRIC_KEY_FOR_DIGITAL_SIGNATURE). This module's validation {} blocks only check that each field is a recognized enum value — they cannot check cross-field validity — so the service itself will reject an invalid combination at apply time. Consult the AWS Payment Cryptography "key attributes" reference.
  • Destroy-ordering / recreate surprises. Any change to exportable or a key_attributes field silently recreates the key (FORCE-NEW) — a new ARN and new key material result, and any aliases pointing at the old key must be re-pointed. Plan changes to these fields as a deliberate rotation event.
  • Key seems "hung" mid-delete. Deletion is scheduled, not immediate (mirroring KMS) — the key transitions through a pending-deletion state before it is gone; use RestoreKey within the window to recover if the destroy was unintended.

🔗 Related Docs

  • Terraform Registry — aws_paymentcryptography_key, aws_paymentcryptography_key_alias
  • AWS Payment Cryptography User Guide — understanding key attributes and valid key/mode combinations
  • AWS Payment Cryptography User Guide — creating keys, managing aliases, key tagging
  • AWS Payment Cryptography User Guide — quotas for control-plane and data-plane operations
  • module suite — tf-mod-aws-iam-role, tf-mod-aws-iam-policy, tf-mod-aws-kms (for general-purpose encryption, a distinct service)

🧡 "Infrastructure as Code should be standardized, consistent, and secure."

About

No description or website provided.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages