Failed Amazon SQS request - php

I am setting up SQS using Amazon's SDK 2 for PHP.
There appears to be very little existing content on the web using the new SDK.
This is the newest Amazon Services SDK built on top of Guzzle.
I am able to successfully:
Create queue
Get queue URL
List all queues
Get a queue ARN
But I cannot get any queue attributes or send a message to a queue.
My call to get the queue attributes is:
$attr = $sqs->getQueueAttributes(
array(
'QueueUrl' => 'test_18_16-36-57'
)
);
When attempting to the the queue attributes I get the following response:
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult
the service documentation for details.
The Canonical String for this request should have been 'POST
/100404228159/test_18_16-36-57
content-type:application/x-www-form-urlencoded
host:sqs.us-east-1.amazonaws.com user-agent:aws-sdk-php2/2.1.0
Guzzle/3.1.2 curl/7.22.0 PHP/5.3.10-1ubuntu3.5
x-amz-date:20130218T213657Z
content-type;host;user-agent;x-amz-date
a70e8dd76245fc6631c1b051623a90752c7cec0cd55fa636000c47ad3d8e4e06'
The String-to-Sign should have been 'AWS4-HMAC-SHA256 20130218T213657Z
20130218/us-east-1/sqs/aws4_request
7695e40b612379da5025fca80e26ed6c29f95428e244d2b083764d203d369e36'
Any ideas?

Does upgrading to the latest version fix the issue?

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.

How to verify if AWS SES API requests are signed using Signature Version 4

