How to access public AWS S3 bucket in laravel - php

I have a public S3 bucket called latheesan-public-bucket (for example) in AWS in the eu-west-1 region.
If I were to visit the following url in the browser (for example):
https://latheesan-public-bucket.s3-eu-west-1.amazonaws.com/
I get the following XML showing that I have one file in the bucket:
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>latheesan-public-bucket</Name>
<Prefix />
<Marker />
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>test.json</Key>
<LastModified>2017-07-11T16:39:50.000Z</LastModified>
<ETag>"056f32ee5cf49404607e368bd8d3f2af"</ETag>
<Size>17658</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
</ListBucketResult>
If I were to then visit https://latheesan-public-bucket.s3-eu-west-1.amazonaws.com/test.json I can download my file from my public bucket.
In order to achieve the same in my Laravel application; I first added this package via composer:
league/flysystem-aws-s3-v3
Then on my .env I've added the following lines:
AWS_REGION=eu-west-1
AWS_BUCKET=latheesan-public-bucket
Lastly, I then tried to use the laravel filesystem to access the public s3 bucket file like this:
$json = Storage::disk('s3')->get('test.json');
When I did this; I got the following error:
Error retrieving credentials from the instance profile metadata
server. (cURL error 28: Connection timed out after 1000 milliseconds
(see http://curl.haxx.se/libcurl/c/libcurl-errors.html))
So, I updated my .env with some fake credentials:
AWS_KEY=123
AWS_SECRET=123
AWS_REGION=eu-west-1
AWS_BUCKET=latheesan-public-bucket
Now I get this error:
Illuminate \ Contracts \ Filesystem \ FileNotFoundException
test.json
So my question is; firstly what am I doing wrong here? Is there no way to access a public s3 bucket in laravel without actually providing a valid S3 Key/secret? what if I don't know them? I only have the url to the public s3 bucket.
P.S. the latheesan-public-bucket does not exist (it was a dummy bucket name to explain my problem, I do have a real public bucket I am trying to work with and it works fine in browser as explained above).

When you try to access it via the HTTPS URL, it works because it is public, and you're
When you try to access it via the SDK, it is trying to use the API to access it.
So either give your instance profile the correct permissions to access the bucket (which would no longer need to be public) or simply use an http client to retrieve the file.

If you use the S3 API to access your bucket, AWS credentials are required. The reasons is that the API needs to sign the S3 request.

Related

Error 409 when copy Azure Blob file within container with PHP

Using PHP to connect to Azure blob storage account. Using azure-storage-php ( github )
For the copy i use BlobRestProxy.copyBlob() using the api.
I am able to connect to the azure blob storage. Able to upload, list, delete blob files. But not able to copy the blob file within the same container. Does anyone has an example of how to copy a blob file within php using azure-storage-php or does anyone recognizes the error?
I already tried it with several blob storage account settings (public and not). For authentication i use a Shared Access Signature. The weird thing is that i am able to do alle things like create, read and delete but copy does give the below error. Thanks in advance.
The storage account is new, created at 3-12-2021
Fail:
Code: 409
Value: Public access is not permitted on this storage account.
details (if any): <?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>Public access is not permitted on this storage account.
RequestId:4b324b08-b01e-0009-6c1e-1187a1000000
Time:2022-01-24T12:30:35.8956602Z</Message></Error>.
Thanks for the reply allready!
The Shared Access Signature specified on the request applies only to the destination blob while using Copy Blob
Access to the source blob is authorized separately
If you are using the shared key (Storage Account Key), the authorization would have been done with the same key
As you are using Shared Access Signature, you need to append the SAS token in the x-ms-copy-source in the request
Thanks to RamaraoAdapa-MT, your answer was very helpfull. The developer has fixed the problem now.
And it was indeed the case that if you use the storage account key the copy is done with the same key. Public access is not necessery in both cases (SAS or AccountKey)

Error retrieving credentials from the instance profile metadata server with credentials defined in .aws folder

I have a web page on an AWS instance located at /var/www/html/
Until now this website used the keys AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in the code itself to access files hosted on S3.
For security reasons,
I have removed these keys from my code and used the aws configure command to ssh to store them on the server as recommended by AWS.
I see that in my directory ~.aws/ folder has been created with 2 files: credentials and config.
Both seem to be correct but in the web logs now I get the following error when trying to access files from S3:
PHP Fatal error: Uncaught Aws\Exception\CredentialsException: Error retrieving credentials from the instance profile metadata server. (Client error: 'GET http://169.254.169.254/latest/meta-data/iam/security-credentials /' resulted in a '404 Not Found resulted in a '404 Not Found' response:
<! DOCTYPE html PUBLIC "- // W3C // DTD XHTML 1.0 Transitional // EN"
"http: // www. (truncated ...)
) in /var/www/html/aws/Aws/Credentials/InstanceProfileProvider.php:88
I don't know what that URL is but I can't access it through the browser.
I have tried it with environment variables:
export AWS_ACCESS_KEY_ID = xxxxx...
I have copied the .aws folder to / var / www
I have given more permissions to .aws, I have changed the owner and group from root to ec2-user ...
How should I do the configuration so that my code correctly calls S3 and gets the files?
Call example that fails:
$s3 = new Aws\S3\S3Client ([
'version' => 'latest',
'region' => 'eu-central-1'
]);
if ($s3) {
$result = $ s3-> getObject (array (
'Bucket' => AWS_S3_BUCKET,
'Key' => $s3_key,
'Range' => 'bytes ='. $Startpos .'- '. ($Startpos + 7)
));
You probably need to move the .aws folder to the home folder of the service (apache) and not your home folder. The aws sdk can't find it and you receive this error. However, it isn't a good idea to use aws configure inside an EC2 instance.
The http://169.254.169.254/latest/meta-data/ is the meta-data url only available from inside an EC2 instance. For services running in EC2 (or other AWS compute service) you SHOULD NOT use AWS credentials to access services. Instead, you should create an IAM role and add assign it to the instance. From the console, you can do that with the Actions button:
Only assign required permissions to the role (S3 read/write).
Your code ($s3 = new Aws\S3\S3Client) will try to load the default credentials. It will first try to call the meta-data service and get temporary credentials that correspond to the IAM role permissions.

Error retrieving credentials from the instance profile metadata server: s3 with Laravel

I am developing a web application using Laravel. In my application, I develop a feature for uploading the file to the server. But, I will store the files in the Amazon S3 bucket instead. So, I am just following the Laravel official documentation - https://laravel.com/docs/5.5/filesystem. But I am getting an error.
First I run this command to install required package in the terminal
composer require league/flysystem-aws-s3-v3
Then in the environment file, I added these variable
AWS_IAM_KEY=xxxxxxx
AWS_IAM_SECRET=xvxxxx
AWS_REGION=eu-west-2
AWS_BUCKET=xxxxxxx
Then in the controller, I upload like this.
$request->file('photo_file')->store(
'activity_files/'.uniqid(), 's3'
);
When I upload the file, it is giving me this error.
Error retrieving credentials from the instance profile metadata server. (cURL error 7: Failed to connect to 169.254.169.254 port 80: Network unreachable (see http://curl.haxx.se/libcurl/c/libcurl-errors.html))
What is wrong with my code?

Error executing "PutObject" on AWS, upload fails

I have established an AWS acct. and am trying to do my first programmatic PUT into S3. I have used the console to create a bucket and put things there. I have also created a subdirectory (myFolder) and made it public. I created my .aws/credentials file and have tried using the sample codes but I get the following error:
Error executing "PutObject" on "https://s3.amazonaws.com/gps-photo.org/mykey.txt"; AWS HTTP error: Client error: PUT https://s3.amazonaws.com/gps-photo.org/mykey.txt resulted in a 403 Forbidden response:
AccessDeniedAccess DeniedFC49CD (truncated...)
AccessDenied (client): Access Denied -
AccessDeniedAccess DeniedFC49CD15567FB9CD1GTYxjzzzhcL+YyYsuYRx4UgV9wzTCQJX6N4jMWwA39PFaDkK2B9R+FZf8GVM6VvMXfLyI/4abo=
My code is
<?php
// Include the AWS SDK using the Composer autoloader.
require '/home/berman/vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
$bucket = 'gps-photo.org';
$keyname = 'my-object-key';
// Instantiate the client.
$s3 = S3Client::factory(array(
'profile' => 'default',
'region' => 'us-east-1',
'version' => '2006-03-01'
));
try {
// Upload data.
$result = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => "myFolder/$keyname",
'Body' => 'Hello, world!',
'ACL' => 'public-read'
));
// Print the URL to the object.
echo $result['ObjectURL'] . "\n";
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
If anyone can help me out, that would be great. Thanks.
--Len
It looks like the same issue I ran into. Add a AmazonS3FullAccess policy to your AWS account.
Log into AWS.
Under Services select IAM.
Select Users > [Your User]
Open Permissoins Tab
Attach the AmazonS3FullAccess policy to the account
I facing same problem and found the solution as below.
remove line
'ACL' => 'public-read'
default permission with list, read, and write but without permission for change object specific permission (PutObjectAcl in AWS policy).
Braden's approach will work, but it is dangerous. The user will have full access to all your S3 buckets and the ability to log into the console. If the credentials used in the site are compromised, well...
A safer approach is:
AWS Console -> IAM -> Policies -> Create policy
Service = S3
Actions = (only the minimum required, e.g. List and Read)
Resources -> Specific -> bucket -> Add ARN (put the ARN of only the buckets needed)
Resources -> Specific -> object -> check Any or put the ARN's of specific objects
Review and Save to create policy
AWS Console -> IAM -> Users -> Add user
Access type -> check "Programmatic access" only
Next:Permissions -> Attach existing policies directly
Search and select your newly created policy
Review and save to create user
In this way you will have a user with only the needed access.
Assuming that you have all the required permissions, if you are getting this error, but are still able to upload, check the bucket permissions section under your bucket, and try disabling (uncheck) "Block all public access," and see if you still get the error. You can enable this option again if you want to.
This is an extra security setting/policy that AWS adds to prevent changing the object permissions. If your app gives you problems or generates the warning, first look at the code and see if you are trying to change any permissions (which you may not want to). You can also customize these settings to better suit your needs.
Again, you can customize this settings by clicking your S3 bucket, permissions/ edit.
The 403 suggests that your key is incorrect, or the path to key is not correct. Have you verified that the package is loading the correct key in /myFolder/$keyname?
Might be helpful to try something simpler (instead of worrying about upload filetypes, paths, permissions, etc.) to debug.
$result = $client->listBuckets();
foreach ($result['Buckets'] as $bucket) {
// Each Bucket value will contain a Name and CreationDate
echo "{$bucket['Name']} - {$bucket['CreationDate']}\n";
}
Taken from http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html Also check out the service builder there.
The problem was a lack of permissions on the bucket themselves once I added those everything worked fine.
I got the same error issue. Project is laravel vue, I'm uploading file using axios to s3.
I'm using vagrant homestead as my server. Turns out the time on the virtual box server is not correct. I had to update it with the correct UTC time. After updating to correct time which I took from the s3 error it worked fine.
Error: I have removed sensitive information
message: "Error executing "PutObject" on "https://url"; AWS HTTP error: Client error: `PUT https://url` resulted in a `403 Forbidden` response:↵<?xml version="1.0" encoding="UTF-8"?>↵<Error><Code>RequestTimeTooSkewed</Code><Message>The difference between the reque (truncated...)↵ RequestTimeTooSkewed (client): The difference between the request time and the current time is too large. - <?xml version="1.0" encoding="UTF-8"?>↵<Error><Code>RequestTimeTooSkewed</Code><Message>The difference between the request time and the current time is too large.</Message><RequestTime>20190225T234631Z</RequestTime><ServerTime>2019-02-25T15:47:39Z</ServerTime><MaxAllowedSkewMilliseconds>900000</MaxAllowedSkewMilliseconds><RequestId>-----</RequestId><HostId>----</HostId></Error>"
Before:
vagrant#homestead:~$ date
Wed Feb 20 19:13:34 UTC 2019
After:
vagrant#homestead:~$ date
Mon Feb 25 15:47:01 UTC 2019

Direct browser upload to Amazon S3

I'm trying to figure out how perform a browser direct upload to Amazon S3 using an XHR. I'm using some pre-made code that creates a signature and performs the upload. All I have to do is enter my S3 security credentials. (For what it's worth, I want to do the policy signing using PHP).
I've forked the code to my GitHub account, you can find it here: https://github.com/keonr/direct-browser-s3-upload-example
As the readme file indicates, I have set my S3 bucket CORS to allow all origins, as such:
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>x-amz-acl</AllowedHeader>
<AllowedHeader>origin</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Now, when I try to perform the file upload, the script returns with XHR Error and my browser's error console gives me a standard CORS error, saying that my Origin is now allowed for that XHR request. I've tried everything I can think of. I've chaned the * wildcard to the actual domain the request originates from to allowing the * wildcard to allowed headers. Nothing seems to work. It continues to produce that CORS error.
Can anyone help me get this off the ground and successfully complete a direct browser upload to S3? I don't care by which means, I just need to be able to get it done. Also, bear in mind that I am a novice when it comes to S3, so the more explicit the instructions, the better.
Thanks!
Try adding a wildcard for the AllowedHeader and allow all methods, like so:
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Great starting points for a direct upload to Amazon S3 are:
For the js:
http://www.designedbyaturtle.co.uk/2013/direct-upload-to-s3-with-a-little-help-from-jquery/
For the php:
http://birkoff.net/blog/post-files-directly-to-s3-with-php/
Or if you're looking for a solution that works out of the box, take a look at Plupload
Hope this gets you started!

Categories