Skip to content

Commit e02ad06

Browse files
committed
Merge branch 'develop'
2 parents 2acdcc1 + 305d445 commit e02ad06

File tree

6 files changed

+164
-98
lines changed

6 files changed

+164
-98
lines changed

CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# terraform-aws-certbot-cloudflare-lambda Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6+
7+
## [2.0.0] - 2019-05-27
8+
9+
- update for HCL2 in Terraform versions > 0.12
10+
- constrain AWS provider for terraform 0.12 version >= 2.12
11+
- added CHANGELOG.md
12+
13+
## [1.1.4] - 2019-05-27
14+
15+
- Update base layer for new Lambda runtime environment
16+
17+
## [1.1.3] - 2019-05-08
18+
19+
- Documentation Adjustments
20+
21+
## [1.1.2] - 2019-04-12
22+
23+
- constrain AWS provider to versions >= 2.0
24+
- necessary due to [attribute values swap](https://www.terraform.io/docs/providers/aws/guides/version-2-upgrade.html#arn-and-layer_arn-attribute-value-swap) in versiions >= 2.0
25+
26+
## [1.1.1] - 2019-03-30
27+
28+
- update README.md
29+
30+
## [1.1.0] - 2019-03-30
31+
32+
- Add Terraform Major version pinning and aws region
33+
34+
## [1.0.0] - 2019-03-30
35+
36+
- Initial Release
37+
38+
[2.0.0]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.1.4...2.0.0
39+
[1.1.4]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.1.3...1.1.4
40+
[1.1.3]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.1.2...1.1.3
41+
[1.1.2]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.1.1...1.1.2
42+
[1.1.1]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.1.0...1.1.1
43+
[1.1.0]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/compare/1.0.0...1.1.0
44+
[1.0.0]: https://github.com/robertpeteuil/terraform-aws-certbot-cloudflare-lambda/tree/1.0.0

README.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@
44

55
`terraform-aws-certbot-cloudflare-lambda` is a Terraform module to provision a Lambda Function which obtains & renews LetsEncrypt Certificates for domains using Cloudflare DNS.
66

7+
- *For Terraform versions > = 0.12, use module `version >= "2.0.0"`*
8+
- for Terraform versions < 0.12, use module `version = "1.1.4"`
9+
710
## Terraform Module Features
811

912
This Module allows simple and rapid deployment
1013

1114
- Creates Lambda function, Lambda Layer, IAM Policies, Triggers, and Subscriptions
12-
- Uses specified S3 Bucket/Key for encrypted storage of Cloudflare API credentials and retrieved SSL Certificates.
13-
- Create CloudWatch Event to trigger function to renew certificates
15+
- note: Terraform moduel doees _not_ trigger the function
16+
- Uses specified S3 Bucket/Key for encrypted storage of
17+
- Cloudflare API credentials
18+
- Retrieved SSL Certificates
19+
- Creates CloudWatch Event to trigger function to renew certificates
1420
- Python function editable in repository and in Lambda UI
1521
- Python dependencies packaged in Lambda Layers zip
1622
- Optionally create custom Lambda Layer zip using [build-lambda-layer-python](https://github.com/robertpeteuil/build-lambda-layer-python)
@@ -42,22 +48,23 @@ Using the Module with optional `cloudflare` params to generate and upload Cloudf
4248
``` ruby
4349
module "certbot_example" {
4450
source = "robertpeteuil/certbot-cloudflare-lambda/aws"
45-
version = "1.1.3"
51+
version = "2.0.0" # HCL2 support - requires Terraform >= 0.12
52+
# version = "1.1.4" # Latest version for Terraform < 0.12
4653

4754
aws_region = "us-west-2"
4855
letsencrypt_domains = "example.com,www.example.com"
4956
letsencrypt_email = "me@example.com"
5057
s3_bucket = "projectx"
5158
s3_path = "certs"
5259

53-
# if specified, terraform will create and store cloudflare credentials file
54-
# alternatively, the file can be manually created as specified below
60+
# OPTIONAL: Terraform creates cloudflare credentials file and stores on S3
61+
# Alternatively, the credentials file can be manually created as specified below
5562
cloudflare_api_key = "key-654654a54c465c87d87f87fg6"
5663
cloudflare_email = "mycloudflareemail@domain.com"
5764
}
5865
```
5966

60-
The Cloudflare Credentials file can be manually created as a text file in the format below and uploaded to the location: `$s3_bucket/$s3_path/dns/cloudflare.ini`
67+
The Cloudflare credentials file can be created manually in the format below and uploaded to the location: `$s3_bucket/$s3_path/dns/cloudflare.ini`
6168

6269
``` ini
6370
dns_cloudflare_email = mycloudflareemail@domain.com

main.tf

Lines changed: 74 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@
22
# AWS LAMBDA CERTBOT FOR CLOUDFLARE DOMAINS
33
# -----------------------------------------------------------------
44

5-
terraform {
6-
required_version = "~> 0.11.11"
7-
}
8-
95
provider "aws" {
10-
region = "${var.aws_region}"
11-
12-
version = "~> 2.0"
6+
region = var.aws_region
7+
version = ">= 2.12"
138
}
149

1510
# Create random two digit number suffix (used to prevent duplicate names)
1611
resource "random_integer" "id" {
1712
keepers = {
1813
# generate new ID when value of domains changes
19-
domains = "${var.letsencrypt_domains}"
14+
domains = var.letsencrypt_domains
2015
}
2116

2217
min = 1000
@@ -28,22 +23,23 @@ resource "random_integer" "id" {
2823
# -----------------------------------------------------------------
2924

3025
data "template_file" "cloudflare_ini" {
31-
count = "${length(var.cloudflare_api_key) > 0 ? length(var.cloudflare_email) > 0 ? 1 : 0 : 0}"
26+
count = length(var.cloudflare_api_key) > 0 ? length(var.cloudflare_email) > 0 ? 1 : 0 : 0
3227

33-
template = "${file("templates/cloudflare_ini.tmpl")}"
28+
template = file("templates/cloudflare_ini.tmpl")
3429

3530
vars = {
36-
cloudflare_email = "${var.cloudflare_email}"
37-
cloudflare_api_key = "${var.cloudflare_api_key}"
31+
cloudflare_email = var.cloudflare_email
32+
cloudflare_api_key = var.cloudflare_api_key
3833
}
3934
}
4035

4136
resource "aws_s3_bucket_object" "cloudflare_ini" {
42-
count = "${length(var.cloudflare_api_key) > 0 ? length(var.cloudflare_email) > 0 ? 1 : 0 : 0}"
37+
count = length(var.cloudflare_api_key) > 0 ? length(var.cloudflare_email) > 0 ? 1 : 0 : 0
4338

44-
bucket = "${var.s3_bucket}"
45-
key = "${var.s3_path}/dns/cloudflare.ini"
46-
content = "${join("", data.template_file.cloudflare_ini.*.rendered)}"
39+
bucket = var.s3_bucket
40+
key = "${var.s3_path}/dns/cloudflare.ini"
41+
# content = join("", data.template_file.cloudflare_ini.*.rendered)
42+
content = data.template_file.cloudflare_ini[0].rendered
4743
server_side_encryption = "AES256"
4844
}
4945

@@ -53,12 +49,12 @@ resource "aws_s3_bucket_object" "cloudflare_ini" {
5349

5450
resource "aws_lambda_layer_version" "certbot_base" {
5551
filename = "${path.root}/base_${var.lambda_runtime}.zip"
56-
source_code_hash = "${base64sha256(file("${path.root}/base_${var.lambda_runtime}.zip"))}"
52+
source_code_hash = filebase64sha256("${path.root}/base_${var.lambda_runtime}.zip")
5753

58-
layer_name = "certbot-cloudflare-base-${replace(var.lambda_runtime,".","")}"
54+
layer_name = "certbot-cloudflare-base-${replace(var.lambda_runtime, ".", "")}"
5955
description = "certbot with cloudflare dns plugin"
6056

61-
compatible_runtimes = ["${var.lambda_runtime}"]
57+
compatible_runtimes = [var.lambda_runtime]
6258
}
6359

6460
# -----------------------------------------------------------------
@@ -74,31 +70,31 @@ data "archive_file" "lambda_function" {
7470

7571
# create lambda using function only zip on top of base layer
7672
resource "aws_lambda_function" "certbot_cloudflare" {
77-
layers = ["${aws_lambda_layer_version.certbot_base.arn}"]
73+
layers = [aws_lambda_layer_version.certbot_base.arn]
7874

7975
filename = "${path.root}/lambda.zip"
80-
source_code_hash = "${data.archive_file.lambda_function.output_base64sha256}"
76+
source_code_hash = data.archive_file.lambda_function.output_base64sha256
8177

8278
function_name = "${var.lambda_func_name}-${random_integer.id.result}"
8379
description = "${var.lambda_description}: ${var.letsencrypt_domains}"
8480

85-
publish = "${var.lambda_publish_func ? 1 : 0}"
86-
role = "${aws_iam_role.lambda_new_funct.arn}"
87-
runtime = "${var.lambda_runtime}"
81+
publish = var.lambda_publish_func ? true : false
82+
role = aws_iam_role.lambda_new_funct.arn
83+
runtime = var.lambda_runtime
8884
handler = "certbot_cloudflare.main"
89-
timeout = "${var.lambda_timeout}"
90-
memory_size = "${var.lambda_mem_size}"
85+
timeout = var.lambda_timeout
86+
memory_size = var.lambda_mem_size
9187

92-
tags = "${var.lambda_tags}"
88+
tags = var.lambda_tags
9389

9490
environment {
9591
variables = {
96-
letsencrypt_domains = "${var.letsencrypt_domains}"
97-
letsencrypt_email = "${var.letsencrypt_email}"
98-
s3_bucket = "${var.s3_bucket}"
99-
s3_path = "${var.s3_path}"
100-
test_cert = "${var.get_test_cert}"
101-
sns_topic_arn = "${length(var.sns_topic) > 0 ? join("", data.aws_sns_topic.sns_log_topic.*.arn) : ""}"
92+
letsencrypt_domains = var.letsencrypt_domains
93+
letsencrypt_email = var.letsencrypt_email
94+
s3_bucket = var.s3_bucket
95+
s3_path = var.s3_path
96+
test_cert = var.get_test_cert
97+
sns_topic_arn = length(var.sns_topic) > 0 ? data.aws_sns_topic.sns_log_topic[0].arn : ""
10298
}
10399
}
104100
}
@@ -110,22 +106,22 @@ resource "aws_lambda_function" "certbot_cloudflare" {
110106
# Create base IAM role
111107
resource "aws_iam_role" "lambda_new_funct" {
112108
name = "lambda-${lower(var.lambda_func_name)}-${random_integer.id.result}"
113-
assume_role_policy = "${data.aws_iam_policy_document.lambda_new_funct.json}"
109+
assume_role_policy = data.aws_iam_policy_document.lambda_new_funct.json
114110
}
115111

116112
# Add policy enabling access to other AWS services
117113
resource "aws_iam_role_policy" "lambda_new_funct_polcy" {
118114
name = "lambda-${lower(var.lambda_func_name)}-policy-${random_integer.id.result}"
119-
role = "${aws_iam_role.lambda_new_funct.id}"
120-
policy = "${length(var.sns_topic) > 0 ? join("", data.aws_iam_policy_document.lambda_new_funct_policy_sns.*.json) : join("", data.aws_iam_policy_document.lambda_new_funct_policy.*.json)}"
115+
role = aws_iam_role.lambda_new_funct.id
116+
policy = length(var.sns_topic) > 0 ? data.aws_iam_policy_document.lambda_new_funct_policy_sns[0].json : data.aws_iam_policy_document.lambda_new_funct_policy[0].json
121117
}
122118

123119
# JSON POLICY - assume role
124120
data "aws_iam_policy_document" "lambda_new_funct" {
125121
statement {
126122
actions = ["sts:AssumeRole"]
127123

128-
principals = {
124+
principals {
129125
type = "Service"
130126
identifiers = ["lambda.amazonaws.com"]
131127
}
@@ -134,7 +130,7 @@ data "aws_iam_policy_document" "lambda_new_funct" {
134130

135131
# JSON POLICY - Logs and S3 only (no SNS)
136132
data "aws_iam_policy_document" "lambda_new_funct_policy" {
137-
count = "${length(var.sns_topic) > 0 ? 0 : 1}"
133+
count = length(var.sns_topic) > 0 ? 0 : 1
138134

139135
statement {
140136
actions = [
@@ -166,13 +162,13 @@ data "aws_iam_policy_document" "lambda_new_funct_policy" {
166162

167163
# find sns topic arn, if specified (used by JSON policy)
168164
data "aws_sns_topic" "sns_log_topic" {
169-
count = "${length(var.sns_topic) > 0 ? 1 : 0}"
170-
name = "${var.sns_topic}"
165+
count = length(var.sns_topic) > 0 ? 1 : 0
166+
name = var.sns_topic
171167
}
172168

173169
# JSON POLICY - Logs, S3 and SNS
174170
data "aws_iam_policy_document" "lambda_new_funct_policy_sns" {
175-
count = "${length(var.sns_topic) > 0 ? 1 : 0}"
171+
count = length(var.sns_topic) > 0 ? 1 : 0
176172

177173
statement {
178174
actions = [
@@ -190,7 +186,7 @@ data "aws_iam_policy_document" "lambda_new_funct_policy_sns" {
190186
"sns:Publish",
191187
]
192188

193-
resources = ["${join("", data.aws_sns_topic.sns_log_topic.*.arn)}"]
189+
resources = [data.aws_sns_topic.sns_log_topic[0].arn]
194190
}
195191

196192
statement {
@@ -216,7 +212,7 @@ data "aws_iam_policy_document" "lambda_new_funct_policy_sns" {
216212

217213
# create cloudwatch event to run every 15 days
218214
resource "aws_cloudwatch_event_rule" "sched" {
219-
count = "${var.create_sched_event ? 1 : 0}"
215+
count = var.create_sched_event ? 1 : 0
220216

221217
name = "cert_renewal-${random_integer.id.result}"
222218
description = "Trigger cert renewal via ${var.lambda_func_name}"
@@ -225,11 +221,11 @@ resource "aws_cloudwatch_event_rule" "sched" {
225221

226222
# set event target as certbot_cloudflare lambda function
227223
resource "aws_cloudwatch_event_target" "sched" {
228-
count = "${var.create_sched_event ? 1 : 0}"
224+
count = var.create_sched_event ? 1 : 0
229225

230-
rule = "${aws_cloudwatch_event_rule.sched.name}"
226+
rule = aws_cloudwatch_event_rule.sched[0].name
231227
target_id = "Lambda"
232-
arn = "${var.lambda_publish_func ? aws_lambda_function.certbot_cloudflare.qualified_arn : aws_lambda_function.certbot_cloudflare.arn}"
228+
arn = var.lambda_publish_func ? aws_lambda_function.certbot_cloudflare.qualified_arn : aws_lambda_function.certbot_cloudflare.arn
233229

234230
input = <<JSON
235231
{
@@ -238,6 +234,7 @@ resource "aws_cloudwatch_event_target" "sched" {
238234
}]
239235
}
240236
JSON
237+
241238
}
242239

243240
# -----------------------------------------------------------------
@@ -246,24 +243,35 @@ JSON
246243
# -----------------------------------------------------------------
247244

248245
# function published - "qualifier" parameter set to function version
249-
resource "aws_lambda_permission" "sched_published" {
250-
count = "${var.create_sched_event ? var.lambda_publish_func ? 1 : 0 : 0}"
251-
252-
statement_id = "AllowExecutionFromCloudWatch"
253-
action = "lambda:InvokeFunction"
254-
function_name = "${aws_lambda_function.certbot_cloudflare.function_name}"
255-
principal = "events.amazonaws.com"
256-
source_arn = "${aws_cloudwatch_event_rule.sched.arn}"
257-
qualifier = "${aws_lambda_function.certbot_cloudflare.version}"
258-
}
259-
260-
# function not published - "qualifier" parameter not be set
261-
resource "aws_lambda_permission" "sched" {
262-
count = "${var.create_sched_event ? var.lambda_publish_func ? 0 : 1 : 0}"
263-
264-
statement_id = "AllowExecutionFromCloudWatch"
265-
action = "lambda:InvokeFunction"
266-
function_name = "${aws_lambda_function.certbot_cloudflare.function_name}"
267-
principal = "events.amazonaws.com"
268-
source_arn = "${aws_cloudwatch_event_rule.sched.arn}"
246+
# resource "aws_lambda_permission" "sched_published" {
247+
# count = var.create_sched_event ? var.lambda_publish_func ? 1 : 0 : 0
248+
249+
# statement_id = "AllowExecutionFromCloudWatch"
250+
# action = "lambda:InvokeFunction"
251+
# function_name = aws_lambda_function.certbot_cloudflare.function_name
252+
# principal = "events.amazonaws.com"
253+
# source_arn = aws_cloudwatch_event_rule.sched[0].arn
254+
# qualifier = aws_lambda_function.certbot_cloudflare.version
255+
# }
256+
257+
# # function not published - "qualifier" parameter not be set
258+
# resource "aws_lambda_permission" "sched" {
259+
# count = var.create_sched_event ? var.lambda_publish_func ? 0 : 1 : 0
260+
261+
# statement_id = "AllowExecutionFromCloudWatch"
262+
# action = "lambda:InvokeFunction"
263+
# function_name = aws_lambda_function.certbot_cloudflare.function_name
264+
# principal = "events.amazonaws.com"
265+
# source_arn = aws_cloudwatch_event_rule.sched[0].arn
266+
# }
267+
268+
resource "aws_lambda_permission" "sched_multi" {
269+
count = var.create_sched_event ? 1 : 0
270+
271+
statement_id = "AllowExecutionFromCloudWatch"
272+
action = "lambda:InvokeFunction"
273+
function_name = aws_lambda_function.certbot_cloudflare.function_name
274+
principal = "events.amazonaws.com"
275+
source_arn = aws_cloudwatch_event_rule.sched[0].arn
276+
qualifier = var.lambda_publish_func ? aws_lambda_function.certbot_cloudflare.version : null
269277
}

0 commit comments

Comments
 (0)