An email from Amazon AWS states:
Beginning October 1st, 2020, Amazon SES will only support requests
signed using Signature Version 4.
You can easily identify API requests that use Signature Version 3 by
looking at the request headers. Requests that use the Signature
Version 3 resemble the following example: X-Amzn-Authorization:
AWS3-HTTPS
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE,Algorithm=HMACSHA256,Signature=lBP67vCvGl
...
I have got "aws/aws-sdk-php" installed through composer.
I'm trying to find out if the request header of SES is Signature Version 3 or 4.
I tried dumping the content of Illuminate\Mail\Events\MessageSent through $event->message->getHeader() which is a Swift_Mime_SimpleHeaderSet Object.
Yet it doesn't include the request version to the SES sdk.
QUESTION:
Could someone please tell me how to dump the outgoing aws ses sdk request so I can see in the header what version is used.
Thank you.
If anyone is interested, finally was able to do it by back tracing the stack.
After sending a mail through a command, I back traced the stack and could see the raw request, which included Authorization: AWS4-HMAC-SHA25, confirming Signature Version 4.
Mail::to($receiver)->send($mailable);
dump(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
Make sure that you have the ses service debug set to true:
config/services.php
'ses' => [
'key' => env('SES_KEY'),
'secret' => env('SES_SECRET'),
'region' => 'us-west-1',
'debug' => true,
],

Google Server-to-Server OAuth2 PHP example not working

I am following this example to get server-to-server access working between my PHP application and Google Cloud API's,
https://developers.google.com/api-client-library/php/auth/service-accounts. In particular, I need to access the Drive API.
When I run the application though I get the following error:
Google_Service_Exception : {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
Here's what I have done:
Created a GCP project
Added a service account to the project, with domain wide delegation, and a set of keys
Enabled the Google Drive API in the project
In my G Suite account, under 'Manage API client access', I have added the Client ID of my service account, with the permission of https://www.googleapis.com/auth/drive
Have I missed a step?
Here's my code:
putenv('GOOGLE_APPLICATION_CREDENTIALS=my_storage/secure/my-app-service-account.json');
$client = new \Google_Client();
$client->setScopes(\Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->useApplicationDefaultCredentials();
$client->setSubject('my_email#my_domain.com');
$drive = new \Google_Service_Drive($client);
echo $drive->about->get();
The example does not include the setScopes() call, however I was getting a scope-related error without it. (The example is not based on the Drive API, so perhaps it's not required in that case?)
UPDATE: In the IAM settings for the GCP, I added the email address of the service account as a Project Owner, but that made no difference.
I found the problem.
In the setScopes() call above, the value passed needs to be the same as the value given when setting up the client in G Suite, in this case https://www.googleapis.com/auth/drive

AWS Access Key Id needs a subscription for the service

I am getting following error when tried to create topic for amazon sns messaging.
The AWS Access Key Id needs a subscription for the service (Service: AmazonSNS; Status Code: 403; Error Code: OptInRequired; Request ID: 9b0bd34b-6ebd-5ece-a78d-8013adb25940)
It may be possible that your account is new and payment mode is still not verified by Amazon. Please re-check and try to contact with their support.

Google Analytics API oauth exception "invalid_grant" with Service Account. Same code on two servers. Only one works

I'm querying the Analytics API via a Service Account.
I have written the code on the dev server and it works without issues.
When running the same code on the production server, it throws this:
Google_AuthException: Error refreshing the OAuth2 token, message: '{
"error" : "invalid_grant" }'
I've tried creating another Service account, and the behavior is the same.
The oAuth IETF draft (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-31) says this about the error:
invalid_grant
The provided authorization grant (e.g. authorization
code, resource owner credentials) or refresh token is
invalid, expired, revoked, does not match the redirection
URI used in the authorization request, or was issued to
another client.
Here is the code I've written:
$GA_CLIENT_ID = 'XX.apps.googleusercontent.com';
$GA_APP_EMAIL = 'XX#developer.gserviceaccount.com';
$GA_APP_NAME = 'XX';
$GA_KEY_FILE = 'XX';
// create client object and set app name
$client = new Google_Client();
$client->setApplicationName($GA_APP_NAME); // name of your app
// set assertion credentials
$client->setAssertionCredentials(
new Google_AssertionCredentials(
$GA_APP_EMAIL, // email you added to GA
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($GA_KEY_FILE) // keyfile you downloaded
));
// other settings
$client->setClientId($GA_CLIENT_ID); // from API console
$client->setAccessType('offline_access'); // this may be unnecessary?
// create service and get data
$service = new Google_AnalyticsService($client);
$result = $service->data_ga->get($ids, $startDate, $endDate, $metrics, $optParams);
return $result;
I've also tried a solution suggested here (https://groups.google.com/forum/?fromgroups#!topic/gs-discussion/3y_2XVE2q7U%5B1-25%5D) using authenticatedRequest() instead of Google_AnalyticsService:
$req = new Google_HttpRequest($apiUrl);
$resp = $client::getIo()->authenticatedRequest($req);
$result = json_decode($resp->getResponseBody(), true);
This alternative also works on the dev server, but not on the production one.
I am totally clueless on this one. Has anyone seen this/fixed it?
Thanks!
Apparently the problem was the system time being off. Worked by sync-ing via NTP with:
sudo ntpdate npt.ubuntu.com
sudo ntpdate pool.ntp.org
Edit
As #RafaSashi suggested below, the pool.ntp.org server is more reliable. Use that instead of ntp.ubuntu.com (which was the first working one I tried, thus the initial choice).
The invalid grant can also be caused if you use the wrong "ServiceAccountId". It should be the email associated with the client id in the service account client id in the google apis access page. You'd also have to add this user to the google analytics account that you're planning to access.
This tripped me up because I assumed the email address they were referring to was the email address of my google account, since I used the same google account to get api access as I do for google analytics. I know Vir's already figured his out, just thought I'd add this in case someone else comes across the same question and, like me, their computer seems to be in sync with NTP.
In addition to Valer's answer:
First, you’ll need to install NTP if it isn’t already installed. For Debian or Ubuntu, that would be this command:
sudo apt-get install ntp
For Redhat or CentOS, you’ll need to use this one:
yum install ntp
If the synchronization via npt.ubuntu.com doesn't work try :
sudo ntpdate pool.ntp.org
Resources
http://www.howtogeek.com/tips/how-to-sync-your-linux-server-time-with-network-time-servers-ntp/
https://www.digitalocean.com/community/tutorials/how-to-set-up-time-synchronization-on-ubuntu-12-04
There are two major reasons for invalid_grant error which you have to take care prior to the POST request for Refresh Token and Access Token.
Request header must contain "content-type: application/x-www-form-urlencoded"
Your request payload should be url encoded Form Data, don't send as json object.
RFC 6749 OAuth 2.0 defined invalid_grant as:
The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
I found another good article, here you will find many other reasons for this error.
https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35
Google Playground is best tool which help you how to send request.
https://developers.google.com/oauthplayground

Categories