Sending message to AWS Lambda from AWS Pinpoint Custom Channel - amazon-web-services

I am trying to send messages to my AWS Lambda Function from AWS Pinpoint through custom channel as described here
My problem is about granting permission to AWS Pinpoint to invoke my lambda function. The AWS CLI command provided in the documentation for granting permission is not working. When I execute the aws lambda add-permission command from AWS CLI like described in the documentation, I got the following error:
"no matches found: arn:aws:mobiletargeting:us-east-1:<account-id>:apps/*"
The result doesn't change if I change the ARN to any of the below:
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/*
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/campaigns/*
arn:aws:mobiletargeting:us-east-1:<account-id>:/apps/<pinpoint-app-id>/*
arn:aws:mobiletargeting:us-east-1:<account-id>:/apps/<pinpoint-app-id>/campaigns/*
I tried the same with AWS Cloudformation instead of AWS CLI, I succeeded to grant permission to AWS Pinpoint to invoke my lambda function. At least the Resource Based Policy appeared in the "Permissions" tab of my AWS Lambda Function Console. The source ARN like condition is
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/*
But, when I try to create a campaign under the same pinpoint application (i.e., project) I got the following error message:
"Amazon Pinpoint couldn’t invoke the Lambda function that you specified for custom delivery. Verify that a function policy is assigned to the function and that Amazon Pinpoint is authorized to invoke the function."
I tried different SourceArn like condition including the followings, but the result is the same:
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/*
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/campaigns/*
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/*
arn:aws:mobiletargeting:us-east-1:<account-id>:*
arn:aws:mobiletargeting:us-east-1:<account-id>:/apps/*
Couldn't figure out what the problem is. Any idea about what I am missing will be greatly appreciated.
Thanks in advance!

Interesting but the same aws lambda add-permission command that returned no matches found: arn:aws:mobiletargeting:us-east-1:<account-id>:apps/* is working after sudo su.

This is probably too late, but for anyone that has a similar problem and don't want to go through the whole cloudformation template at least for now.
I had the same issue with
"no matches found: arn:aws:mobiletargeting:us-east-1::apps/*".
It was due to my terminal behaving weirdly with '*', so adding single quotes around the arn worked, like:
arn:aws:mobiletargeting:us-east-1:<account-id>:apps/<pinpoint-app-id>/*

Related

Amazon S3 Access Denied when calling aws lambda publish-layer-version CLI

I tried to run aws lambda publish-layer-version command line in my local console using my personal aws credentials, but I've got an Amazon S3 Access Denied error for the bucket in which the zip layer is stored.
aws lambda publish-layer-version --layer-name layer_name --content S3Bucket=bucket_name,S3Key=layers/libs.zip
An error occurred (AccessDeniedException) when calling the PublishLayerVersion operation: Your access has been denied by S3, please make sure your request credentials have permission to GetObject for {URI of layer in my S3 bucket}. S3 Error Code: AccessDenied. S3 Error Message: Access Denied
When I'm running the aws cp command in the same bucket, it all works perfectly fine
aws s3 cp s3://bucket_name/layers/libs.zip libs.zip
So I assume that the aws lambda command line is using an other role than the one used when I'm running the aws cp command line ? Or maybe it uses another mecanism that I just don't know. But I couldn't find any thing about it in the AWS documentation.
I've just read that AWS can return a 403 it couldn't find the file. So maybe it could be an issue with the command syntax ?
Thank you for your help.
For your call to publish-layer-version you may need to specify the --content parameter with 3 parts:
S3Bucket=string,S3Key=string,S3ObjectVersion=string
It looks like you are missing S3ObjectVersion. I don't know what the AWS behavior is for evaluating and applying the parts of that parameter, but it could be attempting to do something more since the version is not specified and hence giving you that error. Or it could be returning an error code that is not quite right and is misleading. Try adding S3ObjectVersion and let me know what you get.
Otherwise, AWS permission evaluation can be complex. I like this AWS diagram below, so it is a good one to follow to track down permissions issues, but I suspect that AccessDenied is a bit of a red herring in this case:
Your Lambda does not have privileges (S3:GetObject).
Try running aws sts get-caller-identity. This will give you the IAM role your command line is using.
Go to IAM dashboard, check this role associated with your Lambda execution. If you use AWS wizard, it automatically creates a role called oneClick_lambda_s3_exec_role. Click on Show Policy. It will look something like attached image.Make sure S3:GetObject is listed.
Also, AWS returns 403 (access denied) when the file does not exist. Be sure the target file is in the S3 bucket.

How does S3 get permission from Lambda trigger?

I'm working out the security details for working with Lambda. One thing I can't find out is how S3 gets permission to push to Lambda when you add a trigger from the Lambda console or via S3 - Properties - Events. I know how it works using the CLI and I know you could do it via the SDK but I also noticed it isn't always necessary. Mostly the trigger just 'works' without me adding any permissions. Does anybody know why?
And is there a way to find out what Permissions S3/an S3 bucket has? I know there's a tab 'Permissions' but that's not giving me any information. I also know about Truster Advisor but that's just telling me there's no explicit problem with the permissions. I'm wondering if I can get a list of permissions though?
I hope someone can help me out, thanks in advance!
Adding a trigger in the console is the equivalent of assigning permissions and setting a bucket notification. You can see the policy associated with a particular lambda function by using the get-policy cli command:
aws lambda get-policy --function-name <name>
This will tell you what the policy is for your function. Including the resources with rights to invoke it. This policy isn't applied to the S3 bucket, but instead your lambda function.
You can also see what your bucket is set up to notify in the console under Properties > Events or review this with the cli using the get-bucket-notification command:
aws s3api get-bucket-notification --bucket <bucket>

An error occurred (InvalidParameter) when calling the AddPermission operation: Invalid parameter: Policy contains too many statements

We are trying to add permission to an SNS topic in account 'A'. A lambda function in account 'B' will invoke this. To do this, we used the CLI as below:
aws sns add-permission --topic-arn arn:aws:sns:us-east-1:<account_A>:djif-prod-policy-engine-config-sns --label lambda-<account_B>-us-east-2 --aws-account-id <account_B> --action-name Publish --region us-east-1
This returns the following error:
An error occurred (InvalidParameter) when calling the AddPermission operation: Invalid parameter: Policy contains too many statements!
Can someone help us figure out a way to resolve this. We created a lambda function in a different account (account C) and this command worked fine with no errors.
We figured this out. Whenever we run aws sns add-permission it updates the SNS topic policy. We had a bug in our code that called this multiple times for the same account (we are trying to invoke this SNS topic from multiple accounts). The AWS limit on the number of policies is 100 and when we hit this limit, we get the error.

AWS Execution failed due to configuration error: Authorizer error

I created 2 Authorizers to an API Gateway Endpoint. One manually using console and the other one using boto3.
The one created manually works great, however the one created using script gives error mentioned in the subject line. If you check the contents of these 2 authorizers, they are the same.
What can be the missing part? I dont think this is Invalid permission on lambda as it is working on one authorizer when configured manually.
The code for the same is as below:
response = client.create_authorizer(
restApiId=apiid,
name=authName,
type='TOKEN',
authType='custom',
authorizerUri=authorizerUri,
##arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:<AcctId>:function:CustomAuthorizer/invocations
identitySource='method.request.header.Authorization',
identityValidationExpression= '.*',
authorizerResultTtlInSeconds=300
)
Getting error:
Mon Jul 18 11:53:04 UTC 2016 : Execution failed due to configuration error: Invalid permissions on Lambda function
Mon Jul 18 11:53:04 UTC 2016 : Execution failed due to configuration error: Authorizer error
Mon Jul 18 11:53:04 UTC 2016 : AuthorizerConfigurationException
Just went down this rabbit hole, and came across a solution (worked with boto3 and python, hope it is similar across different sdk's).
The issue is that when you create it manually through the console, there is a popup that asks to enable api gateway (this specific authorizer to be exact) as a trigger to the lambda function you are using as an authorizer. When doing it via sdk, there obviously is no popup, so the authorizer is not authorized to invoke that lambda.
You can enable permissions two ways:
In lambda, create a new trigger for your authorizer in the Designer panel. Specifying an api and stage should do the trick
Create a role that will handle this permission. Give it permission to invoke lambda (you can use the AWSLambdaRole template role) and make sure to add api-gateway as a trusted entity to use this role in the Trust Relationships tab. your policy should look something like this:
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "apigateway.amazonaws.com"},"Action": "sts:AssumeRole"}]}
Now, when creating a custom authorizer using the sdk, you have to provide an authorizerCredentials parameter, which is described as "(string) Specifies the required credentials as an IAM role for API Gateway to invoke the authorizer. To specify an IAM role for API Gateway to assume, use the role's Amazon Resource Name (ARN). To use resource-based permissions on the Lambda function, specify null.".
Copy your newly-created role's arn and use this as the value for the authorizerCredentials param.
Viola! you now have a custom authorizer that is allowed to use the role that allows it to invoke the lambda function!
(sorry for bad formatting, I don't comment often :D)
First, use the test button in API Gateway to confirm if you can call your Lambda function from within it. This will ensure that the API Gateway-to-Lambda connection is working.
To assess your resource policies, you need to call the GetPolicy API; the execution role controls what your code an do in Lambda, not who can call it. That would be a good next check.
You can also turn on logging in API Gateway, which is a good way to gain additional insight into what it's doing on your behalf. These logs then show up in Amazon CloudWatch Logs, where you can check out the flow of your request.
If you're using CORS, it's possible to miss a setting (or two :), so I would double check that as well. CURLing directly to your endpoint (you can easily test from Lambda using its HTTP endpoint blueprint) is a good first step before you "wire up" your API to a website or other app directly.
It would be helpful if you check your CloudWatch Logs Insights.
Go to your lambda function, open "Monitor" section. Read through the last logs received.
In my case, I made a typo on lambda methods handler address. That is why the error thrown.
You need to add a resource-based statement to your Lambda's permissions, in order to allow it to be called by your gateway. As #MichaelJoy points out, this is taken care of in the console when you click "Create" on the popup. Doing this programmatically requires taking a second step after your authorizer has been created.
To do this via CLI, you can do the following (presumably boto3 has all of the corresponding commands):
aws lambda add-permission --function-name 'arn:aws:lambda:us-west-2:<AcctId>:function:CustomAuthorizer' \
--action lambda:InvokeFunction --statement-id 'api_gateway' \
--principal apigateway.amazonaws.com --output text \
--source-arn "AUTHORIZER_ARN"
where AUTHORIZER_ARN is the ARN of the authorizer you just created. Note that the statement id of 'api_gateway' is arbitrary.
You can see all resource-based policies on your Lambda via the following. This may be helpful esp if you want to inspect the permissions added by you via the console as a working example of what you need to effect programmatically to get the same result:
aws lambda get-policy --function-name XXXX
If you're updating an existing resource-based permission, you'll need to remove it first via the remove-policy command

AWS lambda unable to create a scheduled event source

Unable to create a recurring schedule for lambda.
What I did:
1) Created the function and successfully tested it.
2) Went to event source section in the AWS mgmt console.
3) clicked on add event source.
4) with default settings of rate(5 minutes) clicked on submit.
Got the error:
There was an error creating the event source mapping: Could not create
scheduled-event event source
I went through the docs and ran this statement via AWS CLI:
aws lambda add-permission --statement-id Allow-scheduled-events --action lambda:InvokeFunction --principal events.amazonaws.com --function-name function:myfunction
The above statement went through successfully, I tried running it again and it said the permission already exists confirming that it ran.
I tried adding the schedule again but got the same error.
Am i supposed to change the role or something? Can't anything else in the docs. The lambda is running with basic lambda execution role.
UPDATE
I temporarily gave the role under which the Lambda is executing admin access, still the same error.
Workaround
FYI... for people facing this problem, I could achieve the same result by going to cloudwatch and adding an event targeting lambda from there... same thing, that still does not answer this question though. I cant imagine that AWS console has such a gaping bug that they aren't doing anything about.
In my case my Lambda and S3 were not in the same region. I found out by, instead of adding the trigger on the Lambda, adding the event from s3.