The ProblemYou’re trying to pull a database password from Secrets Manager or download an encrypted 2KB configuration file from S3. Your IAM Role has AdministratorAccess, yet your code crashes with a 403 error. It feels like hitting a brick wall because, on paper, you have permission to do everything.
AccessDeniedException: User: arn:aws:iam::123456789012:role/MyRole is not authorized to perform: kms:Decrypt on resource: arn:aws:kms:ap-northeast-1:123456789012:key/abc-123
The Culprit: The "Double-Lock" MechanismAWS KMS is one of the few services where IAM policies aren't the final word. Think of it as a vault with two different locks. To get inside, you need a key from the Identity team (IAM Policy) and a key from the Vault Manager (Key Policy).
If the Key Policy doesn't explicitly mention your role, AWS defaults to a "Deny." This happens even if you are an Account Admin. This failsafe prevents a compromised admin account from instantly accessing sensitive 256-bit encrypted data across the entire infrastructure.
Step-by-Step Fix### Step 1: Grab the Key ARNLook at your error message again. The string starting with arn:aws:kms... is the exact resource blocking you. Copy this ARN; you will need it to find the specific key in a sea of hundreds.
Step 2: Verify the IAM SideYour IAM Role (MyRole) still needs the basic permission to talk to KMS. Open the IAM Console and ensure your policy includes this block:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:ap-northeast-1:123456789012:key/abc-123"
}
]
}
Step 3: Fix the Key Policy (The Real Solution)This is where 90% of these errors are solved. You must tell the KMS key to trust your IAM role.
- Open the KMS Console and find key
abc-123.- Click the Key policy tab and hit Edit.- Insert this statement into theStatementarray:``` { "Sid": "AllowMySpecificRole", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/MyRole" }, "Action": [ "kms:Decrypt", "kms:DescribeKey" ], "Resource": "*" }
**Pro Tip:** In a Key Policy, `"Resource": "*"` doesn't mean "every key in AWS." It specifically refers to the single key this policy is attached to.
### Step 4: Handling Cross-Account AccessAre you trying to decrypt a key in Account B (`444455556666`) using a Lambda in Account A (`111122223333`)? This requires a handshake. Account B’s Key Policy must list the full ARN of the role from Account A as a `Principal`. Without this explicit handshake, the request will fail every time.
## Testing the FixDon't wait for a 10-minute CI/CD pipeline to run. Use the AWS CLI to verify the fix in seconds:
Check if the key is visible to you
aws kms describe-key --key-id arn:aws:kms:ap-northeast-1:123456789012:key/abc-123
Try a mock decryption
aws kms decrypt --key-id arn:aws:kms:ap-northeast-1:123456789012:key/abc-123 --ciphertext-blob fileb://encrypted_data.bin
A successful JSON response containing the `KeyMetadata` means you have successfully cleared the hurdle.
## Troubleshooting Summary- **The "Root" Rule:** Check if your Key Policy allows the `root` user of your account. If it does, IAM policies will work normally. If that block is missing, only the users listed in the Key Policy can use the key.- **Service Roles:** When using S3 or Lambda, ensure you are granting permissions to the **Execution Role**, not your personal IAM user.- **CloudTrail:** If you are still stuck, look at CloudTrail logs. Filter by `EventSource: kms.amazonaws.com`. The logs will tell you exactly which policy—IAM or Key—issued the `Access Denied`.

