How to set Lambda Invoke Role in a for a custom authorizer? - serverless-framework

I've defined my authorizer in the custom section of my serverless.yml as follows:
custom:
authoriser:
name: api-authorizer
arn: arn:aws:lambda:eu-west-1:nnnnnnnnnn:function:api-authorizer
resultTtlInSeconds: 3600
identitySource: method.request.header.Authorization
identityValidationExpression: '^Bearer [-0-9a-zA-z\.]*$'
The bit I can't work out is how to set the Lambda Invoke Role. There doesn't appear to be any mapping between the values I can set and what is needed by Cloud Formation.
Is this possible to do in this way? Or do I need to register my authorizer as a resource?

Related

How to cloudform cognito user pool authentication provider with custom mapping

I've successfully cloudformed a cognito identity-pool and could not see how I add the custom mappings to the "Cognito" "Authentication Providers" in cloudformation.
Inside the Cognito Authentication Provider on the console, there is a dropdown where I manually have to select "Use custom mappings" and then I can manually add the mappings to my custom user attributes. However, I need to be able to cloudform this and am struggling to find the correct place for it.
The user pool that goes along with this identity pool has "SupportedIdentityProviders" set to "COGNITO"
Update
I can get a list of identity providers by running ...
aws cognito-identity list-identities --max-results 2 --identity-pool-id xx-xxxx-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
and this returns me
{
"IdentityPoolId": "xx-xxxx-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
"Identities": [
{
"IdentityId": "yy-yyyy-y:yyyyyyyy-yyyy-yyyy-yyyyyyyyyy",
"Logins": [
"cognito-idp.eu-west-2.amazonaws.com/eu-west-2_tFT6FBwIO"
],
"CreationDate": "2021-11-15T12:38:48.249000+00:00",
"LastModifiedDate": "2021-11-15T12:38:48.263000+00:00"
}
]
}
using the "Logins" information I can now run...
aws cognito-identity get-principal-tag-attribute-map --identity-pool-id xx-xxxx-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx --identity-provider-name "cognito-idp.eu-west-2.amazonaws.com/eu-west-2_tFT6FBwIO"
which returns
{
"IdentityPoolId": "xx-xxxx-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
"IdentityProviderName": "cognito-idp.eu-west-2.amazonaws.com/eu-west-2_tFT6FBwIO",
"UseDefaults": false,
"PrincipalTags": {
"attr_x": "custom:attr_x",
"attr_y": "custom:attr_y",
"attr_z": "custom:attr_z"
}
}
However, I still don't know how to setup this mapping via cloudformation...
Regards
Mark.
Setting PrincipalTag attribute mappings is not yet supported in CloudFormation but, according to the CloudFormation roadmap, will be supported soon.
In the meantime, you would have to create a CloudFormation Custom Resource or Resource Provider to achieve this.

How to validate or filter a wildcard in path for http endpoints in Serverless and AWS API gateway before the process triggs the lambda function?

I have the following http path devices/{sn} in a Serverless-AWS APIgateway API. The wildcard sn is a 15 digits [A-Z0-9] pattern.
In the API today any string that is not recognized as a valid path is redirected to this end-point. Ex: devices/test goes to devices/{sn}, devices/bla goes to devices/{sn} and so on. All those strings will query the database and return null because there is no such sn in the table. I could create a validation process inside the lambda to avoid the unnecessary database query. But I want to save lambda resource and I would like to validate before call the lambda.
This is what I have today for this endpoint:
- http:
path: devices/{sn}
method: GET
private: false
cors: true
authorizer: ${file(env.yml):${self:provider.stage}.authorizer}
request:
parameters:
paths:
sn: true
How can I setup this validation or filter in Serverless.yml?
In fact it should be a very straight-forward functionality of AWS/Serverless.
Let's say we have the following scenario: myPath/{id}. In this case id is a integer (a pk in a table). If I type myPath/blabla it will trigg the lambda. The system will spend resource. It shoul have a kind of previous validation - trig the endpoint only if the {id} === integer.
Your issue is very similar to this issue
According to the post and from my experience, No, I don't think you can perform validation in api-gateway level.

How to delete a elasticache subnet group with cloud custodian?

