DEV Community

How to restrict default access to KMS via key policy

About AWS Key Management Service

AWS Key Management Service (AWS KMS) is a managed service that makes it easy for you to create and control the cryptographic keys that are used to protect your data.

The KMS key policy allows IAM identities in the account to access the KMS key with IAM permissions.

The objective of this article is to implement secure of KMS key from access by AWS Identity and Access Management (IAM) identities.

Note: This article demonstrates the AWS account ID 123456789012 with existing role named TERRAFORM, ADMIN and ANALYST. These values must be replaced for your environment.

The default KMS Authorization behaviour

The default KMS key policy contains the following statement:

{
    "Sid": "Enable IAM User Permissions",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": "kms:*",
    "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

By default KMS policy allow caller's account to use IAM policy to control key access.

The Effect and Principal elements do not refer to the AWS root user account. Instead, it allows any principal in AWS account 123456789012 to have root access to the KMS key as long as you have attached the required permissions to the IAM entity.

Implement secure KMS policy

Example of restricted key policy:

{
    "Sid": "Enable root access and prevent permission delegation",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
        "StringEquals": {
            "aws:PrincipalType": "Account"
        }
    }
},
{
    "Sid": "Allow access for key administrators",
    "Effect": "Allow",
    "Principal": {
        "AWS": [
            "arn:aws:iam::123456789012:role/TERRAFORM",
            "arn:aws:iam::123456789012:role/ADMIN"
        ]
    },
    "Action": [
        "kms:Create*",
        "kms:Describe*",
        "kms:Enable*",
        "kms:List*",
        "kms:Put*",
        "kms:Update*",
        "kms:Revoke*",
        "kms:Disable*",
        "kms:Get*",
        "kms:Delete*",
        "kms:TagResource",
        "kms:UntagResource",
        "kms:ScheduleKeyDeletion",
        "kms:CancelKeyDeletion"
    ],
    "Resource": "*"
},
{
    "Sid": "Enable read access to all identities",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": [
        "kms:List*",
        "kms:Get*",
        "kms:Describe*"
    ],
    "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

The key policy allows the following permissions:

  • First statement: The AWS root user account has full access to the key.
  • Second statement: The principals role ADMIN and TERRAFORM has access to perform management operations on the key.
  • Third statement All account principals are able to read the key.

This way we can ensure that the root user account manages the key and prevents IAM entities from accessing the KMS key.

You can also allow IAM users or roles to use the key for cryptographic operations and with other AWS services by appending other statements like this:

{
    "Sid": "Allow analyst role use the key",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/ANALYST"
    },
    "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
    ],
    "Resource": "*"
},
{
    "Sid": "Allow sms service use the key",
    "Effect": "Allow",
    "Principal": {
        "Service": "sns.amazonaws.com"
    },
    "Action": [
        "kms:GenerateDataKey*",
        "kms:Decrypt"
    ],
    "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

So if the KMS is configured in this way, its access will be restricted and only those identities directly specified in the key policy will have access.

Check out the completed code example:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable root access and prevent permission delegation",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": "kms:*",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalType": "Account"
                }
            }
        },
        {
            "Sid": "Allow access for key administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::123456789012:role/TERRAFORM",
                    "arn:aws:iam::123456789012:role/ADMIN"
                ]
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Enable read access to all identities",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": [
                "kms:List*",
                "kms:Get*",
                "kms:Describe*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/ANALYST"
            },
            "Action": [
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:Encrypt",
                "kms:DescribeKey",
                "kms:Decrypt"
            ],
            "Resource": "*"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)