Cognito Lambda trigger socket timeout [duplicate] - amazon-web-services

This question already has an answer here:
AWS Lambda can't call Cognito Identity - IAM Role
(1 answer)
Closed 4 years ago.
I have a Lambda trigger on my cognito resource for the presignup trigger.
I am following this example
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-sign-up.html#aws-lambda-triggers-pre-registration-example
I am getting a socket timeout and not finding much documentation on this
{
"err": {
"code": "UnexpectedLambdaException",
"name": "UnexpectedLambdaException",
"message": "arn:aws:lambda:region-arn:function:confirm failed with error Socket timeout while invoking Lambda function."
}
}
My resources are defined as so:
"ConfirmPermission" : {
"Type" : "AWS::Lambda::Permission",
"Properties" : {
"Action" : "lambda:InvokeFunction",
"FunctionName" : { "Fn::GetAtt" : [ "confirm", "Arn" ] },
"Principal" : "cognito-idp.amazonaws.com",
"SourceArn" : { "Fn::GetAtt" : [ "Auth", "Arn" ] }
}
},
"confirm" : {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "index.confirm",
"Runtime": "nodejs8.10",
"CodeUri": "./src",
"FunctionName": "confirm",
"ReservedConcurrentExecutions" : 15,
"Timeout": 50,
"Role": "arn:aws:iam::arn:role/lambda-vpc-role"
}
},
"AuthApp" : {
"Type" : "AWS::Cognito::UserPoolClient",
"Properties" : {
"UserPoolId" : {"Ref" : "Auth"}
}
},
"Auth" : {
"Type" : "AWS::Cognito::UserPool",
"Properties": {
"LambdaConfig" : {
"PreSignUp" : { "Fn::GetAtt" : [ "confirm", "Arn" ] }
},
"Schema" : [
{
"AttributeDataType": "String",
"Name": "email",
"Mutable": true,
"Required": true
},
{
"AttributeDataType": "String",
"Name": "family_name",
"Mutable": true,
"Required": true
},
{
"AttributeDataType": "String",
"Name": "given_name",
"Mutable": true,
"Required": true
}
],
"UsernameAttributes": ["email"]
}
}
Lambda Functions:
index.js
let signIn = require('Auth/Auth.js');
exports.signIn = signIn.signIn;
exports.signUp = signIn.signUp;
exports.confirm = signIn.confirm;
sign up / confirm
exports.signUp = async (event, context) => {
var body = JSON.parse(event.body);
var emailAttribute = {
Name : 'email',
Value: body.email
};
var firstNameAttribute = {
Name: 'given_name',
Value: body.firstName
};
var lastNameAttribute = {
Name: 'family_name',
Value: body.lastName
};
var attributeList = [emailAttribute, firstNameAttribute, lastNameAttribute];
try {
var cognitoUser = await cognitoSignUp(body, attributeList);
return {
statusCode : 200,
body : JSON.stringify({res : cognitoUser})
};
} catch(e) {
return {
statusCode : 500,
body : JSON.stringify({err : e})
};
}
}
exports.confirm = (event, context, callback) => {
event.response.autoConfirmUser = true;
callback(null, event);
return;
}
var cognitoSignUp = (body, attributeList) => new Promise((acc, rej) => {
userPool.signUp(body.email, body.password, attributeList, null, function(err, res) {
if (err) {
console.log('ERROR');
console.log(err);
rej(err);
} else {
console.log('SUCCSSS');
acc(res);
}
});
});
Any idea on what is causing this?

As it turns out, it's because the confirm function has an IAM role for aws resources which blocks network requests. I don't need the IAM role on this function. After removing it, it works perfectly. If you do need resource access, then you have to use a nat gateway
See more here:
AWS Lambda can't call Cognito Identity - IAM Role
https://gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7

You can increase the timeout of your function up to 15 minutes 900 seconds as shown below...
"confirm" : {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "index.confirm",
"Runtime": "nodejs8.10",
"CodeUri": "./src",
"FunctionName": "confirm",
"ReservedConcurrentExecutions" : 15,
"Timeout": 900,
"Role": "arn:aws:iam::arn:role/lambda-vpc-role"
}
},
Unless you're encoding something running some long analytics you probably shouldn't even need the to 50 seconds let alone 15 minutes though. you should check your logs for an error somewhere and make sure you're calling...
callback(null, event);
To return response from the Lambda.

Related

