IMPORTANT An updated version of the solution is available in this article. https://www.googlecloudcommunity.com/gc/Cloud-Product-Articles/ApigeeX-and-AWS-Lambda/ta-p/427109 |
|---|
APIs on Apigee can talk to AWS Lambda functions as a backend. This article provides an outline of an approach to perform the connectivity using AWS Javascript SDK (without using a127).
AWS provides SDKs for several languages and we will be using the Javascript SDK 2.149.x in particular here in Apigee node.js. The AWS Java SDK using Apigee Java Callout is an alternative but the SDK performs Java calls that are blocked by Apigee, getEnv() in this case (This can change in the future). You can also connect to AWS Lambda directly using Apigee TargetServer and make direct REST calls to Lambda without using an SDK.
A sample node.js app that you can deploy to Apigee looks as follows:
var AWS = require('aws-sdk');
var apigee = require('apigee-access');
var http = require('http');
var lambda = null;
console.log('node.js application starting...');
var server = http.createServer(function (request, resp) {
var accessKeyId = apigee.getVariable(request, 'aws.accessKeyId');
var secretAccessKey = apigee.getVariable(request, 'aws.secretAccessKey');
var region = apigee.getVariable(request, 'aws.region');
var awsCredentials = new AWS.Credentials({accessKeyId: accessKeyId, secretAccessKey: secretAccessKey});
AWS.config.region = region;
if(!lambda){
lambda = new AWS.Lambda();
}
AWS.config.credentials.get(function(error){
if(error){
console.log(error);
resp.end('Error: ' + error);
}
else {
var lambda = apigee.getVariable(request, 'aws.lambda');
var requestPayload = apigee.getVariable(request, 'request.content');
var params = {
FunctionName: lambda,
InvocationType: 'RequestResponse',
LogType: 'Tail',
Payload: requestPayload
};
// Invoke Lambda
lambda.invoke(params, function (err, data) {
if (err) {
resp.end('Error: ' + err);
} else {
resp.end(data.Payload);
}
});
}
});
});
server.listen(9000, function () {
console.log('Node HTTP server is listening');
});
package.json
{
"name": "lambda-sample",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"aws-sdk": "^2.149.0"
}
}
In the request flow add a KVM policy to fetch AWS credentials from a secure KVM.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<KeyValueMapOperations async="false" continueOnError="false" enabled="true" name="KVMFetchAWSConfig" mapIdentifier="aws-config">
<ExpiryTimeInSecs>3600</ExpiryTimeInSecs>
<Get assignTo="aws.accessKeyId">
<Key>
<Parameter>accessKeyId</Parameter>
</Key>
</Get>
<Get assignTo="aws.secretAccessKey">
<Key>
<Parameter>secretAccessKey</Parameter>
</Key>
</Get>
<Get assignTo="aws.region">
<Key>
<Parameter>region</Parameter>
</Key>
</Get>
<Get assignTo="aws.lambda">
<Key>
<Parameter>region</Parameter>
</Key>
</Get>
<Scope>environment</Scope>
</KeyValueMapOperations>
Populate the KVM aws-config with the necessary AWS config.
Some considerations to note:
- The AWS SDK takes care of fetching OAuth access tokens from AWS and refreshing it as required
- The node.js tier can remain thin and just take care of the SDK calls
- Add API security like spike arrest, quota, threat protection policies
- Add caching and any transformation of JSON response using Apigee policies
Benefits
- Apigee serves as the single API platform that can front-end modern cloud backend like AWS Lambda and also allowing you to front-end legacy backend while presenting a consistent API experience to your customers, partners and vendors
- Stay up to date with developments in AWS SDK by consuming it directly
- Leverage Apigee’s Analytics, Security and App lifecycle management capability to simplify API lifecycle