Check if Glue ML Transform Encryption at Rest is Enabled
Overview
This check verifies that AWS Glue machine learning (ML) transforms have encryption at rest enabled. Glue ML transforms process and store user data, including training datasets and model artifacts. When encryption is not enabled, this data is stored unencrypted in Amazon S3.
Risk
Without encryption at rest:
- Data exposure: Transform artifacts, training data, and sample datasets may be accessible to unauthorized users who gain access to the underlying storage
- Compliance violations: Many regulatory frameworks (ISO27001, C5, KISA-ISMS-P) require encryption of data at rest
- Lateral movement: Attackers could discover sensitive schemas and data relationships by accessing unencrypted ML transform data
Remediation Steps
Prerequisites
- AWS account access with permissions to manage Glue resources and KMS keys
- An existing KMS key, or permission to create one
Important: Encryption settings cannot be changed on existing ML transforms. You must recreate the transform with encryption enabled.
AWS Console Method
- Open the AWS Glue Console at https://console.aws.amazon.com/glue/
- In the left navigation, select ML transforms under Machine learning
- Note the configuration of your existing unencrypted transform (name, input tables, parameters, role, etc.)
- Click Create transform to create a new encrypted version
- Configure the transform with the same settings as your existing one
- In the Transform encryption section:
- For User data encryption mode, select SSE-KMS
- For AWS KMS key, choose an existing key or create a new one
- Click Create
- After verifying the new transform works correctly, delete the old unencrypted transform
AWS CLI (optional)
List existing transforms
aws glue get-ml-transforms \
--region us-east-1 \
--query 'Transforms[*].{TransformId:TransformId,Name:Name}' \
--output table
Get details of an existing transform
aws glue get-ml-transform \
--transform-id <your-transform-id> \
--region us-east-1
Create a new encrypted ML transform
aws glue create-ml-transform \
--name "my-encrypted-transform" \
--input-record-tables '[{"DatabaseName":"my_database","TableName":"my_table"}]' \
--parameters '{"TransformType":"FIND_MATCHES","FindMatchesParameters":{"PrimaryKeyColumnName":"id"}}' \
--role "arn:aws:iam::123456789012:role/GlueServiceRole" \
--transform-encryption '{"MlUserDataEncryption":{"MlUserDataEncryptionMode":"SSE-KMS","KmsKeyId":"arn:aws:kms:us-east-1:123456789012:key/your-key-id"}}' \
--region us-east-1
Delete the old unencrypted transform
After verifying the new transform works correctly:
aws glue delete-ml-transform \
--transform-id <old-transform-id> \
--region us-east-1
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Glue ML Transform with encryption at rest enabled
Parameters:
KMSKeyArn:
Type: String
Description: ARN of the KMS key for encrypting ML transform data
GlueRoleArn:
Type: String
Description: ARN of the IAM role for the Glue ML transform
DatabaseName:
Type: String
Description: Name of the Glue database containing the source table
TableName:
Type: String
Description: Name of the source table for the ML transform
Resources:
EncryptedMLTransform:
Type: AWS::Glue::MLTransform
Properties:
Name: encrypted-ml-transform
Description: ML Transform with encryption at rest enabled
Role: !Ref GlueRoleArn
InputRecordTables:
GlueTables:
- DatabaseName: !Ref DatabaseName
TableName: !Ref TableName
TransformParameters:
TransformType: FIND_MATCHES
FindMatchesParameters:
PrimaryKeyColumnName: id
PrecisionRecallTradeoff: 0.5
AccuracyCostTradeoff: 0.5
TransformEncryption:
MLUserDataEncryption:
MLUserDataEncryptionMode: SSE-KMS
KmsKeyId: !Ref KMSKeyArn
Outputs:
TransformId:
Description: ID of the created ML transform
Value: !Ref EncryptedMLTransform
Deploy the template:
aws cloudformation create-stack \
--stack-name glue-ml-transform-encrypted \
--template-body file://template.yaml \
--parameters \
ParameterKey=KMSKeyArn,ParameterValue=arn:aws:kms:us-east-1:123456789012:key/your-key-id \
ParameterKey=GlueRoleArn,ParameterValue=arn:aws:iam::123456789012:role/GlueServiceRole \
ParameterKey=DatabaseName,ParameterValue=my_database \
ParameterKey=TableName,ParameterValue=my_table \
--region us-east-1
Terraform (optional)
Note: As of early 2026, the Terraform AWS provider does not support the transform_encryption attribute for aws_glue_ml_transform. You can manage the KMS key and IAM resources with Terraform, then create the ML transform using the AWS CLI or a null_resource with a local-exec provisioner.
# KMS key for ML transform encryption
resource "aws_kms_key" "glue_ml_transform" {
description = "KMS key for Glue ML Transform encryption"
deletion_window_in_days = 30
enable_key_rotation = true
tags = {
Name = "glue-ml-transform-key"
}
}
resource "aws_kms_alias" "glue_ml_transform" {
name = "alias/glue-ml-transform"
target_key_id = aws_kms_key.glue_ml_transform.key_id
}
# IAM role for Glue service
resource "aws_iam_role" "glue_service" {
name = "glue-ml-transform-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "glue.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "glue_service" {
role = aws_iam_role.glue_service.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole"
}
# KMS key policy to allow Glue access
resource "aws_kms_key_policy" "glue_ml_transform" {
key_id = aws_kms_key.glue_ml_transform.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
}
Action = "kms:*"
Resource = "*"
},
{
Sid = "Allow Glue Service"
Effect = "Allow"
Principal = {
Service = "glue.amazonaws.com"
}
Action = [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
Resource = "*"
}
]
})
}
data "aws_caller_identity" "current" {}
# Glue catalog resources
resource "aws_glue_catalog_database" "example" {
name = "example_database"
}
resource "aws_glue_catalog_table" "example" {
name = "example_table"
database_name = aws_glue_catalog_database.example.name
storage_descriptor {
columns {
name = "id"
type = "string"
}
}
}
# Create ML transform with encryption using AWS CLI
# (Terraform does not yet support transform_encryption attribute)
resource "null_resource" "encrypted_ml_transform" {
provisioner "local-exec" {
command = <<-EOT
aws glue create-ml-transform \
--name "encrypted-ml-transform" \
--input-record-tables '[{"DatabaseName":"${aws_glue_catalog_database.example.name}","TableName":"${aws_glue_catalog_table.example.name}"}]' \
--parameters '{"TransformType":"FIND_MATCHES","FindMatchesParameters":{"PrimaryKeyColumnName":"id"}}' \
--role "${aws_iam_role.glue_service.arn}" \
--transform-encryption '{"MlUserDataEncryption":{"MlUserDataEncryptionMode":"SSE-KMS","KmsKeyId":"${aws_kms_key.glue_ml_transform.arn}"}}' \
--region us-east-1
EOT
}
depends_on = [
aws_iam_role_policy_attachment.glue_service,
aws_kms_key_policy.glue_ml_transform,
aws_glue_catalog_table.example
]
}
Verification
After creating your encrypted ML transform:
- Go to the AWS Glue Console
- Select ML transforms in the left navigation
- Click on your transform name
- In the Transform details section, verify that User data encryption shows SSE-KMS and displays your KMS key
CLI verification
aws glue get-ml-transform \
--transform-id <your-transform-id> \
--region us-east-1 \
--query 'TransformEncryption.MlUserDataEncryption'
Expected output for an encrypted transform:
{
"MlUserDataEncryptionMode": "SSE-KMS",
"KmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
}
Additional Resources
- AWS Glue ML Transforms Documentation
- AWS Glue Encryption at Rest
- AWS KMS Developer Guide
- Prowler Check Documentation
Notes
-
Encryption cannot be modified: Once an ML transform is created, you cannot change its encryption settings. To enable encryption on an existing unencrypted transform, you must create a new transform with encryption enabled and delete the old one.
-
KMS key permissions: The IAM role used by your Glue ML transform must have permissions to use the KMS key for encryption and decryption operations.
-
Customer-managed keys recommended: While AWS-managed keys work, customer-managed KMS keys provide additional control over key rotation, access policies, and audit logging.
-
Cost considerations: Using KMS encryption adds a small cost for KMS API calls. Customer-managed keys also incur a monthly key storage fee.