Encrypt Data with AWS KMS

Encrypt a DynamoDB table with AWS KMS and test key-policy access controls.

Introduction

30 Second Summary

A person can have permission to reach a locked file without having permission to reveal what is inside it. Sensitive digital records need the same separation.

In this project, you will build a security lab around an Amazon DynamoDB record protected by a customer managed key from AWS Key Management Service (AWS KMS). Two AWS Identity and Access Management (IAM) roles will have matching database permissions, while a key policy lets only the approved role reveal the plaintext.

What You'll Build

You'll switch between two roles with identical DynamoDB permissions to watch one display the protected record while the other reaches the table but receives an access denial.

By the end of this project, you'll have:

  • A live encrypted record that displays RecordId as demo-001 beside SecretValue as quarterly-payroll-demo.
  • A two-role baseline showing that identical DynamoDB permissions let both KMSAllowedRole and KMSBlockedRole read the item under the default AWS owned key.
  • A side-by-side authorization result where KMSAllowedRole displays the plaintext while KMSBlockedRole receives an access denial after the table moves to alias/dynamodb-data-protection-lab.
  • Secret Mission: Give the blocked role a broad kms:* allow, then prove that a targeted kms:Decrypt deny still wins.

Are there any prerequisites?

An AWS account with admin-level access through a non-root IAM or federated identity is required. A Windows device with a web browser provides access to the AWS Management Console.

Before We Start

This first checkpoint locks in the lab's target outcome before any AWS resources exist. KMSAllowedRole should read the demo item, while KMSBlockedRole should fail because AWS KMS authorization sits beyond their identical Amazon DynamoDB permissions.

Set Up a Safe AWS Lab Session

This lab creates policies that depend on your AWS account ID. A wrong account or Region would make later role tests or cleanup point at the wrong place.

The AWS Management Console can switch roles only from supported non-root sessions. You'll verify the active identity before any resource exists.

In this step, get ready to:
  • Confirm a non-root administrative identity.
  • Anchor the lab to your AWS account ID in us-east-1.
  • Prepare separate tabs for AWS Identity and Access Management (IAM), Amazon DynamoDB, and AWS Key Management Service (AWS KMS).
Confirm your active identity

Console role switching requires a supported non-root session. The root user cannot switch roles in the console.

Which sessions support role switching?

The console supports several kinds of non-root sessions.

  • An administrative IAM user is supported.
  • An IAM Identity Center user is supported.
  • A SAML-federated role is supported.
  • A web-identity federated role is supported.

The AWS account root user is excluded from console role switching.

The identity details can be easy to miss because they sit inside the account menu.

  • Navigate to the AWS Management Console in your browser.
  • Sign in with your admin-level identity if the console asks you to authenticate.
  • Open the account menu in the console header.
  • Check the identity shown for the active session.

✔️ I see a non-root identity

Your session supports the role-switch tests used later in the lab.

ⓧ The menu identifies the root user

A root session cannot continue with the console role-switch tests. Change identities before creating any resources.

  • End the root session from the account menu.
  • Return to the AWS Management Console sign-in page.
  • Sign in with a non-root administrative identity.
  • Open the account menu.
  • Confirm that the menu identifies a non-root session.

Can't identify the active session?

Check the identity details inside the account menu. Avoid creating lab resources until you can confirm that the session is not the root user.

Help me identify my AWS session type

Set the Region and record your account ID

Your account ID makes each policy point to your AWS account. The selected Region keeps every regional lab resource in one location.

  • Open the Region selector in the console header.
  • Select US East (N. Virginia).
  • Open the account menu.
  • Locate the 12-digit AWS account ID.
  • Record the value here: your 12-digit AWS account ID.

The Region code for your selection is us-east-1. Later, your recorded value replaces your-12-digit-account-id in the policy JSON.

Prepare the three console tabs

Separate tabs keep the three services ready for later policy comparisons. You can return to the original admin session without losing your place.

  • Open the IAM console in a new browser tab.
  • Open the DynamoDB console in another browser tab.
  • Open the AWS KMS console in another browser tab.

