Can't pass my credentials to AWS PHP SDK - php

I installed AWS PHP SDK and am trying to use SES. My problem is that it's (apparently) trying to read ~/.aws/credentials no matter what I do. I currently have this code:
$S3_AK = getenv('S3_AK');
$S3_PK = getenv('S3_PK');
$profile = 'default';
$path = '/home/franco/public/site/default.ini';
$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);
$client = SesClient::factory(array(
'profile' => 'default',
'region' => 'us-east-1',
'version' => "2010-12-01",
'credentials' => [
'key' => $S3_AK,
'secret' => $S3_PK,
]
));
And am still getting "Cannot read credentials from ~/.aws/credentials" error (after quite a while).
I tried 'credentials' => $provider of course, that was the idea, but as it wasn't working I reverted to hardcoded credentials. I've dumped $S3_AK and $S3_PK and they're fine, I'm actually using them correctly for S3, but there I have Zend's wrapper. I've tried ~/.aws/credentials (no ".ini") to the same result. Both files having 777 permissions.
Curious information: I had to set memory limit to -1 so it would be able to var_dump the exception. The html to the exception is around 200mb.
I'd prefer to use the environment variables, all though the credentials file is fine. I just don't understand why it appears to be trying to read the file even though I've hardcoded the credentials.
EDIT: So a friend showed me this, I removed the profile and also modified the try/catch and noticed the client seems to be created properly, and the error comes from trying to actually send an email.

The trick is just remove 'profile' => 'default' from the factory params, if this is defined we can't use a custom credentials file or environment variables. Is not documented but just works.
I'm using Sns and Sdk v3.
<?php
use Aws\Credentials\CredentialProvider;
$profile = 'sns-reminders';
$path = '../private/credentials';
$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);
$sdk = new Aws\Sdk(['credentials' => $provider]);
$sns = $sdk->createSns([
// 'profile' => $profile,
'region' => 'us-east-1',
'version' => 'latest',
]);

This solution will probably only work if you're using version 3 of the SDK. I use something similar to this:
$provider = CredentialsProvider::memoize(CredentialsProvider::ini($profile, $path));
$client = new SesClient([
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => $provider]);
I use this for S3Client, DynamoDbClient, and a few other clients, so I am assuming that the SesClient constructor supports the same arguments.

OK, I managed to fix it.
I couldn't read the credentials file but it wasn't exactly my idea.
What was happening was that the actual client was being created successfully, but the try/catch also had the sendEmail included. This was what was failing.
About creating the client with explicit credentials: If you specify region, it will try and read a credentials file.
About the SendEmail, this is the syntax that worked for me, I'd found another one also in the AWS docs site, and that one failed. It must've been for an older SDK.

Related

How to authenticate SpeechClient V1 using keyfile (PHP / Laravel)

I'm trying to authenticate the SpeechClient using 'keyFilePath' and 'projectId' parameters like so:
$speech = new SpeechClient([
'projectId' => 'actualProjectId,
'keyFilePath' => $key_path,
]);
If I use Google\Cloud\Speech\SpeechClient - Everything works fine, but if I use Google\Cloud\Speech\V1\SpeechClient I end up with an error: Could not construct ApplicationDefaultCredentials
I've read Google docs for Setting Up Authentication but still don't understand what am I doing wrong.
I need the V1 (in fact V1p1beta1) for additional features that are not available using the old SpeechClient.
Any ideas?
P.S. Using Laravel as the back-end.
For clients within the V1, etc. namespaces, pass the keyFilePath as credentials.
new SpeechClient([
'credentials' => $key_path
]);

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."

Pass Parameter from controller to Component in Cakephp

I have been given a task to maintain a cakephp app. There is an issue with uploading files to server. All these time we were using AWS S3 Bucket now we want upload it to our own file server. The coding part was done by my ex-colleague.
I am trying a simple stuff I want to send fileName from my controller to Component files called S3.
Coding which is done is like this:
$this->S3->uploadFile($this->request->data('upload.tmp_name'),$fileKey);
In S3Component file:
I have written the following:
public function uploadFile($filePath, $fileKey, $metaData = [])
{
$fileUtility = new FileUtility(1024 * 1024, array("ppt", "pdf"));
return $fileUtility->uploadFile($_FILES[$fileKey], $filePath);
}
Now how do I pass the values in S3->uploadFile correctly to reflect the uploadfile function S3Compontent file.
Thanks!
If you can be bothered refactoring, you could try Flysystem, a file management package installable through composer. https://flysystem.thephpleague.com/
The nice thing about it is, you just swap an S3 adapter for a local adapter, ftp adapter, etc (there are a few!), and none of your code needs to change!
For instance:
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;
$client = S3Client::factory([
'credentials' => [
'key' => 'your-key',
'secret' => 'your-secret',
],
'region' => 'your-region',
'version' => 'latest|version',
]);
$adapter = new AwsS3Adapter($client, 'your-bucket-name', 'optional/path/prefix');
And to create a Local Adapter:
use League\Flysystem\Filesystem;
use League\Flysystem\Adapter\Local;
$adapter = new Local(__DIR__.'/path/to/root');
$filesystem = new Filesystem($adapter);
Then, you can make identical calls to $filesystem like these:
$filesystem->write('path/to/file.txt', 'contents');
$contents = $filesystem->read('path/to/file.txt');
$filesystem->delete('path/to/file.txt');
$filesystem->copy('filename.txt', 'duplicate.txt');
Check out the API here: https://flysystem.thephpleague.com/api/

PHP EC2 Wait until volume is available

This is a code snippet I am using to manipulate my EC2 instance.
$ec2 = Aws::factory(array(
'key' => $key,
'secret' => $secret,
'region' => $region)
)->get('ec2', true);
$volId = createVol();// This step creates the volume correctly
$ec2->waitUntil('__VolumeStatus', array(
'VolumeIds' => array($volId),
'waiter.success.value' => VolumeState::AVAILABLE
));
attachVolume();//Error
The problem is attachVolume function is throwing error that volume is not available that means waitUntil function is not working correctly. Is there somethings wrong with the way I called this function?
It seems that the EC2 API is eventually consistent. So waiters are working correctly but sometimes the API is returning the wrong statuses
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/query-api-troubleshooting.html
http://blog.cloudfoundry.com/2013/06/18/dealing-with-eventual-consistency-in-the-aws-ec2-api/

Using AWS SES API

I want to access the AWS SES Webservice to programmatically add new verified Email identities. The API reference does not give the relevant information or at least I can't find it there.
When I try to access the api I get an error due to the missing signature.
https://email.us-east-1.amazonaws.com?AWSAccessKeyId=EXAMPLEKeyId&Action=VerifyEmailIdentity&EmailAddress=someone#somewhere.org&Timestamp=2013-04-27T19:30:00Z&Version=2010-12-01&Signature=
How do I create this signature exactly, for example using php's hash_hmac()?
Do I need to hash the entire parameters using the SES secret key?
Is there a newer version of the SES API than the one documented (2010-12-01)?
You should really go through the documentation (again).
Take a look at the AWS PHP SDK which would help you a lot.
A sample implementation would be something like:
<?php
require 'aws.phar';
use Aws\Common\Enum\Region;
use Aws\Ses\SesClient;
try {
$ses = SesClient::factory(array(
'key' => 'YOUR_KEY',
'secret' => 'YOUR_SECRET',
'region' => Region::US_EAST_1
));
$ses->verifyEmailIdentity( array(
'EmailAddress' => 'the_mail_adress_to_verify#example.com'
));
}
catch( Exception $e )
{
echo $e->getMessage();
}

Categories