Search code examples
amazon-s3boto3amazon-iam

Boto3 set custom user agent to test S3 access policies


I am using boto3 to create some tests to verify microservice access policies on an S3 bucket.

Bucket setup:

test-bucket/
  service/
    micro-a/
    micro-b/    

This bucket policy is meant to limit access to those with the role specified:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAccessIfInThisRole",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::test-bucket/*",
            "Condition": {
                "StringNotLike": {
                    "aws:userid": "*role-id*"
                }
            }
        }
    ]
}

The role id is referencing this IAM role which grants access to each microservice specific folder in the bucket, based on the microservice user agent, ie microservice A's user agent might be 'micro-a' and so should have access to test-bucket/service/micro-a/* but not to test-bucket/service/micro-b/*:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::as-bucket-test/service/${aws:useragent}/*"
            ]
        },
        {
            "Sid": "AllowListingOfUserFolder",
            "Action": [
                "s3:ListBucket"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::as-bucket-test"
            ],
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "service/${aws:useragent}/*"
                    ]
                }
            }
        }
    ]
}

I don't understand how to create the boto3 client so that I can set the user-agent multiple items to verify different access policies. This is what I have so far:

import boto3
import botocore

session = botocore.session.Session(
    user_agent_name="something"
)

session = boto3.session.Session(botocore_session=session)
print session

Resulting in:

AttributeError: 'str' object has no attribute 'user_agent_name'

Solution

  • The S3 client takes a config object where you can set custom config options including setting a custom user agent

    from boto3 import client
    import botocore
    
    # Create a config
    session_config = botocore.config.Config(
      user_agent="new_user_agent"
    )
    
    s3 = client(
      's3',
      config=session_config
    )
    
    # Make an API call
    response = s3.put_object(
      ...
    )