Before you check, decide which identity and Region you expect to see.

  • Return to one of the three service console tabs.
  • Open the account menu.
  • Confirm that the session identifies your non-root administrative identity.
  • Open the Region selector.
  • Confirm that US East (N. Virginia) is selected.
  • Inspect the browser tab bar.

You'll see separate tabs for IAM, DynamoDB, and AWS KMS.

The account menu shows your non-root identity. The Region selector shows US East (N. Virginia).

That's the groundwork secured: your non-root session is ready for role switching.

Your lab session is anchored to a non-root identity in us-east-1. Next up, you'll build the baseline encrypted table.

Build the Baseline Encrypted Table

Your AWS Management Console session is ready in US East (N. Virginia). Your 12-digit account ID is recorded for the policy work ahead.

You now need a readable data baseline for every later access test. Amazon DynamoDB encrypts every table using encryption at rest.

Its default AWS owned key gives you an immediate working result. That key does not accept your own principal-level key policy.

In this step, get ready to:
  • Create the KMSPolicyLab table with default encryption.
  • Store one clearly fake test record.
  • Read the record under the default AWS owned key.
Create the baseline table

A DynamoDB table uses a partition key to identify each item. This lab uses RecordId so every test record has a stable identifier.

  • Switch back to the Amazon DynamoDB console tab from earlier.
  • Select Tables in the left navigation.
  • Choose Create table.
  • Enter KMSPolicyLab as the table name.
  • Enter RecordId as the partition key.
  • Select String as the partition key type.
  • Keep Default settings selected.
  • Choose Create table.

What Does Default Encryption Mean?

All DynamoDB table data is encrypted at rest. Encryption cannot be disabled.

Default settings use an AWS owned key.

AWS manages that key. You cannot view it or change its permissions.

  • Wait until the table status changes to ACTIVE.

The first lab resource is ready: KMSPolicyLab is active under its default encryption.

Table Still Becoming Active?

  • Refresh the table list to retrieve its current status.
  • Confirm that the console still shows US East (N. Virginia).

Help me troubleshoot a DynamoDB table that is not reaching ACTIVE status.

Add the fake test record

The item gives later role tests one fixed plaintext target. Its values are deliberately fake so the lab contains no confidential information.

  • Choose Explore table items for KMSPolicyLab.
  • Choose Create item.
  • Enter demo-001 as the RecordId value.
  • Choose Add new attribute.
  • Choose String.
  • Enter SecretValue as the new attribute name.
  • Enter quarterly-payroll-demo as the new attribute value.
  • Choose Create item.

Good progress: your table now contains the fixed record that every later role test will attempt to read.

Why Use a Fake Record?

Authorization labs should use recognisable test data with no real business value. The fake payroll label makes the protected field easy to spot without exposing confidential information.

Item Not Saving?

  • Check that RecordId contains demo-001.
  • Check that SecretValue uses the String type.
  • Check that the new attribute contains quarterly-payroll-demo.

Help me fix a DynamoDB item that does not save.

Verify the readable baseline

A baseline gives you a known working result before the encryption controls change. This read confirms that the table currently returns its stored plaintext to your original admin session.

Before you check, make a prediction: the original admin session can read this table under the default AWS owned key, or it cannot.

  • Return to Explore table items.
  • Confirm that Items returned shows RecordId equal to demo-001.
  • Confirm that Items returned shows SecretValue equal to quarterly-payroll-demo.

Your baseline is working: the encrypted table returns both values through the original admin session.

Can't See the Demo Item?

  • Refresh Explore table items to reload the item list.
  • Confirm that you are viewing KMSPolicyLab.
  • Confirm that the console still shows US East (N. Virginia).

Help me find the missing DynamoDB demo item.

Your encrypted baseline is readable under the default AWS owned key. Next up, you'll create two roles with matching DynamoDB permissions for a controlled comparison.

Create Matching DynamoDB Roles

Your Amazon DynamoDB table currently reveals the test item under its default AWS owned key. To isolate what changes later, you need two AWS Identity and Access Management (IAM) roles with the same table permissions.

These matching roles create a controlled baseline. If both can read the item now, any later difference points to the authorization rules protecting the encryption key.

