Skip to content

Commit

Permalink
Manually update template to 7fcff11e1ebcddaeaa3c73a5f273acb4bd551106
Browse files Browse the repository at this point in the history
  • Loading branch information
rocketnova committed Aug 1, 2024
1 parent befab76 commit fdcebad
Show file tree
Hide file tree
Showing 18 changed files with 404 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .template-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4d6c144a080edf19d5711d7a0a5cc7ac68d20fa2
7fcff11e1ebcddaeaa3c73a5f273acb4bd551106
7 changes: 7 additions & 0 deletions infra/app/app-config/dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ module "dev_config" {
has_database = local.has_database
has_incident_management_service = local.has_incident_management_service

# Enable and configure identity provider.
enable_identity_provider = local.enable_identity_provider

# Support local development against the dev instance.
extra_identity_provider_callback_urls = ["http://localhost"]
extra_identity_provider_logout_urls = ["http://localhost"]

# Enables ECS Exec access for debugging or jump access.
# See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html
# Defaults to `false`. Uncomment the next line to enable.
Expand Down
45 changes: 45 additions & 0 deletions infra/app/app-config/env-config/identity-provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Identity provider configuration.
# If the notification service is configured, the identity provider will use the
# SES-verified email to send notifications.
locals {
# If your application should redirect users, after successful authentication, to a
# page other than the homepage, specify the path fragment here.
# Example: "profile"
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html
callback_url_path = ""

# If your application should redirect users, after signing out, to a page other than
# the homepage, specify the path fragment here.
# Example: "logout"
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html
logout_url_path = ""

identity_provider_config = var.enable_identity_provider ? {
identity_provider_name = "${local.prefix}${var.app_name}-${var.environment}"

password_policy = {
password_minimum_length = 12
temporary_password_validity_days = 7
}

# Optionally configure email template for resetting a password.
# Set any attribute to a non-null value to override AWS Cognito defaults.
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-message-customizations.html
verification_email = {
verification_email_message = null
verification_email_subject = null
}

# Do not modify this block directly.
client = {
callback_urls = concat(
var.domain_name != null ? ["https://${var.domain_name}/${local.callback_url_path}"] : [],
var.extra_identity_provider_callback_urls
)
logout_urls = concat(
var.domain_name != null ? ["https://${var.domain_name}/${local.logout_url_path}"] : [],
var.extra_identity_provider_logout_urls
)
}
} : null
}
16 changes: 16 additions & 0 deletions infra/app/app-config/env-config/notifications.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Notifications configuration
locals {
notifications_config = var.enable_notifications ? {
# Set to an SES-verified email address to be used when sending emails.
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-email.html
sender_email = null

# Configure the name that users see in the "From" section of their inbox, so that it's
# clearer who the email is from.
sender_display_name = null

# Configure the REPLY-TO email address if it should be different from the sender.
# Note: Only used by the identity-provider service.
reply_to_email = null
} : null
}
8 changes: 8 additions & 0 deletions infra/app/app-config/env-config/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ output "service_config" {
}
}

output "identity_provider_config" {
value = local.identity_provider_config
}

output "notifications_config" {
value = local.notifications_config
}

