Amazon S3 basic action doesn't work - php

I'm trying to use Amazon S3 to store my images.
What I've done so far is installing the AWS SDK via PEAR (link: http://docs.aws.amazon.com/aws-sdk-php-2/guide/latest/installation.html)
Then I've gone to the second step, creating a client:
<?php
// Include the SDK using the Composer autoloader
require 'vendor/autoload.php';
use Aws\S3\S3Client;
// Instantiate the S3 client with your AWS credentials and desired AWS region
$client = S3Client::factory(array(
'key' => 'your-aws-access-key-id',
'secret' => 'your-aws-secret-access-key',
));
My keys are set correctly ... .
Then I want to test all this by creating a bucket like this:
$bucket = 'my-bucket';
try{
$result = $client->createBucket(array(
'Bucket' => $bucket
));
// Wait until the bucket is created
$client->waitUntil('BucketExists', array('Bucket' => $bucket));
}
catch(Exception $e){
var_dump($e->getMessage());
}
But I always get this error:
The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.
I think my SDK isn't properly installed ... Can anyone help me with this? I'm using vagrant so I installed the AWS SDK in my root folder with this command:
sudo pear -D auto_discover=1 install pear.amazonwebservices.com/sdk
I got the message that is was installed ok.
I've also did a var_dump of my $client. The link to my response: http://pastebin.com/KqkEiKGs
Don't now if you're something with it ... (My keys are hidden)

Your error message says it - you are trying to use the name that is not unique for your bucket, you should use some more unique names. And, yes, bucket names must be unique across all of Amazon S3 (not only your account).
You can read more about it here.

Related

AWS dynamodb query from php

