This check flags AWS Glue security configurations that leave job bookmark encryption turned off, which means the state data Glue tracks between job runs sits in S3 unencrypted. Create or update the security configuration with a KMS key for bookmark encryption and attach it to your jobs.
AWS Glue job bookmarks are one of those features that quietly do a lot of work. They let an ETL job remember what it already processed so the next run only picks up new data. Useful, but that bookmark state has to live somewhere, and by default it can be stored without encryption. This check catches Glue security configurations where bookmark encryption is disabled, leaving that state data exposed at rest.
What this check detects
The glue_bookmarkencryption check inspects each AWS Glue security configuration in your account and verifies that the job bookmark encryption mode is set to CSE-KMS rather than DISABLED.
A Glue security configuration is a reusable bundle of encryption settings that you attach to jobs, crawlers, and development endpoints. It controls three independent things:
- S3 encryption for data written by the job
- CloudWatch Logs encryption for the job's logs
- Job bookmark encryption for the bookmark state itself
The check focuses on the third one. When bookmark encryption is set to DISABLED, Glue stores the serialized bookmark state without applying client-side KMS encryption. The check passes only when the mode is CSE-KMS and a KMS key is referenced.
Note: Bookmark encryption in Glue uses client-side encryption with KMS (CSE-KMS). Glue encrypts the bookmark data before it ever reaches storage, using a key you control, rather than relying solely on the storage layer to encrypt it.
Why it matters
It is easy to dismiss bookmarks as harmless metadata. They are not. A job bookmark records which records, files, or partitions a job has already consumed. Depending on your source, that can include:
- S3 object keys and prefixes, which often encode customer IDs, tenant names, or date partitions
- Database table names and primary key ranges
- Timestamps and offsets that reveal processing cadence and data volumes
None of that is the raw data itself, but it is a detailed map of where sensitive data lives and how it flows through your pipeline. An attacker who gains read access to the bucket holding unencrypted bookmark state gets a reconnaissance gift: a structured index pointing straight at your most active datasets.
There is also a compliance angle. Frameworks like PCI DSS, HIPAA, and SOC 2 expect encryption at rest for anything that touches regulated data or its identifiers. A bookmark that contains customer-keyed S3 paths can fall inside that scope. An auditor who finds bookmark encryption disabled while the rest of the pipeline is encrypted will rightly ask why one part was left open.
Warning: Bookmark encryption is configured per security configuration, and a security configuration is immutable once created. You cannot edit an existing one to flip the setting. You create a new configuration and re-point your jobs at it, which means this is not a one-click toggle.
How to fix it
Because security configurations cannot be modified after creation, fixing this involves creating a new one with bookmark encryption enabled and reassigning your jobs.
Step 1: Pick or create a KMS key
You need a customer managed KMS key (or an existing one) that Glue can use. The Glue service role must have permission to use it.
aws kms create-key \
--description "Glue bookmark encryption" \
--tags TagKey=purpose,TagValue=glue-bookmarks
Grant your Glue job role permission on the key. Add a statement like this to the key policy or to the role's IAM policy:
{
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:us-east-1:111122223333:key/your-key-id"
}
Step 2: Create a new security configuration with bookmark encryption
aws glue create-security-configuration \
--name etl-secure-config-v2 \
--encryption-configuration '{
"JobBookmarksEncryption": {
"JobBookmarksEncryptionMode": "CSE-KMS",
"KmsKeyArn": "arn:aws:kms:us-east-1:111122223333:key/your-key-id"
},
"S3Encryption": [{
"S3EncryptionMode": "SSE-KMS",
"KmsKeyArn": "arn:aws:kms:us-east-1:111122223333:key/your-key-id"
}],
"CloudWatchEncryption": {
"CloudWatchEncryptionMode": "SSE-KMS",
"KmsKeyArn": "arn:aws:kms:us-east-1:111122223333:key/your-key-id"
}
}'
Setting all three encryption modes at once is good practice, but the field this check cares about is JobBookmarksEncryption with mode CSE-KMS.
Step 3: Attach the configuration to your jobs
Danger: Updating a production Glue job changes how it runs on the next invocation. Re-point jobs during a maintenance window and verify the run completes before assuming the change is safe, especially if jobs share a schedule or feed downstream consumers.
aws glue update-job \
--job-name daily-customer-etl \
--job-update '{
"Role": "arn:aws:iam::111122223333:role/GlueETLRole",
"Command": {
"Name": "glueetl",
"ScriptLocation": "s3://my-scripts/daily-customer-etl.py"
},
"SecurityConfiguration": "etl-secure-config-v2"
}'
Note that update-job replaces the full job definition, so include the existing values for Role, Command, and any other fields you do not want reset to defaults. Pull the current definition first with aws glue get-job --job-name daily-customer-etl and edit from there.
Note: When you enable bookmark encryption on a job that already has bookmark history, Glue can read the old unencrypted state and write encrypted state going forward. You do not need to reset bookmarks, but test it, since a misconfigured key permission will cause the job to fail on its first encrypted write.
Console steps
- Open the AWS Glue console and go to Data Integration and ETL > Security configurations.
- Choose Add security configuration.
- Give it a name and check Job bookmark encryption, selecting your KMS key.
- Optionally enable S3 and CloudWatch Logs encryption with the same key.
- Create it, then open each affected job, edit Job details > Advanced properties > Security configuration, and select the new one.
Doing this in infrastructure as code
If you manage Glue with Terraform, bake the encryption settings into the resource so they cannot drift back to disabled.
resource "aws_glue_security_configuration" "etl" {
name = "etl-secure-config"
encryption_configuration {
job_bookmarks_encryption {
job_bookmarks_encryption_mode = "CSE-KMS"
kms_key_arn = aws_kms_key.glue.arn
}
s3_encryption {
s3_encryption_mode = "SSE-KMS"
kms_key_arn = aws_kms_key.glue.arn
}
cloudwatch_encryption {
cloudwatch_encryption_mode = "SSE-KMS"
kms_key_arn = aws_kms_key.glue.arn
}
}
}
resource "aws_glue_job" "daily_customer_etl" {
name = "daily-customer-etl"
role_arn = aws_iam_role.glue.arn
security_configuration = aws_glue_security_configuration.etl.name
command {
script_location = "s3://my-scripts/daily-customer-etl.py"
}
}
Because the security configuration is immutable, changing the encryption block forces Terraform to destroy and recreate it. Plan that into your change, and reference the configuration by name on every job so the recreation cascades cleanly.
Tip: Define one shared module for your Glue security configuration and KMS key, then have every team consume it. That way "encryption on" is the default people inherit, not a checkbox each engineer has to remember.
How to prevent it from happening again
One-time remediation does not stop the next job from launching without a security configuration at all. Build guardrails so the secure path is the easy path.
Gate it in CI/CD with policy as code
If you use Terraform, an OPA or Conftest policy can reject any Glue security configuration that does not set bookmark encryption to CSE-KMS.
package glue
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_glue_security_configuration"
mode := resource.change.after.encryption_configuration[_].job_bookmarks_encryption[_].job_bookmarks_encryption_mode
mode != "CSE-KMS"
msg := sprintf("Glue security config '%s' must enable bookmark encryption (CSE-KMS)", [resource.address])
}
Run that against your terraform plan output in the pipeline, and the build fails before anything reaches AWS.
Enforce continuous detection
Policy gates only catch what flows through your pipeline. Resources created by hand in the console, or by another team, slip past. Run a continuous check across all accounts and regions so anything created out of band gets caught. Lensix runs glue_bookmarkencryption on a schedule across your AWS footprint and flags any security configuration that drifts, including ones that never went through Terraform.
Tip: Pair the policy gate with the continuous check. The gate keeps known infrastructure clean, and the scanner catches the shadow resources. Together they close both the front and back doors.
Best practices
- Encrypt all three layers. If you are taking the time to make a security configuration, enable S3, CloudWatch Logs, and bookmark encryption together. Partial encryption is a confusing state to maintain and audit.
- Use customer managed KMS keys. They give you control over rotation, key policies, and an audit trail of every decrypt in CloudTrail. That visibility is exactly what bookmark state deserves.
- Standardize on a single security configuration per environment. Fewer configurations mean fewer places for a misconfiguration to hide, and immutability is far less painful to manage at small numbers.
- Restrict KMS key usage. Grant decrypt permission only to the Glue roles that need it. A bookmark encrypted with a key that half the account can use is barely encrypted at all.
- Audit jobs without any security configuration. A job with no configuration attached has no bookmark encryption by definition. Treat the absence of a configuration as a finding, not just the wrong setting inside one.
- Document the recreation process. Since configurations are immutable, write down how you rotate them so an emergency key change does not turn into a scramble.
Bookmark encryption is a small setting with an outsized payoff. It costs almost nothing to enable, removes a quiet source of metadata leakage, and closes a gap auditors notice. Turn it on, gate it in your pipeline, and scan for drift so it stays on.

