0

I'm trying to create an AWS IAM policy to help my team lock down our CodeCommit repositories. The idea is, any repository which needs to be locked down will have an "Owner" tag, the value of which will be he username of the only user who will have privileges to push/merge to main and/or edit the repository as a whole. The policy I've defined so far is as follows:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LockMasterProductionBranches",
            "Effect": "Deny",
            "Action": [
                "codecommit:GitPush",
                "codecommit:DeleteBranch",
                "codecommit:PutFile",
                "codecommit:MergeBranchesByFastForward",
                "codecommit:MergeBranchesBySquash",
                "codecommit:MergeBranchesByThreeWay",
                "codecommit:MergePullRequestByFastForward",
                "codecommit:MergePullRequestBySquash",
                "codecommit:MergePullRequestByThreeWay"
            ],
            "Resource": "*",
            "Condition": {
                "StringEqualsIfExists": {
                    "codecommit:References": [
                        "refs/heads/master",
                        "refs/heads/prod"
                    ]
                },
                "Null": {
                    "codecommit:References": "false"
                },
                "StringNotEqualsIgnoreCase": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                }
            }
        },
        {
            "Sid": "LockRepo",
            "Effect": "Deny",
            "Action": [
                "codecommit:UpdateDefaultBranch",
                "codecommit:CreatePullRequestApprovalRule",
                "codecommit:DeletePullRequestApprovalRule",
                "codecommit:OverridePullRequestApprovalRules",
                "codecommit:UpdatePullRequestApprovalRuleContent",
                "codecommit:DeleteRepository",
                "codecommit:UpdateRepositoryDescription",
                "codecommit:UpdateRepositoryName",
                "codecommit:TagResource",
                "codecommit:UntagResource",
                "codecommit:PutRepositoryTriggers"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEqualsIgnoreCase": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                }
            }
        }
    ]
}

The issue thus far is that if a repository doesn't have the "Owner" tag, then nobody can edit it.

As such, the question is, how do I need to configure my conditions such that these deny actions only take effect if:

  1. The "Owner" tag exists
  2. The user trying to take the action does NOT have the same username as the value of the "Owner" tag

Any help would be greatly appreciated. Many thanks!

  • 1
    Assuming the no-tag repo actions are currently denied by default, rather than explicitly through your Deny policy statements, perhaps you could simply add an additional Allow statement with the condition that the Owner tag is absent. – jarmod May 15 '23 at 16:34
  • @jarmod This policy is applied to our "Engineers" group that also has the AWS managed AWSCodeCommitFullAccess policy, though they already have access. The issue really just seems to be that I can't get this policy to care whether the tag exists when denying. – Cailean Parker May 16 '23 at 18:03
  • 1
    Maybe some combination of `{"Null":{"aws:ResourceTag/Owner":"true/false"}}` to add a condition that the tag is present plus `"StringNotEqualsIgnoreCaseIfExists": { "aws:ResourceTag/Owner":"${aws:username}"` to deny access if tagged with some other owner. – jarmod May 16 '23 at 18:20
  • @jarmod Adding `{"Null":{"aws:ResourceTag/Owner":"false"}}` seems to have done the trick! It's a little frustrating b/c I tried it before at least set to "true", but must've forgotten to try "false". Thanks so much! – Cailean Parker May 16 '23 at 23:06

1 Answers1

0

Thanks to @jarmod for their comment answering my question. I just had to add {"Null":{"aws:ResourceTag/Owner":"false"}} to the conditions, making the policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LockMasterProductionBranches",
            "Effect": "Deny",
            "Action": [
                "codecommit:GitPush",
                "codecommit:DeleteBranch",
                "codecommit:PutFile",
                "codecommit:MergeBranchesByFastForward",
                "codecommit:MergeBranchesBySquash",
                "codecommit:MergeBranchesByThreeWay",
                "codecommit:MergePullRequestByFastForward",
                "codecommit:MergePullRequestBySquash",
                "codecommit:MergePullRequestByThreeWay"
            ],
            "Resource": "*",
            "Condition": {
                "StringEqualsIfExists": {
                    "codecommit:References": [
                        "refs/heads/master",
                        "refs/heads/prod"
                    ]
                },
                "Null": {
                    "codecommit:References": "false",
                    "aws:ResourceTag/Owner": "false"
                },
                "StringNotEqualsIgnoreCase": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                }
            }
        },
        {
            "Sid": "LockRepo",
            "Effect": "Deny",
            "Action": [
                "codecommit:UpdateDefaultBranch",
                "codecommit:CreatePullRequestApprovalRule",
                "codecommit:DeletePullRequestApprovalRule",
                "codecommit:OverridePullRequestApprovalRules",
                "codecommit:UpdatePullRequestApprovalRuleContent",
                "codecommit:DeleteRepository",
                "codecommit:UpdateRepositoryDescription",
                "codecommit:UpdateRepositoryName",
                "codecommit:TagResource",
                "codecommit:UntagResource",
                "codecommit:PutRepositoryTriggers"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEqualsIgnoreCase": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                },
                "Null": {
                    "aws:ResourceTag/Owner": "false"
                }
            }
        }
    ]
}