I have a react application and i'm trying to use aws dynamodb, i installed the php sdk but i don't know how to query my db.
I copied the tutorial here and i changed the endpoint to: "https://dynamodb.us-west-2.amazonaws.com".
I get this error: {"__type":"com.amazon.coral.service#UnrecognizedClientException","message":"The security token included in the request is invalid."}. I guess i have to add a security token somewhere, i don't know where and neither where to find it.
Any suggestion?
Based on your error, i think you need to check your aws secret key and access key. You can try to install aws cli then create user access programmatically from aws console from this link
Then you can try your source code after that.
The following code example shows how to get an item from a DynamoDB table.
// '/path/to/aws-autoloader.php' to import AWS SDKs.
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
use Aws\Exception\AwsException;
use Aws\DynamoDb\Exception\DynamoDbException;
// Create an SDK class used to share configuration across clients.
$sdk = new Aws\Sdk([
'region' => 'us-west-2',
'version' => 'latest'
]);
// Use an Aws\Sdk class to create the dynamoDbClient object.
$dynamoDbClient = $sdk->createDynamoDb();
try {
$dynamoDbClient->getItem([
'Key' => [
'id' => [
'N' => 1,
],
],
'TableName' => 'products',
]);
} catch (DynamoDbException $e) {
// Catch a DynamoDb-specific exception.
echo $e->getMessage();
} catch (AwsException $e) {
// This catches the more generic AwsException. You can grab information
// from the exception using methods of the exception object.
echo $e->getAwsRequestId() . "\n";
echo $e->getAwsErrorType() . "\n";
echo $e->getAwsErrorCode() . "\n";
// This dumps any modeled response data, if supported by the service
// Specific members can be accessed directly (e.g. $e['MemberName'])
var_dump($e->toArray());
}
Notice that we did not explicitly provide credentials to the client. That’s because the SDK should detect the credentials from environment variables (via AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY), an AWS credentials INI file in your HOME directory, AWS Identity and Access Management (IAM) instance profile credentials, or credential providers.
If we don’t provide a credentials option, the SDK attempts to load credentials from your environment in the following order:
Load credentials from environment variables.
Load credentials from a credentials .ini file.
Load credentials from IAM role.
We can also directly create the service-specific client object like below:
$dynamoDbClient = new DynamoDbClient(
[
'region' => 'us-west-2',
'version' => 'latest',
]
But AWS highly recommended that you use the Sdk class to create clients if you’re using multiple client instances in your application. As per AWS docs:-
The Sdk class automatically uses the same HTTP client for each SDK
client, allowing SDK clients for different services to perform
nonblocking HTTP requests. If the SDK clients don’t use the same
HTTP client, then HTTP requests sent by the SDK client might block
promise orchestration between services.
You can refer to the AWS document pages:-
AWS SDK PHP - BASIC USAGE
AWS SDK PHP - DynamoDB Examples
AWS SDK PHP - Configuration guide
AWS SDK PHP - APIs
I hope this helps.

unable to upload image file to S3 bucket via PHP

I am trying to upload an image to my S3 Bucket via AWS PHP SDK. For my EC2 instance, I have attached a role that allows PutObject and GetObject for my S3 Bucket. Therefore, I do not need to attach credentials when creating the S3Client, supposedly. I'm still learning.
Here is my PHP script:
<?php
require './aws/aws-autoloader.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
use Aws\Credentials\Credentials;
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-east-1'
]);
$filename = $_FILES['file']['name'];
try {
$result = $s3->putObject([
'Bucket' => 'bucket name',
'Key' => 'testimage1',
'Body' => $filename
]);
echo 'DONE';
} catch (Exception $e) {
echo $e;
}
I keep getting a 500 internal error in this form. Apparently the error occurs at S3Client creation, I'm not sure why.
Further probing confirms, that when I try to instantiate the S3Client class, the 500 internal error is thrown. I am able to access the S3 bucket from the CLI but unable to do so using the AWS PHP SDK.
Here is the image of the error:
Can anyone advice in this? Thank you for reading.
According to the docs, the use of the S3Client Class is like this: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_configuration.html
use Aws\S3\S3Client;
$options = [
'region' => 'us-east-1',
'version' => '2006-03-01',
'signature_version' => 'v4'
];
$s3Client = new S3Client($options);
It also says, "We do not recommend Using latest in a production application because pulling in a new minor version of the SDK that includes an API update could break your production application."
I solved it but I used composer. So here's a step by step guide.
This is under the assumption that you have created an IAM role with full S3 access or at least with the PutObject policy attached, and the IAM role is attached to the EC2 instance. Also that your EC2 instance has installed a web server.
In the EC2 instance /var/www/html (folder where your web server hosts your webpage), install composer as guided through here in your project folder. I chose to install composer globally for convenience sake.
Install AWS PHP SDK as seen in this guide.
If you an encounter an error asking for simplexml extension, just yum install php-xml and rerun the installation of AWS PHP SDK.
Now that you have the SDK installed, you can now upload the file you want to the S3 bucket.
Here is my code for uploading, my vendor folder is root level with the php file used for uploading files to the S3 bucket.
require 'vendor/autoload.php';
use Aws\S3\S3Client;
try{
$sharedConfig = [
'region' => 'us-east-1',
'version' => 'latest'
];
$sdk = new Aws\Sdk($sharedConfig); /*Instantiate SDK class with configs for API use*/
$s3Client = $sdk->createS3(); /*creates the S3 Client for API use*/
$file_name = $_FILES['file']['name']; /*file name e.g. name.jpg */
$file_tmp_name = $_FILES['file']['tmp_name']; /*!!! IMPORTANT - this is what you need to supply the SourceFile to properly upload the file*/
$file_type = $_FILES['file']['type']; /*file type*/
/*print_r($_FILES['file']);*/
$result = $s3Client->putObject([
'Bucket' => 'bucket-name',
'Key' => 'testimage.jpg',
'SourceFile' => $file_tmp_name,
'ContentType'=>$file_type,
'ContentDisposition'=>'attachment'
]);
echo "FILE SENT";
}catch(Exception $e){
echo $e;
}

How do I get the AWS PHP SDK to find the credentials I stored in Elastic Beanstalk environment variables?

