The k9-cdk now supports generating least-privilege resource policies for Amazon DynamoDB tables, indices, and streams. This addition complements the existing S3 and KMS capabilities, bringing the same simplified approach for securing data to DynamoDB resources managed by AWS CDK infrastructure code.

Benefits

  • Simplified Security: Define access patterns using k9’s intuitive access capability model instead of writing raw resource policies
  • Consistent: Apply the same security patterns across S3, KMS, and now DynamoDB resources
  • Developer Experience: Easily integrate security into your existing CDK delivery process

Least privilege for DynamoDB (quickly)

The implementation works seamlessly with your existing AWS CDK infrastructure code. First, define the access you would like each principal to have in a K9DynamoDBResourcePolicyProps object. 

#!/usr/bin/env node

import * as cdk from "aws-cdk-lib";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as k9 from "@k9securityio/k9-cdk";

const app = new cdk.App();
const stack = new cdk.Stack(app, 'K9CDKExample');

const administerResourceArns = [
   "arn:aws:iam::123456789012:role/ci",
   "arn:aws:iam::123456789012:role/admin",
];

// admins & auditors should be able to read-config
const readConfigArns = administerResourceArns.concat(
   [
       "arn:aws:iam::123456789012:role/k9-auditor",
       "arn:aws:iam::123456789012:role/aws-service-role/access-analyzer.amazonaws.com/AWSServiceRoleForAccessAnalyzer",
   ]
);

const writeAndDeleteDataArns = [
   "arn:aws:iam::123456789012:role/app-backend",
];

const readDataArns = [
   "arn:aws:iam::123456789012:role/customer-service"
];

// Demonstrate generating and applying a DynamoDB resource policy
const ddbResourcePolicyProps: k9.dynamodb.K9DynamoDBResourcePolicyProps = {
   k9DesiredAccess: new Array<k9.k9policy.IAccessSpec>(
       {
           accessCapabilities: k9.k9policy.AccessCapability.ADMINISTER_RESOURCE,
           allowPrincipalArns: administerResourceArns,
       },
       {
           accessCapabilities: k9.k9policy.AccessCapability.READ_CONFIG,
           allowPrincipalArns: readConfigArns,
       },
       {
           accessCapabilities: k9.k9policy.AccessCapability.READ_DATA,
           allowPrincipalArns: readDataArns,
       },
       {
           accessCapabilities: k9.k9policy.AccessCapability.WRITE_DATA,
           allowPrincipalArns: writeAndDeleteDataArns,
       },
       {
           accessCapabilities: k9.k9policy.AccessCapability.DELETE_DATA,
           allowPrincipalArns: writeAndDeleteDataArns,
       },
   )
};

Then use the k9.dynamodb module’s makeResourcePolicy to generate a least-privilege resource policy. 

const ddbResourcePolicy = k9.dynamodb.makeResourcePolicy(ddbResourcePolicyProps);

This resource policy will allow the access you declared in the props and deny access to unintended principals. 

Finally, attach the policy document to a new or existing DynamoDB data resource:

new dynamodb.TableV2(stack, 'k9-cdk-ddb-example', {
 partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
 resourcePolicy: ddbResourcePolicy
});

In the k9-cdk GitHub repository, you can find a full example showing how to generate and use secure, least privilege policies for DynamoDB, S3, and KMS along with the generated CloudFormation template and resource policy.

Getting Started

k9 Security’s k9-cdk makes strong security usable and helps you provision best practice AWS security policies defined using the simplified k9 access capability model and safe defaults.

In CDK terms, this library provides Curated (L2) constructs that wrap core CloudFormation resources (L1) to simplify security.

Check out k9-cdk on GitHub or ConstructHub for details and examples on how to start using k9-cdk today!