Location to put credentials file for AWS PHP SDK - amazon-web-services

I created an EC2 Ubuntu instance.
The following is working using the AWS 2.6 SDK for PHP:
$client = DynamoDbClient::factory(array(
'key' => 'xxx',
'secret' => 'xxx',
'region' => 'eu-west-1'
));
I created a credentials file in ~/.aws/credentials.
I put this in /home/ubuntu/.aws/credentials
[default]
aws_access_key_id=xxx
aws_secret_access_key=xxx
Trying the following does not work and gives an InstanceProfileCredentialsException :
$client = DynamoDbClient::factory(array(
'profile' => 'default',
'region' => 'eu-west-1'
));
There is a user www-data and a user ubuntu.
In what folder should I put the credentials file?

One solution to set the credentials is:
sudo nano /etc/apache2/envvars
add environment variables:
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"
sudo service apache2 restart
After that the following works:
$client = DynamoDbClient::factory(array(
'region' => 'eu-west-1'
));

If you are calling the API from an EC2 instance, you should use IAM roles.
Using IAM roles is the preferred technique for providing credentials
to applications running on Amazon EC2. IAM roles remove the need to
worry about credential management from your application. They allow an
instance to "assume" a role by retrieving temporary credentials from
the EC2 instance's metadata server. These temporary credentials, often
referred to as instance profile credentials, allow access to the
actions and resources that the role's policy allows.

This is way too late, but the solution I found for shared servers where you can't actually use environment vars is to define a custom ini file location, like this:
require (__DIR__.'/AWSSDK/aws-autoloader.php');
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
$profile = 'default';
$path = '/path/to/credentials';
$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);
$client = new \Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials' => $provider
]);
Note that you could even define different profiles with this method.
Documentation HERE

I have a non-EC2 server that accesses SQS and needs credentials. I can't use envvars because there are various people with differing rights who run on this server and envvars is global. For the same reason I don't think I can use an AWS credential file stored under a user's home (although I also couldn't figure out how to make that work for user www-data.)
What I have done is set up a small file AWS_Creds.php
<?php
define ("AWS_KEY", "MY KEY HERE");
define ("AWS_SECRET", "MY SECRET");
?>
The file is stored outside of the webroot and included with include ('ABSOLUTEPATH/AWS_Creds.php') and I include the hard wired reference to the client factory.
Elegant? No. Done? Yes.
EDIT
I forgot to mention: I gitignore AWS_Creds.php so that it doesn't go into our repo.

basicly you can use like this :
$client = DynamoDbClient::factory(array(
'key' => 'aws_key',
'secret' => 'aws_secret',
'region' => 'us-east-1'
));
but in documentation :
Starting with the AWS SDK for PHP version 2.6.2, you can use an AWS credentials file to specify your credentials. This is a special, INI-formatted file stored under your HOME directory, and is a good way to manage credentials for your development environment. The file should be placed at ~/.aws/credentials, where ~ represents your HOME directory.
and usage :
$dynamoDbClient = DynamoDbClient::factory(array(
'profile' => 'project1',
'region' => 'us-west-2',
));
more info : http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html

After watch the source code Credential.php in aws/aws-sdk-php/src,
php can not directly access /root folder in default. You can write $_SERVER['HOME']=[your new home path] in your php, and put the credential file in newHomePath/.aws/credentials.

require('vendor/autoload.php');
use Aws\Ec2\Ec2Client;
$credentials = new Aws\Credentials\Credentials('Your Access Key',
'Your Secret Key'); // Place here both key
$ec2Client = new Aws\Ec2\Ec2Client([
'version' => 'latest',
'region' => 'ap-south-1',
'credentials' => $credentials
]);
$result = $ec2Client->describeKeyPairs();
echo '<pre>';
print_r($result);
Reference site : https://docs.aws.amazon.com/aws-sdk-php/v2/guide/credentials.html#passing-credentials-into-a-client-factory-method

Related

Aws sdk for .NET custom region endpoint configuration

I am trying to configure aws sdk for .net for using cloud service provider which provides aws compatible api. The code below for uploading using aws sdk for php works, but how to configure it properly for aws sdk .net, especially regions part:
This code works in php:
$bucketName = 'big_bucket';
$filePath = './img33.png';
$keyName = basename($filePath);
$IAM_KEY = 'top_secret_key';
$IAM_SECRET = 'top_secret_secret';
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
// Set Amazon S3 Credentials
$s3 = S3Client::factory(
array(
'endpoint' => 'https://s3-kna1.citycloud.com:8080',
'credentials' => array(
'key' => $IAM_KEY,
'secret' => $IAM_SECRET
),
'version' => 'latest',
'region' => 's3-kna1',
'use_path_style_endpoint' => true
)
);
$s3->putObject(
array(
'Bucket'=>$bucketName,
'Key' => $keyName,
'SourceFile' => $keyName,
'StorageClass' => 'REDUCED_REDUNDANCY',
'ACL' => 'public-read'
)
);
The code below for .net does not work yet:
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
public class CityCloudFileHandler
{
private string _accessKey;
private string _secretKey;
private string _mediaBucket;
private string _serviceUrl;
private S3CannedACL _s3CannedAcl;
private AmazonS3Config _s3Config;
public CityCloudFileHandler(string accessKey, string secretKey, string mediaBucket, string serviceUrl,
S3CannedACL s3CannedAcl = null)
{
_accessKey = accessKey;
_secretKey = secretKey;
_mediaBucket = mediaBucket;
_serviceUrl = serviceUrl;
_s3CannedAcl = s3CannedAcl;
_s3Config = new AmazonS3Config
{
ServiceURL = "https://s3-kna1.citycloud.com:8080",
ForcePathStyle = true
};
}
private IAmazonS3 MediaS3()
{
return new AmazonS3Client(_accessKey, _secretKey, _s3Config);
}
}
A lot of the constructors for the AmazonS3Client accept a RegionEndpoint example. The value looks like this:
RegionEndpoint.USWest2 or RegionEndpoint.USEast1
Here is a link to the AmazonS3Client API documentation: AmazonS3Client
In addition, if you have setup a default user using the AWS CLI by creating two files (stored in: C:\Users\USER_NAME.aws\ on Windows)
The file credentials should contain the following information:
[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key
and a second file named config will contain (at least) the following lines:
[default]
region = us-east-2
Once that user has been setup, you can call the client constructor without parameters as long as the bucket is in the same region as the default user.
There is an example for uploading objects to an S3 bucket here: UploadObjectExample

How to get the AWS S3 bucket location via PHP api call?

I am searching on the internet on how can I get the AWS s3 bucket region with an API call or directly in PHP using their library but have not luck finding the info.
I have the following info available:
Account credentials, bucket name, access key + secret. That is for multiple buckets, that I have access to, and I need to get the region programatically, so logging in to aws console and checking out is not an option.
Assuming you have an instance of the AWS PHP Client in $client, you should be able to find the location with $client->getBucketLocation().
Here is some example code:
<?php
$result = $client->getBucketLocation([
'Bucket' => 'yourBucket',
]);
The result will look like this
[
'LocationConstraint' => 'the-region-of-your-bucket',
]
When you create a S3 client, you can use any of the available regions in AWS, even if it's not one that you use.
$s3Client = new Aws\S3\S3MultiRegionClient([
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => [
'key' => $accessKey,
'secret' => $secretKey,
],
]);
$region = $s3Client->determineBucketRegion($bucketname);

AWS S3 put object (video) with pre-signed URL, Not working?

I am uploading a video on S3 bucket via PHP S3 API with pre-signed URL.
The mp4 video is uploaded successfully to S3, but it's not streaming
and not giving any kind of error.
Here are the details.
My PHP file to create pre-singed url for S3 putObject method.
require 'aws/aws-autoloader.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'ap-south-1',
'credentials' => [
'key' => 'XXXXXXX',
'secret' => 'XXXXXXX'
]
]);
/*echo '<pre>';
print_r($_FILES);die;*/
if(!$_FILES['file']['tmp_name'] || $_FILES['file']['tmp_name']==''){
echo json_encode(array('status'=>'false','message'=>'file path is required!'));die;
}else{
$SourceFile =$_FILES['file']['tmp_name'];
$key=$_FILES['file']['name'];
$size=$_FILES['file']['size'];
}
try {
$cmd = $s3Client->getCommand('putObject', [
'Bucket' => 's3-signed-test',
'Key' => $key,
'SourceFile' => $SourceFile,
'debug' => false,
'ACL' => 'public-read-write',
'ContentType' => 'video/mp4',
'CacheControl'=>'no-cache',
'ContentLength'=>$size
]);
$request = $s3Client->createPresignedRequest($cmd, '+120 minutes');
// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";die;
}
echo json_encode(array('status'=>'true','signedUrl'=>$presignedUrl));die;
This code is working fine and uploading video mp4 on s3 bucket.
But after upload when I am going to access that video, it's not working
I have tried also with getObject pre-singed url but it's not working.
Here are the S3 object URLs-
(1) getObject pre-singed URL
https://s3-signed-test.s3.ap-south-1.amazonaws.com/file.mp4?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIVUO7AT4W4MCPDIA%2F20180402%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20180402T112848Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Signature=d6b877f9bba5dd2221381f10017c8659fe42342d81f7af940d8693478679a8fc
(2) S3 Direct object URL-
https://s3.ap-south-1.amazonaws.com/s3-signed-test/file.mp4
My Problem is I am unable to access video which I have uploaded with pre-singed URL on the s3 bucket, bucket permission is public, and accessible for all origins.
Please let me know, someone who have solution for this.

Send an Email Using the AWS SDK for PHP

I am trying to set up email using AWS SDK for PHP, so far unsuccessfully. I have done the following:
verified my domain and recipient email addresses.
Generated my AWS access key
3.installed pHP version 7.0.25
4.installed nstall the AWS SDK for PHP version 3.
Created a shared credentials file.
The documentation instructs that I need to save this file to the following location: "~/.aws/credentials" (I am using MAC)
My question is i do not have ".aws" folder, so I created one (hidden aws directory) in my home directory and then saved my "credentials" file in there(containing by access key credentials). I am getting the following error:
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` response:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"htt (truncated...)
) in /home/ec2-user/vendor/aws/aws-sdk-
php/src/Credentials/InstanceProfileProvider.php:79
Stack trace:
#0 /home/ec2-user/vendor/guzzlehttp/promises/src/Promise.php(203):
Aws\Credentials\InstanceProfileProvider->Aws\Credentials\{closure}
(Object(GuzzleHttp\Exception\ClientException))
#1 /home/ec2-user/vendor/guzzlehttp/promises/src/Promise.php(156):
GuzzleHttp\Promise\Promise::callHandler(2, Array, Array)
#2 /home/ec2-user/vendor/guzzlehttp/promises/src/TaskQueue.php(47):
GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}()
#3 /home/ec2-
user/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(96):
GuzzleHttp\Promise\TaskQueue- in /home/ec2-user/vendor/aws/aws-sdk-
php/src/Credentials/InstanceProfileProvider.php on line 79
PHP script executed in the terminal (as described by aws: http://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-using-sdk-php.html):
<?php
// Replace path_to_sdk_inclusion with the path to the SDK as described in
// http://docs.aws.amazon.com/aws-sdk-php/v3/guide/getting-started/basic-
usage.html
define('REQUIRED_FILE','path_to_sdk_inclusion');
// Replace sender#example.com with your "From" address.
// This address must be verified with Amazon SES.
define('SENDER', 'sender#example.com');
// Replace recipient#example.com with a "To" address. If your account
// is still in the sandbox, this address must be verified.
define('RECIPIENT', 'recipient#example.com');
// Specify a configuration set. If you do not want to use a configuration
// set, comment the following variable, and the
// 'ConfigurationSetName' => CONFIGSET argument below.
define('CONFIGSET','ConfigSet');
// Replace us-west-2 with the AWS Region you're using for Amazon SES.
define('REGION','us-west-2');
define('SUBJECT','Amazon SES test (AWS SDK for PHP)');
define('HTMLBODY','<h1>AWS Amazon Simple Email Service Test Email</h1>'.
'<p>This email was sent with <a
href="https://aws.amazon.com/ses/">'.
'Amazon SES</a> using the <a href="https://aws.amazon.com/sdk-
for-php/">'.
'AWS SDK for PHP</a>.</p>');
define('TEXTBODY','This email was send with Amazon SES using the AWS SDK for
PHP.');
define('CHARSET','UTF-8');
require REQUIRED_FILE;
use Aws\Ses\SesClient;
use Aws\Ses\Exception\SesException;
$client = SesClient::factory(array(
'version'=> 'latest',
'region' => REGION
));
try {
$result = $client->sendEmail([
'Destination' => [
'ToAddresses' => [
RECIPIENT,
],
],
'Message' => [
'Body' => [
'Html' => [
'Charset' => CHARSET,
'Data' => HTMLBODY,
],
'Text' => [
'Charset' => CHARSET,
'Data' => TEXTBODY,
],
],
'Subject' => [
'Charset' => CHARSET,
'Data' => SUBJECT,
],
],
'Source' => SENDER,
// If you are not using a configuration set, comment or delete the
// following line
'ConfigurationSetName' => CONFIGSET,
]);
$messageId = $result->get('MessageId');
echo("Email sent! Message ID: $messageId"."\n");
} catch (SesException $error) {
echo("The email was not sent. Error message: ".$error-
>getAwsErrorMessage()."\n");
}
?>
First, you do not manually create ~/.aws/credentials. Let the AWS CLI do this for you.
Install the CLI: pip install awscli --upgrade
Delete the credentials file that you created.
Configure the CLI and credentials: aws configure
Your credentials are now setup correctly.
The error message that you received is caused by the PHP SDK trying to get the credentials from the EC2 Instance Metadata. This was failing as you have not configured an IAM Role to this system. This also means that the credentials are not stored correctly in your profile (~/.aws/credentials).
Note: The better method is to NOT store credentials on your EC2 instances. Instead create an IAM Role and assign that role to the EC2 instance. All AWS SDKs know know how to extract the credentials from the instance metadata.
IAM Roles for Amazon EC2

Get s3 metadata without getting object

Is it possible to get just the objects custom metadata from S3 without having to get the whole object? I've looked through the AWS SDK PHP 2 and searched google and SO with no clear answer, or maybe just not the answer I'm hoping for.
Thanks.
Maybe this would help for PHP 2? It uses the Guzzle framework which I'm not familiar with.
Executes a HeadObject command: The HEAD operation retrieves metadata from an object without returning the object itself. This operation is useful if you're only interested in an object's metadata. To use HEAD, you must have READ access to the object.
Final attempt using Guzzle framework (untested code):
use Guzzle\Service\Resource\Model
use Aws\Common\Enum\Region;
use Aws\S3\S3Client;
$client = S3Client::factory(array(
"key" => "YOUR ACCESS KEY ID",
"secret" => "YOUR SECRET ACCESS KEY",
"region" => Region::US_EAST_1,
"scheme" => "http",
));
// HEAD object
$headers = $client->headObject(array(
"Bucket" => "your-bucket",
"Key" => "your-key"
));
print_r($headers->toArray());
PHP 1.6.2 Solution
// Instantiate the class
$s3 = new AmazonS3();
$bucket = 'my-bucket' . strtolower($s3->key);
$response = $s3->get_object_metadata($bucket, 'üpløåd/î\'vé nøw béén üpløådéd.txt');
// Success?
var_dump($response['ContentType']);
var_dump($response['Headers']['content-language']);
var_dump($response['Headers']['x-amz-meta-ice-ice-baby']);
Credit to: http://docs.aws.amazon.com/AWSSDKforPHP/latest/#m=AmazonS3/get_object_metadata
Hope that helps!
AWS HEAD Object http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html
use Aws\S3\S3Client;
use Guzzle\Common\Collection;
$client = S3Client::factory(array(
'key' => 'YOUR-AWS-KEY',
'secret' => 'YOUR-SECRET-KEY'
));
// Use Guzzle's toArray() method.
$result = $client->headObject(['Bucket' => 'YOUR-BUCKET-NAME', 'Key' => 'YOUR-FILE-NAME'])->toArray();
print_r($result['Metadata']);