Update AWS S3 item ACL using new PHP SDK - php

How can an item in S3 be updated with 'public-read' using the new AWS S3 PHP SDK: It would seem it is only possible to GET and PUT? http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html
The iterator returns an array, not a class. Get object returns a class, but there are no obvious methods to update. CopyObject seems a bit of a hack?
$s3->copyObject(array(
'Bucket' => 'media',
'Key' => $k,
'CopySource' => 'media'.'/'.$k,
'ACL' => 'public-read',
));
returns:
PHP Fatal error: Uncaught Aws\S3\Exception\InvalidRequestException: AWS Error Code: InvalidRequest, Status Code: 400, AWS Request ID: FC630F89A049823A, AWS Error Type: client, AWS Error Message: This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes., User-Agent: aws-sdk-php2/2.5.3 Guzzle/3.8.1 curl/7.35.0 PHP/5.5.9-1ubuntu4.4 thrown in /.../vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php on line 91

Better late than never.
$s3Client->putObjectAcl(array(
'Bucket' => 'yourbucket',
'Key' => 'yourkey',
'ACL' => 'public-read'
));

Related

copy folder from one to another in aws s3 in php

I am trying to copy a folder to another in aws s3 as below
$s3 = S3Client::factory(
array(
'credentials' => array(
'key' => 'testbucket',
'secret' => BUCKET_SECRET //Global constant
),
'version' => BUCKET_VERSION, //Global constant
'region' => BUCKET_REGION //Global constant
)
);
$sourceBucket = 'testbucket';
$sourceKeyname = 'admin/collections/Athena'; // Object key
$targetBucket = 'testbucket';
$targetKeyname = 'admin/collections/Athena-New';
// Copy an object.
$s3->copyObject(array(
'Bucket' => $targetBucket,
'Key' => $targetKeyname,
'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
));
It is throwing error as
Fatal error: Uncaught exception 'Aws\S3\Exception\S3Exception' with
message 'Error executing "CopyObject" on
"https://testbucket.s3.us-east-2.amazonaws.com/admin/collections/Athena-New";
AWS HTTP error: Client error: PUT
https://testbucket.s3.us-east-2.amazonaws.com/admin/collections/Athena-New
resulted in a 404 Not Found response:
NoSuchKeyThe specified key does not
exist.admin/collections/AthenaNoSuchKeyThe specified key does not
exist.admin/collections/Athena29EA131A5AD9CB836OjDNLgbdLPLMd0t7MuNi4JH6AU5pKfRmhCcWigGAaTuRlqoX8X5aMicWTui56rTH1BLRpJJtmc='
I can't figure out why it is making wrong bucket url like
https://testbucket.s3.us-east-2.amazonaws.com/admin/collections/Athena-New
While right aws bucket url is
https://s3.us-east-2.amazonaws.com/testbucket/admin/collections/Athena-New
Why it is appending the bucket name to before s3 in url?
In simple words, I wanted to copy the content of
https://s3.us-east-2.amazonaws.com/testbucket/admin/collections/Athena
to
https://s3.us-east-2.amazonaws.com/testbucket/admin/collections/Athena-New
It is not possible to "copy a folder" in Amazon S3 because folders do not actually exist.
Instead, the full path of an object is stored in the object's Key (filename).
So, an object might be called:
admin/collections/Athena/foo.txt
If you wish to copy all objects from one "folder" to another "folder", then you will need to:
Obtain a listing of the bucket for the given Prefix (effectively, full path to the folder)
Loop through each object returned, and copy the objects one-at-a-time to the new name (which effectively puts it in a new folder)
So, it would copy admin/collections/Athena/foo.txt to admin/collections/Athena-New/foo.txt

Uploading object into transfer accelerated S3 bucket using PHP

I am new to AWS. As I understand, S3 transfer acceleration uses the Cloudfront edges for fastest uploading, but I can't find the proper documentation for PHP API, for uploading object into transfer acceleration enabled bucket.
My code :
use Aws\S3\S3Client;
$S3_Client = new S3Client([
'version' => 'latest',
'region' =>'ap-south-1',
'credentials' => [
'key' => 'Accesskey',
'secret' => 'Secretkey',
],
'endpoint' => 'http://my_bucket_name.s3-accelerate.amazonaws.com'
]);
$bucket = 'my_bucket_name';
$key = 'EC2.pdf';
$SourceFile = '/path/to/the/file/EC2.pdf';
$put = $S3_Client->putObject([
'Bucket' => $bucket,
'Key' => $key,
'SourceFile' => $SourceFile
]);
I am getting the following error
The authorization header is malformed;
the region 'ap-south-1' is wrong; expecting 'us-east-1'
but my bucket is located in us-east-1 , when I change the region as
us-east-1
I am getting the following error:
The specified bucket does not exist
Instead of endpoint => ..., pass 'use_accelerate_endpoint' => True to the constructor.
There are a number of different rules that come into play when building a request to send to S3. The endpoint option provides a service endpoint, rather than a bucket endpoint, and is mostly useful for non-standard configurations.
This may be related to this discussion: https://github.com/hashicorp/terraform/issues/2774
Try the following solution -
"I had same issue, i had created the bucket previously and deleted it. I changed the name and it applied no problem."

