Get presigned url of all objects in bucket amazon aws s3 - php

I am trying to get pre-signed url of all object in bucket. I am using amazon php sdk version 3.
What I have tried is
$client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials.ini' => [
'key' => $credentials['key'],
'secret' => $credentials['secret'],
],
]);
$client->listObjects(['Bucket' => $bucketName]);
Above get me all object in arrayAccess but It have object url like
https://s3-us-west-2.amazonaws.com/some-demo/one2.txt
and I don't want that everyone have access to one2.txt so I have created a preassigned url by
$cmd = $client->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $client->createPresignedRequest($cmd, '+20 minutes');
$presignedUrl = (string) $request->getUri();
echo $presignedUrl;
Now I am getting url with token
https://s3-us-west-2.amazonaws.com/some-demo/one2.txt?X-Amz-Content-Sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJUZQHGPBTNOLEUXQ%2F20150828%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20150828T090256Z&X-Amz-SignedHeaders=Host&X-Amz-Expires=1200&X-Amz-Signature=77e52cf99c0f438d48851193dbaba0fsdfe1b4d8e604d6sdf11a22b3be45e410168ab81
which Is exactly what I want but Now my question is
How to get preassigned url all items in bucket rather than making for all item one by one ?

I think there is one way to get preassigned url of all items by creating an array of multiple getCommands, getCommand can handle multiple commands and then you can use toArray() function of Aws\CommandInterface to convert it into an array. The createPresignedRequest() function does not support for multiple requests either you have to called it repetitive or need to use an getObject()

Related

Temporary S3 Bucket URL for serving Images

Using "aws/aws-sdk-php": "^3.0#dev"
I am creating a image sharing website but do not want people to copy my URLs to another site to steal my content/bandwidth.
I was originally storing the objects as
return $s3->putObject([
'Bucket' => $bucket,
'Key' => $key,
'Body' => $file,
'ACL' => 'public-read',
]);
But I have removed 'public-read' so now the URL below no longer works
https://mybucket-images.s3.us-west-1.amazonaws.com/' . $key);
What do I need to do to create a temporary URL that can still be client side cached to access the object?
One thing I was thinking was to change the key once a week or month, but it would require me to update all objects with a cronjob. There must be a way to create a temporary access URL?
Use your server to generate presigned url for the keys in the bucket.
//Creating a presigned request
$s3Client = new Aws\S3\S3Client([
'profile' => 'default',
'region' => 'us-east-2',
'version' => '2006-03-01',
]);
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => 'my-bucket',
'Key' => 'testKey'
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
$presignedUrl = (string) $request->getUri();
taken from https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-presigned-url.html
But you'd have to do this every time there's a request to your page. And the link will be valid everywhere. You just minimize the period of its validity.
If your website is an API based and you retrieve the url via API, this may be relevant to you:
If your website has a login function, you can check for the auth logic prior giving the presigned url.
If not, you can use Http Referrer (which can be spoofed). Or an api key (like in API Gateway)
You can use the following code:
// initiate connection to your S3 bucket
$client = new S3Client(['credentials' => ['key' => 's3 key', 'secret' =>'s3 secrete'], 'region' => 's3 region', 'version' => 'latest']);
$object = $client->getCommand('GetObject', [
'Bucket' => 's3 bucket',
'Key' => 'images/image.png' // file
]);
$presignedRequest = $client->createPresignedRequest($object, '+20 minutes');
$presignedUrl = (string)$presignedRequest->getUri();
if ($presignedUrl) {
return $presignedUrl;//presigned URL
} else {
throw new FileNotFoundException();
}
If your intent is to make your content readable ONLY via a URL posted on your website - versus having the same web client using the same url accessed from another site NOT work, I think you are likely to find that rather difficult. Most of the ways that come to mind are fairly spoofable.
I would take a look at this and see if its good enough for you:
Restricting Access to a Specific HTTP Referrer

Uploading file to S3 using presigned URL in PHP

