Skip to content

Instantly share code, notes, and snippets.

@samuraisam
Last active February 22, 2019 21:50
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save samuraisam/4772337 to your computer and use it in GitHub Desktop.
Save samuraisam/4772337 to your computer and use it in GitHub Desktop.
Using STS (Security Token Service) to grant access for a federated user to a s3 bucket prefix
import json
import boto
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
class UploadToken(models.Model):
user = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add=True)
access_key_id = models.CharField(max_length=255)
secret_access_key = models.CharField(max_length=255)
session_token = models.TextField()
expiration = models.DateTimeField()
uid = models.CharField(max_length=255)
def save(self, force_insert=False, force_update=False, using=None):
if not self.access_key_id:
# connect as the IAM user
conn = boto.connect_sts(
aws_access_key_id=settings.AWS_S3_USER_UPLOAD_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_S3_USER_UPLOAD_SECRET_ACCESS_KEY
)
if not conn:
raise Exception("Could not connect to Amazon STS")
policy = settings.AWS_S3_USER_UPLOAD_POLICY.replace("%%BUCKET_NAME%%", settings.AWS_S3_USER_UPLOAD_BUCKET)
policy = policy.replace("%%USERNAME%%", self.user.username.encode('utf8'))
fed_token = conn.get_federation_token(
self.user.username.encode('utf8'),
settings.AWS_S3_USER_UPLOAD_TOKEN_DURATION,
policy
)
if not fed_token:
raise Exception("Could not get federation token for user")
self.access_key_id = fed_token.credentials.access_key
self.secret_access_key = fed_token.credentials.secret_key
self.session_token = fed_token.credentials.session_token
self.expiration = fed_token.credentials.expiration
self.uid = fed_token.federated_user_id
super(UploadToken, self).save(force_insert=force_insert, force_update=force_update, using=using)
def __unicode__(self):
return 'UploadToken for {}'.format(self.user.username)
{ "Statement" : [ { "Action" : [ "s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Effect" : "Allow",
"Resource" : "arn:aws:s3:::XXX-user-uploads/*"
},
{ "Action" : [ "s3:ListBucket" ],
"Effect" : "Allow",
"Resource" : "arn:aws:s3:::XXX-user-uploads"
},
{ "Action" : "sts:GetFederationToken",
"Effect" : "Allow",
"Resource" : "*"
},
{ "Action" : "iam:GetUser",
"Effect" : "Allow",
"Resource" : "*"
},
{ "Action" : "sdb:*",
"Effect" : "Allow",
"Resource" : "*"
}
] }
AWS_ACCESS_KEY_ID = "xxx"
AWS_SECRET_ACCESS_KEY = "xxx"
AWS_S3_USER_UPLOAD_ACCESS_KEY_ID = "xxx"
AWS_S3_USER_UPLOAD_SECRET_ACCESS_KEY = "xxx"
AWS_S3_USER_UPLOAD_BUCKET = "xxx-user-uploads"
AWS_S3_USER_UPLOAD_TOKEN_DURATION = 60*15 # 15 minutes in seconds
AWS_S3_USER_UPLOAD_POLICY = """{
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::%%BUCKET_NAME%%/%%USERNAME%%/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::%%BUCKET_NAME%%",
"Condition": {
"StringLike": {
"s3:prefix": "%%USERNAME%%/"
}
}
},
{
"Effect": "Deny",
"Action": [
"sts:*",
"iam:*",
"sdb:*"
],
"Resource": "*"
}
]
}"""
Steps to setting up crap in the AWS console
1. create a bucket that will house the user uploads
2. create an IAM group and attach the permissions policy below.
replace "XXX-user-uploads" with the name of the bucket above
3. create an IAM user and add it to the group. these are the access
key and secret access key that you use when creating the federated user
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment