-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify account-specific deploy steps with Terraform. #301
Conversation
This change brings 7 additional resources under Terraform configuration which were previously manually created on the AWS Account-specific level. When this change is merged, existing resources will need to be manually imported into Terraform’s state file so it doesn’t attempt to create duplicate resources when the account-specific manual deployment step is run. To import these resources: ```bash export TF_VAR_dns_domain=${EFCMS_DOMAIN} terraform import aws_route53_zone.primary [HOSTED_ZONE_ID] terraform import aws_iam_user.circle_ci [USER_NAME] terraform import aws_iam_user_policy_attachment.circle_ci_policy_attachment [USER_NAME]/[CI_POLICY_ARN] terraform import aws_s3_bucket.dynamsoft [DYNAMSOFT_BUCKET_NAME] terraform import aws_iam_role.dynamsoft_s3_download_role dynamsoft_s3_download_role terraform import aws_iam_policy.access_dynamsoft_s3_bucket [DYNAMSOFT_POLICY_ARN] terraform import aws_iam_role_policy_attachment.allow_dynamsoft_role_access_to_dynamsoft_s3_bucket dynamsoft_s3_download_role/[DYNAMSOFT_POLICY_ARN] ``` It’s easiest to retrieve these values using the AWS console, as they were created manually and as such may vary slightly: - `HOSTED_ZONE_ID`: Retrieve from the Hosted Zone in Route 53. - `USER_NAME`: Retrieve from the Circle CI user in IAM. - `CI_POLICY_ARN`: Retrieve from the ARN from the circle_ci_policy in IAM. - `DYNAMSOFT_BUCKET_NAME`: Retrieve the bucket name from S3 which contains the Dynamsoft archive. - `DYNAMSOFT_POLICY_ARN`: The policy created which grants access to the Dynamsoft S3 bucket. On first run, it’s recommended to not use `-auto-approve` to confirm that Terraform is tracking the resources correctly and will perform the desired steps.
Tagging @julialeague and @kfoley-18F for code review. Wanted to get @ericsorenson, @codyseibert, and @rachaelparris ’s eyes on this too — this change automates previously manual setup steps in account setup; will require one-time import of previously manually created resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied these changes to the Court’s production account (not captured here, since they were all new resources) and the development account (captured below). The exact commands run.➜ cd iam/terraform/account-specific/main
➜ ../bin/deploy-init.sh
➜ export TF_VAR_dns_domain=${EFCMS_DOMAIN}
# See the execution plan before imports
➜ terraform plan
# Import existing resources
➜ terraform import aws_route53_zone.primary ZZOXVU7QZ7TZQ
➜ terraform import aws_iam_user.circle_ci deployer
➜ terraform import aws_iam_user_policy_attachment.circle_ci_policy_attachment deployer/arn:aws:iam::350455059537:policy/circle_ci_policy
➜ terraform import aws_s3_bucket.dynamsoft ef-cms.ustaxcourt.gov-software
➜ terraform import aws_iam_role.dynamsoft_s3_download_role dynamsoft_s3_download_role
➜ terraform import aws_iam_policy.access_dynamsoft_s3_bucket arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket
➜ terraform import aws_iam_role_policy_attachment.allow_dynamsoft_role_access_to_dynamsoft_s3_bucket dynamsoft_s3_download_role/arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket
# See the execution plan after imports
➜ terraform plan
# Apply the changes
➜ terraform apply The execution plan (never run) before state import, for reference.➜ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
data.aws_caller_identity.current: Refreshing state...
data.aws_iam_policy_document.allow_ec2_to_assume_dynamsoft_s3_download_role: Refreshing state...
aws_iam_service_linked_role.lambda_replication_role: Refreshing state... [id=arn:aws:iam::350455059537:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator]
aws_iam_service_linked_role.lambda_cloudfront_logger_role: Refreshing state... [id=arn:aws:iam::350455059537:role/aws-service-role/logger.cloudfront.amazonaws.com/AWSServiceRoleForCloudFrontLogger]
aws_ecr_repository.image_repository: Refreshing state... [id=ef-cms-us-east-1]
aws_iam_role.cloudwatch: Refreshing state... [id=api_gateway_cloudwatch_global]
aws_iam_policy.circle_ci_policy: Refreshing state... [id=arn:aws:iam::350455059537:policy/circle_ci_policy]
aws_iam_role_policy.cloudwatch: Refreshing state... [id=api_gateway_cloudwatch_global:cloudwatch_policy]
aws_ecr_lifecycle_policy.repo_policy: Refreshing state... [id=ef-cms-us-east-1]
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:
# data.aws_iam_policy_document.allow_read_access_to_dynamsoft_s3_bucket will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "allow_read_access_to_dynamsoft_s3_bucket" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "s3:GetObject",
]
+ resources = [
+ (known after apply),
]
}
}
# aws_iam_policy.access_dynamsoft_s3_bucket will be created
+ resource "aws_iam_policy" "access_dynamsoft_s3_bucket" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "AccessSoftwareS3Bucket"
+ path = "/"
+ policy = (known after apply)
}
# aws_iam_role.dynamsoft_s3_download_role will be created
+ resource "aws_iam_role" "dynamsoft_s3_download_role" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "ec2.amazonaws.com"
}
+ Sid = ""
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ max_session_duration = 3600
+ name = "dynamsoft_s3_download_role"
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_role_policy_attachment.allow_dynamsoft_role_access_to_dynamsoft_s3_bucket will be created
+ resource "aws_iam_role_policy_attachment" "allow_dynamsoft_role_access_to_dynamsoft_s3_bucket" {
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "dynamsoft_s3_download_role"
}
# aws_iam_user.circle_ci will be created
+ resource "aws_iam_user" "circle_ci" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "CircleCI"
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_user_policy_attachment.circle_ci_policy_attachment will be created
+ resource "aws_iam_user_policy_attachment" "circle_ci_policy_attachment" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::350455059537:policy/circle_ci_policy"
+ user = "CircleCI"
}
# aws_route53_zone.primary will be created
+ resource "aws_route53_zone" "primary" {
+ comment = "Managed by Terraform"
+ force_destroy = false
+ id = (known after apply)
+ name = "ef-cms.ustaxcourt.gov"
+ name_servers = (known after apply)
+ vpc_id = (known after apply)
+ vpc_region = (known after apply)
+ zone_id = (known after apply)
}
# aws_s3_bucket.dynamsoft will be created
+ resource "aws_s3_bucket" "dynamsoft" {
+ acceleration_status = (known after apply)
+ acl = "private"
+ arn = (known after apply)
+ bucket = "ef-cms.ustaxcourt.gov-software"
+ bucket_domain_name = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
+ versioning {
+ enabled = (known after apply)
+ mfa_delete = (known after apply)
}
}
# aws_s3_bucket_public_access_block.dynamsoft will be created
+ resource "aws_s3_bucket_public_access_block" "dynamsoft" {
+ block_public_acls = true
+ block_public_policy = true
+ bucket = (known after apply)
+ id = (known after apply)
+ ignore_public_acls = true
+ restrict_public_buckets = true
}
Plan: 8 to add, 0 to change, 0 to destroy.
Warning: Interpolation-only expressions are deprecated
on circle-ci.tf line 8, in resource "aws_iam_user_policy_attachment" "circle_ci_policy_attachment":
8: user = "${aws_iam_user.circle_ci.name}"
Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "${ sequence from the start and the }"
sequence from the end of this expression, leaving just the inner expression.
Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.
(and 7 more similar warnings elsewhere)
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run. The execution plan after state import, for reference.➜ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
aws_iam_user.circle_ci: Refreshing state... [id=deployer]
aws_route53_zone.primary: Refreshing state... [id=ZZOXVU7QZ7TZQ]
aws_iam_service_linked_role.lambda_cloudfront_logger_role: Refreshing state... [id=arn:aws:iam::350455059537:role/aws-service-role/logger.cloudfront.amazonaws.com/AWSServiceRoleForCloudFrontLogger]
data.aws_caller_identity.current: Refreshing state...
aws_iam_role.cloudwatch: Refreshing state... [id=api_gateway_cloudwatch_global]
aws_iam_service_linked_role.lambda_replication_role: Refreshing state... [id=arn:aws:iam::350455059537:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator]
data.aws_iam_policy_document.allow_ec2_to_assume_dynamsoft_s3_download_role: Refreshing state...
aws_s3_bucket.dynamsoft: Refreshing state... [id=ef-cms.ustaxcourt.gov-software]
aws_ecr_repository.image_repository: Refreshing state... [id=ef-cms-us-east-1]
aws_iam_role.dynamsoft_s3_download_role: Refreshing state... [id=dynamsoft_s3_download_role]
aws_iam_policy.circle_ci_policy: Refreshing state... [id=arn:aws:iam::350455059537:policy/circle_ci_policy]
aws_iam_role_policy.cloudwatch: Refreshing state... [id=api_gateway_cloudwatch_global:cloudwatch_policy]
aws_ecr_lifecycle_policy.repo_policy: Refreshing state... [id=ef-cms-us-east-1]
aws_iam_user_policy_attachment.circle_ci_policy_attachment: Refreshing state... [id=deployer-arn:aws:iam::350455059537:policy/circle_ci_policy]
data.aws_iam_policy_document.allow_read_access_to_dynamsoft_s3_bucket: Refreshing state...
aws_iam_policy.access_dynamsoft_s3_bucket: Refreshing state... [id=arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket]
aws_iam_role_policy_attachment.allow_dynamsoft_role_access_to_dynamsoft_s3_bucket: Refreshing state... [id=dynamsoft_s3_download_role-arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket]
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
~ update in-place
-/+ destroy and then create replacement
<= read (data resources)
Terraform will perform the following actions:
# data.aws_iam_policy_document.allow_read_access_to_dynamsoft_s3_bucket will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "allow_read_access_to_dynamsoft_s3_bucket" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "s3:GetObject",
]
+ resources = [
+ "arn:aws:s3:::ef-cms.ustaxcourt.gov-software/*",
]
}
}
# aws_iam_policy.access_dynamsoft_s3_bucket must be replaced
-/+ resource "aws_iam_policy" "access_dynamsoft_s3_bucket" {
~ arn = "arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket" -> (known after apply)
- description = "Access the ef-cms.ustaxcourt.gov-software bucket, so an EC2 instance can retrieve licensed, commercial software." -> null # forces replacement
~ id = "arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket" -> (known after apply)
name = "AccessSoftwareS3Bucket"
path = "/"
~ policy = jsonencode(
{
- Statement = [
- {
- Action = "s3:GetObject"
- Effect = "Allow"
- Resource = "arn:aws:s3:::ef-cms.ustaxcourt.gov-software/*"
- Sid = "VisualEditor0"
},
]
- Version = "2012-10-17"
}
) -> (known after apply)
}
# aws_iam_role.dynamsoft_s3_download_role will be updated in-place
~ resource "aws_iam_role" "dynamsoft_s3_download_role" {
arn = "arn:aws:iam::350455059537:role/dynamsoft_s3_download_role"
assume_role_policy = jsonencode(
{
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
Version = "2012-10-17"
}
)
create_date = "2019-09-05T19:02:45Z"
- description = "Allows EC2 instance to retrieve software from the commercial software S3 bucket." -> null
force_detach_policies = false
id = "dynamsoft_s3_download_role"
max_session_duration = 3600
name = "dynamsoft_s3_download_role"
path = "/"
tags = {}
unique_id = "AROAVDGF72RIVG67S3TII"
}
# aws_iam_role_policy_attachment.allow_dynamsoft_role_access_to_dynamsoft_s3_bucket must be replaced
-/+ resource "aws_iam_role_policy_attachment" "allow_dynamsoft_role_access_to_dynamsoft_s3_bucket" {
~ id = "dynamsoft_s3_download_role-arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket" -> (known after apply)
~ policy_arn = "arn:aws:iam::350455059537:policy/AccessSoftwareS3Bucket" -> (known after apply) # forces replacement
role = "dynamsoft_s3_download_role"
}
# aws_iam_user.circle_ci will be updated in-place
~ resource "aws_iam_user" "circle_ci" {
arn = "arn:aws:iam::350455059537:user/deployer"
+ force_destroy = false
id = "deployer"
~ name = "deployer" -> "CircleCI"
path = "/"
tags = {}
unique_id = "AIDAIIUOL7VSASSAEZVEC"
}
# aws_iam_user_policy_attachment.circle_ci_policy_attachment must be replaced
-/+ resource "aws_iam_user_policy_attachment" "circle_ci_policy_attachment" {
~ id = "deployer-arn:aws:iam::350455059537:policy/circle_ci_policy" -> (known after apply)
policy_arn = "arn:aws:iam::350455059537:policy/circle_ci_policy"
~ user = "deployer" -> "CircleCI" # forces replacement
}
# aws_route53_zone.primary will be updated in-place
~ resource "aws_route53_zone" "primary" {
+ comment = "Managed by Terraform"
+ force_destroy = false
id = "ZZOXVU7QZ7TZQ"
name = "ef-cms.ustaxcourt.gov."
name_servers = [
"ns-1056.awsdns-04.org",
"ns-155.awsdns-19.com",
"ns-2018.awsdns-60.co.uk",
"ns-852.awsdns-42.net",
]
tags = {}
zone_id = "ZZOXVU7QZ7TZQ"
}
# aws_s3_bucket.dynamsoft will be updated in-place
~ resource "aws_s3_bucket" "dynamsoft" {
+ acl = "private"
arn = "arn:aws:s3:::ef-cms.ustaxcourt.gov-software"
bucket = "ef-cms.ustaxcourt.gov-software"
bucket_domain_name = "ef-cms.ustaxcourt.gov-software.s3.amazonaws.com"
bucket_regional_domain_name = "ef-cms.ustaxcourt.gov-software.s3.amazonaws.com"
+ force_destroy = false
hosted_zone_id = "Z3AQBSTGFYJSTF"
id = "ef-cms.ustaxcourt.gov-software"
region = "us-east-1"
request_payer = "BucketOwner"
tags = {}
versioning {
enabled = false
mfa_delete = false
}
}
# aws_s3_bucket_public_access_block.dynamsoft will be created
+ resource "aws_s3_bucket_public_access_block" "dynamsoft" {
+ block_public_acls = true
+ block_public_policy = true
+ bucket = "ef-cms.ustaxcourt.gov-software"
+ id = (known after apply)
+ ignore_public_acls = true
+ restrict_public_buckets = true
}
Plan: 4 to add, 4 to change, 3 to destroy.
Warning: Interpolation-only expressions are deprecated
on circle-ci.tf line 8, in resource "aws_iam_user_policy_attachment" "circle_ci_policy_attachment":
8: user = "${aws_iam_user.circle_ci.name}"
Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "${ sequence from the start and the }"
sequence from the end of this expression, leaving just the inner expression.
Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.
(and 7 more similar warnings elsewhere)
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run. Output from
|
This change brings 7 additional resources under Terraform configuration which were previously manually created on the AWS Account-specific level, removing their manual documentation from the Environment setup documentation.
It’s easiest to retrieve these values using the AWS console, as they were created manually and as such may vary slightly:
HOSTED_ZONE_ID
: Retrieve from the Hosted Zone in Route 53.USER_NAME
: Retrieve from the Circle CI user in IAM.CI_POLICY_ARN
: Retrieve from the ARN from the circle_ci_policy in IAM.DYNAMSOFT_BUCKET_NAME
: Retrieve the bucket name from S3 which contains the Dynamsoft archive.DYNAMSOFT_POLICY_ARN
: The policy created which grants access to the Dynamsoft S3 bucket.On first run, it’s recommended to avoid
-auto-approve
and confirm Terraform’s execution plan will perform the desired steps before approving.Without
-auto-approve
,terraform apply
will prompt for your review.