In this step, get ready to:
  • Create two roles that trust identities from your AWS account.
  • Give both roles the same permissions for the lab table.
  • Switch into each role to verify the same readable item.
Create the same-account roles

An IAM role provides temporary permissions during a role session. The trust settings define which identities can enter that role.

  • Return to the IAM console tab from earlier.
  • Choose Roles in the left navigation pane.
  • Choose Create role.
  • Choose AWS account as the trusted entity type.
  • Choose This account.
  • Keep the external ID requirement disabled.

What does the trust choice control?

The trust policy accepts principals from your AWS account. Your existing admin session supplies the permission required to switch into the role.

An external ID protects certain cross-account relationships. This same-account lab does not need one.

  • Choose Next.
  • Leave Permissions policies unselected.
  • Choose Next.
  • Enter KMSAllowedRole in the Role name field.
  • Choose Create role.

The role detail page confirms that KMSAllowedRole exists without a permissions policy. That first comparison identity is ready.

  • Return to Roles.
  • Choose Create role.
  • Choose AWS account.
  • Choose This account.
  • Keep the external ID requirement disabled.
  • Choose Next.
  • Leave Permissions policies unselected.
  • Choose Next.

The role details page now uses the same trust configuration as the first role.

  • Enter KMSBlockedRole in the Role name field.
  • Choose Create role.
  • Return to Roles.
  • Confirm that KMSAllowedRole appears in the roles list.
  • Confirm that KMSBlockedRole appears in the roles list.

Good progress. You now have two temporary identities with matching trust settings.

Give both roles the same table policy

An inline policy is embedded directly in one IAM identity. Applying the same document to both roles keeps DynamoDB permission from becoming a hidden variable in the comparison.

  • Choose KMSAllowedRole from the Roles list.
  • Choose the Permissions tab.
  • Choose Add permissions.
  • Choose Create inline policy.
  • Choose the JSON editor option.
  • Replace the editor contents by copying the policy below:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllActionsOnLabTable",
      "Effect": "Allow",
      "Action": "dynamodb:*",
      "Resource": "arn:aws:dynamodb:us-east-1:your-12-digit-account-id:table/KMSPolicyLab"
    },
    {
      "Sid": "ListTablesForConsole",
      "Effect": "Allow",
      "Action": "dynamodb:ListTables",
      "Resource": "*"
    }
  ]
}

What does this policy do?

  • The AllActionsOnLabTable statement permits dynamodb:* on the KMSPolicyLab table only.
  • The table ARN anchors that permission to your account in us-east-1.
  • The ListTablesForConsole statement permits dynamodb:ListTables so the console can display the table list.
  • Replace your-12-digit-account-id with the account ID you recorded earlier.
  • Choose Next.
  • Enter dynamodb-table-access.json in the Policy name field.
  • Choose Create policy.
  • Confirm that dynamodb-table-access.json appears on the role's Permissions tab.

Policy validation failing?

  • Check that the account ID contains exactly 12 digits.
  • Check that the table ARN contains us-east-1.
  • Check that the table name is exactly KMSPolicyLab.

Ask for help with the policy document: Help me find the validation problem in my DynamoDB IAM policy.

  • Return to Roles.
  • Choose KMSBlockedRole.
  • Choose the Permissions tab.
  • Choose Add permissions.
  • Choose Create inline policy.
  • Choose the JSON editor option.
  • Paste the same policy shown above into the editor.
  • Replace your-12-digit-account-id with the same recorded account ID.

Why exact matching matters

Both roles need the same actions against the same table ARN. That symmetry makes the encryption key policy the only meaningful permission difference later.

  • Choose Next.
  • Enter dynamodb-table-access.json in the Policy name field.
  • Choose Create policy.
  • Confirm that dynamodb-table-access.json appears on the role's Permissions tab.

The permissions now match. Both roles can perform the same DynamoDB actions against the same lab table.

✔️ Awesome, I've got everything!

Great. Double-check that both roles list dynamodb-table-access.json on their Permissions tab.

