AWS parameter store access in lambda function - amazon-web-services

I'm trying to access the parameter store in an AWS lambda function. This is my code, pursuant to the documentation here: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SSM.html
var ssm = new AWS.SSM({apiVersion: '2014-11-06'});
var ssm_params1 = {
Name: 'XXXX', /* required */
WithDecryption: true
};
ssm.getParameter(ssm_params1, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else clientId = data.value;
});
Upon execution, I get the error:
"TypeError: ssm.getParameter is not a function"
Did amazon change this without changing the docs? Did this function move to another type of object?

Please check and try the latest version of the SDK. It is not the case that Amazon has ditched the getParameter method in favor of only getParameters. The fact is the method is getParameter, together with getParametersByPath, is newly added methods. Old version of SDK would not resolve these methods.

The answer here is that Amazon must have ditched the getParameter() method in favor of only maintaining one method getParameter(s)(). But they didn't update the documentation. That method seems to work just fine.

I have tried both getParameter and getParameters function, and both of them are working fine.
It could be possible that you are getting an error since you are passing "apiVersion: '2014-11-06'" to the SSM constructor.
Do not pass any apiVersion parameter to the function. It should work fine.

There seems to be a bug in AWS that is not including correct sdk version in certain environments. This can be confirmed by logging the sdk version used.
console.log("AWS-SDK Version: " + require('aws-sdk/package.json').version);
Including the required aws-sdk package solved the problem for us.
Try adding the following in package.json:
"aws-sdk": "^2.339.0"

Related

Lambda Snapstart with Serverless framework

