What are the elements of an IAM policy?
Identity Access Management (IAM) is one of the most important services to secure applications in any infrastructure built in AWS.
It determines who can access what and what they can do with that service. It can restrict access from unwanted users and it has an important role in federation as well.
IAM is a global service and as such, settings are available in all regions. For example, if I have permission by IAM to create a CloudFormation stack, I can create it in all regions.
1. Policy types
The document that declares the permissions is called a policy.
Policies are JSON documents, and they can look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
The above policy gives a user full access to CloudWatch Logs.
We can create policies ourselves but we can also use managed policies, which are already defined by AWS and are ready to use.
Policies can be grouped in multiple ways and one of them is to separate them as resource policies and user policies.
1.1. Resource policies
Resource policies are usually attached to a resource or service.
For example, an S3 bucket policy (defining permissions on a particular bucket) is a resource policy.
The following bucket policy is attached to a bucket which has website hosting enabled:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucket/*"
]
}
]
}
If we compare this policy to the one above, there is a key difference: It has a Principal
property, which defines who is allowed to perform the action on the resource. More on that below.
1.2. User policies
User policies are related to an authenticated user. They don’t have the Principal
property, because it wouldn’t make any sense. The user profile (it can be a role as well) already determines who the Principal
is.
2. Policy elements
Policies have a few common properties. These properties can be found in the Statement
array. Statement
- as the name implies - states what the policy is about.
Optionally, a Version
property can also be defined in the JSON file, which locks the version of the policy in case AWS changes it (hardly ever happens).
2.1. Effect
Effect
states if the access to the resource is Allow
(i.e. allowed) or Deny
(i.e. denied).
By default, the value is Deny
, so the access to the resource is implicitly denied, similarly to security group rules. If the Allow
value is not explicitly defined, the access will be denied.
The explicit Deny
can be used to override a former Allow
value.
2.2. Principal
Principal
refers to the entity that is allowed or denied to have access to the resource.
In the bucket policy above, the *
refers to everyone in the world and even beyond. This makes sense in the case of a website, because we want everyone to view our website, so we use the wildcard character as the Principal
.
In other cases we want to limit the access to a resource. It’s not really a good idea to give everyone at the company permission to delete buckets containing critical pieces of information. For reasons like this, Principal
allows us to specify the account or the user as well:
"Principal": {
"AWS": [
"arn:aws:iam::123456789123:user/user.one",
"arn:aws:iam::123456789123:user/user.two"
]
}
2.3. Resource
Resource
refers to the service the permission is given for.
For example, an administrator can have access to every service, in this case we can use the *
wildcard character:
"Resource": "*"
But life is not fair, and not everyone can be administrator and have access to everything.
In the S3 bucket example above, it would be very dangerous to allow everyone in the world ("Principal": "*"
) to gain access to other resources, so we have to limit it to the relevant bucket:
"Resource": [
"arn:aws:s3:::mybucket/*"
]
Again, we can list the resources in an array, because it’s possible to give access to more than one resource in the same policy.
2.4. Action
Action
defines what is allowed or denied on the specified resource. Action
values can sometimes be hard to interpret and a bit of experience in AWS comes definitely handy when it comes to defining actions.
Action
values consist of two parts: the namespace of the service and the actual action that is allowed or denied.
The namespace is usually the name of the service, like logs
(for CloudWatch Logs), ec2
or s3
.
The action part refers to the operation that can be done on the service, for example GetObject
in the case of an S3 bucket, or SendMessage
to an SQS queue.
Similarly to Resource
, it’s also possible to list multiple actions in an array.
If everything is allowed or denied for a service, the *
character can be used:
"Action": "s3:*"
2.5. Condition - optional
Condition
s allow us to specify conditions for the policy. When these conditions are met, the rules in the policy will be in effect.
By using Condition
s, we can create more advanced policies. Several operators can be used to design conditions, which will be the topic of another post.
3. Summary
IAM policies are one of the most important security tools in the AWS toolset.
Policies are JSON documents with some compulsory and optional properties. Although one might take some time to understand IAM policies, the structure of the policies is logical, and developers can eventually become skilled enough to write their own custom policies.
Thanks for reading and see you next time.