Skip to content

Commit

Permalink
Service 9: apigw-lambda-svc (#4)
Browse files Browse the repository at this point in the history
Add apigw-lambda-svc.
  • Loading branch information
mikewrighton authored Apr 29, 2022
1 parent 9fcb061 commit d21c41b
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 97 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ All of the Templates in this directory are set up to work with [AWS Proton Templ
### Running Terraform Using AWS Proton Self-managed Provisioning
If you need an example of how to run your Terraform code, head on over to [this repo](https://github.com/aws-samples/aws-proton-terraform-github-actions-sample) where we offer an example of running Terraform using GitHub Actions.

###Local Development

For local development, the `<template>/dev-resources/` directory contains variable definitions/values which are normally generated
by Proton at provision time:

- `proton.variables.tf`: variable type definitions
- `proton.auto.tfvars.json`: variable value assignments (contains provisioning inputs, environment outputs etc)

To test a template locally, you can create symbolic links to these files in the infrastructure directory. E.g.:

```
cd <template>/vx/<infrastructure>/
ln -s ../../dev-resources/proton.variables.tf .
ln -s ../../dev-resources/proton.auto.tfvars.json .
terraform init
terraform plan
```

Note that you will need to populate `proton.auto.tfvars.json` with the required values according to the template. For
environments, this will typically be the `environment.name` and `environment.inputs` fields.

## Security

See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
Expand Down
Empty file added service-templates/README.md
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"name": "apigw-lambda-svc",
"inputs": {
},
"repository_connection_arn": "arn:aws:codestar-connections:us-east-1:259837135622:connection/2ffbd155-98c8-473d-9bae-c15bfbc2d53d",
"repository_id": "mikewrighton/aws-proton-sample-services",
"branch_name": "main"
"repository_connection_arn": "REPLACE_ME",
"repository_id": "REPLACE_ME",
"branch_name": "REPLACE_ME"
},
"service_instances": [
{
Expand All @@ -20,41 +20,29 @@
"name": "",
"outputs": {}
}
},
{
"name": "instance2",
"inputs": {
},
"outputs": {
},
"environment": {
"account_id": "",
"name": "",
"outputs": {}
}
}
],
"pipeline": {
"inputs": {
"environment_account_ids": "259837135622",
"environment_account_ids": "",
"code_dir": "lambda-ping-sns",
"unit_test_command": "echo 'add your unit test command here'",
"packaging_command": "zip function.zip app.js"
}
},
"environment": {
"outputs": {
"SnsTopicArn": "arn:aws:sns:us-east-1:259837135622:terraform-20220330152010863700000002",
"SnsTopicName": "terraform-20220330152010863700000002"
"SnsTopicArn": "REPLACE_ME",
"SnsTopicName": "REPLACE_ME"
}
},
"service_instance": {
"name": "instance1",
"inputs": {
"lambda_runtime": "nodejs12.x",
"lambda_handler": "app.handler",
"lambda_bucket": "function-bucket20220407174707897600000008",
"lambda_key": "4/function.zip"
"lambda_bucket": "REPLACE_ME",
"lambda_key": "REPLACE_ME"
}
}
}
2 changes: 1 addition & 1 deletion service-templates/apigw-lambda-svc/v1/.compatible-envs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
vpc-ecs-environment:1
vpc-env:1
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ terraform {
}
}

backend "s3" {
region = "us-east-1"
bucket = "terraform-samples-259837135622-apigw-lambda-svc"
key = "instance.tfstate"
}
backend "s3" {}
}

