In this 2nd part, we’re building a CI/CD pipeline using the 'Pipeline as Code' approach, with our sights set on Lambda-based applications.
5 min read
May 26, 2023
In part 2 of Uncomplicating the security pillar of the AWS Well-Architected framework series (check out part 1 if you missed it) we will be breaking down and simplifying Identity and Access Management. In this section, if we are not careful we might overcomplicate things or get stuck in the weeds and not realize that what’s really important is relatively straightforward. We care about what users have access to and additionally which resources can mutually interact. There is always a thin line between overly liberal permissions and excessively strict policies that could leave you open to security threats on the liberal end and could stifle productivity on the overly conservative side. The recommended best practices that can help us successfully walk that line.
Before jumping into the section let’s just define some useful identity management terms:
When it comes to identity management we can think about two main groups:
By understanding the differences between humans and machines it becomes easier to see how we should treat them with regard to access permissions. For example, even though we should always have the least privilege policy in mind for both identities, we can be a bit more flexible with humans. We want to factor in the relevant context and the users' autonomy to not be overly restrictive when it makes little sense to do so. On the other hand, when it comes to granting permissions to machines. There is usually very little upside to not being restrictive. A user might want to test out a new AWS service and would need permission to use it, a database doesn’t require that level of flexibility.
Imagine if every time a new member joined the team you had to individually assign them the permissions they need to perform their tasks. It would be an annoying and error-prone process. In most cases when this process is manual and on an individual basis the permissions that end up being granted to users are usually far more open and permissive than need be. This is why even if the environment and team are small, it is always worth using identity providers or IAM user groups at the very least.
Above we can see the various Identity and Access management methods we have for the different quadrants. For the most part, it is always recommendable to use an Identity provider-based approach and at the very least create user groups instead of applying the roles directly to the individual users. By using an identity provider you can have a centralized management center where you can set granular and precise permissions that can propagate to your workforce and application users. It makes setting up permission guardrails much easier and generally makes the identity access process more streamlined and less error-prone.
Let’s dive into each one.
If you are part of a very small organization, you might decide to avoid configuring an identity provider at the very beginning. Even though the team is small and it might be tempting to give users full access to the environment just out of convenience. It is highly recommended that you don’t handle permissions on a 1:1 basis. You might be small now, but you want to be in a good position to scale easily and add team members down the road without compromising on security. In this case, use AWS IAM to set up the main user groups that make up your organization. For example, frontend developers, backend developers, and administrators.
Even though it might seem like overkill now it is worth taking a little time to create three different roles that will be applied to each identity. Imagine if the frontend developer's account is breached and the hacker can then access an important database. If the frontend developer rarely has to access the database in the first place, we want the role to reflect that. That way even if the account it breached the blast radius is reduced.
The downside of this approach is that it is very manual, any time a new user comes onto the team, the user identity will have to be created for them and will have to be placed in the correct user group.
AWS allows for identity federation via SAML 2.0. This enables users to authenticate easily through single sign-on, without having to manually create an IAM user for them. You will now be using the IdP’s (Microsoft AD, Okta, …) service to configure user federation, as well as countless little details relating to identity access management can now be controlled in a single place such as enabling MFA and credential rotation.
AWS recommends using IAM Identity Center for organizations or any size and type. What is more likely going to be the case though is that you are only going to find the need for it once you get into the multi-AWS account world. The service provides a comprehensive management layer built on top of the Identity provider which allows for seamless permissions and identity management across accounts and applications.
In order to use it you have to enable AWS Organizations.
Using IAM identity center makes it so much easier to apply security best practices from one centralized place.
When it comes to managing a team of users’ access to multiple AWS accounts, if you are still doing it manually it can very quickly become a difficult, imperative process that might open up your environment to a large number of vulnerabilities. With additional accounts come increasing complexity. Almost without a doubt, some accounts will be more critical than others, and unless you have a systematic and standardized way of applying security features like MFA and credential rotations you will be constantly swimming upstream while being quite exposed to danger at all times. There is no reason to not use an external identity provider in this case.
The benefits of using centralized identity providers go beyond simply having a neat directory with all of your federated members. There are multiple best practices that become so much easier to apply thanks to the IdPs.
When it comes to machines, it makes sense to button down the roles that we apply to resources, because if we are applying a role to a lambda function that we know only communicates with a single database why would we give it any other permission about from accessing that specific database?
For machine identities, we should rely on IAM roles to grant access to AWS. If we apply a role to an EC2 instance to allow our application to communicate with another service, the temporary credentials will be automatically created and rotated through the Instance metadata service (IMDS), which helps protect against vulnerabilities. If temporary credential creation isn’t an option, use AWS Systems Manager to easily create and rotate machine-utilised credentials.
Accidents aren’t planned, nobody thinks that is going to be hacked or that a terrible mistake in production will happen. In order to take risk off the table one of the most straightforward and relatively easy best practices to follow is the principle of least privilege. This for human users might mean restricting permissions to certain regions and resources, for other secondary resources you might just be able to read but not write to a service. Applying this principle limits unintended access and helps ensure that you can later audit who has access to which resources.
As an administrator, you want to be able to give your workforce the freedom to be productive and autonomous that is why a permission boundary makes sense because through this management policy we can enable members of our team to create IAM roles for example, or even grant others permissions by they can’t escalate their own permission.
Above we saw how user groups work, we create groups, add the users to them and any IAM roles attached to the groups will be applied to the users in the group. Another way of applying permissions to IAM principals (users or resources) is by leveraging attributes. And attributes in this case make reference to tags. This is especially useful in rapidly scaling environments. These ABAC policies can be designed to allow operations when the principal's tag matches the resource tag.
For example , you can create three roles with the CostCenter tag key. Set the tag value of the first role to Frontend, the second to Backend, and the third to DevOps. You can then use a single policy that allows access when the role and the resource are tagged with the same value for CostCenter. ABAC is a simple but very powerful and clutter-free way of applying access control.
Tags can perform many functions in our cloud accounts, they can be a way to quickly find, sort, and aggregate resources. Using the tags management feature of a tool like Komiser can hugely help to manage tagged resources shedding light on all areas of your cloud environment as well as uncovering hidden costs.
In this case they are being used as a way of communicating with IAM to indicate which role should be applied to a given resource.
If we apply IAM roles to users and resources, we attach SCPs to AWS accounts. We only start talking about SCPs whenever we have enabled the AWS Organization for our accounts, it through this type of policy that we can determine what is the maximum available permissions permitted in an AWS account. A key distinction to keep in mind is that SCPs don’t grant any permissions they simply mark the top end of what is permitted in the account you will then need to apply IAM roles with attached policies to grant permissions.
Inside your accounts, you might have confidential information, such as connection strings, passwords, or secret tokens. Use a secrets management tool like AWS Secrets Manager to have a centralized repository where all the sensitive information lives. A huge benefit of using a managed service like AWS Secrets manager is that you can then easily audit the secret usage history on AWS CloudTrail to have a clear picture of who and when secrets were used.
Once you have enforced the rule to set up MFA through your IdP, make sure to set up an AWS Config rule to ensure that your users have followed through and taken the steps to set it up. You can use one of the pre-built AWS Config MFA-based rules and get alerted via email if a user is non-compliant.
Getting identity and access management right is extremely important, on the one hand, you want to do everything in your power to upkeep a strong security posture that is going to keep you safe and covered as your application and environment scale. At the same time you want to be able to give your workforce the freedom they need to work productively without routinely banging their head against strict permission boundaries. If your organization member hits a boundary and it turns out that it should be expanded or in some cases retracted, the process around doing so can’t take a long time, it has to be fast and efficient.
It’s important then to offload a lot of the management related to identity and access management to an Identity provider. There might be some effort involved at first to set up but it is very likely going to save you time and headaches as your team grows and your applications expand. By leveraging IdP you can easily enforce MFA on user accounts, create credential reports, rotate credentials, and integrate with authentication services like Cognito to serve your customer profiles. All the while enforcing the least required privilege to make sure each user and resource has what is needed to get the job done. Nothing more and nothing less.
Regardless if you are a Developer, DevOps, or Cloud engineer. Dealing with the cloud can be tough at times, especially on your own. If you are using Tailwarden or Komiser and want to share your thoughts doubts and insights with other cloud practitioners feel free to join our Tailwarden Discord server. Where you will find tips, community calls, and much more.