output "storage_config" {
value = {
# Include project name in bucket name since buckets need to be globally unique across AWS
Expand Down
24 changes: 24 additions & 0 deletions infra/app/app-config/env-config/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,35 @@ variable "enable_https" {
default = false
}

variable "enable_identity_provider" {
type = bool
description = "Enables identity provider"
default = false
}

variable "enable_notifications" {
type = bool
description = "Enables notifications"
default = false
}

variable "environment" {
description = "name of the application environment (e.g. dev, staging, prod)"
type = string
}

variable "extra_identity_provider_callback_urls" {
type = list(string)
description = "List of additional URLs that the identity provider will redirect the user to after a successful sign-in. Used for local development."
default = []
}

variable "extra_identity_provider_logout_urls" {
type = list(string)
description = "List of additional URLs that the identity provider will redirect the user to after signing out. Used for local development."
default = []
}

variable "has_database" {
type = bool
}
Expand Down
12 changes: 12 additions & 0 deletions infra/app/app-config/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ locals {

has_incident_management_service = true

# Whether or not the application should deploy an identity provider
# If enabled:
# 1. Creates a Cognito user pool
# 2. Creates a Cognito user pool app client
# 3. Adds environment variables for the app client to the service
enable_identity_provider = false

# Whether or not the application should deploy a notification service
# Note: This is not yet ready for use.
# TODO(https://github.com/navapbc/template-infra/issues/567)
enable_notifications = false

environment_configs = {
dev = module.dev_config
staging = module.staging_config
Expand Down
4 changes: 4 additions & 0 deletions infra/app/app-config/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ output "has_incident_management_service" {
value = local.has_incident_management_service
}

output "enable_identity_provider" {
value = local.enable_identity_provider
}

output "image_repository_name" {
value = local.image_repository_name
}
Expand Down
1 change: 1 addition & 0 deletions infra/app/app-config/prod.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module "prod_config" {
enable_https = false
has_database = local.has_database
has_incident_management_service = local.has_incident_management_service
enable_identity_provider = local.enable_identity_provider

# These numbers are a starting point based on this article
# Update the desired instance size and counts based on the project's specific needs
Expand Down
1 change: 1 addition & 0 deletions infra/app/app-config/staging.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module "staging_config" {
enable_https = false
has_database = local.has_database
has_incident_management_service = local.has_incident_management_service
enable_identity_provider = local.enable_identity_provider

# Enables ECS Exec access for debugging or jump access.
# See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html
Expand Down
72 changes: 58 additions & 14 deletions infra/app/service/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ locals {
database_config = local.environment_config.database_config
storage_config = local.environment_config.storage_config
incident_management_service_integration_config = local.environment_config.incident_management_service_integration
identity_provider_config = local.environment_config.identity_provider_config
notifications_config = local.environment_config.notifications_config

network_config = module.project_config.network_configs[local.environment_config.network_name]
}
Expand Down Expand Up @@ -150,22 +152,38 @@ module "service" {
}
} : null

extra_environment_variables = merge({
FEATURE_FLAGS_PROJECT = module.feature_flags.evidently_project_name
BUCKET_NAME = local.storage_config.bucket_name
}, local.service_config.extra_environment_variables)

secrets = [
for secret_name in keys(local.service_config.secrets) : {
extra_environment_variables = merge(
{
FEATURE_FLAGS_PROJECT = module.feature_flags.evidently_project_name
BUCKET_NAME = local.storage_config.bucket_name
},
module.app_config.enable_identity_provider ? {
COGNITO_USER_POOL_ID = module.identity_provider[0].user_pool_id
COGNITO_CLIENT_ID = module.identity_provider_client[0].client_id
} : {},
local.service_config.extra_environment_variables
)

secrets = concat(
[for secret_name in keys(local.service_config.secrets) : {
name = secret_name
valueFrom = module.secrets[secret_name].secret_arn
}
]

extra_policies = {
feature_flags_access = module.feature_flags.access_policy_arn,
storage_access = module.storage.access_policy_arn
}
}],
module.app_config.enable_identity_provider ? [{
name = "COGNITO_CLIENT_SECRET"
valueFrom = module.identity_provider_client[0].client_secret_arn
}] : []
)

extra_policies = merge(
{
feature_flags_access = module.feature_flags.access_policy_arn,
storage_access = module.storage.access_policy_arn
},
module.app_config.enable_identity_provider ? {
identity_provider_access = module.identity_provider_client[0].access_policy_arn,
} : {}
)

is_temporary = local.is_temporary
}
Expand All @@ -192,3 +210,29 @@ module "storage" {
name = local.storage_config.bucket_name
is_temporary = local.is_temporary
}

module "identity_provider" {
count = module.app_config.enable_identity_provider ? 1 : 0
source = "../../modules/identity-provider"
is_temporary = local.is_temporary

name = local.identity_provider_config.identity_provider_name
password_minimum_length = local.identity_provider_config.password_policy.password_minimum_length
temporary_password_validity_days = local.identity_provider_config.password_policy.temporary_password_validity_days
verification_email_message = local.identity_provider_config.verification_email.verification_email_message
verification_email_subject = local.identity_provider_config.verification_email.verification_email_subject

sender_email = local.notifications_config == null ? null : local.notifications_config.sender_email
sender_display_name = local.notifications_config == null ? null : local.notifications_config.sender_display_name
reply_to_email = local.notifications_config == null ? null : local.notifications_config.reply_to_email
}

module "identity_provider_client" {
count = module.app_config.enable_identity_provider ? 1 : 0
source = "../../modules/identity-provider-client"

name = local.identity_provider_config.identity_provider_name
cognito_user_pool_id = module.identity_provider[0].user_pool_id
callback_urls = local.identity_provider_config.client.callback_urls
logout_urls = local.identity_provider_config.client.logout_urls
}
15 changes: 15 additions & 0 deletions infra/modules/identity-provider-client/access-control.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

resource "aws_iam_policy" "cognito_access" {
name = "${var.name}-cognito-access"
policy = data.aws_iam_policy_document.cognito_access.json
}

data "aws_iam_policy_document" "cognito_access" {
statement {
actions = ["cognito-idp:*"]
effect = "Allow"
resources = ["arn:aws:cognito-idp:${data.aws_region.current.name}:${data.aws_caller_identity.current.id}:userpool/${var.cognito_user_pool_id}"]
}
}
37 changes: 37 additions & 0 deletions infra/modules/identity-provider-client/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
resource "aws_cognito_user_pool_client" "client" {
name = var.name
user_pool_id = var.cognito_user_pool_id

callback_urls = var.callback_urls
logout_urls = var.logout_urls
supported_identity_providers = ["COGNITO"]
refresh_token_validity = 1
access_token_validity = 60
id_token_validity = 60
token_validity_units {
refresh_token = "days"
access_token = "minutes"
id_token = "minutes"
}

generate_secret = true
allowed_oauth_flows_user_pool_client = true
allowed_oauth_flows = ["code"]
allowed_oauth_scopes = ["phone", "email", "openid", "profile"]
explicit_auth_flows = ["ALLOW_ADMIN_USER_PASSWORD_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"]

# Avoid security issue where error messages indicate when a user doesn't exist
prevent_user_existence_errors = "ENABLED"

enable_token_revocation = true
enable_propagate_additional_user_context_data = false

read_attributes = ["email", "email_verified", "phone_number", "phone_number_verified", "updated_at"]
write_attributes = ["email", "updated_at", "phone_number"]
}

resource "aws_ssm_parameter" "client_secret" {
name = "/${var.name}/identity-provider/client-secret"
type = "SecureString"
value = aws_cognito_user_pool_client.client.client_secret
}
13 changes: 13 additions & 0 deletions infra/modules/identity-provider-client/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
output "access_policy_arn" {
value = aws_iam_policy.cognito_access.arn
}

output "client_id" {
description = "The ID of the user pool client"
value = aws_cognito_user_pool_client.client.id
}

output "client_secret_arn" {
description = "The arn for the SSM parameter storing the user pool client secret"
value = aws_ssm_parameter.client_secret.arn
}
21 changes: 21 additions & 0 deletions infra/modules/identity-provider-client/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
variable "callback_urls" {
type = list(string)
description = "The URL(s) that the identity provider will redirect to after a successful login"
default = []
}

variable "cognito_user_pool_id" {
type = string
description = "The ID of the user pool that the client will be associated with"
}

variable "logout_urls" {
type = list(string)
description = "The URL that the identity provider will redirect to after a successful logout"
default = []
}

variable "name" {
type = string
description = "Name of the application or service that will act as a client to the identity provider"
}
Loading

1 comment on commit fdcebad

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for app

St.
Category Percentage Covered / Total
🟢 Statements 93.1% 81/87
🟢 Branches 82.35% 14/17
🟢 Functions 93.33% 14/15
🟢 Lines 93.59% 73/78

Test suite run success

16 tests passing in 5 suites.

Report generated by 🧪jest coverage report action from fdcebad

Please sign in to comment.