unfunco/terraform-aws-contact-form

GitHub: unfunco/terraform-aws-contact-form

这是一个基于 Terraform 的 AWS 无服务器联系表单模块,集成了 Lambda、CloudFront、SES 和 WAF 以实现安全部署和邮件通知。

Stars: 0 | Forks: 0

# AWS 联系表单 Terraform Module [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/16d2b1e0da094851.svg)](https://github.com/unfunco/terraform-aws-contact-form/actions/workflows/ci.yaml) [![Terraform Registry](https://img.shields.io/badge/Terraform%20Registry-unfunco%2Fcontact--form-blue?logo=terraform)](https://registry.terraform.io/modules/unfunco/contact-form/aws) [![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](LICENSE.md) 一个用于 AWS Lambda 联系表单端点的 Terraform 模块,前端使用 CloudFront 并由 AWS WAF 保护。 ## 入门指南 ### 要求 - [Terraform] 1.14+ ### 安装和使用 请参阅 [`examples/minimal`](./examples/minimal) 了解最小的可部署设置, 或参阅 [`examples/static-website`](./examples/static-website) 以通过 `unfunco/static-website/aws` 路由提交内容。 #### 最小化示例 ``` provider "aws" { region = "eu-west-2" } module "contact_form" { source = "unfunco/contact-form/aws" version = "0.2.0" email_recipients = ["hello@example.com"] ses_source_email = "no-reply@example.com" } output "contact_form_url" { value = module.contact_form.endpoint_url } ``` ```
``` #### 位于 `unfunco/static-website/aws` 之后 ``` module "contact_form" { source = "unfunco/contact-form/aws" version = "0.2.0" name = "unfunco-contact-form" create_cloudfront_distribution = false allow_all_cloudfront_distributions = true cors_allow_origins = [ "https://unfun.co", "https://www.unfun.co", ] email_recipients = ["hello@unfun.co"] ses_source_email = "no-reply@unfun.co" } ``` ``` module "unfunco_website" { source = "unfunco/static-website/aws" version = "0.5.0" domain_name = "unfun.co" cloudfront_web_acl_id = module.contact_form.waf_web_acl_arn cloudfront_additional_origins = { contact_form = { domain_name = module.contact_form.cloudfront_origin_domain_name origin_access_control_id = module.contact_form.cloudfront_origin_access_control_id } } cloudfront_ordered_cache_behaviors = [ { path_pattern = "/contact" allowed_methods = ["OPTIONS", "POST"] cached_methods = ["OPTIONS"] cache_policy_id = module.contact_form.cloudfront_cache_policy_id origin_request_policy_id = module.contact_form.cloudfront_origin_request_policy_id target_origin_id = "contact_form" }, ] } ``` ``` curl -X POST https://<> \ -H 'content-type: application/json' \ -d '{"name":"Alice Example","email":"alice@example.com","message":"Hello"}' ``` 成功的提交将返回带有 JSON 确认消息的 `200 OK`。 验证失败将返回描述问题的 JSON `4xx` 响应。 默认情况下,Lambda 预留 5 个并发执行,并拒绝解码后超过 16 KiB 的请求正文、 超过 10 个字段的提交,或任何长度超过 2,000 个字符的字段值。 ### 资源 | 名称 | 类型 | | ---- | ---- | | [aws_cloudfront_distribution.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution) | resource | | [aws_cloudfront_origin_access_control.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_control) | resource | | [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_function_url.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function_url) | resource | | [aws_lambda_permission.function_url_cloudfront_any](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_cloudfront_any_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_cloudfront_managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_cloudfront_managed_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_cloudfront_trusted](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_cloudfront_trusted_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.function_url_public_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_ssm_parameter.email_recipients](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_wafv2_web_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource | | [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_cloudfront_cache_policy.caching_disabled](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_cache_policy) | data source | | [aws_cloudfront_origin_request_policy.all_viewer_except_host_header](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_origin_request_policy) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ### 输入参数 | 名称 | 描述 | 类型 | 默认值 | 必填 | | ---- | ----------- | ---- | ------- | :------: | | allow\_all\_cloudfront\_distributions | 允许任何 CloudFront 分发使用 SigV4 签名请求调用 Lambda Function URL。当在同一 Terraform apply 中与另一个 CloudFront 分发集成且其 ARN 尚不可用时,这非常有用。如果可能,请优先使用 trusted\_cloudfront\_distribution\_arns。 | `bool` | `false` | no | | cloudfront\_price\_class | 面向联系表单端点的 CloudFront 分发的价格等级。 | `string` | `"PriceClass_100"` | no | | cors\_allow\_origins | 允许的 CORS 源列表。 | `list(string)` | ```[ "*" ]``` | no | | create | 启用/禁用所有资源的创建。 | `bool` | `true` | no | | create\_cloudfront\_distribution | 在 Lambda Function URL 前面创建一个 CloudFront 分发,以便公共端点受到 AWS WAF 保护,并且原始函数 URL 对 CloudFront 保持私有。 | `bool` | `true` | no | | create\_waf | 为公共 CloudFront 分发创建一个默认安全的 AWS WAF Web ACL。根据 AWS 要求,CloudFront 范围的 Web ACL 在内部于 us-east-1 中进行管理。 | `bool` | `true` | no | | email\_recipients | 接收通知的电子邮件列表。当不为空时,需要 ses\_source\_email。 | `list(string)` | `[]` | no | | email\_template | 自定义 HTML 电子邮件模板内容。使用 $field\_name 或 $fields\_html 进行表单值的变量替换。当为 null 时,使用默认模板。 | `string` | `null` | no | | enable\_logging | 为 Lambda 函数启用 JSON 应用程序日志记录配置和 Powertools 记录器支持。 | `bool` | `true` | no | | enable\_powertools\_development\_mode | 为 Lambda 函数启用 Powertools 开发模式、调试日志记录和 Powertools 事件日志记录。 | `bool` | `false` | no | | enable\_tracing | 为 Lambda 函数启用 AWS X-Ray 追踪和 Powertools 追踪器支持。 | `bool` | `false` | no | | enable\_waf\_bot\_control | 在模块托管的 WAF 上启用 AWS 托管的 Bot Control 规则组。这可以提高滥用防御能力,但会产生额外的 AWS WAF 费用。 | `bool` | `false` | no | | environment\_variables | 在 Lambda 函数上设置的其他环境变量。 | `map(string)` | `{}` | no | | fields | 接受和验证的表单字段列表。支持的类型:text、email、textarea。 | ```list(object({ name = string type = string }))``` | ```[ { "name": "name", "type": "text" }, { "name": "email", "type": "email" }, { "name": "message", "type": "textarea" } ]``` | no | | kms\_key\_arn | 用于加密日志组的 KMS 密钥的 ARN。 | `string` | `null` | no | | log\_level | Lambda 和 Powertools 的应用程序日志级别。有效值:TRACE、DEBUG、INFO、WARN、ERROR、FATAL。DEBUG 也会启用 Powertools 事件日志记录。 | `string` | `"INFO"` | no | | log\_retention\_in\_days | 在 CloudWatch Log Group 中保留日志的天数。 | `number` | `365` | no | | max\_field\_count | 单次提交中接受的最大字段数,包括隐藏或额外字段。 | `number` | `10` | no | | max\_field\_length | 任何提交字段值中允许的最大字符数。 | `number` | `2000` | no | | max\_request\_body\_size | 解码后的请求主体允许的最大大小(以字节为单位)。 | `number` | `16384` | no | | memory\_size | 分配给 Lambda 函数的内存量(以 MB 为单位)。 | `number` | `128` | no | | name | 用于 Lambda 函数和相关资源的名称。 | `string` | `"contact-form"` | no | | reserved\_concurrent\_executions | Lambda 函数的预留并发执行数,以限制滥用驱动的并行度。设置为 -1 可移除限制。 | `number` | `5` | no | | ses\_source\_email | 用于通知的已验证 SES 发件人地址。当 email\_recipients 不为空时,此项为必填。 | `string` | `null` | no | | tags | 应用于所有适用资源的标签。 | `map(string)` | `{}` | no | | trusted\_cloudfront\_distribution\_arns | 当您通过另一个分发(例如 unfunco/static-website/aws)路由联系表单流量时,应被允许调用 Lambda Function URL 的现有 CloudFront 分发 ARN。 | `list(string)` | `[]` | no | | waf\_rate\_limit | 在模块托管的 AWS WAF 阻止请求之前,单个 IP 地址在滚动的 5 分钟窗口内允许的最大请求数。 | `number` | `100` | no | | waf\_web\_acl\_arn | 要与 CloudFront 分发关联的现有 CLOUDFRONT 范围的 AWS WAF Web ACL ARN,而不是创建一个新的。 | `string` | `null` | no | ### 输出参数 | 名称 | 描述 | | ---- | ----------- | | cloudfront\_cache\_policy\_id | 为联系表单端点禁用缓存的 CloudFront 缓存策略 ID。 | | cloudfront\_distribution\_arn | 面向联系表单端点的 CloudFront 分发的 ARN。 | | cloudfront\_domain\_name | 公共联系表单端点的 CloudFront 域名。 | | cloudfront\_origin\_access\_control\_id | CloudFront 源访问控制 ID,用于在另一个 CloudFront 分发中安全地使用 Lambda Function URL 作为源,例如 unfunco/static-website/aws。 | | cloudfront\_origin\_domain\_name | 将 Lambda Function URL 连接到另一个 CloudFront 分发作为自定义源时使用的域名。 | | cloudfront\_origin\_request\_policy\_id | 转发除 Host 以外的查看器标头的 CloudFront 源请求策略 ID,适用于 Lambda Function URL 源。 | | endpoint\_url | 当此模块自行管理公共端点时,用于联系表单提交的公共 URL。如果启用了分发,则为 CloudFront URL;否则,仅当该 URL 为公共时,才会回退到原始 Lambda Function URL。 | | lambda\_function\_arn | Lambda 函数的 ARN。 | | lambda\_function\_name | Lambda 函数的名称。 | | lambda\_role\_arn | Lambda 执行角色的 ARN。 | | lambda\_url | 用作 CloudFront 源的 Lambda Function URL。当此模块管理 CloudFront 或设置了 trusted\_cloudfront\_distribution\_arns 时,此 URL 需要 IAM 签名请求,并非面向浏览器。 | | log\_group\_name | Lambda 函数使用的 CloudWatch 日志组的名称。 | | waf\_web\_acl\_arn | 为公共 CloudFront 端点创建或使用的 AWS WAF Web ACL 的 ARN,无论该分发是由此处管理还是由另一个模块管理。 | ### 版本发布 此代码仓库使用 [Release Please] 自动化版本发布。当合并带有 [conventional commit] 消息的 拉取请求时,Release Please 将打开或更新一个拉取请求以升级版本并更新变更日志。 一旦该拉取请求被合并,将创建一个新版本。 ## 许可证 © 2026 [Daniel Morris]\ 根据 [MIT License] 的条款提供。
标签:AWS, CDN, CloudFront, CORS, DNS解析, DPI, ECS, Infrastructure as Code, Lambda, SES, Terraform, WAF, Web安全, 前端集成, 开源项目, 特权提升, 联系表单, 自动化部署, 蓝队分析, 表单提交, 邮件发送