AWS Resource Policy

AWS Resource Policy

In the article on IAM policies we saw how we can attach IAM policies to AWS identities like user, group or role for granting access to AWS resources. But there is another way to grant such permissions by assigning them directly to the resources itself, which are called AWS resource policies. So, an IAM policy is attached to an identity like user, group or role, and an AWS resource policy is attached to a resource like S3, KMS, Lambda, etc. 

An IAM policy has four foundational components — Action, Resource, Effect which are mandatory, and Request Conditions which are Optional. Resource policies introduce a fifth component – Principal. Principal is the identity for which the resource policy is applicable. By common sense, since an IAM policy is attached to a Principal (User/Group/Role), it does not need to have the Principal component. 

An example JSON of an IAM policy which allows the principal to which it is attached the invoke privileges on a specific Lambda function is given below:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowLambdaInvokePrivileges",
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:us-west-1:{AccountId}:function:{LambdaFunctionName}"
        }
    ]
}

An AWS resource policy, on the other hand, is applied on resources like S3 and KMS, and so it needs to have the Principal component to specify the identity for which the policy is applicable. Below is an example JSON of Resource policy which allows S3 put object action for a particular IAM role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::{AccountId}:role/{RoleName}"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{BucketName}/{ObjectName}"
        }
    ]
}

Key Security Insight

Some resources like S3 objects have web access urls attached to them, meaning, these resources could be accessed via the public Internet using their specific web urls. This is disabled by default, but by updating the Resource policy for the S3 bucket, it can be enabled. Remember from our article on IAM Policy, Action/Resource component can have “*” as value which means “Applicable for All”. So what happens when we apply the “*” to the Principal component of a S3 bucket:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{BucketName}/{ObjectName}"
        }
    ]
}

The above policy makes the object –> arn:aws:s3:::{BucketName}/{ObjectName}, accessible to anyone over the Internet, even without an AWS account. This is extremely powerful and very easy to be misconfigured. This simple misconfiguration has already caused many high-profile data breaches. In case you have not seen this open-source repo – AWS Exposable Resources, it contains the list of AWS resources which can be made publicly exposable via AWS resource resource policies.

Lab Demo

In the video walk-through, we will create a S3 bucket resource policy, compare that policy with an equivalent IAM policy and see how easy it is to publicly expose a S3 object. 

Video walk-through on Resource Policy

Security tidbits

Summary of security best practices to keep in mind regarding Resource Policies:

Follow us on: