Access aws services without key & secret in php - php

To be clear, We have created the EC2 policy, so my site can directly access the services like Parameter store, S3, Amazon SES etc.
As of now, all of my credentials are stored on AWS Parameter Store and then site is using those credentials i.e. DB credentials, diff. API keys etc. So only hard coded credentials are the one which fetch the parameters from Parameter Store. Now client want to remove those hard coded credentials as well, that's why we have created the EC2 Policy.
Till now, we have code like below to fetch the parameters:
$config = array(
'version' => 'latest',
'region' => '*****',
'credentials' => array(
'key' => '*******',
'secret' => '******',
)
);
$s3_instance = new \Aws\Ssm\SsmClient($config);
$result = $s3_instance->getParameters([
'Names' => $credential_group,
'WithDecryption' => true
]);
//converting S3 private data to array to read
$keys = $result->toArray();
var_dump($keys);
Now the question is what i have to change in above code, so it should work without passing those credentials.
Note: I am using AWS PHP library to perform above.
Update
Further reading the documentation, https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html
Using Credentials from Environment Variables
If you don't provide credentials to a client object at the time of its instantiation, the SDK attempts to find credentials in your environment. The first place the SDK checks for credentials is in your environment variables. The SDK uses the getenv() function function to look for the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables. These credentials are referred to as environment credentials.
So after that, i have tried the below:
var_dump(getenv('AWS_ACCESS_KEY_ID'));
But it returns the bool(false). So does i need to manually setup those in environment credentials?
Which things i need to change in above code?
Update
Based on this doc: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_configuration.html#credentials
I had made below change (Removed the credentials part from array):
$config = array(
'version' => 'latest',
'region' => '*****'
);
Then system throws the below warnings:
Warning: include(Test_Role_Cognitoaccess_from_instanceRole.php): failed to open stream
Warning: include(): Failed opening 'Test_Role_Cognitoaccess_from_instanceRole.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php')
Warning: include(Test_Role_Cognitoaccess_from_instanceRole.php): failed to open stream
Warning: include(): Failed opening 'Test_Role_Cognitoaccess_from_instanceRole.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php')

As you already mentioned that you attached the policy to EC2 IAM role to access other AWS services.
You should try to create a default credential provider, this will automatically pick keys from the role.
$provider = CredentialProvider::chain(CredentialProvider::env(), CredentialProvider::ini(), CredentialProvider::instanceProfile(), CredentialProvider::ecsCredentials());

When you pass credentials directly to SsmClient and same time you have defined a role to the EC2 machine then you are making confusion for the AWS. If you have defined the permission for the EC2 instance then just do as follow:
use Aws\Ssm\SsmClient;
$client = new SsmClient(['version' => 'latest', 'region' => 'ap-southeast-2']);
$result = $client->getParameters(['Names' => ['My-SECRATE-KEY'], 'WithDecryption' => true]);
print_r($result);
Please keep in mind that permissions take a little time to propagate and in this period you will get permission error for the specific user. If you wait and let the changes take effect then mentioned code will work without any error. In my case I attached AmazonSSMReadOnlyAccess to the EC2 role and to EC2 instance. If you key/value in Parameter store is not encrypted then you can remove 'WithDecryption' => true or change it to false.

Related

Get AWS IAM credentials from PHP SDK

I use AWS Services regularly and have my PHP SDK automatically retrieve credentials from my ec2 instance when I connect with Amazon.
I now have a library that I want to use which also requires my AWS secret key and access key to be included when I instantiate the class.
How can I retrieve the current access token and secret key through the AWS PHP SDK so I don't hard code keys into my application?
Where are you storing your AWS Credentials? In a credentials file or IAM Role?
[EDIT after the OP provided specific use case details]
From the link that you provided modify the example to look like this. Note: I have not tested the code, but this will be close:
// Require Composer's autoloader
require_once __DIR__ . "/vendor/autoload.php";
use Aws\Credentials\Credentials
use Aws\Credentials\CredentialProvider;
use Aws\Exception\CredentialsException;
use EddTurtle\DirectUpload\Signature;
// Use the default credential provider
$provider = CredentialProvider::defaultProvider();
$credentials = $provider()->wait();
$upload = new Signature(
$credentials->getAccessKeyId(),
$credentials->getSecretKey(),
"YOUR_S3_BUCKET",
"eu-west-1"
);
[END EDIT]
The simplest answer if you are using a credentials file is to open ~/.aws/credentials in a text editor and extract them. Otherwise follow the details below.
See the bottom for the actual answer on how to extract your access key once you have them loaded.
The following example will create a DynamoDB client using credentials stored in ~/.aws/credentials (normally created by the AWS CLI) from the profile named 'project1':
$client = new DynamoDbClient([
'profile' => 'project1',
'region' => 'us-west-2',
'version' => 'latest'
]);
However, usually you will want the SDK to locate your credentials automatically. The AWS SDK will search for your credentials in the following order (not all cases included):
Environment Variables (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, etc.)
In the default profile section of ~/.aws/credentials
EC2 IAM Role
Normally just use this example and let the SDK find the credentials for you:
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
// Use the default credential provider
$provider = CredentialProvider::defaultProvider();
// Pass the provider to the client
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $provider
]);
The SDK has a number of credential providers so that you can control exactly where your credentials are coming from.
PHP Class CredentialProvider
One item is that you mention Access Token. This means that you are using STS Assume Role type of access. The PHP SDK supports this also. Just dig into the documentation for STS:
PHP STS Client
Once you have loaded your credentials into a provider you can use the class Credentials to extract the three components (AccessKeyId, AcessKeySecret, SecurityToken):
PHP Class Credentials

PHP SDK Cannot get AWS Credentials on EC2 Instance with IAM Role attached

Simple question. But cannot get it to work.
I created an IAM Role for EC2 with full access to CloudWatch.
I launched a new EC2 instance with this IAM Role attached.
I wrote a simple PHP application on this EC2 instance which tries to publish metrics to CloudWatch.
I am getting this error in nginx logs:
2017/08/23 11:44:06 [error] 32142#32142: *5 FastCGI sent in stderr:
"PHP message: PHP Fatal error:
Uncaught Aws\Exception\CredentialsException:
Cannot read credentials from /var/www/.aws/credentials
in /var/www/app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php:394
From that same EC2 instance, the command:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-attached-to-ec2-instance>
returns 200 OK with the Access Key and Secret in the response.
This is my PHP code that tries to write CloudWatch metrics:
<?php
require 'vendor/autoload.php';
use Aws\CloudWatch\CloudWatchClient;
use Aws\Exception\AwsException;
$count = $_GET["count"];
publishMetric($count);
function publishMetric($count) {
$client = new CloudWatchClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => '2010-08-01'
]);
try {
$result = $client->putMetricData(array(
'Namespace' => 'com.mynamespace',
'MetricData' => array(
array(
'MetricName' => 'Count',
//Timestamp : mixed type: string (date format)|int (unix timestamp)|\DateTime
'Timestamp' => time(),
'Value' => $count,
'Unit' => 'Number'
)
)
));
var_dump($result);
echo 'Done publishing metrics';
} catch (AwsException $e) {
// output error message if fails
error_log($e->getMessage());
echo 'Failure to publish metrics';
}
}
?>
Any idea what is missing in this setup?
I know this is late. I had the same issue and resolved it by removing profile => default line while initializing the client. If you do not provide credentials and profile, SDK will try to retrieve instance profile creds from metadata server.
Authentication of EC2 instance while accessing other AWS Services can be done in multiple ways:
Assigning a role to EC2 instance. Used when u have to give some "EC2 instance" a permission.
Do not assign a role; but use access-key which has all required permissions. Used when you give permission to a "User"
Both these are independent authentication mechanism. If you have already assigned role to your server; you do not have to write any code in your application (CredentialProvider.php) to authenticate.
Your current code can also be worked by creating a file /var/www/.aws/credentials which will look something like this:
accessKey=AKIAIB6FA52IMGLREIIB
secretKey=NQjJWKT+WZOUOrQ2Pr/WcRey3PnQFaGMJ8nRoaVU

How to control access to EC2 and RDS

I have an Android app in which I've implemented AWS Cognito. I'm hoping to use this as a means for controlling access to PHP scripts on my web root which connect to an RDS instance with a MySQL db. So far, I've set the registration process in my app to use a developer authenticated id to register the user in a cognito identity pool. Now, what I would like to do is have a method for checking whether the user trying to access the various scripts I've exposed in my web root is indeed a verified user. What I was thinking of doing is implementing a script like this:
use Aws\CognitoIdentity\CognitoIdentityClient;
$identityId = $_POST['identityId'];//sending cached identity id from client
$client = CognitoIdentityClient::factory ( array (
'profile' => 'profile',
'region' => 'region'
) );
$result = $client->lookupDeveloperIdentity(array(
'IdentityPoolId' => 'IdentityPoolId',
'IdentityId' => $identityId,
'MaxResults' => 1,
));
if ($result != null) {
//connect to db and do whatever operation/query needs to be done
}
However, checking this every time I need to make some kind of transaction on my db seems to be pretty inefficient and slow.
a) Am I using Cognito in the intended fashion?
b) If not, what is a better way of going about this?
Please let me know if I'm way off base here. Thanks!

