Working with Key Policies

Working with Key Policies

Key policies are the primary resource for controlling who has access to do what with your CMKs.

Up to now, the assigned IAM role (KMSWorkshop-InstanceInitRole) of our working instance allows us to perform many things in AWS KMS. Following best practices like Least Privilege and Separation of Duties, Our instance is meant to be used only for uploading data with server side encryption, but not decrypt it and download it. Maybe the download and decrypt operation needs to be done from another instance with more specific security constraints.

How can we comply with these requirements? We will use two main resources:

  • IAM roles and their policies are helpful to control access to CMKs.
  • Key policies are resource based policies that we can use to fine grain the access to the CMKs and tweak it to our needs.

Each key that is generated in AWS KMS, has an initial policy attached. Execute the below command to check the policy of the CMK whose alias is ImportedCMK

aws kms get-key-policy --key-id <key ID of the CMK whose alias is ImportedCMK> --policy-name default

Key Policies

The default key policy gives the AWS account (root user) that owns the CMK full access to the CMK. This has policy has two important effects:

  • Reduces the risk of the CMK becoming unmanageable. You cannot delete your AWS account’s root user, so allowing access to this user reduces the risk of the CMK becoming unmanageable.
  • Enables IAM policies to allow access to the CMK. Giving the AWS account full access to the CMK does this; it enables you to use IAM policies to give IAM users and roles in the account access to the CMK. It does not by itself give any IAM users or roles access to the CMK, but it enables you to use IAM policies to do so.
IAM roles - only Encrypt the KMS but not Decrypt the KMS.
  1. Go to AWS IAM Console.
  • Click Roles.
  • Click KMSWorkshop-InstanceInitRole. Key Policies
  1. Go to Permissions policies section
  • Click KMSWorkshop-AdditionalPermissions Key Policies
  1. In the Summary page
  • Click Edit policy Key Policies
  1. In the Edit KMSWorkshop-AdditionalPermissions page
  • Click KMS
  • Click Actions
  • Go to Actions section, type Decrypt into the search bar
  • Unselect Decrypt
  • Click Review policy Key Policies
  1. Go to Review policy section
  • Click Save changes Key Policies
  1. Execute the below command to start Web App
sudo python WebAppEncSSE.py 80
  • Type the Key Id of the CMK whose alias is ImportedCMK we have saved in the section 5.2 Key Policies
  1. Go to Web App by Public IP http://54.221.111.102 of KMSWorkshop-Instance Key Policies
  2. To see the content of file SampleFile-KMS.txt click S3//SampleFile-KMS.txt Key Policies
  • We will see the Web App will not respond to the request Key Policies
  1. Check the log we will see the error. The reason is that Instance has not have decrypt permission and can’t generate the readable file. Key Policies
Least Privilege - Access only from the account.

Now this role is able to encrypt but not to decrypt. Furthermore, we want to enforce “Least Privilege” access and ensure that the encryption Role, providing capability to encrypt, is only used from our account, and not subject to Cross-Account Role access policies that could grant access to the CMK.

  1. Go to AWS IAM Console.
  • Click Roles.
  • Click KMSWorkshop-InstanceInitRole. Key Policies
  1. In the Summary page
  • Copy the ARN Key Policies
  1. To change the Key Policy of ImportedCMK we go to KMS Console
  • Click Customer managed keys
  • Click ImportedCMK Key Policies
  1. Go to Key policy section
  • Click Edit Key Policies
  1. Go to Key policy section
  • Type
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
    {
    "Sid": "Enable IAM User Permissions",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::<your acount id>:root"
    },
    "Action": "kms:*",
    "Resource": "*"
    },
    {
    "Sid": "Allow for Use only within our Account",
    "Effect": "Allow",
    "Principal": {
        "AWS": "<the ARN we copied in the step 11>"
    },
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
        "StringEquals": {
        "kms:CallerAccount": "<your acount id>"
        }
    }
    }
]
}
  • Click Save changes Key Policies
Access only from a Role

Another type of key policy that can become very useful when enforcing “Least Privilege” is the capability to also ensure that this CMK is only called by our role and other roles or user can´t use the key for encryption or decryption.

  1. Do the same as section Access only from the account but change Key policy of the CMK by the below text
{
  "Version": "2012-10-17",
  "Id": "key-default-1",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<your acount id>:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow for Use only within our Account",
      "Effect": "Deny",
      "NotPrincipal": { 
        "AWS": [ "arn:aws:iam::<your acount id>:role/KMSWorkshop-InstanceInitRole", "arn:aws:iam::<your acount id>:root"]
      },
      "Action": "kms:*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:CallerAccount": "<your acount id>"
        }
      }
    }
  ]
}
Key Policy - Including conditions.

Furthermore, you can also include conditions over key policies to help you fine tune access and link to several other parameters.

  1. Add another layer of security via MFA.
{
  "Version": "2012-10-17",
  "Id": "key-default-1",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<your acount id>:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow for Use only within our Account",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::<your acount id>:user/userA"
        ]
      },
      "Action": [
        "kms:DeleteAlias",
        "kms:DeleteImportedKeyMaterial",
        "kms:PutKeyPolicy",
        "kms:ScheduleKeyDeletion"
      ],
      "Resource": "*",
      "Condition": {
        "NumericLessThan": {
          "aws: MultiFactorAuthAge": "300"
        }
      }
    }
  ]
}