Access Denied to S3 Objects Uploaded via SDK - amazon-s3

I am trying to create an IAM user that is permitted to:
Upload Objects
Get Objects
List Bucket Objects
The policy seems to be working. However, I cannot view the images that were uploaded via the S3 SDK. When referencing one of the image files in an HTML <img /> tag, I get a 403 Forbidden error. On the other hand, I am able to successfully view images that were uploaded via the AWS Console with the defaults, without setting any additional policies, etc. Is there an attribute I'm not setting when uploading the image to S3 using the SDK?
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my_bucket"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "MyIpV4Address"
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl"
],
"Resource": [
"arn:aws:s3:::my_bucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "MyIpV4Address"
}
}
}
]}
The JavaScript code I am using to upload the files.
handleFileUpload(acceptedFiles, rejectedFiles) {
return Promise.map(acceptedFiles.map(file => {
const object = {
Key: `some-image-key.jpg`,
Body: file,
ContentType: file.type,
StorageClass: 'STANDARD_IA'
}
return this.s3.putObject(object).promise(response => {
console.log(response);
});
}));

Try uploading with an additional: .withCannedAcl(BucketOwnerFullControl)
This specifies the owner of the bucket, but not necessarily the same as the owner of the object, is granted Permission.FullControl.
See:
withCannedAcl()
CannedAccessControlList

Related

How do I allow Cognito users access to private content on my AWS static S3 bucket?

I have spent weeks going in circles over this. I have a static S3 website with several 'folders'. I would like to allow public access to the 'root' and 'public' (css, javascript, etc.) folders, but want to restrict access to a 'user' folder.
I set up a User Pool & Group in Cognito that works well for my users (JWTs for customer usernames), but I am having one heck of a time connecting the dots! I have tried using the IAM policy (below), but I know I'm doing something wrong. Would love any suggestions on where to go from here...
Anyone see errors on my policy language? Will a policy similar to this work despite having "Block All Public Access" enabled?
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessToMyBucket",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket",
"Condition": {
"StringEquals": {
"s3:prefix": [ "", "public/*" ],
"s3:delimiter": [ "/" ]
}
}
},
{
"Sid": "AllowAccessToUserFolder",
"Effect": "Allow",
"Action": [ "s3:GetObject" ],
"Resource": [ "arn:aws:s3:::mybucket/user" ],
"Condition": {
"StringLike": {
"s3:prefix": [ "${aws:username}/*" ],
"s3:delimiter": [ "/" ]
}
}
}
]
}

Need help understanding inconsistent behaviour and KMS error when deploying changes via CDK

We are using CDK to create s3 buckets in different regions and to manage a codepipeline which deploys to these cross region and cross account buckets.
We have seen some inconsistent behavior lately when we deployed changes to the pipeline (Add a permission to Codebuild role).
We were getting the following error:
Policy contains a statement with one or more invalid principals. (Service: AWSKMS; Status Code: 400; Error Code: MalformedPolicyDocumentException;
We do not explicitly create KMS keys. The KMS keys and its policy were auto generated during CDK deploy.
To resolve this error, we destroyed the existing S3 buckets and the pipeline and re-deployed it with a different name. The 1st time the deploy was successful in deploying the S3 buckets in all regions except for ap-southeast-2 (With the same error). The second time we rinsed and repeated, it deployed fine.
We are not sure what is causing this behavior. We wanted to confirm if this is a known bug or something we need to change in our code to resolve this inconsistency.
Following is the KMS policy auto-generated for ap-southeast-2 using cdk synth when it was failing to deploy :
"KeyPolicy": {
"Statement": [
{
"Action": [
<Truncated>
],
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::<Bucket_ACCOUNT_ID>:root"
]
]
}
},
"Resource": "*"
},
{
"Action": [
<Truncated>
],
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::<Bucket_ACCOUNT_ID>:root"
]
]
}
},
"Resource": "*"
},
{
"Action": [
<Truncated>
],
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::<Pipeline_Account_ID>:role/<role_name>"
]
]
}
},
"Resource": "*"
},
{
"Action": [
<Truncated>
],
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::<Pipeline_Account_ID>:role/<role_name>"
]
]
}
},