create new user IAM with aws php sdk and limit access of one bucket

i am using aws php sdk for creating bucket in S3
i want to create new user IAM using aws php sdk.. .and then i want to save userkey and acceskey. ..
I got the tutorial for limit the access to user,but not get any for creating new user.
is there any way to create new user?
Install AWS SDK - http://docs.aws.amazon.com/aws-sdk-php/guide/latest/installation.html
Create an Iam client however you like by supplying your AWS credentials. The easiest example to demonstrate is putting the credentials in the PHP file directly - See http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html
Then this example will create a user
<?php
require 'vendor/autoload.php';
$iamClient = \Aws\Iam\IamClient::factory(
[
'credentials' => [
'key' => 'YOUR_ACCESS_KEY',
'secret' => 'YOUR_SECRET_KEY'
]
]
);
$result = $iamClient->createUser(
[
// UserName is required
'UserName' => 'carlton',
// Optional
'Path' => '/packager/dev/'
]
);
4.Check http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.Iam.IamClient.html for all of the methods available on the $iamClient variable we created. A good IDE will provide code completion on $iamClient so you can see available methods that way.

Amazon AWS PHP SDK - Cluster fails to launch -The given SSH key name was invalid

I am trying to create a PHP page to launch cluster and add jobs to the jobflow.
$response = $emr->run_job_flow($nameOfRun, array(
'Ec2KeyName' => 'hadoop',
'HadoopVersion' => '0.20',
'KeepJobFlowAliveWhenNoSteps' => $clusterAlive,
'InstanceGroups' => array(
array( // Group #1
'InstanceCount' => $numOfMaster,
'InstanceRole' => 'MASTER',
'InstanceType' => $masterInstanceType,
'Market' => 'ON_DEMAND',
'Name' => 'Master',
),
array( // Group #2
'InstanceCount' => $numOfSlaves,
'InstanceRole' => 'CORE',
'InstanceType' => $slaveInstanceType,
'Market' => 'ON_DEMAND',
'Name' => 'Slaves',
)
),
'Placement' => array(
'AvailabilityZone' => 'us-east-1d'
)
));
The cluster is launched and I can see the job flow ID. But it starts to shut down immediately after launch. When I do a elastic-mapreduce --list, for that cluster the state is Failed.
Any known issues or anywhere I am doing wrong? Is AvailabilityZone may be causing the issue?
I checked from the AWS Console, it is giving this error - The given SSH key name was invalid
I checked, the access key and secret key I provided in config.inc.php are correct and working.
Regards,
Kartikeya Sinha
Looks like there are four different gotchas that might cause the error, as outlined in this AWS thread:
Specifying the exact keypair name from the console.
Specifying a keypair that exists in a different region than your the region of your endpoint.
Using a keypair for a different AWS service, instead of one for EC2.
Using a renamed keypair pem file, when it should match the keypair in the console (really a special case of 1).
If all that looks right, try deleting the keypair and making a new one.
Based on a reading of the PHP SDK docs, I think the problem is that you're specifying EC2KeyName at all (your comments suggest you don't want to tie a particular pem file to the EC2 instances; you rather just want access with a secret key and access key).
Ec2KeyName - string - Optional - Specifies the name of the Amazon EC2 key pair that can be used to ssh to the master node as the user called “hadoop.” [Constraints: The value must be between 0 and 256 characters, and must match the following regular expression pattern:
[\u0020-\uD7FF\uE000-\uFFFD\uD800\uDC00-\uDBFF\uDFFF\r\n\t]*]
This parameter refers to the pem keypair files you can associate with EC2 instances. Your comments suggest you're speaking specifically about AccessKeys and SecretAccessKeys, which are different concepts. The pem files give you ssh access to EC2 instances. The latter authorize you against the AWS API.
You should be able to kill that optional parameter and have the job work, although you won't be able to ssh into its affiliated EC2 instances without a pem file.
Where I was wrong: (This solved my case)
The name of the keypair of which access key and secret key are specified in the config.ini.php file of AWS SDK and the EC2KeyName to be supplied while launching a cluster should be the same.

Categories