Step Functions state machine is encrypted at rest with a customer-managed KMS key
AWS Step Functions state machines store execution history and input/output data passed between workflow states. This check verifies that each state machine uses a customer-managed KMS key (CUSTOMER_MANAGED_KMS_KEY) for encryption at rest rather than the default AWS-owned key.
Risk
Without a customer-managed KMS key, execution history containing sensitive input/output data is protected only by an AWS-owned key you cannot control, rotate, or revoke. This limits auditability via CloudTrail, prevents independent access revocation, and weakens confidentiality for regulated workloads.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks stepfunctions_statemachine_encrypted_with_cmkRecommendation
Configure each Step Functions state machine to use a customer-managed KMS key for encryption at rest. Assign a least-privilege key policy, enable automatic key rotation, and grant the execution role kms:GenerateDataKey and kms:Decrypt. Monitor key usage via CloudTrail.
Remediation
CLI
aws stepfunctions update-state-machine --state-machine-arn <state-machine-arn> --encryption-configuration '{"kmsKeyId": "<kms-key-id>", "type": "CUSTOMER_MANAGED_KMS_KEY", "kmsDataKeyReusePeriodSeconds": 300}'Terraform
resource "aws_sfn_state_machine" "<example_resource_name>" {
name = "<example_resource_name>"
role_arn = "arn:aws:iam::<account-id>:role/<example_role_name>"
definition = jsonencode({ StartAt = "Pass", States = { Pass = { Type = "Pass", End = true } } })
encryption_configuration {
kms_key_id = "arn:aws:kms:<region>:<account-id>:key/<key-id>" # Critical: customer-managed KMS key
type = "CUSTOMER_MANAGED_KMS_KEY" # Critical: must be CUSTOMER_MANAGED_KMS_KEY
kms_data_key_reuse_period_seconds = 300
}
}NativeIaC
Resources:
<example_resource_name>:
Type: AWS::StepFunctions::StateMachine
Properties:
RoleArn: arn:aws:iam::<account-id>:role/<example_role_name>
DefinitionString: |
{"StartAt":"Pass","States":{"Pass":{"Type":"Pass","End":true}}}
EncryptionConfiguration:
KmsKeyId: arn:aws:kms:<region>:<account-id>:key/<key-id> # Critical: customer-managed KMS key
Type: CUSTOMER_MANAGED_KMS_KEY # Critical: must be CUSTOMER_MANAGED_KMS_KEY
KmsDataKeyReusePeriodSeconds: 300Other
Check Code
from typing import List
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.stepfunctions.stepfunctions_client import (
stepfunctions_client,
)
from prowler.providers.aws.services.stepfunctions.stepfunctions_service import (
EncryptionType,
)
class stepfunctions_statemachine_encrypted_with_cmk(Check):
"""Ensure Step Functions state machines are encrypted at rest with a customer-managed KMS key.
This check evaluates whether each AWS Step Functions state machine uses a
customer-managed KMS key (CUSTOMER_MANAGED_KMS_KEY) for encryption at rest rather
than the default AWS-owned key (AWS_OWNED_KEY).
- PASS: The state machine encryption_configuration type is CUSTOMER_MANAGED_KMS_KEY.
- FAIL: The state machine has no encryption_configuration or its type is AWS_OWNED_KEY.
"""
def execute(self) -> List[Check_Report_AWS]:
"""Execute the Step Functions state machine encryption at rest check.
Iterates over all Step Functions state machines and generates a report
indicating whether each state machine uses a customer-managed KMS key
for encryption at rest.
Returns:
List[Check_Report_AWS]: A list of report objects with the results of the check.
"""
findings = []
for state_machine in stepfunctions_client.state_machines.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=state_machine)
if (
state_machine.encryption_configuration
and state_machine.encryption_configuration.type
== EncryptionType.CUSTOMER_MANAGED_KMS_KEY
):
report.status = "PASS"
report.status_extended = f"Step Functions state machine {state_machine.name} is encrypted at rest with a customer-managed KMS key."
else:
report.status = "FAIL"
report.status_extended = f"Step Functions state machine {state_machine.name} is not encrypted at rest with a customer-managed KMS key."
findings.append(report)
return findings