Upload to s3 via PHP fails access denied - php

I feel a bit stupid to ask this, but is there anything special required to upload something via the current PHP SDK to S3? I can upload via the cli with the same credentials, but when I try the SDK it fails.
Here the code:
<?php
require "awssdk_v3/aws-autoloader.php";
use Aws\S3\S3Client;
function s3_upload($file, $name) {
$s3 = S3Client::factory(
array(
'key' => getenv('AWS_ACCESS_KEY_ID'),
'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
'version' => "2006-03-01",
'region' => getenv('AWS_REGION')
)
);
$result = $s3->putObject(
array(
'Bucket' => getenv('AWS_BUCKET'),
'Key' => $name,
'SourceFile' => $file,
'ContentType' => mime_content_type($file),
'ACL' => 'public-read'
)
);
return true;
}
I call it like this
s3_upload($_FILES['avatarfile']['tmp_name'], "avatar_2.jpg");
The user I use has this policy attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1480066717000",
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
},
{
"Sid": "Stmt1480066765000",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket"
]
}
]
}
As mentioned I was able to upload a file from the CLI using that users credentials. The region is Frankfurt, so I specified eu-central-1, correct?
The error I get starts like this:
Fatal error: Uncaught exception 'Aws\S3\Exception\S3Exception' with message 'Error executing "PutObject" on "https://my-bucket.s3.eu-central-1.amazonaws.com/avatar_2.jpg"; AWS HTTP error: Client error: `PUT https://my-bucket.s3.eu-central-1.amazonaws.com/avatar_2.jpg` resulted in a `403 Forbidden` response

I found the problem thanks to this answer. I'm trying to set the ACL 'public-read', but haven't granted myself s3:PutObjectAcl, just s3:PutObject. Changing either fixes the problem.
Thanks anyway for the help.

Under IAM Policy, add S3:PutObjectAcl in permission if you set S3:PutObject for action.

I ran into this same error message, and it turns out my S3 buckets were created in the wrong region.

Related

Amazon Athena "Error opening Hive split" Access Denied Error

I am trying to run query in Amazon Athena from PHP code:
$client = Aws\Athena\AthenaClient::factory(array(
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => array(
'key' => '<KEY>',
'secret' => '<SECRET>'
)
));
$result1 = $client->StartQueryExecution(array(
'QueryExecutionContext' => array('Database' => 'default'),
'QueryString' => "select * from logs where date between TIMESTAMP '2020-02-27 00:00:00' and TIMESTAMP '2020-02-27 23:59:59' limit 100",
'ResultConfiguration' => array(
'EncryptionConfiguration' => array('EncryptionOption'=> 'SSE_S3'),
'OutputLocation' => 's3://bucket_name/temp'
)
));
and got this error:
Error opening Hive split s3:///data-mining/logs/2019/07/12/07/Log-6-2019-07-12-07-35-01-a1c6d0a9-27e5-458b-b72a-8942a6d2b261.parquet (offset=0, length=756977): com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: 4A00D465F919D8AB; S3 Extended Request ID: ...), S3 Extended Request ID: ... (Path: s3://<bucket_name>/data-mining/logs/2019/07/12/07/Log-6-2019-07-12-07-35-01-a1c6d0a9-27e5-458b-b72a-8942a6d2b261.parquet
I can confirm these:
Same query from Athena console (with root user) can be run without problem
I execute query from user which has permissions: AmazonAthenaFullAccess and AmazonS3FullAccess
Make sure you are using an IAM policy associated with the user performing the query that allows operations on the KMS key associated with the parquet files. Even though a bucket may be using SSE_S3, the files may already have been encrypted with KMS instead.
A policy like so:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": [
"arn:aws:kms:"region":"account":key/"keyid"
]
}
]
}

AWS S3 Upload to Frankfurt region using PHP SDK - Access denied error

In development environment, below code works perfectly to upload a file to AWS S3 Frankfurt region with credentials set up as mentioned in
https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html
PHP
require("aws.phar");
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
$bucket = 'my bucket';
$filepath = 'currentfilepath.jpeg';
$filename = 'newfilename.jpeg';
$s3 = S3Client::factory(array(
'key' => 'XXX',
'secret' => 'YYY',
'region' => 'eu-west-2',
'version' => 'latest'
));
try {
$result = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => $filename,
'SourceFile' => $filepath,
'ACL' => 'public-read'
));
var_dump($result);
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
However in deployed environment, I get Access denied error.
Error executing "PutObject" on
"https://s3.eu-west-2.amazonaws.com/mybucket/newfilename.jpeg";
AWS HTTP error: Client error: 403 AccessDenied (client): Access Denied
The only difference from development and deployed is that I do not have a credential file like in dev environment. I wonder how to manage credentials in deployed environment to make this work?
Reza Mousavi's answer in my view should help.
But I got this fixed by adding AmazonS3FullAccess to aws-elasticbeanstalk-ec2-role. This is done from the
IAM control panel >> Roles >>
Choose aws-elasticbeanstalk-ec2-role >> Attach Policies:AmazonS3FullAccess
Thanks
You should create the new API key/secret and assign the right IAM for access to your S3 bucket and publish the new credentials like the document you mentioned before:
https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html
Also, if your EC2 has a public IP address, you can grant access by the change in your S3 bucket policy:
{
"Version": "2012-10-17",
"Id": "Policy1462808223348",
"Statement": [
{
"Sid": "Stmt1462808220978",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::714656454815:role/ecsInstanceRole"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "YOUR-PUBLIC-IP/32"
}
}
}
]
}

