From b9dca8a1f46f2108e33cb05ba8c154d855e6db88 Mon Sep 17 00:00:00 2001 From: Alis Akers <94012653+alismx@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:20:28 -0500 Subject: [PATCH] setup postgres and sqlserver data variable for connecting to a metadata database (#11) --- README.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++- _check.tf | 12 +++++ _local.tf | 28 +++++++++++- _variable.tf | 42 ++++++++++++++--- alb.tf | 2 +- tfutil.sh | 5 ++ 6 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 _check.tf create mode 100755 tfutil.sh diff --git a/README.md b/README.md index 910a3b0..59a9bfe 100644 --- a/README.md +++ b/README.md @@ -89,4 +89,129 @@ The current architectural design for dibbs-aws is as follows: ![Current DIBBS Architecture as of 6-24-2024](https://github.com/CDCgov/dibbs-aws/assets/29112142/7d43d3c1-5d61-41b8-a1c3-bb4884073825) -+ [Return to Table of Contents](#table-of-contents). \ No newline at end of file ++ [Return to Table of Contents](#table-of-contents). + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.9.0 | +| [aws](#requirement\_aws) | ~> 5.56.1 | +| [dockerless](#requirement\_dockerless) | ~> 0.1.1 | +| [null](#requirement\_null) | ~> 3.2.3 | +| [random](#requirement\_random) | ~> 3.6.3 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.56.1 | +| [dockerless](#provider\_dockerless) | ~> 0.1.1 | +| [null](#provider\_null) | ~> 3.2.3 | +| [random](#provider\_random) | ~> 3.6.3 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_alb.ecs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb) | resource | +| [aws_alb_listener.http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener) | resource | +| [aws_alb_listener.https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener) | resource | +| [aws_alb_listener_rule.http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener_rule) | resource | +| [aws_alb_listener_rule.https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener_rule) | resource | +| [aws_alb_target_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_target_group) | resource | +| [aws_appmesh_mesh.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appmesh_mesh) | resource | +| [aws_appmesh_virtual_node.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appmesh_virtual_node) | resource | +| [aws_cloudwatch_log_group.ecs_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_ecr_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | +| [aws_ecs_cluster.dibbs_app_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | +| [aws_ecs_service.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | +| [aws_ecs_task_definition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | +| [aws_flow_log.ecs_flow_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | +| [aws_iam_policy.s3_bucket_ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.ecs_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.ecs_task_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.s3_role_for_ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_s3_bucket.ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_public_access_block.ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.ecr_viewer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [aws_security_group.alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.ecs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.alb_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.alb_http_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.alb_https_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.ecs_alb_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.ecs_all_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.ecs_ecs_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_service_discovery_private_dns_namespace.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/service_discovery_private_dns_namespace) | resource | +| [aws_vpc_endpoint.endpoints](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | +| [aws_vpc_endpoint.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | +| [dockerless_remote_image.dibbs](https://registry.terraform.io/providers/nullstone-io/dockerless/latest/docs/resources/remote_image) | resource | +| [null_resource.target_groups](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [random_string.s3_viewer](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_ecr_authorization_token.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_authorization_token) | data source | +| [aws_iam_policy.amazon_ec2_container_service_for_ec2_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source | +| [aws_iam_policy.ecs_task_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_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.ecr_viewer_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_route_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route_table) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [appmesh\_name](#input\_appmesh\_name) | Name of the AWS App Mesh | `string` | `""` | no | +| [certificate\_arn](#input\_certificate\_arn) | ARN of the SSL certificate that enables ssl termination on the ALB | `string` | `""` | no | +| [cloudmap\_namespace\_name](#input\_cloudmap\_namespace\_name) | Name of the AWS Cloud Map namespace | `string` | `""` | no | +| [cw\_retention\_in\_days](#input\_cw\_retention\_in\_days) | Retention period in days for CloudWatch logs | `number` | `30` | no | +| [disable\_ecr](#input\_disable\_ecr) | Flag to disable the aws ecr service for docker image storage, defaults to false | `bool` | `false` | no | +| [ecr\_viewer\_app\_env](#input\_ecr\_viewer\_app\_env) | The current environment that is running. This may modify behavior of auth between dev and prod. | `string` | `"prod"` | no | +| [ecr\_viewer\_auth\_pub\_key](#input\_ecr\_viewer\_auth\_pub\_key) | The public key used to validate the incoming authenication for the eCR Viewer. | `string` | `"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqjrH9PprQCB5dX15zYfd\nS6K2ezNi/ZOu8vKEhQuLqwHACy1iUt1Yyp2PZLIV7FVDgBHMMVWPVx3GJ2wEyaJw\nMHkv6XNpUpWLhbs0V1T7o/OZfEIqcNua07OEoBxX9vhKIHtaksWdoMyKRXQJz0js\noWpawfOWxETnLqGvybT4yvY2RJhquTXLcLu90L4LdvIkADIZshaOtAU/OwI5ATcb\nfE3ip15E6jIoUm7FAtfRiuncpI5l/LJPP6fvwf8QCbbUJBZklLqcUuf4qe/L/nIq\npIONb8KZFWPhnGeRZ9bwIcqYWt3LAAshQLSGEYl2PGXaqbkUD2XLETSKDjisxd0g\n9j8bIMPgBKi+dBYcmBZnR7DxJe+vEDDw8prHG/+HRy5fim/BcibTKnIl8PR5yqHa\nmWQo7N+xXhILdD9e33KLRgbg97+erHqvHlNMdwDhAfrBT+W6GCdPwp3cePPsbhsc\noGSHOUDhzyAujr0J8h5WmZDGUNWjGzWqubNZD8dBXB8x+9dDoWhfM82nw0pvAeKf\nwJodvn3Qo8/S5hxJ6HyGkUTANKN8IxWh/6R5biET5BuztZP6jfPEaOAnt6sq+C38\nhR9rUr59dP2BTlcJ19ZXobLwuJEa81S5BrcbDwYNOAzC8jl2EV1i4bQIwJJaY27X\nIynom6unaheZpS4DFIh2w9UCAwEAAQ==\n-----END PUBLIC KEY-----\n"` | no | +| [ecr\_viewer\_basepath](#input\_ecr\_viewer\_basepath) | The basepath for the ecr-viewer | `string` | `"/ecr-viewer"` | no | +| [ecs\_alb\_name](#input\_ecs\_alb\_name) | Name of the Application Load Balancer (ALB) | `string` | `""` | no | +| [ecs\_alb\_tg\_name](#input\_ecs\_alb\_tg\_name) | Name of the ALB Target Group | `string` | `""` | no | +| [ecs\_cloudwatch\_group](#input\_ecs\_cloudwatch\_group) | Name of the AWS CloudWatch Log Group for ECS | `string` | `""` | no | +| [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | Name of the ECS Cluster | `string` | `""` | no | +| [ecs\_task\_execution\_role\_name](#input\_ecs\_task\_execution\_role\_name) | Name of the ECS Task Execution Role | `string` | `""` | no | +| [ecs\_task\_role\_name](#input\_ecs\_task\_role\_name) | Name of the ECS Task Role | `string` | `""` | no | +| [internal](#input\_internal) | Flag to determine if the several AWS resources are public (intended for external access, public internet) or private (only intended to be accessed within your AWS VPC or avaiable with other means, a transit gateway for example). | `bool` | `true` | no | +| [owner](#input\_owner) | Owner of the resources | `string` | `"CDC"` | no | +| [phdi\_version](#input\_phdi\_version) | Version of the PHDI application | `string` | `"v1.6.9"` | no | +| [postgres\_database\_data](#input\_postgres\_database\_data) | n/a |
object({|
non_integrated_viewer = string
metadata_database_type = string
metadata_database_schema = string
secrets_manager_postgres_database_url_arn = string
})
{| no | +| [private\_subnet\_ids](#input\_private\_subnet\_ids) | List of private subnet IDs | `list(string)` | n/a | yes | +| [project](#input\_project) | The project name | `string` | `"dibbs"` | no | +| [public\_subnet\_ids](#input\_public\_subnet\_ids) | List of public subnet IDs | `list(string)` | n/a | yes | +| [region](#input\_region) | The AWS region where resources are created | `string` | n/a | yes | +| [s3\_viewer\_bucket\_name](#input\_s3\_viewer\_bucket\_name) | Name of the S3 bucket for the viewer | `string` | `""` | no | +| [s3\_viewer\_bucket\_role\_name](#input\_s3\_viewer\_bucket\_role\_name) | Name of the IAM role for the ecr-viewer bucket | `string` | `""` | no | +| [service\_data](#input\_service\_data) | Data for the DIBBS services |
"metadata_database_schema": "",
"metadata_database_type": "",
"non_integrated_viewer": "false",
"secrets_manager_postgres_database_url_arn": ""
}
map(object({| `{}` | no | +| [sqlserver\_database\_data](#input\_sqlserver\_database\_data) | n/a |
short_name = string
fargate_cpu = number
fargate_memory = number
min_capacity = number
max_capacity = number
app_image = string
app_version = string
container_port = number
host_port = number
public = bool
registry_url = string
env_vars = list(object({
name = string
value = string
}))
}))
object({|
non_integrated_viewer = string
metadata_database_type = string
metadata_database_schema = string
secrets_manager_sqlserver_user_arn = string
secrets_manager_sqlserver_password_arn = string
secrets_manager_sqlserver_host_arn = string
})
{| no | +| [tags](#input\_tags) | Tags to apply to resources | `map(string)` | `{}` | no | +| [vpc\_id](#input\_vpc\_id) | ID of the VPC | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [alb\_arn](#output\_alb\_arn) | n/a | +| [alb\_listener\_arn](#output\_alb\_listener\_arn) | n/a | +| [alb\_security\_group\_arn](#output\_alb\_security\_group\_arn) | n/a | +| [alb\_target\_groups\_arns](#output\_alb\_target\_groups\_arns) | n/a | +| [ecs\_cluster\_arn](#output\_ecs\_cluster\_arn) | n/a | +| [ecs\_security\_group\_arn](#output\_ecs\_security\_group\_arn) | n/a | +| [ecs\_task\_definitions\_arns](#output\_ecs\_task\_definitions\_arns) | n/a | +| [ecs\_task\_execution\_role\_arn](#output\_ecs\_task\_execution\_role\_arn) | n/a | +| [ecs\_task\_role\_arn](#output\_ecs\_task\_role\_arn) | n/a | +| [http\_alb\_listener\_rules\_arns](#output\_http\_alb\_listener\_rules\_arns) | n/a | +| [https\_alb\_listener\_rules\_arns](#output\_https\_alb\_listener\_rules\_arns) | n/a | +| [s3\_bucket\_arn](#output\_s3\_bucket\_arn) | The ARN of the S3 bucket | +| [s3\_bucket\_ecr\_viewer\_policy\_arn](#output\_s3\_bucket\_ecr\_viewer\_policy\_arn) | n/a | +| [s3\_role\_for\_ecr\_viewer\_arn](#output\_s3\_role\_for\_ecr\_viewer\_arn) | n/a | +| [service\_data](#output\_service\_data) | n/a | + \ No newline at end of file diff --git a/_check.tf b/_check.tf new file mode 100644 index 0000000..14186dd --- /dev/null +++ b/_check.tf @@ -0,0 +1,12 @@ +check "database_data_non_integrated_viewer" { + assert { + condition = ( + (local.database_data.non_integrated_viewer == "false" && + length(local.database_data.metadata_database_type) == 0) || + (local.database_data.non_integrated_viewer == "true" && + length(local.database_data.metadata_database_type) > 0 && + length(local.database_data.metadata_database_schema) > 0) + ) + error_message = "When non_integrated_viewer is false, no other database data should be provided. When non_integrated_viewer is true, metadata_database_type, metadata_database_schema, and secrets_manager_* variables should be provided." + } +} diff --git a/_local.tf b/_local.tf index 88dfa46..e02d7c4 100644 --- a/_local.tf +++ b/_local.tf @@ -8,6 +8,8 @@ locals { registry_url = var.disable_ecr == false ? "${data.aws_caller_identity.current.account_id}.dkr.ecr.${var.region}.amazonaws.com" : "ghcr.io/cdcgov/phdi" registry_username = data.aws_ecr_authorization_token.this.user_name registry_password = data.aws_ecr_authorization_token.this.password + database_data = var.postgres_database_data.non_integrated_viewer == "true" ? var.postgres_database_data : var.sqlserver_database_data + service_data = length(var.service_data) > 0 ? var.service_data : { ecr-viewer = { short_name = "ecrv", @@ -36,7 +38,7 @@ locals { }, { name = "NEXT_PUBLIC_NON_INTEGRATED_VIEWER", - value = var.non_integrated_viewer + value = local.database_data.non_integrated_viewer }, { name = "SOURCE", @@ -53,6 +55,30 @@ locals { { name = "NEXT_PUBLIC_BASEPATH", value = var.ecr_viewer_basepath + }, + { + name = "METADATA_DATABASE_TYPE", + value = local.database_data.non_integrated_viewer == "true" ? local.database_data.metadata_database_type : "" + }, + { + name = "METADATA_DATABASE_SCHEMA", + value = local.database_data.non_integrated_viewer == "true" ? local.database_data.metadata_database_schema : "" + }, + { + name = "DATABASE_URL", + value = local.database_data.metadata_database_type == "postgres" ? local.database_data.secrets_manager_postgres_database_url_arn : "" + }, + { + name = "SQL_SERVER_USER", + value = local.database_data.metadata_database_type == "sqlserver" ? local.database_data.secrets_manager_sqlserver_user_arn : "" + }, + { + name = "SQL_SERVER_PASSWORD", + value = local.database_data.metadata_database_type == "sqlserver" ? local.database_data.secrets_manager_sqlserver_password_arn : "" + }, + { + name = "SQL_SERVER_HOST", + value = local.database_data.metadata_database_type == "sqlserver" ? local.database_data.secrets_manager_sqlserver_host_arn : "" } ] }, diff --git a/_variable.tf b/_variable.tf index 416f7d9..5e3f5a9 100644 --- a/_variable.tf +++ b/_variable.tf @@ -113,10 +113,44 @@ variable "service_data" { default = {} } +variable "postgres_database_data" { + type = object({ + non_integrated_viewer = string + metadata_database_type = string + metadata_database_schema = string + secrets_manager_postgres_database_url_arn = string + }) + default = { + non_integrated_viewer = "false" + metadata_database_type = "" + metadata_database_schema = "" + secrets_manager_postgres_database_url_arn = "" + } +} + +variable "sqlserver_database_data" { + type = object({ + non_integrated_viewer = string + metadata_database_type = string + metadata_database_schema = string + secrets_manager_sqlserver_user_arn = string + secrets_manager_sqlserver_password_arn = string + secrets_manager_sqlserver_host_arn = string + }) + default = { + non_integrated_viewer = "false" + metadata_database_type = "" + metadata_database_schema = "" + secrets_manager_sqlserver_user_arn = "" + secrets_manager_sqlserver_password_arn = "" + secrets_manager_sqlserver_host_arn = "" + } +} + variable "certificate_arn" { type = string description = "ARN of the SSL certificate that enables ssl termination on the ALB" - default = "" + default = "" } variable "vpc_id" { @@ -148,12 +182,6 @@ variable "tags" { default = {} } -variable "non_integrated_viewer" { - type = string - description = "A flag to determine if the viewer is the non-integrated version" - default = "false" -} - variable "ecr_viewer_basepath" { type = string description = "The basepath for the ecr-viewer" diff --git a/alb.tf b/alb.tf index 3f99dcc..00ffbd6 100644 --- a/alb.tf +++ b/alb.tf @@ -120,7 +120,7 @@ resource "aws_alb_listener_rule" "http" { } resource "aws_alb_listener" "https" { - count = var.certificate_arn != "" ? 1 : 0 + count = var.certificate_arn != "" ? 1 : 0 load_balancer_arn = aws_alb.ecs.arn port = "443" protocol = "HTTPS" diff --git a/tfutil.sh b/tfutil.sh new file mode 100755 index 0000000..058a552 --- /dev/null +++ b/tfutil.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +terraform fmt +terraform-docs markdown table --output-file README.md --output-mode inject . +tflint -f compact
"metadata_database_schema": "",
"metadata_database_type": "",
"non_integrated_viewer": "false",
"secrets_manager_sqlserver_host_arn": "",
"secrets_manager_sqlserver_password_arn": "",
"secrets_manager_sqlserver_user_arn": ""
}