ⓧ I'd like to double check the full code

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllActionsOnLabTable",
      "Effect": "Allow",
      "Action": "dynamodb:*",
      "Resource": "arn:aws:dynamodb:us-east-1:your-12-digit-account-id:table/KMSPolicyLab"
    },
    {
      "Sid": "ListTablesForConsole",
      "Effect": "Allow",
      "Action": "dynamodb:ListTables",
      "Resource": "*"
    }
  ]
}
Test the baseline under the AWS owned key

The table still uses its default AWS owned key. Testing both roles now establishes what matching DynamoDB permissions can access before you introduce a customer-controlled key policy.

  • Pause to predict whether both roles reveal the same item under the AWS owned key.
  • Open the account menu in the original admin session.
  • Choose Switch role.
  • Enter the 12-digit account ID you recorded earlier.
  • Enter KMSAllowedRole as the role name.
  • Choose Switch Role.

The account menu now identifies the active session as KMSAllowedRole.

  • Return to the DynamoDB console tab from earlier.
  • Choose KMSPolicyLab from Tables.
  • Choose Explore table items.

You'll see demo-001 under RecordId. Its SecretValue is quarterly-payroll-demo.

The first controlled read works. KMSAllowedRole can display the same plaintext as your admin identity.

  • Open the account menu.
  • Choose Switch back.
  • Open the account menu again.
  • Choose Switch role.
  • Enter the same 12-digit account ID.
  • Enter KMSBlockedRole as the role name.
  • Choose Switch Role.

The account menu now identifies the active session as KMSBlockedRole.

  • Return to the DynamoDB console tab from earlier.
  • Choose KMSPolicyLab from Tables.
  • Choose Explore table items.

You'll see demo-001 under RecordId. Its SecretValue is still quarterly-payroll-demo.

What did this baseline prove?

Both roles have matching DynamoDB permissions. Both roles can read the same item.

DynamoDB always uses encryption at rest. The AWS owned key has no customer-editable policy that can distinguish these named roles.

Can't read the item from a role?

  • Confirm that the active role's Permissions tab lists dynamodb-table-access.json.
  • Confirm that the policy ARN contains your recorded account ID.
  • Confirm that the policy ARN ends with table/KMSPolicyLab.

Ask for help with the role comparison: Help me diagnose why one of my matching IAM roles cannot read KMSPolicyLab.

  • Open the account menu.
  • Choose Switch back to restore the original admin session.

Your comparison is ready. Next, you'll place the table behind a customer managed key that treats these matching roles differently.

Encrypt the Table with Your KMS Key

Your two AWS Identity and Access Management (IAM) roles can currently read the same record. Amazon DynamoDB protects the table with encryption at rest through its default AWS owned key.

The default key offers no editable principal-level key policy. You'll create a customer managed key in AWS Key Management Service (AWS KMS) so only KMSAllowedRole receives service-scoped key use.

In this step, get ready to:
  • Create a single-Region symmetric KMS key for the lab.
  • Replace the key policy with service-scoped permissions for KMSAllowedRole.
  • Move KMSPolicyLab from its AWS owned key to your customer managed key.
Create a customer managed KMS key

DynamoDB requires a symmetric encryption key for table encryption. A single-Region key gives this lab one key to configure.

Creating this customer managed key starts the $1/month prorated hourly storage charge. Keeping the lab brief keeps the estimated project cost under $0.01.

  • Select the search box in the AWS Management Console navigation bar.
  • Enter AWS Key Management Service (AWS KMS).
  • Select the AWS Key Management Service result.
  • Choose Customer managed keys in the left navigation panel.
  • Choose Create key.
  • Choose the Symmetric key type.
  • Choose the Encrypt and decrypt key usage.
  • Choose the single-Region option.

Why a customer managed key?

The AWS managed key for DynamoDB has permissions you cannot change. A customer managed key gives you an editable policy for naming approved principals.

  • Choose Next.
  • Enter dynamodb-data-protection-lab in the Alias field. The console adds the alias/ prefix automatically.
  • Choose Next.
  • Select your current non-root admin identity under Key administrators.
  • Choose Next.
  • Leave KMSAllowedRole unselected under Key users.
  • Leave KMSBlockedRole unselected under Key users.
  • Choose Next.

Protect Administrative Access