PHP Amazon SDK, S3 Bucket Access Denied

I try for the first time to use the PHP AWS SDK ("aws/aws-sdk-php": "^3.19") to use S3.
I created a bucket : 'myfirstbucket-jeremyc'
I created a policy :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::myfirstbucket-jeremyc/*"
]
}
]
}
I applied the policy to a group and then created a user 's3-myfirstbucket-jeremyc' in this group.
My PHP code is :
<?php
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
error_reporting(E_ALL);
require(__DIR__ . '/vendor/autoload.php');
$s3Client = S3Client::factory([
'credentials' => [
'key' => $_SERVER['AWS_S3_CLIENT_KEY'],
'secret' => $_SERVER['AWS_S3_CLIENT_SECRET']
],
'region' => 'eu-west-1',
'version' => 'latest',
'scheme' => 'http'
]);
$result = $s3Client->putObject(array(
'Bucket' => 'myfirstbucket-jeremyc',
'Key' => 'text.txt',
'Body' => 'Hello, world!',
'ACL' => 'public-read'
));
But i get this error :
Error executing "PutObject" on
"http://s3-eu-west-1.amazonaws.com/myfirstbucket-jeremyc/text.txt";
AWS HTTP error: Client error: PUT
http://s3-eu-west-1.amazonaws.com/myfirstbucket-jeremyc/text.txt
resulted in a 403 Forbidden response
Do you know where i'm wrong ?
Thanks in advance !
You're setting the ACL for the new object but you haven't allowed s3:PutObjectAcl.

Amazon Lambda invocation error

I need to call my Amazon Lambda function, from php, but I am getting strange rights error when I have AWSLambdaFullAccess rights.
My code:
$client = LambdaClient::factory(array(
'key' => 'AKI...G',
'secret' => 'VXD...YOse',
'region' => 'us-west-2'
));
$result = $client->invokeAsync(array(
'FunctionName' => 'arn:aws:lambda:us-west-2:180...52:function:fe...st',
'InvokeArgs' => json_encode($array),
));
This is the error:
User: arn:aws:iam::69...67:user/developer is not authorized to
perform: lambda:InvokeFunction on resource:
arn:aws:lambda:us-west-2:180...52:function:fe...st
Any ideas? Thanks
You should give your PHP code the permission to call your Lambda function (otherwise everybody will be able to call your code...).
You need to create a role with the right permission and make sure that your PHP code assumes that role (for examples with Cognito or EC2 roles).
The role should include something like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1234567890",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:us-west-2:<YOUR-ACOUNT-ID>:function:<YOUR-FUNCTION-NAME>"
]
}
]
}

AWS S3 Permissions - Access Denied ON GetObjectUrl PHP

putObject works well for me. But when I do a getObjectURL s3 responds with an Access Denied. Looked into different ways to set the policy, etc. Still no luck. Any help appreciated!
putObject code:
$this->load->library('aws');
$temporary_png_path = tempnam(sys_get_temp_dir(), 'sig') . $upload_data['file_ext'];
$document_s3_key = 'profile_pictures/'.$user->id.'/profile_'.$user->id.$upload_data['file_ext'];
$resource = fopen($upload_data['full_path'], 'r');
try{
$aws_object=$this->aws->putObject(array(
'Bucket' => 'tbucket',
'Key' => $document_s3_key,
'SourceFile' => $resource,
'Body' => $resource,
'ContentType' => 'image/jpeg'
));
}
catch (Exception $e)
{
$error = "Something went wrong saving your file.\n".$e;
echo $error;
}
getObjectURL code:
$this->load->library('aws');
$profile_image = $this->aws->getObjectUrl('tbucket', 'profile_pictures/'.$user->id.'/'.'profile_'.$user->id.'.jpeg');
$this->data['image'] = ($profile_image == '')? "/public/images/avatar-large.jpg" : $profile_image;
AWS Permissions:
Authenticated Users => All Permissions enabled
Bucket Policy:
{
"Version": "2008-10-17",
"Id": "Policynumber",
"Statement": [
{
"Sid": "Stmtnumber",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::number:user/t_master"
},
"Action": [
"s3:GetObjectAcl",
"s3:GetObjectTorrent",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl"
],
"Resource": "arn:aws:s3:::tbucket/*"
}
]
}

Categories