I am running a web application on AWS Elastic Beanstalk, using PHP.
The application uses an RDS MySQL database. I would like to store the db credentials via AWS Secrets Manager.
I successfully created the secret.
Via composer, I installed the AWS PHP SDK, version 3.129. I ran the compatibility.test php file to verify my development environment. Everything was green (except for a warning not to use Xdebug for performance reasons).
Using the AWS documentation, I wrote a PHP class to get the secret values. I wrote a unit test for that class. The unit tests pass, and I was able to display the secret values with my username, password, etc. for RDS.
To provide credentials for my local development environment, I used a credentials file stored in an .aws directory. In this file, I stored:
aws_access_key_id
aws_secret_access_key
I ran my application on my local apache webserver, and it was able to successfully retrieve the RDS credentials from the AWS secrets manager, and make MySQL calls to the RDS database.
My final step was to run the application in AWS via my Elastic Beanstalk platform (which has been functioning for months, with hardcoded RDS credentials, which I want to stop using).
I looked at the AWS document which explains "Credentials for the AWS SDK for PHP Version 3". The document describes a "Default Credential Provider Chain".
I tried (unsuccessfully) using the first link in the chain, which is environment variables, following this AWS document entitled "Using Credentials from Environment Variables". The document states:
If you're hosting your application on AWS Elastic Beanstalk, you can set the AWS_ACCESS_KEY_ID and AWS_SECRET_KEY environment variables through the AWS Elastic Beanstalk console so that the SDK can use those credentials automatically.
I did so via the AWS console, using these values for my variables:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
During my testing, I tried both of my access keys, and I know they work because I use them for other purposes, and the IAM console shows recent use for both.
When I run my test, I always encounter the same exception in the AWS PHP SDK code, which reports "Cannot read credentials from /.aws/credentials".
This suggests to me that either:
The PHP SDK code is not looking for my environment variables
It tried to find them but could not
It found them but was not able to use them
When I hit the exception, I get the "Whoops" output, which shows the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables and their values exactly as I entered them.
The PHP SDK code is correct that it cannot find my credentials file because I did not upload one to Elastic Beanstalk. That way of doing it does not make sense to me in Elastic Beanstalk, though it works fine for my local environment.
Here are the last few calls in the backtrace of the exception:
Aws\Exception\CredentialsException
…/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php691
21
Aws\Credentials\CredentialProvider reject
…/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php424
20
Aws\Credentials\CredentialProvider Aws\Credentials{closure}
…/vendor/aws/aws-sdk-php/src/Middleware.php121
19
Aws\Middleware Aws{closure}
…/vendor/aws/aws-sdk-php/src/RetryMiddleware.php269
18
Aws\RetryMiddleware __invoke
…/vendor/aws/aws-sdk-php/src/Middleware.php206
17
Aws\Middleware Aws{closure}
…/vendor/aws/aws-sdk-php/src/StreamRequestPayloadMiddleware.php83
Here is the code I hit in the "Credential Provide reject":
if (!is_readable($filename)) {
return self::reject("Cannot read credentials from $filename");
}
Here is the code I wrote to get the secret (with some extraneous debugging statements which I will remove later):
public function getSecretString(): ?string
{
echo 'In getSecretString' . "\r\n";
$result = null;
$client = new SecretsManagerClient([
'profile' => 'default',
'version' => '2017-10-17',
'region' => 'us-east-2'
]);
echo 'Lets try' . "\r\n";
try {
$result = $client->getSecretValue([
'SecretId' => $this->secretName,
]);
echo 'Got a result' . "\r\n";
} catch (AwsException $e) {
echo 'FAILED!' . "\r\n";
// output error message if fails
echo $e->getMessage();
echo "\n";
}
if ($result !== null) {
echo 'We got our secret string!' . "\r\n" .
$this->secretString = $result['SecretString'];
} else {
echo 'We DID NOT get our secret string!' . "\r\n" .
$this->secretString = null;
}
print_r($this->secretString);
echo "\r\n";
return $this->secretString;
}
From my debugging it appears that the SDK simply ignores any credential provide method other than the credentials file. I have tried:
Setting local environment variables on my local machine when running the local webserver.
Setting my SDK client array to only look at the env() method.
Hardcoding my credentials.
None of these methods of setting my creds worked.
I also tried using older versions of the SDK to see if a bug was recently introduced, going as far back as 3.76.0. No difference.
Here is the revised code showing the commented out attempt #2 above, and attempt #3 above:
public function getSecretString(): ?string
{
echo 'In getSecretString' . "\r\n";
$result = null;
// Only load credentials from environment variables
//$provider = CredentialProvider::env();
$client = new SecretsManagerClient([
'profile' => 'default',
'version' => '2017-10-17',
'region' => 'us-east-2',
//'credentials' => $provider,
'credentials' => [
'key' => 'AKIAVGZKSJ5G76TTG2P4',
'secret' => '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',
],
// 'debug' => true
]);
try {
$result = $client->getSecretValue([
'SecretId' => $this->secretName,
]);
echo 'Got a result' . "\r\n";
} catch (AwsException $e) {
echo 'FAILED!' . "\r\n";
// output error message if fails
echo $e->getMessage();
echo "\n";
}
if ($result !== null) {
echo 'We got our secret string!' . "\r\n" .
$this->secretString = $result['SecretString'];
} else {
echo 'We DID NOT get our secret string!' . "\r\n" .
$this->secretString = null;
}
return $this->secretString;
}
I also tried a second way of getting the credentials via the Default chain: Assume an IAM role. I tried to follow the documentation here, but admittedly found it confusing. In my Elastic Beanstalk Security configuration, I noticed two IAM roles:
aws-elasticbeanstalk-ec2-role
aws-elasticbeanstalk-service-role
I assigned the following policies to both roles:
SecretsManagerReadWrite
IAMFullAccess (because when I assigned the previous policy, there was a note to assign this one also)
Assigning these IAM policies did not correct the problem.
My first preference is to solve this problem via the Elastic Beanstalk environment variables, since it seems extremely simple, and the AWS documentation clearly states it should work. Alternatively, solving it via IAM policies would be desirable if it does not require a lot of scripting.
How can I solve this problem?
(Posted solution on behalf of the question author, in order to move it from the question).
In my client SecretsManagerClient array, I had included the following line:
'profile' => 'default',
By stepping through the SDK code, I observed the presence of that line is interpreted to mean "look for a credentials file and skip the default chain of credentials".
I removed the line, and then the SDK processed the credentials set in my environment variables.