So AWS announced Lambda Snapstart very recently, I tried to give it a go since my application has cold start time ~4s.
I was able to do this by adding the following under resources:
- extensions:
NodeLambdaFunction:
Properties:
SnapStart:
ApplyOn: PublishedVersions
Now, when I actually go to the said lambda, this is what I see :
So far so good!
But, the issue is that when I check my Cloudwatch Logs, there's no trace of Restore Time instead the good old Init Duration for cold starts which means Snapstart isn't working properly.
I dug deeper, so Snapstart only works for versioned ARNs. But the thing is Serverless already claims that :
By default, the framework creates function versions for every deploy.
And on checking the logs, I see that the logStreams have the prefix : 2022/11/30/[$LATEST].
When I check the Versions tab in console, I see version number 240. So I would expect that 240 is the latest version of this lambda function and this is the function version being invoked everytime.
However, clicking on the version number open a lambda function with 240 attached to its ARN and testing that function with Snapstart works perfectly fine.
So I am confused if the LATEST version and version number 240 ( in my case ), are these different?
If no, then why isn't Snapstart automatically activated for LATEST?
If yes, how do I make sure they are same?
SnapStart is only available for published versions of a Lambda function. It cannot be used with $LATEST.
Using Versions is pretty hard for Serverless Framework, SAM, CDK, and basically any other IaC tool today, because by default they will all use $LATEST to integrate with API Gateway, SNS, SQS, DynamoDB, EventBridge, etc.
You need to update the integration with API Gateway (or whatever service you're using) to point to the Lambda Version you publish, after that Lambda deployment has completed. This isn't easy to do using Serverless Framework (and other tools). You may be able to achieve this using this traffic-shifting plugin.
In case you use stepFuntions to call your lambda function, you can set useExactVersion: true in
stepFunctions:
stateMachines:
yourStateMachine:
useExactVersion: true
...
definition:
...
This will reference the latest version of your function you just deployed
This has got to be one of the worst feature launches that I have seen in a long time. How the AWS team could put in all the time and effort required to bring this feature to market, while simultaneously rendering it useless, because we can't script the thing is beyond me.
We were ready to jump on this and start migrating apps to lambda, but now we are back in limbo. Even knowing there was a fix coming down the line would be something. Hopefully somebody from the AWS lambda team can provide some insights...
Here is a working POC of a serverless plugin that updates the lambda references to use the most recent version. This fixed the resulting cloud formation code and was tested with both SQS and API-Gateway.
'use strict'
class SetCycle {
constructor (serverless, options) {
this.hooks = {
// this is where we declare the hook we want our code to run
'before:package:finalize': function () { snapShotIt(serverless) }
}
}
}
function traverse(jsonObj,functionVersionMap) {
if( jsonObj !== null && typeof jsonObj == "object" ) {
Object.entries(jsonObj).forEach(([key, value]) => {
if(key === 'Fn::GetAtt' && value.hasOwnProperty('length') && value.length === 2 && value[1] === "Arn" && functionVersionMap.get(value[0])){
console.log(jsonObj);
let newVersionedMethod = functionVersionMap.get(value[0]);
delete jsonObj[key];
jsonObj.Ref = newVersionedMethod;
console.log('--becomes');
console.log(jsonObj);
}else{
// key is either an array index or object key
traverse(value,functionVersionMap);
}
});
}
else {
// jsonObj is a number or string
}
}
function snapShotIt(serverless){
resetLambdaReferencesToVersionedVariant (serverless)
}
function resetLambdaReferencesToVersionedVariant (serverless) {
const functionVersionMap = new Map();
let rsrc = serverless.service.provider.compiledCloudFormationTemplate.Resources
// build a map of all the lambda methods and their associated versioned resource
for (let key in rsrc) {
if (rsrc[key].Type === 'AWS::Lambda::Version') {
functionVersionMap.set(rsrc[key].Properties.FunctionName.Ref,key);
}
}
// loop through all the resource and replace the non-verioned with the versioned lambda arn reference
for (let key in rsrc) {
if (! (rsrc[key].Type === 'AWS::Lambda::Version' || rsrc[key].Type === 'AWS::Lambda::Function')) {
console.log("--" + key);
traverse(rsrc[key],functionVersionMap);
}
}
// add the snapshot syntax
for (let key in rsrc) {
if (rsrc[key].Type === 'AWS::Lambda::Function') {
console.log(rsrc[key].Properties);
rsrc[key].Properties.SnapStart = {"ApplyOn": "PublishedVersions"};
console.log("--becomes");
console.log(rsrc[key].Properties);
}
}
// prints the method map
//for(let [key,value] of functionVersionMap){
//console.log(key + " : " + value);
//}
}
// now we need to make our plugin object available to the framework to execute
module.exports = SetCycle
I was able to achieve this by updating my serverless version to 3.26.0 and adding the property snapStart: true to the functions that i have created. currently serverless creates version numbers and as soon as the new version is published the SnapStart gets enabled to latest version.
ApiName:
handler: org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler
events:
- httpApi:
path: /end/point
method: post
environment:
FUNCTION_NAME: ApiName
runtime: java11
memorySize: 4096
snapStart: true

The create_profile_job() method is not accepting the new parameters

I am trying to use a Lambda function (written in python) to create a series of profile jobs in DataBrew. AWS recently added a new parameter to this function ("Configuration) which I have added in my code. However, when I call the function, I get the following error message: "Unknown parameter in input: "Configuration", must be one of: DatasetName, EncryptionKeyArn, EncryptionMode, Name, LogSubscription, MaxCapacity, MaxRetries, OutputLocation, RoleArn, Tags, Timeout, JobSample." This does not match the parameter list in the boto3 documentation, which was recently updated to align with the new features added to DataBrew on 07/23/21. Has anyone else had this issue? If so, is there a timeline for this bug to be fixed?
It turns out that the version of boto3 that is available in Lambda by default is not the most updated version. Hence, in order to use all the parameters for this method, you have to add the latest version of boto3 (and all dependencies) as a Lambda layer.

Cannot Read Context in Dialogflow Fulfillment (Suddenly Undefined)

We built a Dialogflow agent using google cloud functions as webhook which worked properly until yesterday evening. At that time I exported the agent and reimported it later on and it worked for a while.
What stopped working is that agent.context.get('...'); (also agent.getContext('...')) does return undefined even if the context is set according to the UI and raw API response.
As an example I have an intent which has a required slot shop, webhook for slot filling enabled.
When I test the agent, the intent named info is matched correctly and also the context info_dialog_params_store seems to be there:
And here is part of the output context according to the raw API response:
"outputContexts": [
{
"name": "projects/MYAGENTNAME/agent/sessions/0b753e8e-b377-587b-3db6-3c8dc898879b/contexts/info_dialog_params_store",
"lifespanCount": 1,
"parameters": {
"store": "",
"store.original": "",
"kpi": "counts",
"date_or_period": "",
"kpi.original": "trafico",
"date_or_period.original": ""
}
}
In the webhook I mapped the intent correctly to a js function:
let intentMap = new Map();
intentMap.set('info', info);
agent.handleRequest(intentMap);
And the first line of the info function looks like:
function info(agent) {
store_context = agent.context.get('info_dialog_params_store');
}
Which returns
TypeError: Cannot read property 'get' of undefined
at info (/user_code/index.js:207:36)
at WebhookClient.handleRequest (/user_code/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:303:44)
at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/user_code/index.js:382:9)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:57:9)
at /var/tmp/worker/worker.js:762:7
at /var/tmp/worker/worker.js:745:11
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
I am quite sure that I did not change anything which could affect the proper functioning of agent, except some refactoring.
I also tried the beta functions activated as well as deactivated as I read that there can be issues with environments, but that did not change anything.
Anyone knows in which direction I can investigate further?
I had the same issue, I resolved it updating dialogflow-fulfillment in package.json:
from "dialogflow-fulfillment": "^0.5.0"
to "dialogflow-fulfillment": "^0.6.0"
I solved the problem by turning off "Beta features"
enter image description here
Actually I could fix it by the following 'magic' steps:
Copied my original function to a text file
Copy and pasted the original example code into the GUI fulfillment code editor (Code on GitHub)
Deployed the function
Created a minimal example for my info function:
function info(agent) {
store_context = agent.context.get('info_dialog_params_store');
}
Tested it, and it worked
Copied back my original code
Everything was fine again

Failed to create AmazonGameLiftClient in Unity3d

I use below code to create GameClient in Unity3d:
AmazonGameLiftClient client =
new AmazonGameLiftClient("accessKeyId",
"accessKey",
RegionEndpoint.CNNorth1);
Above code is the first line in Awake(), no any other leading codes.
I get below error:
NullReferenceException: Object reference not set to an instance of an object
Amazon.CSMSection.get_CSMEnabled ()
Amazon.Util.CSMConfig.Configure (Amazon.CSMSection section)
Amazon.Util.Internal.RootConfig..ctor ()
Amazon.AWSConfigs..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Amazon.AWSConfigs
Amazon.Runtime.ClientConfig..ctor ()
Amazon.GameLift.AmazonGameLiftConfig..ctor ()
Amazon.GameLift.AmazonGameLiftClient..ctor (System.String awsAccessKeyId, System.String awsSecretAccessKey, Amazon.RegionEndpoint region)
Is there anything I forgot to do?
I assume the root cause is I do not put app.config in the correct place.
So AWS SDK does not init correctly, but I have not found any tutorial for using Unity3d as Amazon GameLift client :(
My Environment:
OS: Mac OS X 10.14.1
Unity3d: 2018.2.12f1
AWS SDK Core: 3.3.29.10(.net35)
AWS SDK GameLift: 3.3.12.29(.net35)
Update:
The AWS SDK relies on System.ConfigurationManager which seems not available in Unity3d projects. It seems the root cause of the NullReferenceException.
Please refer to this answer, it completely solves this question.

“The page has expired due to inactivity” appears when using a services methods - Laravel 5.5

According to other asked questions like this one, I did many doings to prevent this request expired message but there is no solution for my issue.
In the long run I recognized that the message appears when I call a service method inside a controller which run on form action!
Here is my codes samples with some descriptions:
My route:
Route::post('Material/{id}', 'MaterialController#updateMaterial')->name('updateMaterial');
Material Controller Constructor:
public function __construct(CustomService $srv)
{
$this->middleware('admin')->only(['updateMaterial']);
$this->srv= $srv;
}
srv is a protected attribute in MaterialController class.
updateMaterial Method:
public function updateMaterial($id,Request $request)
{
$this->validate($request, [...]);
$material = $this->srv->updateMaterial($request, $id);
if ($material)
return view('panel._materials.edit-material')
->with('material', $material)
->with('success', 1);
}
I also have a provider for CustomService with name CustomServiceProvider and here is the register method of the provider:
public function register()
{
$this->app->bind(CustomService::class,function($app){
return new CustomService();
});
}
and I registered it as a provider in config/app.php.
So when I return something before calling service updateMaterial method, it's OK. but when the method runs, the issue appears!
I don'n have any idea about!
Update:
And here is updateMaterial of CustomService:
public function updateMaterial($request, $id)
{
$material = Material::find($id);
if (!$material)
return false;
if ($request->has('unit'))
$material->unit = $request['unit'];
if ($request->has('price'))
$material->price = $request['price'];
if ($request->has('type'))
$material->type = $request['type'];
if ($request->has('is_active'))
$material->is_active = $request['is_active'];
$material->updated_at = Carbon::now();
$material->save();
return $material;
}
I also create a new project with Laravel 5.5.0 and without adding any complexity I just added a post route and call it in form action, but nothing changed!
This is just an issue for Windows users on Local Environment. I suffered a lot with this also when on Windows. Once you deploy to your production server, you won't have any issue at all.
It's important to note that this is not an issue with Laravel 5.5 version only. I first saw this issue in version 5.2.
I think a good fix for this would maybe be using something like Homestead or Vessel from Fideloper. Honestly I only suffered this problem when using Windows.