The policy preview retains an account-access safety statement. This allows your owning AWS account to delegate administrative key permissions through IAM policies.

  • Confirm the account-access safety statement remains visible in the policy preview.
  • Choose Finish.
  • Confirm alias/dynamodb-data-protection-lab appears in the customer managed keys list.

Good progress. The new alias now identifies the key that will protect your DynamoDB table.

Don't See the New Key?

Confirm the console still shows US East (N. Virginia). Check the customer managed keys list for alias/dynamodb-data-protection-lab.

Help me find the customer managed KMS key I created.

Replace the key policy

The key policy decides which principals can use this key. The replacement policy preserves account administration while granting DynamoDB-scoped key use to KMSAllowedRole.

  • Select alias/dynamodb-data-protection-lab from the customer managed keys list.
  • Select the Key policy tab.
  • Choose Switch to policy view.
  • Choose Edit.
  • Select the second tab below.
  • Replace the policy editor contents with the full kms-key-policy.json reference.

✔️ Awesome, I've got everything!

Your policy is ready once the editor matches the full file in the second tab.

ⓧ I'd like to double check the full code

{
  "Id": "key-policy-dynamodb-lab",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EnableIAMPoliciesForAccountAdministration",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::your-12-digit-account-id:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowDynamoDBUseForApprovedRole",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::your-12-digit-account-id:role/KMSAllowedRole"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey",
        "kms:CreateGrant"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "kms:ViaService": "dynamodb.*.amazonaws.com"
        }
      }
    }
  ]
}

What Does This Key Policy Do?

  • The EnableIAMPoliciesForAccountAdministration statement preserves key administration through the owning account.
  • The AllowDynamoDBUseForApprovedRole statement grants the approved role the KMS actions DynamoDB needs.
  • The kms:ViaService condition limits those permissions to requests made through DynamoDB.
  • The missing key-use allow for KMSBlockedRole creates an implicit deny for that role.
  • Replace every occurrence of your-12-digit-account-id in the policy editor with the 12-digit account ID you recorded earlier.
  • Choose Save changes.
  • Confirm the policy view lists EnableIAMPoliciesForAccountAdministration.
  • Confirm the policy view lists AllowDynamoDBUseForApprovedRole.

The key now grants service-scoped use to KMSAllowedRole. KMSBlockedRole has no matching KMS allow.

Policy Won't Save?

Confirm that every account ID placeholder has been replaced. Compare the braces and quotation marks with the full kms-key-policy.json reference.

Help me fix my KMS key policy.

Encrypt the DynamoDB table

DynamoDB can switch a table from an AWS owned key to a customer managed key. This changes the key authorization boundary while preserving KMSPolicyLab and its demo item.

  • Return to the original admin session by choosing Switch back if the account menu shows a switched role.
  • Select the search box in the AWS Management Console navigation bar.
  • Enter Amazon DynamoDB.
  • Select the Amazon DynamoDB result.
  • Choose Tables in the left navigation panel.
  • Select KMSPolicyLab.
  • Choose Actions.
  • Choose Update settings.

What Changes During the Update?

This setting changes the KMS key that protects the table data. It leaves the table name and stored demo item in place.

  • Expand Additional settings.
  • Choose Manage encryption.
  • Choose the customer managed key encryption option.
  • Select alias/dynamodb-data-protection-lab.
  • Choose Save.
  • Stay on the table page until its status returns to ACTIVE.

Before you open the details, predict which encryption type and alias the table will report.

  • Choose the Overview tab.
  • Expand Additional details.
  • Inspect the Encryption details.

You'll see encryption type KMS with status ENABLED. The displayed KMS key ARN resolves to alias/dynamodb-data-protection-lab.

Still See the AWS Owned Key?

Confirm the table has returned to ACTIVE before refreshing the overview. Check that the console Region is still US East (N. Virginia).

Help me verify my DynamoDB encryption update.

That's the encryption boundary in place. Next up, you'll test both roles to see how the key policy changes access to the plaintext record.

Prove DynamoDB Access Is Not Enough

Your table is now protected by a customer managed AWS KMS key. Both test roles still hold the same Amazon DynamoDB permissions.

This step keeps the table permission constant while the active role changes. That controlled test reveals whether key authorization protects the plaintext.

