S3 CreateEventSourceMapping triggers "Operation not found" error - php

I'm trying to create source maps so when someone uploads something inside the bucket, Lambda will trigger a previously created function, as described here
But, when I call this:
$fnName = 'my_function';
$s3->createEventSourceMapping([
//'BatchSize' => <integer>,
'Enabled' => true, //<boolean>
'EventSourceArn' => 'arn:aws:s3:::'.S3_BUCKET.'/'.$fnName, // REQUIRED
'FunctionName' => $fnName, // REQUIRED
'StartingPosition' => 'LATEST', //'TRIM_HORIZON|LATEST|AT_TIMESTAMP',
//'StartingPositionTimestamp' => <integer || string || DateTime>,
]);
I get the following error message Operation not found: CreateEventSourceMapping.
Some of those parameters are not active because according to the documentation found in https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-lambda-2015-03-31.html#createeventsourcemapping they have default values or aren't required (as far as I undestand)
At the moment I am using PHP SDK (ver 3.94.2). Is there something I am missing?

The createEventSourceMapping() method is a method on a Lambda client, not on an S3 client.

Related

How can I query AWS Batch for jobs matching multiple jobStatus values in AWS PHP SDK Version 3?

I am currently working on a PHP project using the AWS PHP SDK. I have a data import process that utilizes AWS batch. The PHP application needs to be able to check AWS for jobs that are not complete, prior to letting the user start a new job.
I am currently using the listJobs() call on the BacthClint like so, following an example given by the documentation:
<?php
$client = new Aws\Batch\BatchClient([
...
]);
$jobs = $client->listJobs([
'jobQueue' => '...',
'jobStatus' => 'RUNNING',
]);
However, I would like to get jobs matching the statuses of SUBMITTED, PENDING, RUNNABLE and STARTING as well as RUNNING.
The docs make it seem like I could submit the following value, as a pipe delinted list. But this syntax caused the request to fail:
<?php
$jobs = $client->listJobs([
'jobQueue' => '...',
'jobStatus' => 'SUBMITTED|PENDING|RUNNABLE|STARTING|RUNNING',
]);
Error:
Error executing request, Exception : Invalid job status SUBMITTED|PENDING|RUNNABLE|STARTING|RUNNING. Valid statuses are [SUBMITTED, PENDING, RUNNABLE, STARTING, RUNNING, SUCCEEDED, FAILED]
Is there some kind of way that I can submit multiple values under the 'jobStatus' input?
If not, is there some other way I can do this utilizing the AWS PHP SDK?
Note:
It looks like there is a 'filters' feature listed under the heading "Parameter Details" and "Parameter Syntax" secotion in the documentation example from before. This seems to suggest that something like this should work:
<?php
$jobs = $client->listJobs([
'jobQueue' => '...',
'filters' => [
'name' => 'jobStatus',
'values' => ['SUBMITTED', 'PENDING', 'RUNNABLE', 'STARTING', 'RUNNING']
]
]);
"You can filter the results by job status with the jobStatus parameter. If you don't specify a status, only RUNNING jobs are returned."
"The job status used to filter jobs in the specified queue. If the filters parameter is specified, the jobStatus parameter is ignored and jobs with any status are returned. If you don't specify a status, only RUNNING jobs are returned."
However this seems to return blank result sets.

AWS facade in Laravel fails to instantiate CloudSearch class properly

I am using the AWS facade for Laravel and I can instantiate a CloudSearchDomainClient object like this:
$c = AWS::createClient('cloudsearchdomain', ['endpoint' => '{our-endpoint}']);
But when I attempt to search like so:
$c->search(['query' => 'test']);
I get this error: Aws\CloudSearchDomain\Exception\CloudSearchDomainException with message 'Error executing "Search" on "2013-01-01/search"; AWS HTTP error: cURL error 6: Could not resolve host: 2013-01-01
It thinks the version is the endpoint.
I have the proper .env vars, eg. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION. I am able to use other AWS services, but CloudSearch specifically is a problem. What am I doing incorrectly?
I think you are mixing two things. An endpoint is a domain and api version is a date. So it should be more like this:
$c = AWS::createClient(
'cloudsearchdomain',
[
'endpoint' => 'https://example.com',
'apiVersion' => '2013-01-01',
]
);

Test error handling of the PHP S3Client uploadAsync method

Method uploadAsync automatically decides and uploads object in single or multiple chunks. And we can expect 2 different kind of expectations S3Exception and S3MultipartUploadException in our $result['reason']. I'm trying to mock part of the S3 client to throw the exception, I have done this by MockHandler:
$s3->getHandlerList()->setHandler(new MockHandler([$result], null, null));
And the $result is:
new S3Exception("", new Command("mockCommand"), [
'code' => 'mockCode',
'response' => new Response(401)
])
Or either this:
new S3MultipartUploadException(new UploadState(['testid']))
Since the S3MultipartUploadException is not instance of AwsException I got this exception:
InvalidArgumentException: Expected an Aws\ResultInterface or Aws\Exception\AwsException.
How can I handle such scenario?
I have asked this on the project repo and they confirmed this is a bug https://github.com/aws/aws-sdk-php/issues/2143.

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.

Access aws services without key & secret in 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.

Categories