I want to use cloud custodian to cleanup some aws resources.( elasticache in this case) .
However ; I got error when trying to delete elasticache subnet groups. According to custodian cache.subnet-group documentation, delete is not a valid action for cache.subnet-group.
How do I perform delete in this case?
my policy file.
policies:
- name: cleanup-elasticache-subnet-group
resource: aws.cache-subnet-group
filters:
- type: value
key: "CacheSubnetGroupName"
op: contains
value: foo
actions:
- type: delele >>> !!! delete is not a valaid action type !!!
Since Cloud Custodian doesn't natively provide the delete action today, your main options are:
Open a feature request for an aws.cache-subnet-group.delete action.
Use Cloud Custodian to report/notify on subnet groups you need to delete, but handle the actual deletion with external tools.
For what it's worth, you can review open feature requests here. I didn't see any for this action, but it's always good to check!

Serverless Framework - S3 upload lambda trigger

I'd like to trigger different lambdas on the same bucket according to the folder where the file is uploaded. Basically, when the user uploads a file to "user/some_id/bills" I want to trigger lambda 1; When the user upload a file to "user/some_id/docs" I want to trigger lambda 2;
I tried the configuration bellow but did not work...
insertUploadBill:
handler: resources/insertUploadBill.main
events:
- s3:
bucket: ${self:custom.settings.BUCKET}
event: s3:ObjectCreated:*
rules:
- prefix: user/*/bills/
insertUploadDocs:
handler: resources/insertUploadDoc.main
events:
- s3:
bucket: ${self:custom.settings.BUCKET}
event: s3:ObjectCreated:*
rules:
- prefix: user/*/docs/
if you look at the docs
https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#notification-how-to-filtering
The wild card characters in rules (prefix / suffix) cannot be used.
So either you can change the S3 object key to match something like this
user/images/[user-id]
Or you can make a separate lambda to be invoked on all the s3:ObjectCreated:* events and then use this lambda to match the key and invoke your current lambdas. resources/insertUploadBill.main and resources/insertUploadDoc.main

Way to access S3 Bucket's name from cloudformation/boto3?

My team wants to create an S3 bucket in a cloudformation template without assigning it a bucket name (to let cloudformation name it itself).
When putting a file into the S3 bucket from my lambda function, is there a way for me to get the S3 bucket's name without having to manually look at the AWS console and check what name was created?
Using the Serverless Application Model (SAM) you can include environment variables with the function properties
AWSTemplateFormatVersion: '2010-09-09'
Description: "Demo"
Transform: 'AWS::Serverless-2016-10-31'
Resources:
MyLambdaFunction:
Type: 'AWS::Serverless::Function'
Properties:
Runtime: nodejs10.x
Handler: index.handler
CodeUri: ./src
Policies:
- Version: '2012-10-17'
Statement:
- Action:
- s3:PutObject
Effect: 'Allow'
Resource: !Sub ${MyS3Bucket.Arn}/*
Environment:
Variables:
BUCKET_NAME: !Ref MyS3Bucket
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Then your function can access the environment variables using process.env.BUCKET_NAME in node.js. In python I think you'd use os.environ['BUCKET_NAME']
const aws = require('aws-sdk');
const s3 = new aws.S3();
exports.handler = async (event) => {
const params = {
Body: 'The Body',
Bucket: process.env.BUCKET_NAME,
Key: 'abc123',
}
return s3.putObject(params).promise();
}
I would assume this works for any CloudFormation templates which aren't using the SAM transform too.
You can use Fn::GetAtt to get the values from your newly created S3 bucket.
You can check it here.
S3 Ref & Get Attribute Documentation
The problem is how to pass the value to lambda function.
Here is the step that might be works.
Use the function Get Attribute above to get the s3 bucket name that cloudformation created.
Insert the value into a file, you can use the UserData, or use Metadata if you are using cloud-init already.
Store the file into existed s3 bucket (or any other storage that lambda can access), you can using the cloud formation template bucket, that always been created when you launch a cloudformation template (usually named cf-template...).
Add a code to your lambda to access the s3 and get the file. Now you get the data of the s3 bucket that your cloudformation has been created and can use it on lambda.
Hope this help.