Skip to content

Update ses #12

Merged
merged 18 commits into from
Mar 26, 2021
7 changes: 4 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.47.0
rev: v1.48.0
hooks:
# - id: terraform_validate
- id: terraform_fmt
- id: terraform_docs_replace
args: ['table']
exclude: common/*.tf
exclude: version.tf

- id: terraform_tflint
args: [ "--args=--config=__GIT_WORKING_DIR__/.tflint.hcl"]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.1.0
rev: v3.4.0
hooks:
- id: check-symlinks
- id: detect-aws-credentials
Expand Down
21 changes: 21 additions & 0 deletions .tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
config {
module = true
force = false
disabled_by_default = false

# ignore_module = {
# "terraform-aws-modules/vpc/aws" = true
# "terraform-aws-modules/security-group/aws" = true
# }

# varfile = ["example1.tfvars", "example2.tfvars"]
# variables = ["foo=bar", "bar=[\"baz\"]"]
}

rule "aws_instance_invalid_type" {
enabled = true
}

plugin "aws" {
enabled = true
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@
* v1.7.3 -- 20210324
- iam-general-policies
- fix bad arn

* v1.7.4 -- 20210326
- ses-domain
- add code to enable move to production, runs aws cli script
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "1.7.3"
_module_version = "1.7.4"
}
119 changes: 79 additions & 40 deletions ses-domain/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
# aws-inf-setup :: ses-domain

This sets up the domain identity for SES. We create by default `{account_id}.aws.mail.census.gov`
as a sender domain, and generate the details which are to be submitted to TCO for inclusion in DNS.
The contents of the file `${path.root}/setup/ses_dns.md` contain the text which goes to TCO. A future enhancement
to this will include the ability to automatically incorporate the changes into DNS. This is a multi-step
This sets up the domain identity for SES. We create by default `{account_id}.aws.mail.census.gov`
as a sender domain, and generate the details which are to be submitted to TCO for inclusion in DNS.
The contents of the file `${path.root}/setup/ses_dns.md` contain the text which goes to TCO. A future enhancement
to this will include the ability to automatically incorporate the changes into DNS. This is a multi-step
setup:

1. Create initial resources
1. Provide TCO Details for DNS Update
1. Create initial resources
1. Provide TCO Details for DNS Update
1. Complete domain validation
1. Enable for production

## Select proper region

Note that at this time, this needs to be done from the `us-gov-west-1` region for GovCloud. For East/West, any US region
will work. Ideally, this will check that the west zone is selected for gov, and not create any resources if in the incorrect region.
However, that's not current possible with Terraform 0.12, and we need to get to 0.13 to make that possible. You will see this
Note that at this time, this needs to be done from the `us-gov-west-1` region for GovCloud. For East/West, any US region
will work. Ideally, this will check that the west zone is selected for gov, and not create any resources if in the incorrect region.
However, that's not current possible with Terraform 0.12, and we need to get to 0.13 to make that possible. You will see this
error if in the incorrect region:
```console
% tf-apply
Expand All @@ -29,17 +30,21 @@ Error: Error requesting SES domain identity verification: SignatureDoesNotMatch:

## Request TCO/OIS approval for 3rd Party Domain

A submission of a form authorizing 3rd party mail is required to TCO, who then puts in a ticket to OIS. This has
A submission of a form authorizing 3rd party mail is required to TCO, who then puts in a ticket to OIS. This has
been done for the AWS accounts as whole, using the default format. Any variation (that is, using a custom
`ses_domain_name` requires this form be filled out. Details are available on the [TCO Wiki Mail Section](https://wiki.apps.tco.census.gov/index.php/Services#Mail) or in [Sending Mail](https://wiki.apps.tco.census.gov/index.php/Sending_Mail).

# Usage
# Usage
This can be used without any variables to get the default configuration.

```hcl
module "ses" {
source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//ses-domain"
profile = var.profile
## once validated, get out of sandbox
# ses_enable_production = true
## optional, changing this is not recommended
# ses_domain_name = "123456789012.postal.census.gov"
## while these can be changed, it is not advised
Expand All @@ -56,8 +61,8 @@ module "ses" {

See and example [ses\_dns.md](example.ses\_dns.md). This file will be in `setup/ses_dns.md`. Submit this to TCO to get the records added to DNS.

## After DNS is updated
Once DNS has been updated, you can run `tf-apply` on the resource again. It will look for a non-empty value
## After DNS is updated
Once DNS has been updated, you can run `tf-apply` on the resource again. It will look for a non-empty value
for the TXT record and if so, complete the validation process. Here is an example:
```console
% tf-apply -target=module.ses
Expand All @@ -76,6 +81,35 @@ Plan: 1 to add, 0 to change, 0 to destroy.
module.ses.aws_ses_domain_identity_verification.this[0]: Creating...
module.ses.aws_ses_domain_identity_verification.this[0]: Creation complete after 1s [id=817869416306.aws.mail.census.gov]
```
## Getting out of the Sandbox
Reference: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html

Use the variable `ses_enable_production=true` to do this. There is no terraform resource for this.
This enables the use of a script which requires the AWS CLIv2, and it will fail otherwise.

```hcl
module "ses" {
source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//ses-domain"
profile = var.profile
ses_enable_production = true
}
```
then run `tf-apply`
```console
% tf-apply -target=module.ses
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

# module.ses.null_resource.to_production[0] is tainted, so must be replaced
-/+ resource "null_resource" "to_production" {
~ id = "283142555786980861" -> (known after apply)
}

Plan: 1 to add, 0 to change, 1 to destroy.
```

# Sample Output
```hcl
Expand Down Expand Up @@ -110,8 +144,6 @@ ses_domain_verification = {
"value" = "/Pz6+wpIUfumhdG8l0NkdfLx+wHMp+/Za2Nf5jOQTos="
}
```
# Getting out of the Sandbox
Refence: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html

## Requirements

Expand All @@ -121,44 +153,51 @@ No requirements.

| Name | Version |
|------|---------|
| aws | n/a |
| external | n/a |
| null | n/a |
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |
| <a name="provider_external"></a> [external](#provider\_external) | n/a |
| <a name="provider_null"></a> [null](#provider\_null) | n/a |

## Modules

No Modules.
No modules.

## Resources

| Name |
|------|
| [aws_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) |
| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) |
| [aws_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) |
| [aws_ses_domain_dkim](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_dkim) |
| [aws_ses_domain_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) |
| [aws_ses_domain_identity_verification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity_verification) |
| [external_external](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) |
| [null_resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) |
| Name | Type |
|------|------|
| [aws_ses_domain_dkim.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_dkim) | resource |
| [aws_ses_domain_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) | resource |
| [aws_ses_domain_identity_verification.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity_verification) | resource |
| [null_resource.this_output](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
| [null_resource.to_production](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
| [external_external.ses_dns_txt](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| account\_alias | AWS Account Alias | `string` | `""` | no |
| account\_id | AWS Account ID (default will pull from current user) | `string` | `""` | no |
| override\_prefixes | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
| ses\_base\_dkim\_domain\_name | SES Base DKIM Domain Name | `string` | `"dkim.amazonses.com"` | no |
| ses\_base\_domain\_name | SES Base Domain Name | `string` | `"aws.mail.census.gov"` | no |
| ses\_domain\_name | SES Fully Qualified Domain Name (default: {account\_id}.aws.mail.census.gov) | `string` | `""` | no |
| tags | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no |
| <a name="input_account_alias"></a> [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no |
| <a name="input_account_id"></a> [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no |
| <a name="input_override_prefixes"></a> [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
| <a name="input_profile"></a> [profile](#input\_profile) | AWS Config profile (required for calling the aws cli) | `string` | `""` | no |
| <a name="input_region"></a> [region](#input\_region) | AWS Region (default takes from current executing region) | `string` | `""` | no |
| <a name="input_ses_additional_contact_email"></a> [ses\_additional\_contact\_email](#input\_ses\_additional\_contact\_email) | SES Additional Contact email address list (for move to production) | `list(string)` | `[]` | no |
| <a name="input_ses_base_dkim_domain_name"></a> [ses\_base\_dkim\_domain\_name](#input\_ses\_base\_dkim\_domain\_name) | SES Base DKIM Domain Name | `string` | `"dkim.amazonses.com"` | no |
| <a name="input_ses_base_domain_name"></a> [ses\_base\_domain\_name](#input\_ses\_base\_domain\_name) | SES Base Domain Name | `string` | `"aws.mail.census.gov"` | no |
| <a name="input_ses_domain_name"></a> [ses\_domain\_name](#input\_ses\_domain\_name) | SES Fully Qualified Domain Name (default: {account\_id}.aws.mail.census.gov) | `string` | `""` | no |
| <a name="input_ses_enable_production"></a> [ses\_enable\_production](#input\_ses\_enable\_production) | SES Enable calling of AWS CLI to move from sandbox to production | `bool` | `false` | no |
| <a name="input_ses_use_case_description"></a> [ses\_use\_case\_description](#input\_ses\_use\_case\_description) | SES use case description (for move to production) | `string` | `""` | no |
| <a name="input_ses_website_url"></a> [ses\_website\_url](#input\_ses\_website\_url) | SES website URL (for move to production) | `string` | `"https://census.gov"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no |

## Outputs

| Name | Description |
|------|-------------|
| ses\_dkim\_values | DNS entries to add for DKIM |
| ses\_domain\_identity | SES Domain Identity |
| ses\_domain\_identity\_arn | SES Domain Identity ARN |
| ses\_domain\_verification | DNS entries to add for domain verification |
| <a name="output_ses_dkim_values"></a> [ses\_dkim\_values](#output\_ses\_dkim\_values) | DNS entries to add for DKIM |
| <a name="output_ses_domain_identity"></a> [ses\_domain\_identity](#output\_ses\_domain\_identity) | SES Domain Identity |
| <a name="output_ses_domain_identity_arn"></a> [ses\_domain\_identity\_arn](#output\_ses\_domain\_identity\_arn) | SES Domain Identity ARN |
| <a name="output_ses_domain_verification"></a> [ses\_domain\_verification](#output\_ses\_domain\_verification) | DNS entries to add for domain verification |
39 changes: 28 additions & 11 deletions ses-domain/bin/move-to-production.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,54 @@ $AWS sesv2 help >/dev/null 2>&1
status=$?
if [ $status != 0 ]
then
echo "* aws sesv2 CLI missing"
echo "* aws sesv2 CLI missing or error with profile/region status=$status"
exit 1
fi

if [[ -z $AWS_PROFILE ]] || [[ -z $AWS_DEFAULT_REGION ]
if [[ -z $AWS_PROFILE ]] || [[ -z $AWS_DEFAULT_REGION ]]
then
echo "* missing AWS_PROFILE=$AWS_PROFILE or AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION"
echo "* missing AWS_PROFILE='$AWS_PROFILE' or AWS_DEFAULT_REGION='$AWS_DEFAULT_REGION'"
exit 1
fi

if [ -z $SES_USE_CASE_DESCRIPTION ]
then
SES_USE_CASE_DESCRIPTION="Used for alerting and notification from lambda and other applications to users within our own enterprise mail system"
SES_USE_CASE_DESCRIPTION="Used for alerting and notification from lambda and other applications to users registered within our own enterprise mail system."
fi

if [ -z $SES_ADDITIONAL_CONTACT_EMAIL ]
then
SES_ADDITIONAL_CONTACT_EMAIL="donald.e.badrak.ii@census.gov,roy.d.ashley.jr@census.gov"
SES_ADDITIONAL_CONTACT_EMAIL="donald.e.badrak.ii@census.gov roy.d.ashley.jr@census.gov"
fi

$AWS sesv2 put-account-details \
--production-access-enabled \
--mail-type TRANSACTIONAL \
--use-case-description "$SES_USE_CASE_DESCRIPTION" \
--additional-contact-email-addresses "$SES_ADDITIONAL_CONTACT_EMAIL" \
--contact-language EN
if [ -z $SES_WEBSITE_URL ]
then
SES_WEBSITE_URL="https://census.gov"
fi

if [ ! -z $SES_DEBUG ]
then
SES_DEBUG="true"
fi

$SES_DEBUG $AWS sesv2 put-account-details \
--production-access-enabled \
--mail-type TRANSACTIONAL \
--website-url "$SES_WEBSITE_URL" \
--use-case-description "$SES_USE_CASE_DESCRIPTION" \
--additional-contact-email-addresses $SES_ADDITIONAL_CONTACT_EMAIL \
--contact-language EN
status=$?

if [ $status != 0 ]
then
echo "* error requesting production access for SES"
exit $status
fi

# now, get the details
$SES_DEBUG $AWS sesv2 get-account

exit $status

# unused options
Expand All @@ -54,3 +70,4 @@ exit $status
# AWS_PROFILE
# SES_ADDITIONAL_CONTACT_EMAIL
# SES_USE_CASE_DESCRIPTION
# SES_WEBSITE_URL
Loading