Managing GitHub using IaC in GitHub

During a recent migration, I seized an opportunity to have permissions for our workspace closer to the team, to reduce bottlenecks and keep the team moving quickly.

We moving from an on-premise github instance to github’s managed offering, there will almost always be someone from your IT department tasked with enterprise security and Active Directory integrations and whatnot. This is a fairly tedious and likely thankless job.

A typical setup might be as follows:

  • someone does some analysis to work out what AD groups ought to exist, and creates them. This is often painful, as the person provisioning those groups is probably not the person with the best understanding of the team boundaries and roles within the team. Often times to keep things simple, this maps directly to HR department boundaries. However, this doesn't encapsulate the roles that might have evolved in the teams, or might still be created.
  • We add the users to those groups. This takes a while initially, but the real pain point here, is changing them later. When a new joiner comes to your team or department, you have to go to IT with your request to modify the user groups. Depending on the size of your company, if your a small-ish organisation, that could be a few hours. If you’re working at a multi-billion pound company, there’s chance you’ve never even heard of the person who will execute that work, and it won’t be done in a flash.
  • We then need to set about mapping those user groups to permissions somehow within github. Since everything so far has been managed by IT, and the centralised github is configured and managed by IT, it’s likely that they’ll take on this role.

On the plus side, you get a nice audit trail of every change that was requested to permissions. On the not so nice side, you need to either email your IT department, or create a ticket (or know someone on the inside who likes you!). I thought this was inefficient, and wanted a better way.

What if the IT department could delegate the permissions for a relevant area, to a single responsible admin within that area? And that admin was more of a software/devops engineer, than a sysadmin? What would the effect be?

I decided I really wanted to try this model, so I had the following:

  • I convinced our IT department to create me an organisation in our github enterprise. They’d set up our Single Sign On feature, but only either allow sign in or not, no group management — that would all be done by me. So now, they just need one big AD group, for everyone who can sign in to github. That’s easy enough to automate when they create the accounts in the first place.
  • Although they lose the ability to audit changes to groups and permissions, they’re no longer responsible for this — it’s been delegated to the department in question. Now, should we be audited, the github audit logs within the product provide detailed information about all changes. This is likely richer and easier to use than the centralised OneIdentity management solution, because it’s built specifically for the tool and not as a general solution.
  • Started to provision our environment using terraform. Github has a terraform module that can be used to reference github users, create teams, repositories, and permissions.
  • Create github actions to run a plan for every pull request, and apply the changes every time there’s a merge.

Looks like a swell plan, but how did it work in practice?

  • We had a set of users in a file:
  • we got to define the list of github teams we wanted those users to be in:
  • we create a suite of repos. (Or in some cases, imported already existing ones). We can also create local variables for the list of all repos, and lists of repositories based on tags.
  • we can now grant permissions for the repos we’ve made, to the teams we’ve made, either for a single repo, or a list of repos based on the tags we apply. Note that this doesn’t mean someone can just modify the repo to add a tag and that will grant permissions, this needs to be done via terraform — any changes made outside this repo will be reverted the next time it runs.
  • lastly, add a main terraform file for some config:

We now have total control over how we manage who has permissions to what within github, and easy enough mechanisms to group repos with tags for permissions.

We just needed a way to deploy things now, and github actions makes this pretty simple, we just need to add an access token as a secret in the repo, which we can get from the github UI:

And we can do the same for pull request changes, to quickly see if we’ve got a valid set of terraform files:

So how did it work out in the end?

This mechanism worked great for us, and our IT department were happy for us to own this administrative domain. This made our team more autonomous.

business analysts started writing valid terraform!

When someone wanted a change, they were able to create that change themselves. Because this was fairly simple, we soon had business analysts with no prior experience in terraform, making valid pull request changes. It wasn't just shifting the admin burden off IT and onto someone in the department, the users in that department were empowered to request the change themselves, and once approved it was applied in seconds! We didn’t have to submit tickets as such (these became pull requests), and invalid changes were quickly highlighted to users in the pull request checks. We still had all the auditing capabilities of GitHub, and the security of our organisation’s SSO setup. IT happy, end-users happy, and everyone moving fast :)

This actually worked so well, that we started to move our GCP permissions towards a similar model, so everything could be managed in code in a similar fashion. This was a high risk area, so I’m glad we got to experiment with it in GitHub first, it gave us the confidence to apply this ownership model to other areas.