'AWS Secrets Manager Resource Policy to Deny all roles Except one Role

I have a secret in secrets manager and there are multiple IAM roles in the system. I only want only one role to access the scecret. Unfortunately there are some other IAM roles that have full Secrets Manager privileges. So i want to restrict the access to the secret to all other roles except desired one by me.

roles

  1. IAM_role_that_need_to_access_the_secret.
  2. IAM_role_1_that_should_not_access_the_secret.
  3. IAM_role_2_that_should_not_access_the_secret.

The following is working.

    {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "secretsmanager:GetSecretValue",
      "Principal": {
        "AWS": "arn:aws:iam::IAM_role_1_that_should_not_access_the_secret",
        "AWS": "arn:aws:iam::IAM_role_2_that_should_not_access_the_secret"
      },
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
      },
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*",
      "Condition": {
        "ForAnyValue:StringEquals": {
          "secretsmanager:VersionStage": "AWSCURRENT"
        }
      }
    }
  ]
}

But i want to Deny access to all roles without explicitly mentioning each of them in the Deny permission section. Something like below. But it will restrict to all roles including the desired role.

    {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "secretsmanager:GetSecretValue",
      "Principal": {"AWS": "*"},
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
      },
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*",
      "Condition": {
        "ForAnyValue:StringEquals": {
          "secretsmanager:VersionStage": "AWSCURRENT"
        }
      }
    }
  ]
}


Solution 1:[1]

Update:

I asked AWS Support, and they said:

It is a known issue where NotPrinicipal fails the resource policy with an explicit deny.

The workaround is to use "StringNotEquals":"aws:PrincipalArn" condition key.


Previous answer:

You can use NotPrincipal:

    {
      "Effect": "Deny",
      "NotPrincipal": {
        "AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
      },
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*",
      ...

Solution 2:[2]

You could create a KMS key then create a policy for the KMS key which grants access only to the roles you need. Something like below:

{
    "Version": "2012-10-17",
    "Id": "key-default-admin",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<AWS_ACCOUNT_ID>:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow administration of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>",
                    "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
                ]
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<AWS_ACCOUNT_ID>:role/AdminRole",
                    "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
                ]
            },
            "Action": [
                "kms:DescribeKey",
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey",
                "kms:GenerateDataKeyWithoutPlaintext"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Deny use of the key",
            "Effect": "Deny",
            "Principal": {
                "AWS": "arn:aws:iam::<AWS_ACCOUNT_ID>:root"
            },
            "Action": "kms:*",
            "Resource": "*",
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalArn": [
                        "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>",
                        "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
                    ]
                }
            }
        }
    ]
}

Solution 3:[3]

I was able to achieve this with using a Condition on the Resource Policy and specifying the ARN of the Role in aws:PrincipalArn (Ref: https://aws.amazon.com/blogs/security/iam-makes-it-easier-to-manage-permissions-for-aws-services-accessing-resources/)

{
  "Version" : "2012-10-17",
  "Statement" : [ 
    {
        "Sid" : "Get",
        "Effect" : "Deny",
        "Principal" : "*",
        "Action" : "secretsmanager:GetSecretValue",
        "Resource" : "<<ARN OF Secret>>",
        "Condition" : {
          "StringNotLike" : {
            "aws:PrincipalArn" : [ 
                "<<ARN of IAM_role_that_need_to_access_the_secret>>" ]
          }
    }
  } ]
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Luis Silva
Solution 3 smk081