# Configure the AWS Provider
provider "aws" {
region = data.aws_region.current.id
region = var.aws_region
alias = "default"

default_tags {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,46 @@ data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

data "aws_partition" "current" {}
data "aws_partition" "current" {}

data "aws_iam_policy_document" "sns_publish_policy_document" {
statement {
actions = [
"sns:Publish"
]
resources = [
var.environment.outputs.SnsTopicArn
]
}
}

data "archive_file" "lambda_zip_inline" {
type = "zip"
output_path = "lambda_zip_inline.zip"

source {
filename = "index.js"
content = <<EOF
exports.handler = async (event, context) => {
try {
// Log event and context object to CloudWatch Logs
console.log("Event: ", JSON.stringify(event, null, 2));
console.log("Context: ", JSON.stringify(context, null, 2));
// Create event object to return to caller
const eventObj = {
functionName: context.functionName,
rawPath: event.rawPath,
};
const response = {
statusCode: 200,
body: JSON.stringify(eventObj, null, 2),
};
return response;
} catch (error) {
console.error(error);
throw new Error(error);
}
};
EOF
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ resource "aws_apigatewayv2_api" "lambda" {
"POST",
]
}

# target = aws_lambda_function.lambda_function.arn
}

resource "aws_apigatewayv2_stage" "lambda" {
api_id = aws_apigatewayv2_api.lambda.id

name = "serverless_lambda_stage"
name = "${var.service.name}-${var.service_instance.name}-stage"
auto_deploy = true

access_log_settings {
Expand Down Expand Up @@ -45,7 +42,7 @@ resource "aws_cloudwatch_log_group" "api_gw" {
}

resource "aws_lambda_function" "lambda_function" {
function_name = "${var.service_instance.name}-function"
function_name = "${var.service.name}-${var.service_instance.name}-function"
runtime = var.service_instance.inputs.lambda_runtime
role = aws_iam_role.lambda_exec.arn

Expand Down Expand Up @@ -86,7 +83,7 @@ resource "aws_lambda_permission" "api_gw" {
}

resource "aws_iam_role" "lambda_exec" {
name = "serverless_lambda"
name_prefix = "serverless_lambda"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Expand Down Expand Up @@ -115,45 +112,3 @@ resource "aws_iam_role_policy_attachment" "ssn_publish_policy" {
resource "aws_iam_policy" "sns_publish_policy" {
policy = data.aws_iam_policy_document.sns_publish_policy_document.json
}

data "aws_iam_policy_document" "sns_publish_policy_document" {
statement {
actions = [
"sns:Publish"
]
resources = [
var.environment.outputs.SnsTopicArn
]
}
}

data "archive_file" "lambda_zip_inline" {
type = "zip"
output_path = "lambda_zip_inline.zip"

source {
filename = "index.js"
content = <<EOF
exports.handler = async (event, context) => {
try {
// Log event and context object to CloudWatch Logs
console.log("Event: ", JSON.stringify(event, null, 2));
console.log("Context: ", JSON.stringify(context, null, 2));
// Create event object to return to caller
const eventObj = {
functionName: context.functionName,
rawPath: event.rawPath,
};
const response = {
statusCode: 200,
body: JSON.stringify(eventObj, null, 2),
};
return response;
} catch (error) {
console.error(error);
throw new Error(error);
}
};
EOF
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ terraform {
}
}

backend "s3" {
region = "us-east-1"
bucket = "terraform-samples-259837135622-apigw-lambda-svc"
key = "pipeline.tfstate"
}
backend "s3" {}
}

# Configure the AWS Provider
provider "aws" {
region = data.aws_region.current.id
region = var.aws_region
alias = "default"

default_tags {
Expand All @@ -28,4 +24,4 @@ provider "aws" {
variable "aws_region" {
type = string
default = "us-east-1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,25 @@ data "aws_iam_policy_document" "publish_role_policy_document" {
"s3:Abort*"
]
}
statement {
effect = "Allow"
resources = [aws_kms_key.pipeline_artifacts_bucket_key.arn]
actions = [
"kms:Decrypt",
"kms:DescribeKey",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*"
]
}
}

data "aws_iam_policy_document" "deployment_role_policy" {
statement {
effect = "Allow"
resources = [
"arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/codebuild/Deploy*Project*",
"arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/codebuild/Deploy*Project:*",
"arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/codebuild/deploy-*",
"arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/codebuild/deploy-:*",
]
actions = [
"logs:CreateLogGroup",
Expand All @@ -99,7 +110,7 @@ data "aws_iam_policy_document" "deployment_role_policy" {
statement {
effect = "Allow"
resources = [
"arn:aws:codebuild:${local.region}:${local.account_id}:report-group:/Deploy*Project-*",
"arn:aws:codebuild:${local.region}:${local.account_id}:report-group:/deploy-*",
]
actions = [
"codebuild:CreateReportGroup",
Expand Down Expand Up @@ -204,7 +215,6 @@ data "aws_iam_policy_document" "pipeline_artifacts_bucket_key_policy" {
effect = "Allow"
resources = ["*"]
principals {
#todo -
identifiers = [aws_iam_role.deployment_role.arn]
type = "AWS"
}
Expand Down Expand Up @@ -287,7 +297,7 @@ data "aws_iam_policy_document" "pipeline_build_codepipeline_action_role_policy"
data "aws_iam_policy_document" "pipeline_deploy_codepipeline_action_role_policy" {
statement {
effect = "Allow"
resources = ["arn:aws:codebuild:${local.region}:${local.account_id}:project/Deploy*", ]
resources = ["arn:aws:codebuild:${local.region}:${local.account_id}:project/deploy-*"]
actions = [
"codebuild:BatchGetBuilds",
"codebuild:StartBuild",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "aes256" {
}

resource "aws_s3_bucket_policy" "function_bucket_policy" {
count = var.pipeline.inputs.environment_account_ids != "" ? 1 : 0
policy = data.aws_iam_policy_document.function_bucket_policy_document.json
bucket = aws_s3_bucket.function_bucket.id
}
Expand Down Expand Up @@ -81,8 +82,8 @@ resource "aws_codebuild_project" "build_project" {
"post_build": {
"commands": [
"aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml",
"yq w service.yaml 'instances[*].spec.lambda_bucket' \"$bucket_name\" > rendered_service.yaml",
"yq w service.yaml 'instances[*].spec.lambda_key' \"$FUNCTION_KEY\" > rendered_service.yaml"
"yq w service.yaml 'instances[*].spec.lambda_bucket' \"$bucket_name\" > rendered_service_tmp.yaml",
"yq w rendered_service_tmp.yaml 'instances[*].spec.lambda_key' \"$FUNCTION_KEY\" > rendered_service.yaml"
]
}
},
Expand All @@ -103,8 +104,7 @@ encryption_key = aws_kms_key.pipeline_artifacts_bucket_key.arn

resource "aws_codebuild_project" "deploy_project" {
for_each = { for instance in var.service_instances : instance.name => instance }

name = "Deploy${index(var.service_instances, each.value)}Project"
name = "deploy-${var.service.name}-${index(var.service_instances, each.value)}"
service_role = aws_iam_role.deployment_role.arn

artifacts {
Expand Down Expand Up @@ -138,6 +138,8 @@ resource "aws_codebuild_project" "deploy_project" {
"build": {
"commands": [
"pip3 install --upgrade --user awscli",
"echo 'rendered_service.yaml':",
"cat ${var.pipeline.inputs.code_dir}/rendered_service.yaml",
"aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://${var.pipeline.inputs.code_dir}/rendered_service.yaml",
"aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name"
]
Expand Down Expand Up @@ -268,7 +270,7 @@ resource "aws_codepipeline" "pipeline" {
name = "Source"
action {
category = "Source"
name = "Source"
name = "Checkout"
owner = "AWS"
provider = "CodeStarSourceConnection"
version = "1"
Expand Down Expand Up @@ -306,18 +308,18 @@ resource "aws_codepipeline" "pipeline" {
for_each = toset(var.service_instances)

content {
name = "Deploy${index(var.service_instances, stage.value)}Project"
name = "deploy-${var.service.name}-${index(var.service_instances, stage.value)}"

action {
category = "Build"
name = "Deploy${index(var.service_instances, stage.value)}"
name = "deploy-${var.service.name}-${index(var.service_instances, stage.value)}"
owner = "AWS"
provider = "CodeBuild"
version = "1"
run_order = 1

configuration = {
ProjectName = "Deploy${index(var.service_instances, stage.value)}Project"
ProjectName = "deploy-${var.service.name}-${index(var.service_instances, stage.value)}"
}
input_artifacts = ["BuildOutput"]
role_arn = aws_iam_role.pipeline_deploy_codepipeline_action_role.arn
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
output "pipeline_endpoint" {
output "PipelineEndpoint" {
value = "https://${local.region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${aws_codepipeline.pipeline.id}/view?region=${local.region}"
}

0 comments on commit d21c41b

Please sign in to comment.