Amplify Push erroring out when updating CustomResources.json

I'm building a geospatial search on properties using AWS Amplify and ElasticSearch.
I'm currently following this guide: https://gerard-sans.medium.com/finding-the-nearest-locations-around-you-using-aws-amplify-part-2-ce4603605be6
I set up my model as follows
type Property #model #searchable #auth(rules: [{allow: public}]) {
id: ID!
...
Loc: Coord!
}
type Coord {
lon: Float!
lat: Float!
}
I also added a custom Query:
type Query {
nearbyProperties(
location: LocationInput!,
m: Int,
limit: Int,
nextToken: String
): ModelPropertyConnection
}
input LocationInput {
lat: Float!
lon: Float!
}
type ModelPropertyConnection {
items: [Property]
total: Int
nextToken: String
}
I added resolvers for request and response:
## Query.nearbyProperties.req.vtl
## Objects of type Property will be stored in the /property index
#set( $indexPath = "/property/doc/_search" )
#set( $distance = $util.defaultIfNull($ctx.args.m, 500) )
#set( $limit = $util.defaultIfNull($ctx.args.limit, 10) )
{
"version": "2017-02-28",
"operation": "GET",
"path": "$indexPath.toLowerCase()",
"params": {
"body": {
"from" : 0,
"size" : ${limit},
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "${distance}m",
"Loc" : $util.toJson($ctx.args.location)
}
}
}
},
"sort": [{
"_geo_distance": {
"Loc": $util.toJson($ctx.args.location),
"order": "asc",
"unit": "m",
"distance_type": "arc"
}
}]
}
}
}
and response:
## Query.nearbyProperties.res.vtl
#set( $items = [] )
#foreach( $entry in $context.result.hits.hits )
#if( !$foreach.hasNext )
#set( $nextToken = "$entry.sort.get(0)" )
#end
$util.qr($items.add($entry.get("_source")))
#end
$util.toJson({
"items": $items,
"total": $ctx.result.hits.total,
"nextToken": $nextToken
})
And now the CustomStacks.json:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "An auto-generated nested stack.",
"Metadata": {},
"Parameters": {
"AppSyncApiId": {
"Type": "String",
"Description": "The id of the AppSync API associated with this project."
},
"AppSyncApiName": {
"Type": "String",
"Description": "The name of the AppSync API",
"Default": "AppSyncSimpleTransform"
},
"env": {
"Type": "String",
"Description": "The environment name. e.g. Dev, Test, or Production",
"Default": "NONE"
},
"S3DeploymentBucket": {
"Type": "String",
"Description": "The S3 bucket containing all deployment assets for the project."
},
"S3DeploymentRootKey": {
"Type": "String",
"Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory."
}
},
"Resources": {
"QueryNearbyProperties": {
"Type": "AWS::AppSync::Resolver",
"Properties": {
"ApiId": { "Ref": "AppSyncApiId" },
"DataSourceName": "ElasticSearchDomain",
"TypeName": "Query",
"FieldName": "nearbyProperties",
"RequestMappingTemplateS3Location": {
"Fn::Sub": [
"s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Query.nearbyProperties.req.vtl", {
"S3DeploymentBucket": { "Ref": "S3DeploymentBucket" },
"S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" }
}]
},
"ResponseMappingTemplateS3Location": {
"Fn::Sub": [ "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Query.nearbyProperties.res.vtl", {
"S3DeploymentBucket": { "Ref": "S3DeploymentBucket" },
"S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" }
}]
}
}
}
},
"Conditions": {
"HasEnvironmentParameter": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "env"
},
"NONE"
]
}
]
},
"AlwaysFalse": {
"Fn::Equals": ["true", "false"]
}
},
"Outputs": {
"EmptyOutput": {
"Description": "An empty output. You may delete this if you have at least one resource above.",
"Value": ""
}
}
}
But when i try to amplify push, it does not work. Something about: Resource is not in the state stackUpdateComplete
Any help?
You could take a look in cloudformation at the resource. You're instance is probably stuck in update. Go to : Cloudformation, select your instance (or uncheck view nested first) and go to the events tab. There you will probably find a reason why the instance can't update.
If it's stuck, cancel within the stack actions.

ResourceRegistrationFailureException when calling the RegisterThing operation - thing groups conflict

