This isn’t a tutorial, just a conceptual framework that’s helped me write better IAM policies. It’s extra useful when an app needs a group of services like DynamoDB, S3, and Kinesis. The method is called “CARE,” and it’s an acronym based on the four parts of an IAM policy statement.
Writing Policies
CARE started out as a mnemonic to use when writing policy statements, standing for:
- Condition
- Action
- Resource
- Effect
Moving further towards serverless apps typically means taking advantage of more and more external services, and a need for granular RBAC. Managing the right levels of access for each function is great for limiting the blast radius of a bug, since code can’t ruin what it can’t change.
Serverless meant writing more IAM policies than usual, and remembering CARE meant I could skip looking up the policy structure in the docs every single time.
Note: The team at Cloudonaut have a great IAM reference site that’s often quicker to use than finding the AWS policy/action documentation.
CARE, Evolved
At first, a single role per “service” in my application seemed right. Every function wouldn’t have its own role, and it felt familiar to how I’d delegate permissions to a regular web service. It’s also pretty low-management, since a full application might only have a couple roles along these lines:
- A role for frontend type functions that talk to DynamoDB or a SQL database. Typically this would be extra-restrictive since untrusted input could be coming in from the outside world.
- A role for backend functions that handle Kinesis or DynamoDB stream events, but don’t take untrusted input. Data handled here would have been sanitized and validated by public-facing frontend functions.
- A role for administrivia functions that handled infra tasks like scheduled jobs. These sometimes need super-privileges like managing ECS containers or kicking off tasks.
That worked well enough, but sometimes I’d end up with functions that needed a special (somewhat powerful) permission. Usually it would get tacked on to the administrivia role. Unfortunately, that meant the administrivia role ended up grossly over-permissioned. It could terminate RDS and EC2 instances, nuke CloudFormation stacks, redeploy other Lambdas, and change VPC’s. Not even close to the principle of least privilege.
Special thanks to ServerlessCode sponsor Trek10, experts in supporting high-scale serverless and event-driven applications.
Now CARE is part of how I divide permission statements between managed
policies. When redesigning the permission scheme to break up the
overpowered administrivia role, I switched to making one IAM role per function
and using a regular naming scheme. Every function would have a role named
{app}-{environment}-{function}
, for example: myapp-prod-dbbackup
. Each role
can have up to 5 managed policies attached, so permissions can be quite
granular.
The four parts of an individual IAM statement are a nice lens to look through when building a shared policy. A managed policy has similar principles, applied at a higher level. Since policies are shared, consider whether all the permissions granted are cohesive in covering a specific goal. Going over my policies, here are a few custom ones I use:
- ProdAppDataStoreAccess
- ProdLambdaVPCAttachment
- ProdFrontendApiRead
- ProdFrontendApiWrite
Before writing one, I describe it in CARE terms so it covers everything about
the policy. Take the ApplicationDataStoreAccess
policy for example:
- Condition: The environment has to be production, and the function has to be in the VPC for RDS access.
- Action: Read and write to DynamoDB tables, a Kinesis stream, and an RDS database.
- Resource: The
prod-users
andprod-queues
DynamoDB tables and theprod-clickstream
Kinesis stream. RDS is excluded because that’s handled by the security group, since RDS connections aren’t IAM. - Effect: Allow specified, deny everything else.
Wrapping Up
And that’s CARE. I hope this helps you when you’re writing your own IAM policies. Remember: one role per function, but reuse policies where it makes sense. The fewer places you need to update security rules, the more likely you are to get it right.