In this step, get ready to:
  • Display the demo item as the approved role.
  • Test the same item view as the blocked role.
  • Compare the authorization layers that produced each result.
Test the approved role

Opening an encrypted table item makes DynamoDB request decryption through AWS KMS on behalf of the active role. The key policy must permit that role to use the key through DynamoDB.

  • Open the account menu in the AWS Management Console.
  • Select Switch role.
  • Enter the 12-digit account ID from earlier.
  • Enter KMSAllowedRole as the role name.
  • Choose Switch Role.
  • Return to the DynamoDB console tab from earlier.
  • Select Tables in the left navigation.

Before you open the item view, predict whether the approved role can reveal the plaintext value.

  • Select KMSPolicyLab from the table list.
  • Select Explore table items.

You'll see RecordId equal to demo-001 under Items returned. You'll also see SecretValue equal to quarterly-payroll-demo.

Strong result. You have confirmed that the approved role can reach the table and reveal its plaintext record.

What Proves the Approved Path?

  • The key-policy statement AllowDynamoDBUseForApprovedRole names KMSAllowedRole as an approved principal.
  • The kms:ViaService condition limits that permission to requests made through DynamoDB.
  • DynamoDB requests decryption on behalf of the active role when it needs the table key.

Can't See the Demo Item?

  • Confirm that the account menu names KMSAllowedRole as the active role.
  • Confirm that the table's encryption details resolve to alias/dynamodb-data-protection-lab.
  • Confirm that AllowDynamoDBUseForApprovedRole names KMSAllowedRole in the key policy.

Help me diagnose why the approved role cannot read the encrypted item.

Test the blocked role

The table stays unchanged for this test. Switching the role makes the active identity the only difference.

  • Open the account menu.
  • Choose Switch back.
  • Open the account menu again.
  • Select Switch role.
  • Enter the 12-digit account ID from earlier.
  • Enter KMSBlockedRole as the role name.
  • Choose Switch Role.

Before you open the same item view, predict whether matching DynamoDB permissions are enough to reveal the plaintext.

  • Return to the DynamoDB console tab from earlier.
  • Select Tables in the left navigation.
  • Select KMSPolicyLab from the table list.
  • Select Explore table items.

You'll reach KMSPolicyLab through the DynamoDB permissions. The item view returns an access-denied result instead of the demo item.

That denial is the breakthrough in this lab. You have isolated key authorization as the boundary protecting the plaintext.

Why Is This Denial Expected?

The key policy gives KMSBlockedRole no applicable KMS allow. No IAM policy or grant supplies one.

Without an applicable allow for kms:Decrypt, authorization resolves to an implicit deny.

Can the Blocked Role Still Read?

  • Confirm that the account menu names KMSBlockedRole as the active role.
  • Check KMSBlockedRole for any additional KMS identity policy.
  • Check the customer managed key for a grant that covers KMSBlockedRole.

Help me find the unexpected KMS permission.

Compare the authorization layers

Both policy files stay unchanged during this step. The result depends on which role matches the existing key policy.

Before you compare the policies, predict which authorization layer explains the different results.

  • Review the dynamodb-table-access.json policy from earlier.
  • Confirm that dynamodb:* targets KMSPolicyLab.
  • Review the kms-key-policy.json policy from earlier.
  • Locate AllowDynamoDBUseForApprovedRole.
  • Confirm that its Principal names KMSAllowedRole.
  • Check that no key-use allow names KMSBlockedRole.

How Does the Policy Decision Work?

  • Both roles receive dynamodb:* for the lab table through the same identity policy.
  • Only KMSAllowedRole receives DynamoDB-scoped key use through AllowDynamoDBUseForApprovedRole.
  • The EnableIAMPoliciesForAccountAdministration statement lets the account delegate KMS permissions through IAM. It does not directly grant KMSBlockedRole access.
  • The missing KMS allow causes the blocked role's implicit denial.

Your final evidence now matches the policy decision. KMSAllowedRole displays quarterly-payroll-demo.

KMSBlockedRole reaches the table but receives an access-denied result. You have proved that DynamoDB access alone does not guarantee readable plaintext.

Secret mission