PHP SDK Cannot get AWS Credentials on EC2 Instance with IAM Role attached

Simple question. But cannot get it to work.
I created an IAM Role for EC2 with full access to CloudWatch.
I launched a new EC2 instance with this IAM Role attached.
I wrote a simple PHP application on this EC2 instance which tries to publish metrics to CloudWatch.
I am getting this error in nginx logs:
2017/08/23 11:44:06 [error] 32142#32142: *5 FastCGI sent in stderr:
"PHP message: PHP Fatal error:
Uncaught Aws\Exception\CredentialsException:
Cannot read credentials from /var/www/.aws/credentials
in /var/www/app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php:394
From that same EC2 instance, the command:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-attached-to-ec2-instance>
returns 200 OK with the Access Key and Secret in the response.
This is my PHP code that tries to write CloudWatch metrics:
<?php
require 'vendor/autoload.php';
use Aws\CloudWatch\CloudWatchClient;
use Aws\Exception\AwsException;
$count = $_GET["count"];
publishMetric($count);
function publishMetric($count) {
$client = new CloudWatchClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => '2010-08-01'
]);
try {
$result = $client->putMetricData(array(
'Namespace' => 'com.mynamespace',
'MetricData' => array(
array(
'MetricName' => 'Count',
//Timestamp : mixed type: string (date format)|int (unix timestamp)|\DateTime
'Timestamp' => time(),
'Value' => $count,
'Unit' => 'Number'
)
)
));
var_dump($result);
echo 'Done publishing metrics';
} catch (AwsException $e) {
// output error message if fails
error_log($e->getMessage());
echo 'Failure to publish metrics';
}
}
?>
Any idea what is missing in this setup?
I know this is late. I had the same issue and resolved it by removing profile => default line while initializing the client. If you do not provide credentials and profile, SDK will try to retrieve instance profile creds from metadata server.
Authentication of EC2 instance while accessing other AWS Services can be done in multiple ways:
Assigning a role to EC2 instance. Used when u have to give some "EC2 instance" a permission.
Do not assign a role; but use access-key which has all required permissions. Used when you give permission to a "User"
Both these are independent authentication mechanism. If you have already assigned role to your server; you do not have to write any code in your application (CredentialProvider.php) to authenticate.
Your current code can also be worked by creating a file /var/www/.aws/credentials which will look something like this:
accessKey=AKIAIB6FA52IMGLREIIB
secretKey=NQjJWKT+WZOUOrQ2Pr/WcRey3PnQFaGMJ8nRoaVU

Using Authentication Signature v4 in aws SDK

I am creating EC2 Instances using AWS PHP SDK. When I try to create an instance in Frankfurt region the API gives me authentication error as this region supports v4 signature service.
When I try to provide 'signature' => 'v4' parameters to client factory method, I get this error
Fatal error: Call to a member function signRequest() on a non-object in \Aws\Common\Signature\SignatureListener.php on line 78
Any suggestions on what's the correct method to use signature v4. Currently I'm using this code.
Aws::factory(array(
'key' => $this->key,
'secret' => $this->secret,
'region' => $region,
'signature' => 'v4')
)->get($service, true);
Finally got it to work, basically we have to provide an Aws\Common\Signature\SignatureV4 Instance in the client factory.
'signature' => new SignatureV4()

AWS - You are not authorized to perform this operation on accessing describeInstanceStatus from ec2 client object

I have created an ec2 client using the method mentioned in the AWS docs. I am using the aws.phar file for the SDK. The ec2 client is created properly because when I var_dump the client, it returns the Ec2Client object. But when I attempt to access the describeInstanceStatus from the ec2 client it throws a You are not authorized to perform this operation. exception. This is my code.
use Aws\Ec2\Ec2Client;
require 'aws.phar';
$ec2Client = Ec2Client::factory(array(
'key' => '<aws access key>',
'secret' => '<aws secret key>',
'region' => 'us-east-1'
));
try{
$ec2Client->describeInstanceStatus(array(
'DryRun' => false,
'InstanceIds' => array('InstanceId'),
'Filters' => array(
array(
'Name' => 'availability-zone',
'Values' => array('us-east-1'),
),
),
'MaxResults' => 10,
'IncludeAllInstances' => false,
));}
catch(Exception $e){
echo $e->getMessage();
}
Please tell me where am I getting this wrong. I've tried googling it, looked in the AWS forums but to no result. Thank you.
The error is coming from the Access that you have been granted/denied via AWS IAM.
The user, whose access/secret keys you are using in the code, does not have privilege to describe instances. This privilege is configured in the IAM policy which is applied to this user.
There is nothing wrong with your code. You need to look into the IAM policy about what all privileges are granted/denied to this user.

Categories