Identity and Access Management is the foundation of security in the cloud, yet writing secure IAM policies for applications is a daunting task that developers dread. You might find yourself manually adding permissions to a policy only to realize they are blocked by a Service Control Policy (SCP). To determine what permissions are required for your application to function, you might start building a new application with s3:* because you are not sure what permissions are required by the application and need to perform trial and error with broader permissions.
In this article I will show you how to incorporate automated IAM policy validation as a part of your GitHub workflow using GitHub Apps. Incorporating policy validation earlier in the development process can help improve the security posture of your IAM policy by flagging overly permissive elements in the policy that are deemed security risks. Having policy validation also helps catch errors from incorrect syntax or other misconfigurations.
Applying the Principle of Least Privilege is even more challenging because it requires a considerable amount of big data and analytics to help drive the decision making to help identify patterns that can be applied to your IAM policies. A common analytical practice is to leverage historic IAM usage data to provide context on what permissions the application actually uses to operate. “What are the least privilege permissions required for the application to function?” is the million dollar question. As a result: New, restrictive IAM policies need to be generated, tested, and validated before being rolled out into production environments.
What are GitHub Apps?
GitHub Apps are first-class actors within GitHub that help incorporate custom automation into your GitHub workflows. They allow you to automate project validation workflows and improve code quality. GitHub Apps are not acting on behalf of a GitHub user because an app has its own identity. This means it doesn’t require authorization like other third party apps that you integrate with GitHub. GitHub Apps are passive by design. They wait for something to happen, such as a commit or Pull Request, and then react, usually via the GitHub API. When waiting for events to occur on GitHub, there are two approaches: webhooks and polling. Webhooks are the recommended approach for event handling. Once an event occurs within the monitored scope of the GitHub App, it’s handled immediately and sent to the Webhook for processing.
How do I create a GitHub App?
GitHub has documentation for creating GitHub Apps that will have you up and running in a short period of time. When creating a GitHub App the following fields need to be populated:
- GitHub App Name - The unique name of the app.
- Homepage URL - The website users can visit to install the GitHub App after creation.
- Webhook URL - The endpoint of the webhook used for external integration that processes event data from the GitHub App.
- GitHub App Permissions - For the purpose of this article we will define permissions in the next section, for now just complete the creation of the GitHub App after defining the above three parameters.
What permissions do I need?
When working in GitHub some actions require permissions to be granted by the repository owner. For example, if your workflow requires the code to be checked for linting, appropriate permissions are needed (like read/write access to code). As you iterate on building GitHub Apps, you will recognize what permissions are required. But how do we get those permissions into our app?
There is a settings page for GitHub Apps where GitHub allows you to configure the permissions required by the GitHub App. Whenever someone installs the GitHub App, they will be asked to grant these permissions to the app in their repository.
To access this settings page:
- Go to the settings page of your GitHub organization
- Under the Developer Settings section select GitHub Apps
- This will show all the GitHub apps that exist in your organization.
- Click on Edit in front of the app name.
- Go to Permissions & events to edit the permissions.
Once you have defined the desired permissions, a private key should be generated to allow communication between the GitHub REST API and the Webhook application that will be processing information from GitHub. GitHub documentation has great information on how to generate your private key.
GitHub App Policy Validation High-Level Architecture
Now that we have created our GitHub App, using a serverless architecture in AWS, we will walk through a high-level approach for validating IAM policies when they are committed to GitHub. There are many different options for deploying the backend infrastructure that includes the Webhook, such as Terraform, CloudFormation or the Serverless Framework. The Infrastructure as Code (IaC) mechanism is totally agnostic to this solution. Let’s walk through, at a high-level, all the components required to support IAM policy validation in a GitHub App.
At a high level a developer will submit an IAM policy to GitHub via a commit. The policy will trigger a GitHub event which is monitored and handled by your GitHub App. The GitHub App will send the event to the defined Webhook for processing. The Webhook will then process the event, extract and validate the IAM policy document, and finally send feedback to the developer via GitHub comments or check suite results. In order to have your GitHub App validate policies the backend magic for the Webhook needs to be deployed. The components used in our basic architecture are:
- Application Load Balancer
- Webhook Lambda
Application Load Balancer
This provides the connectivity between your GitHub App and the Webhook lambda being used to process IAM policies. This allows the Webhook lambda to remain private and secure by only being accessible from predefined entities, such as the GitHub server. In this scenario, the lambda will be VPC based, which could allow it to communicate to internal private networks or private servers, such as GitHub Enterprise servers. However, if that is not required the ALB could also be replaced with an API Gateway.
This lambda function is where the magic really happens. The Webhook will interact with the GitHub REST API to obtain the policy file info (i.e. GitHub URL). This information is pushed as part of the event payload from GitHub to the lambda function. From this event payload, the function can extract the policy file URL and then download it directly from GitHub. The function will then take the policy and process it against custom code that is designed to validate the policy against any internal requirements we have. Part of the processing includes determining if the policies being processed are JSON documents and the syntax of the JSON document is correct. If both checks pass, then policy is processed by tooling such as AWS Access Analyzer Policy Validation or a community favorite, Parliament. The new Policy Validation feature for Access Analyzer is a good fit because it is a cloud native solution provided by AWS and includes many of the best practices integrated into it by default. Once the lambda function processes the IAM policy it will then send the feedback back to the user in GitHub for the user to take action on.
As part of this process, we want to track each time a user commits a policy file to GitHub and provide feedback as the commits are happening. To do this we leverage the GitHub Checks API. The Checks API allows you to set up integration tests that are automatically run against code committed to a repository. The Checks API can provide information about each check on GitHub in the pull request’s Checks tab. With the Checks API, you can produce annotations with additional details for specific lines of code. Annotations are visible in the Checks tab. When you create an annotation for a file that is part of the pull request, the annotations are also shown in the ‘files changed’ tab. This API allows us to provide Pass/Fail checks and per commit feedback before any commits are allowed to be merged into your main branch. This can help prevent invalid policies from making it to production.
In closing, GitHub Apps allow you to incorporate automated security analysis into your development workflow. Getting feedback early in the development process is crucial to prevent security incidents. With this approach you can handle policy management at scale and ensure guardrails are in place at the start of the development journey.