I am getting the following error when trying to use the RegisterThings action from AWS IoT. Within the API, call, I am trying to set the thing groups but getting the following error:
An error occurred (ResourceRegistrationFailureException) when calling the RegisterThing operation: Existing ThingGroups: [] conflict with ThingGroups: [mythingggroup] in Template
Here is my provisioning template:
provision_json = json.dumps({
"Parameters": {
"ThingName": {
"Type": "String"
},
"ThingGroup": {
"Type": "String"
},
"CertificateId": {
"Type": "String"
},
"PolicyName": {
"Type": "String"
},
"AssumeRolePolicyName": {
"Type": "String"
}
},
"Resources": {
"Thing": {
"Type": "AWS::IoT::Thing",
"Properties": {
"ThingName": {
"Ref": "ThingName"
},
"ThingGroups": [{
"Ref": "ThingGroup"
}]
},
"OverrideSettings" : {
"ThingGroups" : "REPLACE"
}
},
"Certificate": {
"Type": "AWS::IoT::Certificate",
"Properties": {
"CertificateId": {
"Ref": "CertificateId"
}
}
},
"DevicePolicy": {
"Type": "AWS::IoT::Policy",
"Properties": {
"PolicyName": {
"Ref": "PolicyName"
}
}
},
"TESAssumeRolePolicy": {
"Type": "AWS::IoT::Policy",
"Properties": {
"PolicyName": {
"Ref": "AssumeRolePolicyName"
}
}
}
}
})
then I call the boto3 client like this:
iot = boto3.client("iot")
response = iot.register_thing(
templateBody=provision_json,
parameters={
"CertificateId": "1234",
"ThingName": "mythingname",
"ThingGroup": "mythinggroupname",
"PolicyName": "mypolicyname",
"AssumeRolePolicyName": "anotherpolicyname"
}
)
I thought this might be a permissions error, but even after I give the caller iot:*, I still have the same issue.
AWS isn't providing great documentation on why this error is occurring. Does anyone have any ideas?

How to I get just the temperature from the new google SDM for nest thermostat

Using : Get
https://smartdevicemanagement.googleapis.com/v1/enterprises/project-id/devices/device-id/
It returns all the info below. i just want the temperature. I am using postnam with: Content-Type and Authorization.
{
"name": "enterprises/c7ad210f-e05d-418c-a52a-1efc0891b3cf/devices/AVPHwEu-AUnrc2QEy_wmf7_u1hXWh_fH2V4q_DA5S1C3_bnLc2H-IxPEsNKtbc5NJZGCXFNAgK9HyZ96slFUQuyShlqauw",
"type": "sdm.devices.types.THERMOSTAT",
"assignee": "enterprises/c7ad210f-e05d-418c-a52a-1efc0891b3cf/structures/AVPHwEsL0trQSBq4GoBJFNrt_eBujz2A9uQvOxg112ZkvUSGMw3A2l3BBFGrLQ-Q8nyc-Mvvqb-Dy6YabT4625fGH1fcIg/rooms/AVPHwEuauRh8KXX1R_kRoTnxKUXRomQ_u80JOyjhfVKKCbn-OPPPigjoAOIJ7kFFwy1-PEs9z6BIP4DugImZLQ2bL59Uv0nZuHLjVsb0If9q0-pGQZcFgY5dxx7iIX63GuIezOW4paE8NNE",
"traits": {
"sdm.devices.traits.Info": {
"customName": ""
},
"sdm.devices.traits.Humidity": {
"ambientHumidityPercent": 63
},
"sdm.devices.traits.Connectivity": {
"status": "ONLINE"
},
"sdm.devices.traits.Fan": {},
"sdm.devices.traits.ThermostatMode": {
"mode": "HEAT",
"availableModes": [
"HEAT",
"OFF"
]
},
"sdm.devices.traits.ThermostatEco": {
"availableModes": [
"OFF",
"MANUAL_ECO"
],
"mode": "OFF",
"heatCelsius": 8.82,
"coolCelsius": 24.44443
},
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF"
},
"sdm.devices.traits.Settings": {
"temperatureScale": "CELSIUS"
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 16
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 20.23
}
},
"parentRelations": [
{
"parent": "enterprises/c7ad210f-e05d-418c-a52a-1efc0891b3cf/structures/AVPHwEsL0trQSBq4GoBJFNrt_eBujz2A9uQvOxg112ZkvUSGMw3A2l3BBFGrLQ-Q8nyc-Mvvqb-Dy6YabT4625fGH1fcIg/rooms/AVPHwEuauRh8KXX1R_kRoTnxKUXRomQ_u80JOyjhfVKKCbn-OPPPigjoAOIJ7kFFwy1-PEs9z6BIP4DugImZLQ2bL59Uv0nZuHLjVsb0If9q0-pGQZcFgY5dxx7iIX63GuIezOW4paE8NNE",
"displayName": "Hallway"
}
]
}
According to the API documentation, it's not possible to only get the temperature.
But you can get it from the response body you posted, in Postman's test tab:
const resBody = pm.response.json();
temperature = resBody.traits['sdm.devices.traits.Temperature'].ambientTemperatureCelsius;
console.log(temperature);

