Cloud resources with excessive permissions are a common target for attackers, allowing them to gain more privileges in compromised environments. Attackers use various privilege escalation and other techniques to execute further attacks. A process to periodically apply and review the principle of least privilege on your resources is vital to prevent security incidents and breaches related to over-permissive privileges.
Given the cyber threat, coupled with growing numbers of applications and environments, it has become clear that defining least privilege permissions needs to be automated.
Here at T-Systems, we have built a solution called a PLP Generator, a Python application that generates policies according to the principle of least privilege (PoLP). It uses AWS and a GitLab API for managing IAM policies end-to-end: their generation and periodic updates. The resulting policies are then attached to IAM roles used by engineering teams to deploy their code. The application runs regularly, looping through the roles and executing the policy generation and refinement process.
The PLP Generator can be best utilized on medium-sized projects. Such projects should include an Identity and Security team responsible for managing the IAM roles used by the CI/CD pipelines and defining their permissions.
The following is how we implemented the process using common DevOps tooling like GitLab and Terraform and security-related AWS services such as AWS Organizations, CloudTrail, and the AWS IAM Access Analyzer.
The project consists of multiple applications, each with numerous SDLC (Software Development Lifecycle) stages. A separate AWS account represents each SDLC in line with AWS best practices for organizing workloads. However, some workloads share one AWS account for the same SDLC stage.
The software engineers developing the applications use GitLab to host their code and CI/CD (continuous integration/continuous deployment) pipelines which deploy the resulting artifacts on AWS.
A separate sub-folder (a Terraform configuration) in a Git repository represents each application. The subfolder defines deployment IAM roles for each SDLC application stage. The Terraform Outputs for a given application include environments scoped for generating the policies.
This structure allows the exclusion of Sandbox environments, which often serve as a developers’ playground; permissions used there wouldn’t make sense in a higher environment. Vice-versa, not all environments have to use the policy generated by the process and can allow more freedom.
The core component of the automation is the AWS IAM Access Analyzer service. It requires the CloudTrail to be enabled on the target account to function properly. CloudTrail is an AWS service that records actions taken by AWS IAM entities and stores them in a secure location. Per security best practices, the resulting S3 bucket with CloudTrail data is provisioned in a separate archive account designated only for this purpose and encrypted with a KMS key.
The Access Analyzer service roles are deployed in each AWS account in the organization. They have just enough permissions to access the CloudTrail data to generate the least-privilege policies.
The IAM Management roles deployed in each account create the actual deployment roles and can adjust their permissions. Initially, each deployment role is initialized with broader permissions which are then reduced based on their previous activity using the solution described here.
The Developers’ CICD pipelines use the deployment roles to deploy the actual workloads to the target AWS accounts.
For each application and environment in scope, the application calls the AWS IAM Access Analyzer API in the corresponding AWS account to request the latest IAM permissions for the given IAM deployment role based on its activity in the past seven days.
The returned data consists of two parts. One part is the so-called “last accessed” data which only indicates which AWS services were used without more details.
The other part of the returned response is more detailed and includes in-depth action-level information for each service. This feature is not available for all services, but the list of supported services includes some of the most commonly used.
After parsing and processing the data for the IAM roles in the repository and merging the data with the existing generated policies (if they already exist), the PLP Generator creates a merge request. These are the new permissions added since the last generation and assign the request to a security team member.
The merge request is marked “draft,” preventing it from automatically merging. Instead, a security team member must manually review the newly added permissions and either merge or discard them.
When a merge request is approved, it triggers the CI/CD pipeline and executes the “terraform plan” command against the existing infrastructure. It shows the differences again and waits for another human approval before executing the “terraform apply” command.
Except for the manual reviews and approvals, the solution is fully automated and requires zero maintenance once it is set up.
The solution includes two safeguards to prevent assigning the deployment roles more permissions than needed – the merge request, which has to be reviewed and merged, and the “terraform apply” step, which modifies the permissions on AWS and must be manually approved.
The security engineers can:
Most importantly, our solution allows security engineers’ periodic review. It provides just enough permissions for developers’ CICD pipelines to work without disturbing them with “access denied” errors. It also maintains high-security standards in higher environments. By automatically applying the principle of least privilege, the environment maintains a proper security posture which, together with other measures, helps prevent security incidents.