diff --git a/modules/perforce/helix-authentication-service/README.md b/modules/perforce/helix-authentication-service/README.md index ceb36242..0c673e23 100644 --- a/modules/perforce/helix-authentication-service/README.md +++ b/modules/perforce/helix-authentication-service/README.md @@ -7,6 +7,7 @@ |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | | [aws](#requirement\_aws) | >= 5.30 | +| [awscc](#requirement\_awscc) | >= 1.2.0 | | [random](#requirement\_random) | >=3.6 | ## Providers @@ -14,6 +15,7 @@ | Name | Version | |------|---------| | [aws](#provider\_aws) | >= 5.30 | +| [awscc](#provider\_awscc) | >= 1.2.0 | | [random](#provider\_random) | >=3.6 | ## Modules @@ -30,6 +32,7 @@ No modules. | [aws_ecs_service.HAS_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | | [aws_ecs_task_definition.HAS_task_definition](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | | [aws_iam_policy.HAS_default_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.HAS_secrets_manager_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.HAS_default_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.HAS_task_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_lb.HAS_alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb) | resource | @@ -42,10 +45,13 @@ No modules. | [aws_vpc_security_group_egress_rule.HAS_service_outbound_ipv4](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | | [aws_vpc_security_group_egress_rule.HAS_service_outbound_ipv6](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | | [aws_vpc_security_group_ingress_rule.HAS_service_inbound_alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | +| [awscc_secretsmanager_secret.has_admin_password](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/secretsmanager_secret) | resource | +| [awscc_secretsmanager_secret.has_admin_username](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/secretsmanager_secret) | resource | | [random_string.HAS](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [random_string.HAS_alb_access_logs_bucket_suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_ecs_cluster.HAS_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecs_cluster) | data source | | [aws_iam_policy_document.HAS_default_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.HAS_secrets_manager_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.ecs_tasks_trust_relationship](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | @@ -74,6 +80,8 @@ No modules. | [environment](#input\_environment) | The current environment (e.g. dev, prod, etc.) | `string` | `"dev"` | no | | [existing\_security\_groups](#input\_existing\_security\_groups) | A list of existing security group IDs to attach to the Helix Authentication Service load balancer. | `list(string)` | `[]` | no | | [fqdn](#input\_fqdn) | The fully qualified domain name of Helix Authentication Service. | `string` | `"localhost"` | no | +| [has\_admin\_password\_secret\_arn](#input\_has\_admin\_password\_secret\_arn) | Optionally provide the ARN of an AWS Secret for the HAS Administrator password. | `string` | `null` | no | +| [has\_admin\_username\_secret\_arn](#input\_has\_admin\_username\_secret\_arn) | Optionally provide the ARN of an AWS Secret for the HAS Administrator username. | `string` | `null` | no | | [internal](#input\_internal) | Set this flag to true if you do not want the Helix Authentication Service load balancer to have a public IP. | `bool` | `false` | no | | [name](#input\_name) | The name attached to HAS module resources. | `string` | `"HAS"` | no | | [project\_prefix](#input\_project\_prefix) | The project prefix for this workload. This is appeneded to the beginning of most resource names. | `string` | `"cgd"` | no | diff --git a/modules/perforce/helix-authentication-service/iam.tf b/modules/perforce/helix-authentication-service/iam.tf index fb35cdcc..b0ba35f6 100644 --- a/modules/perforce/helix-authentication-service/iam.tf +++ b/modules/perforce/helix-authentication-service/iam.tf @@ -37,8 +37,24 @@ data "aws_iam_policy_document" "HAS_default_policy" { "*" ] } + statement { + effect = "Allow" + actions = [ + "secretsmanager:ListSecrets", + "secretsmanager:ListSecretVersionIds", + "secretsmanager:GetRandomPassword", + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:BatchGetSecretValue" + ] + resources = [ + var.has_admin_username_secret_arn == null ? awscc_secretsmanager_secret.has_admin_username[0].secret_id : var.has_admin_username_secret_arn, + var.has_admin_password_secret_arn == null ? awscc_secretsmanager_secret.has_admin_password[0].secret_id : var.has_admin_password_secret_arn, + ] + } } + resource "aws_iam_policy" "HAS_default_policy" { count = var.create_HAS_default_policy ? 1 : 0 @@ -47,6 +63,8 @@ resource "aws_iam_policy" "HAS_default_policy" { policy = data.aws_iam_policy_document.HAS_default_policy[0].json } + + # - Roles - # HAS resource "aws_iam_role" "HAS_default_role" { @@ -61,9 +79,33 @@ resource "aws_iam_role" "HAS_default_role" { tags = local.tags } +data "aws_iam_policy_document" "HAS_secrets_manager_policy" { + statement { + effect = "Allow" + actions = [ + "secretsmanager:ListSecrets", + "secretsmanager:ListSecretVersionIds", + "secretsmanager:GetRandomPassword", + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:BatchGetSecretValue" + ] + resources = [ + var.has_admin_username_secret_arn == null ? awscc_secretsmanager_secret.has_admin_username[0].secret_id : var.has_admin_username_secret_arn, + var.has_admin_password_secret_arn == null ? awscc_secretsmanager_secret.has_admin_password[0].secret_id : var.has_admin_password_secret_arn, + ] + } +} + +resource "aws_iam_policy" "HAS_secrets_manager_policy" { + name = "${var.project_prefix}-HAS-secrets-manager-policy" + description = "Policy granting permissions for HAS task execution role to access SSM." + policy = data.aws_iam_policy_document.HAS_secrets_manager_policy.json +} + resource "aws_iam_role" "HAS_task_execution_role" { name = "${var.project_prefix}-HAS-task-execution-role" assume_role_policy = data.aws_iam_policy_document.ecs_tasks_trust_relationship.json - managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"] + managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", aws_iam_policy.HAS_secrets_manager_policy.arn] } diff --git a/modules/perforce/helix-authentication-service/main.tf b/modules/perforce/helix-authentication-service/main.tf index a4893695..0cf9a515 100644 --- a/modules/perforce/helix-authentication-service/main.tf +++ b/modules/perforce/helix-authentication-service/main.tf @@ -25,6 +25,24 @@ resource "aws_ecs_cluster_capacity_providers" "HAS_cluster_fargate_rpvodiers" { } } +resource "awscc_secretsmanager_secret" "has_admin_password" { + count = var.has_admin_password_secret_arn == null && var.enable_web_based_administration == true ? 1 : 0 + name = "hasAdminUserPassword" + description = "The password for the created HAS administrator." + generate_secret_string = { + exclude_numbers = false + exclude_punctuation = true + include_space = false + } +} + +resource "awscc_secretsmanager_secret" "has_admin_username" { + count = var.has_admin_username_secret_arn == null && var.enable_web_based_administration == true ? 1 : 0 + name = "hasAdminUsername" + secret_string = "perforce" +} + + resource "aws_cloudwatch_log_group" "HAS_service_log_group" { #checkov:skip=CKV_AWS_158: KMS Encryption disabled by default name = "${local.name_prefix}-log-group" @@ -40,6 +58,10 @@ resource "aws_ecs_task_definition" "HAS_task_definition" { cpu = var.container_cpu memory = var.container_memory + volume { + name = "helix-auth-config" + } + container_definitions = jsonencode([ { name = var.container_name, @@ -54,7 +76,7 @@ resource "aws_ecs_task_definition" "HAS_task_definition" { protocol = "tcp" } ] - environment = [ + environment = concat([ { name = "SVC_BASE_URL" value = var.fqdn @@ -62,9 +84,16 @@ resource "aws_ecs_task_definition" "HAS_task_definition" { { name = "ADMIN_ENABLED" value = var.enable_web_based_administration ? "true" : "false" - } - ] + }, + ], + var.enable_web_based_administration ? [ + { + name = "ADMIN_PASSWD_FILE", + value = "/var/has/password.txt" + } + ] : [] + ) logConfiguration = { logDriver = "awslogs" options = { @@ -73,8 +102,49 @@ resource "aws_ecs_task_definition" "HAS_task_definition" { awslogs-stream-prefix = "HAS" } } - - readonlyRootFilesystem = false + mountPoints = [ + { + sourceVolume = "helix-auth-config" + containerPath = "/var/has" + } + ], + dependsOn = [ + { + containerName = "has-config" + condition = "COMPLETE" + } + ] + }, + { + name = "has-config" + image = "bash" + essential = false + command = ["sh", "-c", "echo $ADMIN_PASSWD | tee /var/has/password.txt"] + readonly_root_filesystem = false + secrets = var.enable_web_based_administration ? [ + { + name = "ADMIN_USERNAME" + valueFrom = var.has_admin_username_secret_arn != null ? var.has_admin_username_secret_arn : awscc_secretsmanager_secret.has_admin_username[0].secret_id + }, + { + name = "ADMIN_PASSWD" + valueFrom = var.has_admin_password_secret_arn != null ? var.has_admin_username_secret_arn : awscc_secretsmanager_secret.has_admin_password[0].secret_id + }, + ] : [], + logConfiguration = { + logDriver = "awslogs" + options = { + awslogs-group = aws_cloudwatch_log_group.HAS_service_log_group.name + awslogs-region = data.aws_region.current.name + awslogs-stream-prefix = "HAS-config" + } + } + mountPoints = [ + { + sourceVolume = "helix-auth-config" + containerPath = "/var/has" + } + ], } ]) @@ -99,6 +169,8 @@ resource "aws_ecs_service" "HAS_service" { desired_count = var.desired_container_count force_new_deployment = true + enable_execute_command = true + load_balancer { target_group_arn = aws_lb_target_group.HAS_alb_target_group.arn container_name = var.container_name diff --git a/modules/perforce/helix-authentication-service/variables.tf b/modules/perforce/helix-authentication-service/variables.tf index a8f68e49..dc28e612 100644 --- a/modules/perforce/helix-authentication-service/variables.tf +++ b/modules/perforce/helix-authentication-service/variables.tf @@ -182,3 +182,15 @@ variable "create_HAS_default_policy" { description = "Optional creation of Helix Authentication Service default IAM Policy. Default is set to true." default = true } + +variable "has_admin_username_secret_arn" { + type = string + description = "Optionally provide the ARN of an AWS Secret for the HAS Administrator username." + default = null +} + +variable "has_admin_password_secret_arn" { + type = string + description = "Optionally provide the ARN of an AWS Secret for the HAS Administrator password." + default = null +} diff --git a/modules/perforce/helix-authentication-service/versions.tf b/modules/perforce/helix-authentication-service/versions.tf index 27b25203..6e6672b3 100644 --- a/modules/perforce/helix-authentication-service/versions.tf +++ b/modules/perforce/helix-authentication-service/versions.tf @@ -6,6 +6,10 @@ terraform { source = "hashicorp/aws" version = ">= 5.30" } + awscc = { + source = "hashicorp/awscc" + version = ">= 1.2.0" + } random = { source = "hashicorp/random" version = ">=3.6"