Google BigQuery API PHP Credential

I want to implement Google BigQuery API so I can execute query from my PHP code in BigQuery.
First I have installed the client library by following command:
composer require google/cloud
Second I have installed the Google Cloud SDK by following command:
curl https://sdk.cloud.google.com | bash
Then I run this command to create the credential:
gcloud beta auth application-default login
All the process is success and after run credential request I get the following message:
Credentials saved to file:
[/home/some/my/dir/application_default_credentials.json]
These credentials will be used by any library that requests
Application Default Credentials.
Then I want to run this code on PHP:
# Includes the autoloader for libraries installed with composer
require __DIR__ . '/vendor/autoload.php';
# Imports the Google Cloud client library
use Google\Cloud\BigQuery\BigQueryClient;
# Your Google Cloud Platform project ID
$projectId = 'PROJECT ID';
# Instantiates a client
$bigquery = new BigQueryClient([
'projectId' => $projectId
]);
# The name for the new dataset
$datasetName = 'my_new_dataset';
# Creates the new dataset
$dataset = $bigquery->createDataset($datasetName);
echo 'Dataset ' . $dataset->id() . ' created.';
But unfortunately I got following message error:
Fatal error: Uncaught exception 'Google\Cloud\Exception\ServiceException' with message 'Could not load the default credentials
So my question is: whats wrong and what must I do?
Thank you
Default credentials are provided by the Google APIs Client Library for PHP, versions 2.0.0 and newer. To use them, call useApplicationDefaultCredentials:
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
Then, use the credentials to access an API service as follows:
$client->setScopes(['https://www.googleapis.com/auth/books']);
$service = new Google_Service_Books($client);
$results = $service->volumes->listVolumes('Henry David Thoreau');
I am suggesting checking out the link I gave it has much more options and we recommend using service accounts.

transfer file from AWS s3 budget to ec2 instance using php

I have been working on a project where we will have a website process on EC2 server. In my project, I was able to write a php code that allow users to upload file from web server to AWS S3 budget. However, in order to access that file from EC2, i think we need to transfer file from S3 budget to EC2 instance. I saw that there is a unix command line way to do that, but the project i'm working on is based on PHP/HTML/JSON. I wonder is there a way or tutorial to access or transfer file from S3 to EC2 instance using PHP?
Thanks
You do not need to transfer the file from S3 to EC2, in fact, this would be a waste of resources. Instead, you can generate a signed url pointing to the file directly on S3 (even if the bucket/file is private). This link can also be set to expire after a certain period. Here's an example using the AWS PHP SDK:
<?php
require 'aws-autoloader.php'; //SDK autoloader file
//*** Initiate an S3 client
$client = S3Client::factory(array(
'key' => "public_key",
'secret' => "private_key",
'region' => "your s3 region"
));
$url = $client->getObjectUrl("bucket_name", "full_object_name", "+1 minutes"[optional]);
echo $url; //Print the direct S3 link to the file, which will expire in 1 minute.
//This will work even if the bucket is private.
[update]
If you still need to download the file from S3 to EC2, do this:
<?php
require 'aws-autoloader.php'; //SDK autoloader file
//*** Initiate an S3 client
$client = S3Client::factory(array(
'key' => "public_key",
'secret' => "private_key",
'region' => "your s3 region"
));
$result = $client->getObject(array(
'Bucket' => "bucket_name",
'Key' => "name of file",
'SaveAs' => "ec2 path to save the file at"
));
echo $result; //make sure download worked.
Further reading:
http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html

Categories