From 58de36beb06a2c0ed96735b51454243b795539cc Mon Sep 17 00:00:00 2001 From: Gregory Campbell Date: Mon, 22 Nov 2021 23:21:52 -0500 Subject: [PATCH] Created basic RESTapi to work with aws --- index.js | 69 +++++++++++++++++++++ stack.yaml | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 index.js create mode 100644 stack.yaml diff --git a/index.js b/index.js new file mode 100644 index 0000000..1f84b22 --- /dev/null +++ b/index.js @@ -0,0 +1,69 @@ +"use strict"; + +var AWS = require('aws-sdk'); + +// Get "Hello" Dynamo table name. Replace DEFAULT_VALUE +// with the actual table name from your stack. +const helloDBArn = process.env['HELLO_DB'] || 'DEFAULT_VALUE'; //'Mark-HelloTable-1234567'; +const helloDBArnArr = helloDBArn.split('/'); +const helloTableName = helloDBArnArr[helloDBArnArr.length - 1]; + +// handleHttpRequest is the entry point for Lambda requests +exports.handleHttpRequest = function(request, context, done) { + try { + const userId = request.pathParameters.userId; + let response = { + headers: {}, + body: '', + statusCode: 200 + }; + + switch (request.httpMethod) { + case 'GET': { + console.log('GET'); + let dynamo = new AWS.DynamoDB(); + var params = { + TableName: helloTableName, + Key: { 'user_id' : { S: userId } }, + ProjectionExpression: 'email' + }; + // Call DynamoDB to read the item from the table + dynamo.getItem(params, function(err, data) { + if (err) { + console.log("Error", err); + throw `Dynamo Get Error (${err})` + } else if (data.Item) { + console.log("Success", data.Item.email); + response.body = JSON.stringify({ "email": data.Item.email.S }); + done(null, response); + } else { + console.log("Not found id=", userId); + response.body = "Not found" + response.statusCode = 404 + done(null, response); + } + }); + break; + } + case 'POST': { + console.log('POST'); + let bodyJSON = JSON.parse(request.body || '{}'); + let dynamo = new AWS.DynamoDB(); + let params = { + TableName: helloTableName, + Item: { + 'user_id': { S: userId }, + 'email': { S: bodyJSON['email'] } + } + }; + dynamo.putItem(params, function(error, data) { + if (error) throw `Dynamo Error (${error})`; + else done(null, response); + }) + break; + } + } + } catch (e) { + done(e, null); + } +} \ No newline at end of file diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..33e6e62 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,171 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 + +Description: API Gateway, Lambda, and Dynamo. + +Resources: + # Policy required for all lambda function roles. + BaseLambdaExecutionPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + Description: Base permissions needed by all lambda functions. + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - ec2:CreateNetworkInterface + - ec2:DescribeNetworkInterfaces + - ec2:DeleteNetworkInterface + Resource: "*" + + HelloTable: + Type: AWS::DynamoDB::Table + Properties: + ProvisionedThroughput: + ReadCapacityUnits: 5 + WriteCapacityUnits: 5 + AttributeDefinitions: + - AttributeName: user_id + AttributeType: S + KeySchema: + - AttributeName: user_id + KeyType: HASH + + # FIXME How to hook up custom domain? + MyApiGateway: + Type: AWS::ApiGateway::RestApi + Properties: + Name: !Sub "${AWS::StackName}-MyApiGateway" + Description: A description + FailOnWarnings: true + Body: + swagger: 2.0 + info: + description: | + The account API. + version: 1.0 + basePath: / + schemes: + - https + consumes: + - application/json + produces: + - application/json + paths: + /users/{userId}/hello: + get: + description: TBD + x-amazon-apigateway-integration: + uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations" + credentials: !GetAtt MyApiGatewayRole.Arn + passthroughBehavior: when_no_match + httpMethod: POST + type: aws_proxy + operationId: getHello + parameters: + - name: userId + in: path + description: TBD + required: true + type: string + format: uuid + post: + description: TBD + x-amazon-apigateway-integration: + uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations" + credentials: !GetAtt MyApiGatewayRole.Arn + passthroughBehavior: when_no_match + httpMethod: POST + type: aws_proxy + operationId: postHello + parameters: + - name: userId + in: path + description: TBD + required: true + type: string + format: uuid + - name: body + in: body + description: TBD + required: true + schema: + type: object + required: + - email + properties: + email: + type: string + + MyApiGatewayDeployment: + Type: AWS::ApiGateway::Deployment + Properties: + RestApiId: !Ref MyApiGateway + StageName: prod + + MyApiGatewayRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: apigateway.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: InvokeLambda + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - lambda:InvokeFunction + Resource: + - !GetAtt HelloLambda.Arn + + HelloLambda: + Type: AWS::Lambda::Function + Properties: + Role: !GetAtt HelloLambdaRole.Arn # TODO + Handler: index.handleHttpRequest + Runtime: nodejs12.x + Environment: + Variables: + HELLO_DB: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}" + Code: + ZipFile: | + exports.handlers = function(event, context) {} + HelloLambdaRole: # -> AppAPIRole + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Ref BaseLambdaExecutionPolicy + Policies: + - PolicyName: getHello + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}" + - PolicyName: putHello + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:PutItem + Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}" \ No newline at end of file