Connecting aspera on cloud with S3bucket

I used this policy on AWS to try connecting AoC with an S3 bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::880559705280:role/atp-aws-us-east-1-ts-atc-node"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"sts:ExternalId": "crn:v1:bluemix:public:aspservice-service:global:a/2dd2425e9a424641a12855a1fd5e85ee:70740386-6ca4-4473-bf9b-69a1fd22be12:::c1893698-abfa-4934-a7ca-1a6d837df5e0"
}
}
}
]
}
but when copied on Bucket Policy, I receive Error: Statement is missing required element.
What is wrong?
You need to paste this policy file into Trust relationship policy in Role tab.

How to access AWS S3 bucket logging in with Google and Cognito User/Identity Pool

I'm using the AWS Cognito Enhanced (Simplified) Flow to get the Cognito Identity Credentials providing the idToken received after logging in with Google sign-in api:
export function getAWSCredentialWithGoogle(authResult) {
if (authResult['idToken'] != null) {
AWS.config.region = 'eu-central-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'eu-central-1:xxxxxxxxxxxxxxxxxxxxxxxx',
Logins: {
'accounts.google.com': authResult['idToken']
}
})
return AWS.config.credentials.getPromise()
.then(
function(){
return getAWSCredentials(AWS.config.credentials);
},
function(err) {
}
)
} else {
console.log('no auth code found!');
}
}
I get the:
accessKeyId:"ASIAXXXXXX",
secretAccessKey:"ta4eqkCcxxxxxxxxxxxxxxxxxxx",
sessionToken:"xxxxxxxxx...etc..."
Then I try to upload a picture to an S3 bucket passing the above received accessKeyId and secretAccessKey.
But I receive this error result:
InvalidAccessKeyIdThe AWS Access Key Id you provided does not exist in our records.ASIAXXXXXXXXXXXXXXXX
This is how I set up the AWS S3 (managed) policy (the resource policy for the bucket is the default one) to access progammaticaly the bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::xxxxxxxxxx",
"arn:aws:s3:::xxxxxxxxxx/users"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"${cognito-identity.amazonaws.com:sub}/*"
]
}
}
},
{
"Action": [
"s3:PutObject",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:PutObjectVersionAcl",
"s3:DeleteObject",
"s3:PutObjectAcl",
"s3:GetObjectVersion"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::xxxxxxxxx/users/${cognito-identity.amazonaws.com:sub}",
"arn:aws:s3:::xxxxxxxxx/users/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
this policy has been attached to an IAM role with the following trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "eu-central-1xxxxxxxxxxx"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
I've properly configured the Federated Identity Pool to use this role, and added Google as an OpenID Connect provider.
I also configured my Cognito Identity Pool to accept users federated with my Cognito User Pool by supplying the User Pool ID and the App Client ID.
I would like to to give to any Google sign-in authenticated user, access to the S3 bucket and have read/write permission to his own directory.

CREATE_FAILED Bucketpolicy - Unknown field Fn::Join

My Cloudformation stack fails and keeps getting rolled back because of the following S3 bucket policy. The referenced S3 bucket is a separate bucket meant for CloudTrail logs (as I read that such a thing is best practice when using CloudTrail). The bucket gets created along with the rest of the stack during the cloudFormation process: [stackname]-cloudtraillogs-[randomstring]
I tried not using any functions to specify the bucket, but that doesn't seem to work. My guess is because it then goes looking for a bucket 'cloudtraillogs' and can't find any bucket with that name. Using a Fn::Join with a reference might solve that(?), but then CloudFormation gives 'Unknown field Fn::Join' when evaluating bucket policy.
Anyone who can spot what I might be doing wrong here?
Bucketpolicy
{
"Resources": {
"policycloudtraillogs": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "cloudtraillogs"
},
"PolicyDocument": {
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck20160224",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "cloudtraillogs"
},
"/*"
]
]
},
{
"Sid": "AWSCloudTrailWrite20160224",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "cloudtraillogs"
},
"/AWSLogs/myAccountID/*"
]
]
},
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
}
}
}
}
Your template does not appear to be valid JSON. Your first policy statement (AWSCloudTrailAclCheck20160224) is missing a closing bracket } for its Resource object.