diff --git a/functions.tf b/functions.tf new file mode 100644 index 0000000000000000000000000000000000000000..50d092090a5b95ca007ca3dabef2455f264b8c55 --- /dev/null +++ b/functions.tf @@ -0,0 +1,180 @@ +locals { + function_name_prefix = local.Name + functions = [ + "_dns", + ] +} + +data "aws_iam_policy_document" "lambda_assume_policy" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["lambda.amazonaws.com"] + } + } +} + +locals { + lambda_assume_policy_doc = data.aws_iam_policy_document.lambda_assume_policy.json +} + +resource "aws_iam_role" "lambda" { + name = local.Name + assume_role_policy = local.lambda_assume_policy_doc + tags = local.common_tags +} + +locals { + lambda_role_arn = aws_iam_role.lambda.arn + lambda_role_name = aws_iam_role.lambda.name +} + +output "lambda_role_arn" { + description = "ARN of the Lambda function IAM role." + value = local.lambda_role_arn +} + +output "lambda_role_name" { + description = "Name of the Lambda function IAM role." + value = local.lambda_role_name +} + +locals { + function_role_policies = [ + local.publish_policy_arn, + #local.log_policy_arn, + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ] +} + +resource "aws_iam_role_policy_attachment" "function" { + count = length(local.function_role_policies) + role = local.lambda_role_name + policy_arn = local.function_role_policies[count.index] +} + +variable "runtime" { + default = "python3.8" + description = "The Lambda function runtime." + type = string +} + +output "runtime" { + description = "The Lambda function runtime." + value = var.runtime +} + +variable "memory_size" { + default = 128 + description = "Amount of memory in MB allocated to the function invocation." + type = number +} + +output "memory_size" { + description = "Amount of memory in MB allocated to the function invocation." + value = var.memory_size +} + +variable "timeout" { + default = 30 + description = "Amouyynt of time in seconds the function has to run." + type = number +} + +output "timeout" { + description = "Amount of memory in MB allocated to the function invocation." + value = var.timeout +} + +resource "aws_lambda_function" "function" { + count = length(local.functions) + runtime = var.runtime + function_name = "${local.function_name_prefix}_${local.functions[count.index]}" + role = local.lambda_role_arn + source_code_hash = filebase64sha256("payload.zip") + s3_bucket = local.payloads_bucket_name + s3_key = local.payload_object_name + s3_object_version = local.payload_object_version + package_type = "Zip" + handler = "${local.functions[count.index]}.handler" + description = "${local.module} ${local.functions[count.index]} check in ${local.env}." + memory_size = var.memory_size + tags = local.common_tags + timeout = var.timeout + + environment { + variables = { + ENV = local.env + MODULE = local.module + TOPIC_ARN = local.topic_arn + VERSION = local.payload_object_version + } + } + + # Create the log group with retention before the function is created. + # Otherwise it's created without retention and need to be imported. + depends_on = [ + aws_cloudwatch_log_group.lambda, + ] +} + +locals { + function_arns = aws_lambda_function.function.*.arn + function_names = aws_lambda_function.function.*.id + function_versions = aws_lambda_function.function.*.version +} + +output "function_arns" { + description = "ARNs of the Lambda functions." + value = local.function_arns +} + +output "function_names" { + description = "Names of the Lambda functions." + value = local.function_names +} + +output "function_versions" { + description = "Versions of the Lambda functions." + value = local.function_versions +} + +output "function_version_mapping" { + description = "Mapping of the function and version." + value = zipmap(local.functions, local.function_versions) +} + +resource "aws_lambda_alias" "function" { + count = length(local.functions) + name = "${local.function_name_prefix}_${local.functions[count.index]}" + function_name = local.function_arns[count.index] + function_version = local.function_versions[count.index] +} + +locals { + function_alias_arns = aws_lambda_alias.function.*.arn + function_alias_names = aws_lambda_alias.function.*.name +} + +output "function_alias_arns" { + description = "ARNs of the Lambda functions aliases." + value = local.function_alias_arns +} + +output "function_alias_names" { + description = "Names of the Lambda functions aliases." + value = local.function_alias_names +} + +resource "aws_lambda_permission" "cloudwatch" { + count = length(local.function_arns) + statement_id = "AllowExecutionFromCloudWatch" + action = "lambda:InvokeFunction" + principal = "events.amazonaws.com" + source_arn = local.cloudwatch_rule_arn + function_name = local.function_names[count.index] + qualifier = local.function_alias_names[count.index] +} diff --git a/log-groups.tf b/log-groups.tf new file mode 100644 index 0000000000000000000000000000000000000000..e74ed2647a95f8fda7889f64af380c0797dc553d --- /dev/null +++ b/log-groups.tf @@ -0,0 +1,59 @@ +resource "aws_cloudwatch_log_group" "lambda" { + count = length(local.functions) + name = "/aws/lambda/${local.function_name_prefix}_${local.functions[count.index]}" + retention_in_days = var.log_retention + tags = local.common_tags +} + +locals { + log_group_arns = aws_cloudwatch_log_group.lambda.*.arn + log_group_names = aws_cloudwatch_log_group.lambda.*.name +} + +output "log_group_arns" { + description = "ARNs of the CloudWatch log groups for Lambda function invocations." + value = local.log_group_arns +} + +output "log_group_names" { + description = "Names of the CloudWatch log groups for Lambda function invocations." + value = local.log_group_names +} + +data "aws_iam_policy_document" "log" { + statement { + effect = "Allow" + + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + + resources = [for arn in local.log_group_arns : "${arn}/*"] + } +} + +locals { + log_policy_doc = data.aws_iam_policy_document.log.json +} + +resource "aws_iam_policy" "log" { + name = "${local.module}-${local.env}-log" + policy = local.log_policy_doc + tags = local.common_tags +} + +locals { + log_policy_arn = aws_iam_policy.log.arn + log_policy_name = aws_iam_policy.log.name +} + +output "log_policy_arn" { + value = local.log_policy_arn + description = "CloudWatch log IAM policy ARN." +} + +output "log_policy_name" { + value = local.log_policy_name + description = "CloudWatch log IAM policy name." +} diff --git a/main.tf b/main.tf index e156d2da3eb1b339daa38391dfa86efda8ea5f30..89281085e6d01641e18af3c1ac276f244e92ec48 100644 --- a/main.tf +++ b/main.tf @@ -12,8 +12,72 @@ locals { Name = "${local.module}-${local.env}" } +output "env" { + description = "Environment (prod/dev etc.)." + value = local.env +} + +output "module" { + description = "The name of the Terraform module, used to tagging resources." + value = local.module +} + +variable "region" { + default = "us-east-1" + description = "AWS region." + type = string +} + +output "region" { + description = "AWS region." + value = var.region +} + provider "aws" { region = var.region } -provider "template" {} +resource "aws_resourcegroups_group" "group" { + name = local.Name + tags = local.common_tags + resource_query { + query = <<EOF +{ + "ResourceTypeFilters": [ + "AWS::AllSupported" + ], + "TagFilters": [ + { + "Key": "Module", + "Values": ["${local.module}"] + }, + { + "Key": "Environment", + "Values": ["${local.env}"] + } + ] +} +EOF + } +} + +locals { + resource_group_arn = aws_resourcegroups_group.group.arn + resource_group_name = aws_resourcegroups_group.group.name +} + +output "resource_group_arn" { + description = "ARN of the resource group." + value = local.resource_group_arn +} + +output "resource_group_name" { + description = "Name of the resource group." + value = local.resource_group_name +} + +variable "log_retention" { + default = 3 + description = "Number of days to retain logs." + type = number +} diff --git a/outputs.tf b/outputs.tf deleted file mode 100644 index 13939773a216a404c2939332f1ff578a0f8570d6..0000000000000000000000000000000000000000 --- a/outputs.tf +++ /dev/null @@ -1,14 +0,0 @@ -output "env" { - description = "Environment (prod/dev etc.)." - value = local.env -} - -output "module" { - description = "The name of the Terraform module, used to tagging resources." - value = local.module -} - -output "region" { - description = "AWS region." - value = var.region -} diff --git a/s3.tf b/s3.tf new file mode 100644 index 0000000000000000000000000000000000000000..23aab352a5400c059a6fc2e54668d5e000977e27 --- /dev/null +++ b/s3.tf @@ -0,0 +1,53 @@ +resource "aws_s3_bucket" "payloads" { + bucket = local.Name + tags = local.common_tags + acl = "private" + + versioning { + enabled = true + } +} + +locals { + payloads_bucket_arn = aws_s3_bucket.payloads.arn + payloads_bucket_name = aws_s3_bucket.payloads.bucket +} + +output "payloads_bucket_arn" { + description = "ARN of the payloads S3 bucket." + value = local.payloads_bucket_arn +} + +output "payloads_bucket_name" { + description = "Name of the payloads S3 bucket." + value = local.payloads_bucket_name +} + +resource "aws_s3_bucket_object" "payload" { + bucket = local.payloads_bucket_name + key = "${local.env}/payload.zip" + source = "payload.zip" + etag = filemd5("payload.zip") + tags = local.common_tags +} + +locals { + payload_object_etag = aws_s3_bucket_object.payload.etag + payload_object_name = aws_s3_bucket_object.payload.key + payload_object_version = aws_s3_bucket_object.payload.version_id +} + +output "payload_object_etag" { + description = "ETag of the payload S3 object." + value = local.payload_object_etag +} + +output "payload_object_name" { + description = "Name of the payload S3 object." + value = local.payload_object_name +} + +output "payload_object_version" { + description = "Version of the payload S3 object." + value = local.payload_object_version +} diff --git a/sns.tf b/sns.tf index 6e489495df3c5ec44e8b77290217aec708a15e88..725e2e56dbfd217070759383b159c1cfe987eddb 100644 --- a/sns.tf +++ b/sns.tf @@ -42,17 +42,7 @@ data "aws_iam_policy_document" "publish" { effect = "Allow" actions = [ - "SNS:ListTopics" - ] - - resources = ["*"] - } - - statement { - effect = "Allow" - - actions = [ - "SNS:Publish" + "SNS:Publish", ] resources = [ diff --git a/triggers.tf b/triggers.tf new file mode 100644 index 0000000000000000000000000000000000000000..d35c5c5b1ff4970f2e467152bad84bc4761f16ad --- /dev/null +++ b/triggers.tf @@ -0,0 +1,41 @@ +variable "rate" { + default = 15 + description = "How often in minutes the Lambda functions will trigger." + type = number +} + +output "rate" { + description = "How often in minutes the Lambda functions will trigger." + value = var.rate +} + +resource "aws_cloudwatch_event_rule" "schedule" { + name = local.Name + description = "Schedule to trigger ${local.module} functions in ${local.env}." + schedule_expression = "rate(${var.rate} minutes)" + tags = local.common_tags +} + +locals { + cloudwatch_rule_arn = aws_cloudwatch_event_rule.schedule.arn + cloudwatch_rule_name = aws_cloudwatch_event_rule.schedule.name +} + +output "cloudwatch_rule_arn" { + description = "ARN of the CloudWatch schedule rule." + value = local.cloudwatch_rule_arn +} + +output "cloudwatch_rule_name" { + description = "Name of the CloudWatch schedule rule." + value = local.cloudwatch_rule_name +} + +resource "aws_cloudwatch_event_target" "schedule" { + count = length(local.function_arns) + arn = local.function_alias_arns[count.index] + rule = local.cloudwatch_rule_name + depends_on = [ + aws_lambda_permission.cloudwatch, + ] +} diff --git a/variables.tf b/variables.tf deleted file mode 100644 index d86dca0c21cc789a387837174173aea52841ead1..0000000000000000000000000000000000000000 --- a/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -variable "region" { - default = "us-east-1" - description = "AWS region." -}