In this series of tutorials, we have learned how to upload files to S3 and list all files from S3. But we still have not talked about how to grant public read access to S3 objects using python.

By default, all objects when uploaded to S3 will be private, and except the owner of that object, no one will be able to view that file. In many cases, you will want to give the general public to view that file for example, when we are sharing images or using S3 as our static data hosting service.

In this blog, we will learn about different access control lists (ACLs) for objects in S3, and how we can list these ACLs for some objects. We will also learn how we can use python, boto3, and set_object_access_policy functions to grant public read access to s3 objects.

Setting up permissions for S3

For this tutorial to work, we will need an IAM user who has access to upload a file to S3. We can configure this user on our local machine using AWS CLI or we can use its credentials directly in python script. We have already covered this topic on how to create an IAM user with S3 access. If you do not have this user setup please follow that blog first and then continue with this blog.

What are ACLs

AWS S3 provides predefined grants that we can assign to buckets or objects to give them different access levels. These grants are known as Access Control Lists (ACLs). The below table list down all ACLs available with the access levels they grant on object or bucket.

ACLApplies ToPermissions Added to ACL
privatecan be added to Bucket and objectOwner gets FULL_CONTROL. No one else has access rights (default).
public-readcan be added to Bucket and objectOwner gets FULL_CONTROL. The AllUsers group gets READ access.
public-read-writecan be added to Bucket and objectOwner gets FULL_CONTROL. The AllUsers group gets READ and WRITE access. Granting this on a bucket is generally not recommended.
aws-exec-readcan be added to Bucket and objectOwner gets FULL_CONTROL. Amazon EC2 gets READ access to GET an Amazon Machine Image (AMI) bundle from Amazon S3.
authenticated-readcan be added to Bucket and objectOwner gets FULL_CONTROL. The AuthenticatedUsers group gets READ access.
bucket-owner-readcan be added to ObjectObject owner gets FULL_CONTROL. Bucket owner gets READ access. If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
bucket-owner-full-controlcan be added to ObjectBoth the object owner and the bucket owner get FULL_CONTROL over the object. If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
log-delivery-writecan be added to ObjectThe LogDelivery group gets WRITE and READ_ACP permissions on the bucket.

You can learn more about ACLs in AWS Documentation. Now that we are familiar with ACLs, let us learn how we can use them with S3 objects. We can also use these with S3 buckets but we will cover that in another blog.

Listing ACLs on s3 object

First, we will write python code to list all grants or ACLs present on some object in S3. We can use the get_object_access_policy function from the boto3 client to list ACLs for objects.

def get_object_access_policy():
    """
    This function prints ACL policy for object in S3 bucket
    :return: None
    """
    s3_client = boto3.client("s3")
    bucket_name = "testbucket-frompython-2"
    object_key = "test9.txt"

    response = s3_client.get_object_acl(
        Bucket=bucket_name,
        Key=object_key,
    )

    pprint(response["Grants"])

When we run the above function we will see the below output that is an array of ACLs on the object. As mentioned before, by default there is a “private” ACL on any object in S3 and it grants full access to the owner.

 
[{'Grantee': {'ID': 'a601289bf62bcd8a0fccb6ff6efa66fc234208dd2efa7d
076551ea907cbf0cff',
              'Type': 'CanonicalUser'},
  'Permission': 'FULL_CONTROL'}]

When the object has a “private” ACL attached to it, no one will be able to read that object. We can easily test this. When we click on the object and its URL from the S3 console we will see the below error.

can-not-read-private-objects-in-s3-bucket
Can not read private objects in s3 bucket

I am trying to read the test9.text file from my s3 bucket but as it has private ACL attached, we see the above page with access denied error. This can be changed by attaching “public-read” ACL to the object. Let us learn how we can do that.

Grant public read access to S3 objects

Now that we want to add public read access to our file so that we can share a link with someone, let us learn how we can do that using python.

def set_object_access_policy():
    """
    This function adds ACL policy for object in S3 bucket.
    :return: None
    """
    s3_client = boto3.client("s3")
    bucket_name = "testbucket-frompython-2"
    object_key = "test9.txt"

    response = s3_client.put_object_acl(
        ACL="public-read", Bucket=bucket_name, Key=object_key
    )
    pprint(response)

When we run this code, the “test9.txt” file in the S3 bucket will have public read access and if we click on its link, we can see the below output.

can-read-public-read-objects-from-s3
Once an object has a public-read policy, we can read it

Conclusion

In this tutorial, we have learned how to list objects access list (ACLs) and how to add ACLs to S3 objects using python and boto3. I hope you have found this useful. In the next blog, we will learn how to add bucket-level policies. See you there.

Similar Posts