How can I verify amazon keys on correctness programmatically? - php

I'm connecting to Amazon SES via this php-code
$ses = new SesClient([
'credentials' => [
'key' => KEY,
'secret' => SECRET_KEY,
],
'region' => REGION,
'version' => SES_VERSION,
]);
How can I recognize here, whether constants KEY and SECRET_KEY are valid or invalid (such as wrong, inputed with typos and so on) ?
Is there any method in AWS SDK to verify it ?

I use the Python call get_user(). With no arguments, this call will return the user name based on the access key ID. This validates that the credentials are correct. This technique is not bulletproof, but does provide a simple, quick method. You can test this concept with the CLI aws iam get-user.
Python IAM get_user()

Related

Handling SRP Auth and Generating Device Key (PHP - Server side)

I've implemented in my backend Cognito with Signup and Login, MFA activation and inactivation, but now I want to implement the remember devices, to reduce SMS confirmation.
For that, I've adjusted the InitiateAuth Function to the following code:
$client->initiateAuth([
'AuthFlow' => 'USER_SRP_AUTH', // REQUIRED
'AuthParameters' => [
"USERNAME" => $email,
"PASSWORD" => $password,
"SRP_A" => $bigA,
],
'ClientId' => $this->getClientId(), // REQUIRED
]);
This function runs properly, and returns the code in following image:
https://i.gyazo.com/a439e48e2de85a094f56ed4cfee10f83.png
Then, I continue generating SRP Values, and call in the function respondToAuthChallenge, with the following code:
$client->respondToAuthChallenge([
'ChallengeName' => 'DEVICE_SRP_AUTH',
'ChallengeResponses' => [
'USERNAME' => $username,
'SRP_A' => $bigA,
],
'ClientId' => $this->getClientId(),
]);
Yet, It returns me an error saying: 'Missing required parameter DEVICE_KEY'.
If I put a DEVICE_KEY key inside ChallengeResponses it starts returning me the error 'Device does not exist.'
I've searched a lot and cannot find a way to generate the DEVICE_KEY. I've tried with unique ID and sending it in both initiateAuthand respondToAuthChallenge but the error is the same.
Any clue how can I do it? I Believe that SRP code is not 100% yet, as still understanding the concept, yet, cannot understand the DEVICE_KEY part.
Thanks
It looks like you have to use Server Side Authentication Flow
For server-side apps, user pool authentication is similar to that for client-side apps, except:
The server-side app calls the AdminInitiateAuth API (instead of InitiateAuth). This method requires AWS admin credentials. This method returns the authentication parameters.
Once it has the authentication parameters, the app calls the AdminRespondToAuthChallenge API (instead of RespondToAuthChallenge), which also requires AWS admin credentials.
The AdminInitiateAuth returns among other stuff the device key.

Can't pass my credentials to AWS PHP SDK

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.

Amazon S3 SDK PHP doesObjectExist() problems

I've re-written this question to make it clearer, since I've updated it.
I'm having trouble with the Amazon AWS S3 PHP SDK. I'm just trying to check if a file exists.
Using this PHP script:
<?php
require_once("../../../configs/config.".get_current_user().".php");
require INCLUDES_PATH . 'libraries/aws/aws-autoloader.php';
use Aws\S3\S3Client;
$client = S3Client::factory(array(
'key' => AWS_ACCESS_KEY_ID,
'secret' => AWS_SECRET_KEY
));
$key = 'profile/avatar/80745d03-c295-4205-bd82-58161f2fd2d1-320.jpg';
$result = $client->doesObjectExist( AWS_S3_BUCKET, $key );
var_dump(AWS_S3_BUCKET);
var_dump($key);
var_dump($result);
?>
This is the output:
string(19) "stage.socialite.app"
string(59) "profile/avatar/80745d03-c295-4205-bd82-58161f2fd2d1-320.jpg"
bool(false)
I know the file exists, it's here:
http://stage.socialite.app.s3.amazonaws.com/profile/avatar/80745d03-c295-4205-bd82-58161f2fd2d1-320.jpg
This is the IAM policy for the user, whose Key ID and Secret Key I'm using:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::stage.socialite.app/*",
"arn:aws:s3:::stage.socialite.app"
]
}
]
}
I've just created a new Key/Secret pair and added them to my config - what have I done wrong?
If var_dump() says bool(false) or bool(true), then it is correctly returning a boolean value. print_r() does not include detailed type information and returns an empty string for false and null values.
So does the object actually exist? Things to check on:
S3 keys do not have a leading slashes. According to your code and output above, I suspect this is the problem.
Make sure you are providing the actual S3 bucket name and not the CloudFront distribution name.
doesObjectExist() returns false if the user does not have read permissions for that object.
In addition to correct bucket location and read permissions:
If using server-side encryption you need to provide the SSE options with doesObjectExist.
$s3Client->doesObjectExist($bucket, $key, array(
'SSECustomerAlgorithm' => 'AES256',
'SSECustomerKey' => $encryptionKey,
'SSECustomerKeyMD5' => md5($encryptionKey, true)
));
Missing or incorrect SSE options will yield false return from doesObjectExist.
I found the answer on another SO post, in a comment from Carlos Castillo:
AWS PHP SDK Version 2 S3 filename encoding issue
He pointed me in the direction of a Github Issue that suggested setting the region when initializing the S3 client, this is because I'm using an S3 instance in Ireland for my dev server, not the default US servers.
So this is the solution:
$client = S3Client::factory(array(
'key' => AWS_ACCESS_KEY_ID,
'secret' => AWS_SECRET_KEY,
'region' => AWS_S3_REGION
));
Where AWS_S3_REGION is a constant set in my config file, like the Key and Secret.
Credit goes to neilscastle, Carlos and Stack Overflow for it's excellent SEO

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.

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