Skip to content
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

Added support for IAM based auth and managing master user password in secrets manager #11

Merged
merged 2 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,47 @@ Truefoundry AWS Control Plane Module
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.4 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | 5.32.1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | 5.44.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | 3.5.1 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.32.1 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.44.0 |
| <a name="provider_random"></a> [random](#provider\_random) | 3.5.1 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_truefoundry_bucket"></a> [truefoundry\_bucket](#module\_truefoundry\_bucket) | terraform-aws-modules/s3-bucket/aws | 3.14.0 |
| <a name="module_truefoundry_oidc_iam"></a> [truefoundry\_oidc\_iam](#module\_truefoundry\_oidc\_iam) | terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc | 5.27.0 |
| <a name="module_truefoundry_oidc_iam"></a> [truefoundry\_oidc\_iam](#module\_truefoundry\_oidc\_iam) | terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc | 5.39.0 |

## Resources

| Name | Type |
|------|------|
| [aws_db_instance.truefoundry_db](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/db_instance) | resource |
| [aws_db_subnet_group.rds](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/db_subnet_group) | resource |
| [aws_iam_policy.svcfoundry_access_to_multitenant_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/iam_policy) | resource |
| [aws_iam_policy.svcfoundry_access_to_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/iam_policy) | resource |
| [aws_iam_policy.truefoundry_assume_role_all](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/iam_policy) | resource |
| [aws_iam_policy.truefoundry_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/iam_policy) | resource |
| [aws_security_group.rds](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/security_group) | resource |
| [aws_security_group.rds-public](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/resources/security_group) | resource |
| [aws_db_instance.truefoundry_db](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/db_instance) | resource |
| [aws_db_subnet_group.rds](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/db_subnet_group) | resource |
| [aws_iam_policy.svcfoundry_access_to_multitenant_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/iam_policy) | resource |
| [aws_iam_policy.svcfoundry_access_to_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/iam_policy) | resource |
| [aws_iam_policy.truefoundry_assume_role_all](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/iam_policy) | resource |
| [aws_iam_policy.truefoundry_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/iam_policy) | resource |
| [aws_iam_policy.truefoundry_db_iam_auth_policy](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/iam_policy) | resource |
| [aws_kms_alias.truefoundry_db_master_user_secret_kms](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/kms_alias) | resource |
| [aws_kms_key.truefoundry_db_master_user_secret_kms_key](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/kms_key) | resource |
| [aws_secretsmanager_secret_rotation.turefoundry_db_secret_rotation](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/secretsmanager_secret_rotation) | resource |
| [aws_security_group.rds](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/security_group) | resource |
| [aws_security_group.rds-public](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/resources/security_group) | resource |
| [random_password.truefoundry_db_password](https://registry.terraform.io/providers/hashicorp/random/3.5.1/docs/resources/password) | resource |
| [aws_iam_policy.servicefoundry_ecr_policy](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy_document.svcfoundry_access_to_multitenant_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.svcfoundry_access_to_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_assume_role_all](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.32.1/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy.servicefoundry_ecr_policy](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy_document.svcfoundry_access_to_multitenant_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.svcfoundry_access_to_ssm](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_assume_role_all](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_db_iam_auth_policy_document](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.truefoundry_db_master_user_secret_kms_policy](https://registry.terraform.io/providers/hashicorp/aws/5.44.0/docs/data-sources/iam_policy_document) | data source |

## Inputs

Expand All @@ -52,6 +58,12 @@ Truefoundry AWS Control Plane Module
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | EKS Cluster region | `string` | n/a | yes |
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Cluster name | `string` | n/a | yes |
| <a name="input_cluster_oidc_issuer_url"></a> [cluster\_oidc\_issuer\_url](#input\_cluster\_oidc\_issuer\_url) | The oidc url of the eks cluster | `string` | n/a | yes |
| <a name="input_iam_database_authentication_enabled"></a> [iam\_database\_authentication\_enabled](#input\_iam\_database\_authentication\_enabled) | Enable IAM database authentication | `bool` | `false` | no |
| <a name="input_manage_master_user_password"></a> [manage\_master\_user\_password](#input\_manage\_master\_user\_password) | Enable master user password management. If set to true master user management is done by RDS in secrets manager, if false a random password is generated | `bool` | `false` | no |
| <a name="input_manage_master_user_password_rotation"></a> [manage\_master\_user\_password\_rotation](#input\_manage\_master\_user\_password\_rotation) | Enable master user password rotation | `bool` | `false` | no |
| <a name="input_master_user_password_rotate_immediately"></a> [master\_user\_password\_rotate\_immediately](#input\_master\_user\_password\_rotate\_immediately) | Rotate master user password immediately | `bool` | `false` | no |
| <a name="input_master_user_password_rotation_automatically_after_days"></a> [master\_user\_password\_rotation\_automatically\_after\_days](#input\_master\_user\_password\_rotation\_automatically\_after\_days) | Rotate master user password automatically after days | `number` | `90` | no |
| <a name="input_master_user_password_rotation_duration"></a> [master\_user\_password\_rotation\_duration](#input\_master\_user\_password\_rotation\_duration) | Master user password rotation duration | `string` | `"3h"` | no |
| <a name="input_mlfoundry_k8s_namespace"></a> [mlfoundry\_k8s\_namespace](#input\_mlfoundry\_k8s\_namespace) | The k8s mlfoundry namespace | `string` | n/a | yes |
| <a name="input_mlfoundry_k8s_service_account"></a> [mlfoundry\_k8s\_service\_account](#input\_mlfoundry\_k8s\_service\_account) | The k8s mlfoundry service account name | `string` | n/a | yes |
| <a name="input_mlfoundry_name"></a> [mlfoundry\_name](#input\_mlfoundry\_name) | Name of mlfoundry deployment | `string` | n/a | yes |
Expand Down
20 changes: 20 additions & 0 deletions iam-rds.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# policy for IAM based authentication to RDS
data "aws_iam_policy_document" "truefoundry_db_iam_auth_policy_document" {
statement {
effect = "Allow"
actions = [
"rds-db:connect"
]
resources = [
"arn:aws:rds-db:${var.aws_region}:${var.aws_account_id}:dbuser:${aws_db_instance.truefoundry_db.id}/*"
]
}
}

# we cannnot apply count here as module.truefoundry_oidc_iam requires fixed no of role_policy_arns
resource "aws_iam_policy" "truefoundry_db_iam_auth_policy" {
name_prefix = "${local.svcfoundry_unique_name}-db-iam-auth-policy"
description = "IAM based authentication policy for ${var.svcfoundry_name} and ${var.mlfoundry_name} in cluster ${var.cluster_name}"
policy = data.aws_iam_policy_document.truefoundry_db_iam_auth_policy_document.json
tags = local.tags
}
5 changes: 3 additions & 2 deletions iam-sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ data "aws_iam_policy" "servicefoundry_ecr_policy" {

module "truefoundry_oidc_iam" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "5.27.0"
version = "5.39.0"

create_role = true
role_name = "${var.cluster_name}-truefoundry-deps"
Expand All @@ -21,7 +21,8 @@ module "truefoundry_oidc_iam" {
aws_iam_policy.svcfoundry_access_to_ssm.arn,
aws_iam_policy.svcfoundry_access_to_multitenant_ssm.arn,
aws_iam_policy.truefoundry_assume_role_all.arn,
data.aws_iam_policy.servicefoundry_ecr_policy.arn
data.aws_iam_policy.servicefoundry_ecr_policy.arn,
aws_iam_policy.truefoundry_db_iam_auth_policy.arn,
]
tags = local.tags
}
27 changes: 27 additions & 0 deletions kms.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
resource "aws_kms_key" "truefoundry_db_master_user_secret_kms_key" {
count = var.manage_master_user_password ? 1 : 0
enable_key_rotation = true
description = "Truefoundry RDS Postgres Database encryption key"
policy = data.aws_iam_policy_document.truefoundry_db_master_user_secret_kms_policy[0].json
tags = local.tags
}

resource "aws_kms_alias" "truefoundry_db_master_user_secret_kms" {
count = var.manage_master_user_password ? 1 : 0
name = "alias/${var.cluster_name}-db-kms"
target_key_id = aws_kms_key.truefoundry_db_master_user_secret_kms_key[0].id
}

data "aws_iam_policy_document" "truefoundry_db_master_user_secret_kms_policy" {
count = var.manage_master_user_password ? 1 : 0
version = "2012-10-17"
statement {
effect = "Allow"
actions = ["kms:*"]
principals {
identifiers = ["arn:aws:iam::${var.aws_account_id}:root"]
type = "AWS"
}
resources = ["*"]
}
}
17 changes: 16 additions & 1 deletion rds.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
resource "random_password" "truefoundry_db_password" {
count = var.manage_master_user_password ? 0 : 1
length = 24
special = true
override_special = "#%&*()-_=+[]{}<>:"
Expand Down Expand Up @@ -65,16 +66,30 @@ resource "aws_db_instance" "truefoundry_db" {
identifier_prefix = var.truefoundry_db_enable_override ? null : local.truefoundry_db_unique_name
db_name = local.truefoundry_db_database_name
skip_final_snapshot = var.truefoundry_db_skip_final_snapshot
password = random_password.truefoundry_db_password.result
password = var.manage_master_user_password ? null : random_password.truefoundry_db_password[0].result
manage_master_user_password = var.manage_master_user_password ? true : null
master_user_secret_kms_key_id = var.manage_master_user_password ? aws_kms_key.truefoundry_db_master_user_secret_kms_key[0].arn : null
final_snapshot_identifier = var.truefoundry_db_skip_final_snapshot ? null : "${local.truefoundry_db_database_name}-${formatdate("DD-MM-YYYY-hh-mm-ss", timestamp())}"
backup_retention_period = var.truefoundry_db_backup_retention_period
instance_class = var.truefoundry_db_instance_class
performance_insights_enabled = var.truefoundry_db_enable_insights
performance_insights_retention_period = var.truefoundry_db_enable_insights ? 31 : 0
publicly_accessible = var.truefoundry_db_publicly_accessible
deletion_protection = var.truefoundry_db_deletion_protection
iam_database_authentication_enabled = var.iam_database_authentication_enabled
apply_immediately = true
storage_encrypted = var.truefoundry_db_storage_encrypted
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
storage_type = var.truefoundry_db_storage_type
iops = var.truefoundry_db_storage_iops == 0 ? null : var.truefoundry_db_storage_iops
}

resource "aws_secretsmanager_secret_rotation" "turefoundry_db_secret_rotation" {
count = var.manage_master_user_password ? var.manage_master_user_password_rotation ? 1 : 0 : 0
secret_id = aws_db_instance.truefoundry_db.master_user_secret[0].secret_arn
rotate_immediately = var.master_user_password_rotate_immediately
rotation_rules {
automatically_after_days = var.master_user_password_rotation_automatically_after_days
duration = var.master_user_password_rotation_duration
}
}
42 changes: 39 additions & 3 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ variable "truefoundry_db_publicly_accessible" {
}

variable "truefoundry_db_backup_retention_period" {
type = number
default = 14
type = number
default = 14
description = "Backup retention period for RDS"
}

Expand Down Expand Up @@ -142,6 +142,42 @@ variable "truefoundry_db_multiple_az" {
default = false
}

variable "iam_database_authentication_enabled" {
description = "Enable IAM database authentication"
type = bool
default = false
}

variable "manage_master_user_password" {
description = "Enable master user password management. If set to true master user management is done by RDS in secrets manager, if false a random password is generated"
type = bool
default = false
}

variable "manage_master_user_password_rotation" {
description = "Enable master user password rotation"
type = bool
default = false
}

variable "master_user_password_rotate_immediately" {
description = "Rotate master user password immediately"
type = bool
default = false
}

variable "master_user_password_rotation_automatically_after_days" {
description = "Rotate master user password automatically after days"
type = number
default = 90
}

variable "master_user_password_rotation_duration" {
description = "Master user password rotation duration"
type = string
default = "3h"
}

##################################################################################
## Mlfoundry bucket
##################################################################################
Expand All @@ -151,6 +187,7 @@ variable "truefoundry_s3_enable_override" {
type = bool
default = false
}

variable "truefoundry_s3_override_name" {
description = "Override name for s3 bucket. truefoundry_s3_enable_override must be set true"
type = string
Expand Down Expand Up @@ -192,7 +229,6 @@ variable "truefoundry_s3_cors_origins" {
default = ["*"]
}


##################################################################################
## MLfoundry service account
##################################################################################
Expand Down
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.32.1"
version = "5.44.0"
}
random = {
source = "hashicorp/random"
Expand Down