5

I'm using AWS CDK.

I have created Customer Managed CMK KMS key to enable Server Side encryption on dynamoDB tables.

KMS Key Policy:

  public static getKMSKeyPolicyDocument(): PolicyDocument {
    return new PolicyDocument({
      statements: [
        //Allow root in IAM Policy: https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam
        new PolicyStatement({
          principals: [new AccountRootPrincipal()],
          actions: ["kms:*"],
          resources: ["*"],
        }),
 
        new PolicyStatement({
          principals: [
            new ServicePrincipal("dynamodb.amazonaws.com"),
            new ServicePrincipal("lambda.amazonaws.com"),
          ],
          actions: [
            "kms:Encrypt",
            "kms:Decrypt",
            "kms:ReEncrypt*",
            "kms:GenerateDataKey*",
            "kms:DescribeKey",
            "kms:Get*",
            "kms:List*",
          ],
          resources: ["*"],
        }),
      ],
    });
  }

Some Lambdas use these dynamo db tables to get the data. So, my question is:

Do we again need to give permissions explicitly to each lambda to access KMS key like this??

public static grantAccessToKMSKey(role: IRole, kmsKey: IKey): void {
    role.addToPrincipalPolicy(
      new PolicyStatement({
        actions: [
          "kms:CreateGrant",
          "kms:Decrypt",
          "kms:DescribeKey",
          "kms:Encrypt",
          "kms:GenerateDataKey*",
          "kms:ReEncrypt*",
          "kms:Get*",
          "kms:List*",
        ],
        resources: [kmsKey.keyArn],
      })
    );
  }

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Aman kumar
  • 83
  • 1
  • 7
  • 2
    You could just try it and find out for yourself!? – luk2302 Apr 21 '21 at 15:58
  • Actually, my idea is if we give permissions as ServicePrincipal it means that all lambda will have the permissions to perform those actions, but that is not happening. So wanted to confirm as this is a small part of code where complication are getting started. – Aman kumar Apr 21 '21 at 16:02
  • 3
    Yeah, you gave the lambda service the permission, but not the lambda itself. The role a lambda runs with needs the permission to do the KMS operations, not the lambda service. Practically speaking the lambda service assumes the role of the lambda function and performs operations as that role, it no longer is a lambda service but "just" the role. – luk2302 Apr 21 '21 at 16:05
  • @Amankumar Did you find a running solution? – droebi Nov 25 '21 at 10:57
  • yes, we would need to give these perms to the lambda – user3608245 Mar 30 '22 at 04:37

1 Answers1

1

You have given permission to AWS Lambda service to access your key, not an actual lambda function. This is neither sufficient nor required for lambda function to have access to KMS key.

Instead, you have two options:

  1. Update KMS policy and use your lambda function arn as a principal
  2. Update lambda iam role policy to have access to KMS key

If both your lambda and key are in the same account then any one of two options above would be sufficient. If they are in different accounts, then you need to do both.

Tofig Hasanov
  • 3,303
  • 10
  • 51
  • 81
  • Can you please add a sample snippet for both these cases just for reference. Thanks :) – kaushalpranav May 29 '23 at 12:18
  • @kaushalpranav - I think in both cases the only thing you need to do is call `key.grantEncryptDecrypt(myLambda)`. CDK will then check if principal and resource are in the same account. If they are, it will only update the Lambda role policy. If they are in a different account, CDK will also update KMS key policy. This logic is implemented in [this](https://github.com/aws/aws-cdk/blob/ce5a9f3d9c36e5b32d7099830816b90c6f3bccab/packages/aws-cdk-lib/aws-iam/lib/grant.ts#L122) method. – Tofig Hasanov Jun 01 '23 at 16:20