I am developing a Web Application using PHP. In my application, I need to upload the file to the AWS S3 bucket using Presigned URL. Now, I can read the private file from the S3 bucket using pre-signed like this.
$s3Client = new S3Client([
'version' => 'latest',
'region' => env('AWS_REGION', ''),
'credentials' => [
'key' => env('AWS_IAM_KEY', ''),
'secret' => env('AWS_IAM_SECRET', '')
]
]);
//GetObject
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => env('AWS_BUCKET',''),
'Key' => 'this-is-uploaded-using-presigned-url.png'
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
//This is for reading the image. It is working.
$presignedUrl = (string) $request->getUri();
When I access the $presignedUrl from the browser, I can get the file from the s3. It is working. But now, I am uploading a file to S3. Not reading the file from s3. Normally, I can upload the file to the S3 like this.
$client->putObject(array(
'Bucket' => $bucket,
'Key' => 'data.txt',
'Body' => 'Hello!'
));
The above code is not using the pre-signed URL. But I need to upload the file using a pre-signed URL. How, can I upload the file using a pre-signed URL. For example, what I am thinking is something like this.
$client->putObject(array(
'presigned-url' => 'url'
'Bucket' => $bucket,
'Key' => 'data.txt',
'Body' => 'Hello!'
));
How can I upload?
It seems reasonable that you can create a pre-signed PutPobject command by running:
$cmd = $s3Client->getCommand('PutObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes')->withMethod('PUT');
Then you might want to perform the PUT call from PHP using:
file_put_contents(
$request->getUri(),
'Hello!',
stream_context_create(['http' => [ 'method' => 'PUT' ]])
);
If you want to create a URL that a browser can submit, then you need to have the browser send the file as a form POST. This AWS documentation explains how to create a pre-signed POST request with the fields that you then need to put into an HTML form and display to the user: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-presigned-post.html
Also, this answer might be useful: https://stackoverflow.com/a/59644117/53538

Trying to register an amazon s3 presigned url and getting an error

The question it self explanatory, when trying to create a presigned url I get the following error:
Error retrieving credentials from the instance profile metadata server. (cURL error 28: Connection timed out after 1001 milliseconds (see http://curl.haxx.se/libcurl/c/libcurl-errors.html))
I have used the code from here exactly https://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-presigned-url.html
My code is below:
$s3Client = new S3Client([
'region' => 'eu-west-1',
'version' => '2006-03-01',
]);
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => 'my-bucket-name',
'Key' => 'AKIAJNCZ5***********'
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();
print_r($presignedUrl);
Any reason why this is happening?
EDIT::
Ok so this fixed my problem, but it wasnt not actually even in the docs:
$s3Client = new S3Client([
'region' => 'eu-west-1',
'version' => '2006-03-01',
'credentials' => ['key' => 'AKIAJNCZ5MY*******8','secret'=>'NgeFc+2/Q2cUAmL/+lP2gp***********8']
]);
Adding the credentials assoc array :)
However I am now unsure how to use this presigned url to download one of my files aha, so if anyone knows and doesnt mind putting me in the right direction :)
'Key' in the getCommand array is the name/path to the file you want to generate a pre-signed URL for, not your AWS key :)
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => 'my-bucket-name',
'Key' => 'path/to/file.txt', // or just file.txt if it's in the root of the bucket
]);

In codeigniter get file list from Amazon s3 bucket

I have an amazon s3 bucket that has 20+ records in it. How to get all file names with pagination support using PHP codeigniter.
Thanks in advance!
First you need to get all object by listObjects
$result = $s3->listObjects([
'Bucket' => 'your-bucket-name'
]);
it will return array of objects and with links( if your bucket is public than you can open those link else you need to use signed url or cloudfront )
And i would simply suggest you to use dataTable (it has pagination, Search ) and your record is not like 30-40k so it will work fine
As you have asked you can bucket object list by passing key and secret in constructor, i am using aws phpsdk v3
s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials.ini' => [
'key' => $credentials['key'],
'secret' => $credentials['secret'],
],
]);
Now just
$result = $s3->listObjects([
'Bucket' => 'your-bucket-name'
]);
That's it you got array of all object in your bucket

AWS PHP SDK deleteMatchingObjects() does not return count

The AWS PHP SDK documentation for deleteMatchingObjects states that it returns an integer: "Returns the number of deleted keys"
http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html#_deleteMatchingObjects
My media is deleted successfully but I get an empty value back where I'm supposed to get a count of deleted objects. Am I doing something wrong?
This is in the beforeDelete method of a CakePHP 2.x Model Behavior.
$s3 = new Aws\Sdk(array('version' => 'latest', 'region' => 'us-west-1', 'credentials' => array('key' => $this->s3Key, 'secret' => $this->s3Secret)));
$client = $s3->createS3();
$delete = $client->deleteMatchingObjects($this->s3ReadBucket, $this->fileGroupPrefix($model->name, $model->id));
$this->__logger($delete);

Categories