Skip to content

Commit

Permalink
new configuration for ssm
Browse files Browse the repository at this point in the history
- custom object which can be enhanced for kms_key later
- adapted documentation and added example
- allow `ssm:GetParameter`

for spring-media users, this fixes spring-media/terraform-aws-lambda#61 and spring-media/terraform-aws-lambda#59
  • Loading branch information
moritzzimmer committed Aug 28, 2020
1 parent e0eaa9e commit c7cc971
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 21 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![](https://github.com/moritzzimmer/terraform-aws-lambda/workflows/Terraform%20CI/badge.svg) [![Terraform Module Registry](https://img.shields.io/badge/Terraform%20Module%20Registry-5.3.0-blue.svg)](https://registry.terraform.io/modules/moritzzimmer/lambda/aws/5.3.0) ![Terraform Version](https://img.shields.io/badge/Terraform-0.12+-green.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Terraform module to create AWS [Lambda](https://www.terraform.io/docs/providers/aws/r/lambda_function.html) resources with configurable event sources, IAM configuration (following the [principal of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)), VPC as well as SSM/KMS and log streaming support.
Terraform module to create AWS [Lambda](https://www.terraform.io/docs/providers/aws/r/lambda_function.html) resources with configurable event sources, IAM configuration (following the [principal of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)), VPC as well as SSM and log streaming support.

The following [event sources](https://docs.aws.amazon.com/lambda/latest/dg/invoking-lambda-function.html) are supported (see [examples](#examples)):

Expand All @@ -15,7 +15,7 @@ The following [event sources](https://docs.aws.amazon.com/lambda/latest/dg/invok

Furthermore this module supports:

- reading configuration and secrets from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html) including decryption of [SecureString](https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html) parameters
- adding IAM permissions for read access to parameters from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html)
- [CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html) Log group configuration including retention time and [subscription filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html) e.g. to stream logs via Lambda to Elasticsearch

## History
Expand Down Expand Up @@ -79,8 +79,9 @@ module "lambda" {
module "lambda" {
// see above
ssm_parameter_names = ["some/config/root/*"]
kms_key_arn = "arn:aws:kms:eu-west-1:647379381847:key/f79f2b-04684-4ad9-f9de8a-79d72f"
ssm = {
parameter_names = [aws_ssm_parameter.string.name, aws_ssm_parameter.secure_string.name]
}
}
```

Expand All @@ -102,6 +103,7 @@ module "lambda" {
- [example-with-s3-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-s3-event)
- [example-with-sns-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-sns-event)
- [example-with-sqs-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-sqs-event)
- [example-with-ssm-permissions](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-ssm-permissions)
- [example-with-vpc](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-vpc)
- [example-without-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-without-event)

Expand Down Expand Up @@ -154,7 +156,8 @@ MINOR, and PATCH versions on each release to indicate any incompatibilities.
| s3\_key | The S3 key of an object containing the function's deployment package. Conflicts with filename. | `string` | `""` | no |
| s3\_object\_version | The object version containing the function's deployment package. Conflicts with filename. | `string` | `""` | no |
| source\_code\_hash | Used to trigger updates. Must be set to a base64-encoded SHA256 hash of the package file specified with either filename or s3\_key. The usual way to set this is filebase64sha256('file.zip') where 'file.zip' is the local filename of the lambda function source archive. | `string` | `""` | no |
| ssm\_parameter\_names | List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms\_key\_arn needs to be provided as well. | `list` | `[]` | no |
| ssm | List of AWS Systems Manager Parameter Store parameter names. The IAM role of this Lambda function will be enhanced with read permissions for those parameters. Parameters must start with a forward slash and can be encrypted with the default KMS key. | <pre>object({<br> parameter_names = list(string)<br> })</pre> | `null` | no |
| ssm\_parameter\_names | DEPRECATED: use `ssm` object instead. This variable will be removed in version 6 of this module. (List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms\_key\_arn needs to be provided as well.) | `list` | `[]` | no |
| tags | A mapping of tags to assign to the Lambda function. | `map(string)` | `{}` | no |
| timeout | The amount of time your Lambda Function has to run in seconds. Defaults to 3. | `number` | `3` | no |
| vpc\_config | Provide this to allow your function to access your VPC (if both 'subnet\_ids' and 'security\_group\_ids' are empty then vpc\_config is considered to be empty or unset, see https://docs.aws.amazon.com/lambda/latest/dg/vpc.html for details). | <pre>object({<br> security_group_ids = list(string)<br> subnet_ids = list(string)<br> })</pre> | `null` | no |
Expand Down
10 changes: 6 additions & 4 deletions docs/part1.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![](https://github.com/moritzzimmer/terraform-aws-lambda/workflows/Terraform%20CI/badge.svg) [![Terraform Module Registry](https://img.shields.io/badge/Terraform%20Module%20Registry-5.3.0-blue.svg)](https://registry.terraform.io/modules/moritzzimmer/lambda/aws/5.3.0) ![Terraform Version](https://img.shields.io/badge/Terraform-0.12+-green.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Terraform module to create AWS [Lambda](https://www.terraform.io/docs/providers/aws/r/lambda_function.html) resources with configurable event sources, IAM configuration (following the [principal of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)), VPC as well as SSM/KMS and log streaming support.
Terraform module to create AWS [Lambda](https://www.terraform.io/docs/providers/aws/r/lambda_function.html) resources with configurable event sources, IAM configuration (following the [principal of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)), VPC as well as SSM and log streaming support.

The following [event sources](https://docs.aws.amazon.com/lambda/latest/dg/invoking-lambda-function.html) are supported (see [examples](#examples)):

Expand All @@ -15,7 +15,7 @@ The following [event sources](https://docs.aws.amazon.com/lambda/latest/dg/invok

Furthermore this module supports:

- reading configuration and secrets from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html) including decryption of [SecureString](https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html) parameters
- adding IAM permissions for read access to parameters from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html)
- [CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html) Log group configuration including retention time and [subscription filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html) e.g. to stream logs via Lambda to Elasticsearch

## History
Expand Down Expand Up @@ -79,8 +79,9 @@ module "lambda" {
module "lambda" {
// see above
ssm_parameter_names = ["some/config/root/*"]
kms_key_arn = "arn:aws:kms:eu-west-1:647379381847:key/f79f2b-04684-4ad9-f9de8a-79d72f"
ssm = {
parameter_names = [aws_ssm_parameter.string.name, aws_ssm_parameter.secure_string.name]
}
}
```

Expand All @@ -102,6 +103,7 @@ module "lambda" {
- [example-with-s3-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-s3-event)
- [example-with-sns-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-sns-event)
- [example-with-sqs-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-sqs-event)
- [example-with-ssm-permissions](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-ssm-permissions)
- [example-with-vpc](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-with-vpc)
- [example-without-event](https://github.com/moritzzimmer/terraform-aws-lambda/tree/master/examples/example-without-event)

Expand Down
3 changes: 2 additions & 1 deletion docs/part2.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
| s3\_key | The S3 key of an object containing the function's deployment package. Conflicts with filename. | `string` | `""` | no |
| s3\_object\_version | The object version containing the function's deployment package. Conflicts with filename. | `string` | `""` | no |
| source\_code\_hash | Used to trigger updates. Must be set to a base64-encoded SHA256 hash of the package file specified with either filename or s3\_key. The usual way to set this is filebase64sha256('file.zip') where 'file.zip' is the local filename of the lambda function source archive. | `string` | `""` | no |
| ssm\_parameter\_names | List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms\_key\_arn needs to be provided as well. | `list` | `[]` | no |
| ssm | List of AWS Systems Manager Parameter Store parameter names. The IAM role of this Lambda function will be enhanced with read permissions for those parameters. Parameters must start with a forward slash and can be encrypted with the default KMS key. | <pre>object({<br> parameter_names = list(string)<br> })</pre> | `null` | no |
| ssm\_parameter\_names | DEPRECATED: use `ssm` object instead. This variable will be removed in version 6 of this module. (List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms\_key\_arn needs to be provided as well.) | `list` | `[]` | no |
| tags | A mapping of tags to assign to the Lambda function. | `map(string)` | `{}` | no |
| timeout | The amount of time your Lambda Function has to run in seconds. Defaults to 3. | `number` | `3` | no |
| vpc\_config | Provide this to allow your function to access your VPC (if both 'subnet\_ids' and 'security\_group\_ids' are empty then vpc\_config is considered to be empty or unset, see https://docs.aws.amazon.com/lambda/latest/dg/vpc.html for details). | <pre>object({<br> security_group_ids = list(string)<br> subnet_ids = list(string)<br> })</pre> | `null` | no |
Expand Down
15 changes: 15 additions & 0 deletions examples/example-with-ssm-permissions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Example without event

Creates an AWS Lambda function with read permissions to SSM parameters.

## requirements

- [Terraform 0.12+](https://www.terraform.io/)
- authentication configuration for the [aws provider](https://www.terraform.io/docs/providers/aws/)

## usage

```
terraform init
terraform plan
```
33 changes: 33 additions & 0 deletions examples/example-with-ssm-permissions/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
provider "aws" {
region = "eu-west-1"
}

module "source" {
source = "../fixtures"
}

resource "aws_ssm_parameter" "string" {
name = "/example/string"
type = "String"
value = "changeme"
}

resource "aws_ssm_parameter" "secure_string" {
name = "/example/secure.string"
type = "SecureString"
value = "changeme"
}

module "lambda" {
source = "../../"
description = "Example usage for an AWS Lambda with read permissions to SSM parameters."
filename = module.source.output_path
function_name = "example-without-event"
handler = "handler"
runtime = "nodejs12.x"
source_code_hash = module.source.output_base64sha256

ssm = {
parameter_names = [aws_ssm_parameter.string.name, aws_ssm_parameter.secure_string.name]
}
}
4 changes: 4 additions & 0 deletions examples/example-with-ssm-permissions/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

terraform {
required_version = ">= 0.12"
}
2 changes: 1 addition & 1 deletion examples/example-with-vpc/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Example with VPC and CloudWatch scheduled event

Creates an AWS Lambda function inside a VPC triggered by a CloudWatch (scheduled) [event](https://docs.aws.amazon.com/lambda/latest/dg/with-scheduled-events.html).
Creates an AWS Lambda function inside a VPC.

## requirements

Expand Down
38 changes: 34 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,36 @@ resource "aws_cloudwatch_log_subscription_filter" "cloudwatch_logs_to_es" {
distribution = "ByLogStream"
}

data "aws_iam_policy_document" "ssm" {
count = try((var.ssm != null && length(var.ssm.parameter_names) > 0), false) ? 1 : 0

statement {
actions = [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath",
]

resources = formatlist("arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter%s", var.ssm.parameter_names)
}
}

resource "aws_iam_policy" "ssm" {
count = try((var.ssm != null && length(var.ssm.parameter_names) > 0), false) ? 1 : 0

description = "Provides minimum SSM read permissions."
name = "${var.function_name}-ssm-policy-${data.aws_region.current.name}"
policy = data.aws_iam_policy_document.ssm[count.index].json
}

resource "aws_iam_role_policy_attachment" "ssm" {
count = try((var.ssm != null && length(var.ssm.parameter_names) > 0), false) ? 1 : 0

role = module.lambda.role_name
policy_arn = aws_iam_policy.ssm[count.index].arn
}


// Deprecated - will be removed in the next major version
data "aws_iam_policy_document" "ssm_policy_document" {
count = length(var.ssm_parameter_names)
Expand All @@ -134,8 +164,8 @@ data "aws_iam_policy_document" "ssm_policy_document" {
// Deprecated - will be removed in the next major version
resource "aws_iam_policy" "ssm_policy" {
count = length(var.ssm_parameter_names)
name = "${module.lambda.function_name}-ssm-${count.index}-${data.aws_region.current.name}"
description = "Provides minimum Parameter Store permissions for ${module.lambda.function_name}."
name = "${var.function_name}-ssm-${count.index}-${data.aws_region.current.name}"
description = "Provides minimum Parameter Store permissions for ${var.function_name}."
policy = data.aws_iam_policy_document.ssm_policy_document[count.index].json
}

Expand Down Expand Up @@ -165,8 +195,8 @@ data "aws_iam_policy_document" "kms_policy_document" {
resource "aws_iam_policy" "kms_policy" {
count = var.kms_key_arn != "" ? 1 : 0

name = "${module.lambda.function_name}-kms-${data.aws_region.current.name}"
description = "Provides minimum KMS permissions for ${module.lambda.function_name}."
name = "${var.function_name}-kms-${data.aws_region.current.name}"
description = "Provides minimum KMS permissions for ${var.function_name}."
policy = data.aws_iam_policy_document.kms_policy_document[count.index].json
}

Expand Down
20 changes: 14 additions & 6 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ variable "description" {

variable "environment" {
description = "Environment (e.g. env variables) configuration for the Lambda function enable you to dynamically pass settings to your function code and libraries"
default = null
type = object({
variables = map(string)
})
default = null
}

variable "event" {
description = "Event source configuration which triggers the Lambda function. Supported events: cloudwatch-scheduled-event, dynamodb, s3, sns"
type = map(string)
default = {}
type = map(string)
}

variable "filename" {
Expand All @@ -51,8 +51,8 @@ variable "kms_key_arn" {
}

variable "layers" {
default = []
description = "List of Lambda Layer Version ARNs (maximum of 5) to attach to your Lambda Function."
default = []
type = list(string)
}

Expand Down Expand Up @@ -101,15 +101,23 @@ variable "source_code_hash" {
default = ""
}

variable "ssm" {
description = "List of AWS Systems Manager Parameter Store parameter names. The IAM role of this Lambda function will be enhanced with read permissions for those parameters. Parameters must start with a forward slash and can be encrypted with the default KMS key."
default = null
type = object({
parameter_names = list(string)
})
}

variable "ssm_parameter_names" {
description = "List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms_key_arn needs to be provided as well."
description = "DEPRECATED: use `ssm` object instead. This variable will be removed in version 6 of this module. (List of AWS Systems Manager Parameter Store parameters this Lambda will have access to. In order to decrypt secure parameters, a kms_key_arn needs to be provided as well.)"
default = []
}

variable "tags" {
description = "A mapping of tags to assign to the Lambda function."
type = map(string)
default = {}
type = map(string)
}

variable "timeout" {
Expand All @@ -118,8 +126,8 @@ variable "timeout" {
}

variable "vpc_config" {
default = null
description = "Provide this to allow your function to access your VPC (if both 'subnet_ids' and 'security_group_ids' are empty then vpc_config is considered to be empty or unset, see https://docs.aws.amazon.com/lambda/latest/dg/vpc.html for details)."
default = null
type = object({
security_group_ids = list(string)
subnet_ids = list(string)
Expand Down

0 comments on commit c7cc971

Please sign in to comment.