Protecting your Git branches on AWS CodeCommit
Tags: aws, git, codecommit, devops
Published: 2019-03-19 18:30:31

---
title: Protecting your Git branches on AWS CodeCommit
published: true
description: Give granular permissions who can merge into master/production branches when using CodeCommit on AWS.
tags: aws, git, codecommit, devops
---
![](https://thepracticaldev.s3.amazonaws.com/i/zg9g4s97p4ryysl0ptgz.jpg)
_Borovets, Rila mountain, Bulgaria_


----
This post gives a quick recipe on how to enable only selected users to merge/commit into CodeCommit Git branches.
# The problem
Let's consider a common CD/CI scenario:
1) you have a team which pushes to a Git repo with important code. 
2) when ready for a deploy, someone merges `dev` into `master`
3) the merge event triggers a preconfigured deployment pipeline which would package the code from the repo and then delpoy it to production

The above is very nice and all, but care must be taken when it comes to who should be allowed to merge into the production branch.

# The solution
([jump straight to the sample IAM policies](#show-me-the-code))


Since we are in the context of AWS, the solution lies in using the IAM service (Identity and Access Management).  
Here are the main steps of the solution:
- Have a generic group for all developers, say `Dev-Group`. All developers  within your team belong to this group. Generic CodeCommit actions are allowed  - e.g. `pull`, `clone`, etc. 
- Also attach to the `Dev-Group` a policy which specifies the repositories which we want to protect via the [NotResource](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html). For all other repos developers can have full access, if so desired.
- Have a second IAM Group - e.g. `ImportantRepo-PowerUser` - it has a policy which enables the `merge`/`commit` actions for the `ImportantRepo` repo.
- Add the selected few developers which should be able to trigger a build to this `ImportantRepo-PowerUser` group

Why bother writing this article - well, it's not that obvious how to implement the above. The tricky part is the [evaluation logic of IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow). Due to it, the naïve solution below won't work:
- all devs in `Dev-Group`, the selected few in `SelectedFew`
- use a `Deny` statement in a policy in `Dev-Group` to deny devs merge into master
- attach a policy to `SelectedFew` which allows its users to merge into     `master`

If in the `Dev-Group` you add a statement which explictly **forbids** (with a `Deny`) users of the group to merge into master, then it's not possible to allow these actions in a different policy - so it won't be possible to allow our selected few developers to merge.  


This is where the [`NotResource`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.htmlhttps://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html) comes in handy. With it you can exclude the protected repositories from a given statement __without explicitly using the `Deny` action__. I.e. you can give full perms to all repositories excluding the protected ones. Since we haven't explicitly Deny-ied actions on the protected repositories, we can later add explicit Allow in a different policy - in a policy attached to the `SelectedFew` group.


## Show me the code
### dev-group-generic-policy
We need the Dev-Group which gives generic permissions to all devs and also lists the protected repositories. 
```
// the policy atached to the Dev-Group
{
  "Version": "2012-10-17",
  "Statement": [
    // generic permissions for all devs
    {
      "Effect": "Allow",
      "Action": [
        "codecommit:Get*",
        "codecommit:GitPull",
        <whatever you need but not Push/Merge/etc.>
      ],
      "Resource": "*"
    },

    // the gotcha - in the NotResource put the important repos whose branches you want to protect
    {
      "Effect": "Allow",
      "Action": [
        "codecommit:GitPush",
        "codecommit:DeleteBranch",
        "codecommit:Merge*"
      ],
      "NotResource": [
        "arn:aws:codecommit:*:*:<important-repo-name-1>",
        "arn:aws:codecommit:*:*:<important-repo-name-2>"
      ]
    },

    // still allow all devs to push to non-production branches of the imporant repos
    {
      "Effect": "Allow",
      "Action": [
        "codecommit:GitPush",
        "codecommit:DeleteBranch",
        "codecommit:Merge*"
      ],
      "Resource": [
        "arn:aws:codecommit:*:*:<important-repo-name-1",
        "arn:aws:codecommit:*:*:<important-repo-name-2"
      ],
      "Condition": {
        "StringNotEquals": {
          "codecommit:References": [
            "refs/heads/master",
            "refs/heads/prod",
            "refs/heads/Stg"
          ]
        }
      }
    }
  ]
}
```
### important-repo-1-power-users
A group for the power users for a specific important repo.
```
// the policy attached to the group for users that can push to all branches for a given important repo 
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "codecommit:GitPush",
        "codecommit:DeleteBranch",
        "codecommit:Merge*"
      ],
      "Resource": [
        "arn:aws:codecommit:*:*:<important-repo-name-1>",
      ]
    }
  ]
}
```


To make the solution more generic, you can use some naming convention for the repositories - i.e. all repo names starting with `xyz-` are considered important and only users in group `xyz-power-users` can merge into the prod branch of these repos.