Please explain why a CMK can be used even when it is not permitted by IAM policies and key policies when using KMS CMK
The issue
I am using KMS CMK for encrypting environment variables in Lambda.
I understood that to use CMK, it is necessary to allow CMK usage either through IAM policies attached to Lambda's execution role or through the CMK's key policy.
However, I was able to use CMK in Lambda even though neither of them granted permission.
Please explain why a CMK can be used even when it is not permitted by IAM policies and key policies when using KMS CMK.
The solution
Access may be permitted through KMS Grants.
Grants in AWS KMS - AWS Key Management Service
A grant is a policy instrument that allows AWS principals to use KMS keys in cryptographic operations. It also can let them view a KMS key (DescribeKey) and create and manage grants. When authorizing access to a KMS key, grants are considered along with key policies and IAM policies.
Access permissions in KMS are determined by the following three methods:
- IAM policies
- Key policies
- Grants
Even if access is not permitted by IAM policies and key policies, CMK can be used if access is granted through Grants.
For KMS access permissions, please also refer to the flowchart in the following AWS official documentation:
Troubleshooting AWS KMS permissions - AWS Key Management Service
To check if access is permitted through Grants, please use the ListGrants API.
I tried it
I verified how access permissions are granted through Grants when using CMK for encrypting Lambda environment variables.
First, I created a CMK in KMS for verification.
In the key policy, I only allowed access from the IAM role used for switch role, and did not define access from Lambda's execution role.
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::012345678901:role/my-role"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
Next, I created a Lambda function with default settings for verification.
When creating a Lambda function with default settings, an IAM role with the following permissions is also automatically created.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:ap-northeast-1:012345678901:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:ap-northeast-1:012345678901:log-group:/aws/lambda/function-name:*"
]
}
]
}
The above Lambda execution role also does not have access permissions to the CMK.
Before setting environment variables, I will check the current Grants using the AWS CLI list-grants command
$ aws kms list-grants --key-id my-key-id
{
"Grants": []
}
It was confirmed that no access permissions were granted through Grants before setting the environment variables.
Now I will create Lambda environment variables and encrypt them with CMK.

In this state, I will run the list-grants command again.
$ aws kms list-grants --key-id my-key-id
{
"Grants": [
{
"KeyId": "arn:aws:kms:ap-northeast-1:012345678901:key/xxx",
"GrantId": "60f37ec4106eb161780bd5530a3564e62cb0935a831661372f93a7e8670299df",
"Name": "test/8135ba14-4a6f-495a-8b59-80730abb9fa2",
"CreationDate": "2025-11-05T00:43:25+00:00",
"GranteePrincipal": "arn:aws:sts::012345678901:assumed-role/test-role-cu5o193j/test",
"RetiringPrincipal": "lambda.ap-northeast-1.amazonaws.com",
"IssuingAccount": "arn:aws:iam::012345678901:root",
"Operations": [
"Decrypt",
"RetireGrant"
],
"Constraints": {
"EncryptionContextEquals": {
"aws:lambda:FunctionArn": "arn:aws:lambda:ap-northeast-1:012345678901:function:test"
}
}
}
]
}
By setting environment variables, the following two permissions were automatically granted, so it appears that when specifying CMK for environment variable encryption from the Lambda console, permissions through Grants are automatically granted.
- Decrypt
- RetireGrant
As a confirmation of CMK access, I will execute the Lambda function with the following code.
exports.handler = async (event) => {
console.log(process.env.key);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
I was able to confirm that the environment variable values could be output with the above code.
2025-11-05T00:45:17.325Z f73b66f6-7f7f-40e1-9730-f3d472bcf503 INFO value
Now I will check the behavior when deleting the access permissions through Grants using the retire-grant command.
$ aws kms retire-grant \
--key-id my-key-arn \
--grant-id 60f37ec4106eb161780bd5530a3564e62cb0935a831661372f93a7e8670299df
I will run the list-grants command again.
$ aws kms list-grants --key-id my-key-id
{
"Grants": []
}
I was able to confirm that the access permissions through Grants that were granted to Lambda have been deleted.
When I executed Lambda again in this state, the following error occurred.
Calling the invoke API action failed with this message:
Lambda was unable to decrypt the environment variables because KMS access was denied. Please check the function's KMS key settings.
KMS Exception: AccessDeniedExceptionKMS Message: User: arn:aws:sts::012345678901:assumed-role/test-role-cu5o193j/test is not authorized to perform: kms:Decrypt on resource: arn:aws:kms:ap-northeast-1:012345678901:key/xxx because no resource-based policy allows the kms:Decrypt action (Service: Kms, Status Code: 400, Request ID: 7c2b4065-21a8-4e9f-b965-b1243ae09441) (SDK Attempt Count: 1)
By deleting the Grants, access is not permitted by any of IAM policies, key policies, or Grants, which is why the above access denial error occurred.
In this state, the Lambda code was not executed and no execution logs were output.
From the above, I was able to confirm that CMK can be used if access is permitted through Grants, even when access is not allowed by IAM policies and key policies.