CloudFormation Custom Resource responseKey

I have got lambda backed Custom Stack in CloudFormation , So I need the fetch function output and put it to the AWS Console, how I can handle this problem?
My Stack is shown as below ;
"CreateExistingVPC": {
"Type": "Custom::CreateExistingVPC",
"Properties": {
"ServiceToken": { "Fn::If": ["LambdaAvailable",{ "Fn::GetAtt": [ "CustomLogic", "Outputs.LambdaAttachHostedZoneArn" ] }, { "Ref": "AWS::NoValue" } ] },
"Region": { "Ref": "AWS::Region" },
"HostedZoneId": { "Ref": "InternalHostedZone" },
"VpcId": { "Fn::GetAtt": [ "VPC", "Outputs.VPC" ] }
}
}
},
"Outputs": {
"Route53VPC": {
"Description": "ExistingRoute53VPCStatus",
"Value": { "Fn::GetAtt": [ "CreateExistingVPC", "{ ??????? }" ] }
}
}
In actually, I have found some answers but 'response key' not worked in my case , how I can find response key ??
AWS Cloudformation, Output value from Custom Resource
You need to use the variable you are using to return your response. e.g. (nodeJs)
module.exports.createPoolList = (event, context, callback) => {
if (event.RequestType == 'Create') {
let array = event.ResourceProperties.OpsPoolArnList.split(",");
array.push(event.ResourceProperties.UserPool);
let response = {
'list': array.join(),
};
sendresponse(event, "SUCCESS", response, "");
}
if (event.RequestType == 'Delete') {
sendresponse(event, "SUCCESS", null, "");
}
callback(null, "");
};
Here list is the variable which contains my output & returning in my response. The built payload looks like
let payload = {
'StackId': event.StackId,
'Status' : responsestatus,
'Reason' : reason,
'RequestId': event.RequestId,
'LogicalResourceId': event.LogicalResourceId,
'PhysicalResourceId': event.LogicalResourceId + 'qwerty',
'Data': response
};
And I refer to this in my script as
!GetAtt <ResourceName>.list
Hope it helps.

x-amazon-apigateway-integration get lambda arn for uri property

The x-amazon-apigateway-intregration extension has a URI property that takes an arn value of the backend. When I try to deploy this with SAM I get the following error
Unable to parse API definition because of a malformed integration at path /auth/signIn
How can I get the ARN value of my lambda function that is specified in my template?
Template:
"api" : {
"Type" : "AWS::Serverless::Api",
"Properties" : {
"StageName" : "prod",
"DefinitionUri" : "src/api/swagger.json"
}
},
"signIn": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "index.signIn",
"Runtime": "nodejs8.10",
"CodeUri": "./src",
"FunctionName": "signIn",
"ReservedConcurrentExecutions": 15,
"Timeout": 5,
"Events": {
"SignIn": {
"Type": "Api",
"Properties": {
"Path": "/signIn",
"Method": "post",
"RestApiId" : {
"Ref": "api"
}
}
}
}
}
},
Swagger Definition:
"paths" : {
"/auth/signIn" : {
"post" : {
"x-amazon-apigateway-integration" : {
"httpMethod" : "POST",
"type" : "aws_proxy",
"uri" : {
"Fn::Sub" : {
"Fn::GetAtt": [
"signIn",
"Arn"
]}
}
},
"parameters" : [
{
"name" : "email",
"in" : "body",
"required" : "true",
"schema" : {
"type" : "string"
}
},
{
"name" : "password",
"in" : "body",
"required" : "true",
"schema" : {
"type" : "string"
}
}
],
"responses" : {
"200" : {
"description" : "Authenticated"
},
"default" : {
"description" : "Unexpected Error"
}
}
}
},