Make an Explicit Deny Win

KMSBlockedRole currently fails because no KMS allow applies. Give it a temporary broad allow. Then add a targeted key-policy deny and prove that the denial still wins after DynamoDB refreshes its cached table key.

Clean Up Your Resources

Clean Up Your Resources

Your lab resources remain active in the AWS Management Console. Choose whether to keep them, pause requests, or remove them now. The customer managed AWS KMS key continues to accrue its prorated storage charge until you schedule deletion.

Cost warning

A customer managed KMS key costs $1 per month prorated hourly while active. AWS KMS provides 20,000 free requests per month.

DynamoDB charges depend on your account's remaining free-tier allowances. Choose Pause or Delete if you have finished testing the lab.

Resources you used:

  • Amazon DynamoDB table KMSPolicyLab containing the fake test record.
  • Customer managed KMS key with alias alias/dynamodb-data-protection-lab.
  • AWS Identity and Access Management (IAM) roles KMSAllowedRole and KMSBlockedRole.
  • Inline DynamoDB policies attached to both roles.
  • Temporary broad KMS policy attached to KMSBlockedRole.

Keep everything running

No action needed. Choose this if you want to preserve the complete authorization lab for more testing.

  • Keep the KMSPolicyLab table available for future role-switch tests.
  • Keep both IAM roles with their current inline policies.
  • Keep alias/dynamodb-data-protection-lab with its explicit-deny key policy.

The customer managed key continues to accrue its prorated storage charge. Future requests may also incur charges.

Pause - I'll come back to this later

Stop making requests while keeping the lab ready for another session. This preserves every policy and access result.

  • Stop accessing KMSPolicyLab through either role.
  • Leave the table, roles, inline policies, and customer managed key unchanged.

The customer managed key still accrues its prorated storage charge while the lab is paused.

Delete - I don't want to use this again

Remove the table and both roles before scheduling deletion of the customer managed key.

Delete in this order

Deleting the lab is a big reset. Follow this order so the KMS key stays usable until DynamoDB removes the encrypted table.

Delete the DynamoDB Table
  • Use the account menu's Switch back option to return to your original admin identity.
  • In Amazon DynamoDB, choose Tables.
  • Select KMSPolicyLab.
  • Choose Delete.
  • Complete the on-screen confirmation.

You should no longer see KMSPolicyLab in the table list. Its fake test item has also been removed.

Delete the IAM Roles
  • In IAM, choose Roles.
  • Choose KMSAllowedRole.
  • Delete the inline policy containing AllActionsOnLabTable.
  • Return to Roles.
  • Delete KMSAllowedRole.

You should no longer see KMSAllowedRole in the roles list.

  • Choose KMSBlockedRole from the roles list.
  • Delete the inline policy containing AllActionsOnLabTable.
  • Delete the inline policy containing TemporaryBroadKMSAllowForDenyTest.
  • Delete KMSBlockedRole.

You should no longer see either lab role in IAM.

Schedule KMS Key Deletion
  • In AWS KMS, choose Customer managed keys.
  • Select the key with alias alias/dynamodb-data-protection-lab.
  • Choose Key actions.
  • Choose Schedule key deletion.
  • Enter 7 for Waiting period (in days).
  • Complete the on-screen confirmation.

That's the cleanup handled. You should see the key state change to Pending deletion.

AWS does not charge the key storage fee during the waiting period. The key is permanently deleted after that period ends.

Nice Work!

Nice Work!

Outstanding work! You built a working data-protection lab with Amazon DynamoDB, AWS Key Management Service (AWS KMS), and AWS Identity and Access Management (IAM). Your final role test proves that database access alone does not guarantee access to encrypted plaintext.

What you learned:

  • Built a readable encrypted DynamoDB table and verified its default AWS owned key behavior.
  • Created two IAM roles with identical DynamoDB permissions for a controlled access comparison.
  • Protected the table with a customer managed KMS key that permits DynamoDB key use for KMSAllowedRole while blocking KMSBlockedRole.
  • Secret Mission: Proved that an explicit key-policy deny overrides a broad KMS identity-policy allow after DynamoDB refreshes its cached table key.

Ready to quiz yourself?