diff --git a/modules/aws-rds-aurora/sql-server.tf b/modules/aws-rds-aurora/sql-server.tf index d536e1a..83a47f8 100644 --- a/modules/aws-rds-aurora/sql-server.tf +++ b/modules/aws-rds-aurora/sql-server.tf @@ -234,7 +234,7 @@ resource "aws_iam_role" "monitoring_role" { resource "aws_db_option_group" "this" { count = var.enable_custom_option_group ? 1 : 0 - name = "${var.name}-option-group" + name = "${var.db_group_name}-option-group" option_group_description = "RDS SSRS and SSIS Option Group" engine_name = var.engine major_engine_version = var.option_group_engine_version @@ -264,7 +264,7 @@ resource "aws_db_option_group" "this" { resource "aws_db_parameter_group" "sql_server" { count = var.enable_custom_parameter_group ? 1 : 0 - name = "${var.name}-paramater-group" + name = "${var.db_group_name}-paramater-group" family = var.db_parameter_group_family dynamic "parameter" { @@ -358,9 +358,20 @@ resource "aws_db_instance" "rds_sql_server_read_replica" { kms_key_id = var.kms_key_id parameter_group_name = var.custom_db_paramater_group_name + + domain_ou = var.ad_domain_ou + domain_fqdn = var.ad_domain_fqdn + domain_dns_ips = var.ad_domain_dns_ips + domain_auth_secret_arn = var.ad_domain_auth_secret_arn + storage_type = var.storage_type storage_encrypted = var.storage_encrypted + monitoring_interval = 60 + monitoring_role_arn = aws_iam_role.monitoring_role[0].arn + performance_insights_enabled = true + enabled_cloudwatch_logs_exports = ["error"] + vpc_security_group_ids = compact(concat([try(aws_security_group.this[0].id, "")], var.vpc_security_group_ids)) replicate_source_db = element(aws_db_instance.rds_sql_server[*].identifier, 0) diff --git a/modules/aws-rds-aurora/variables.tf b/modules/aws-rds-aurora/variables.tf index 2f41b1b..fc89263 100644 --- a/modules/aws-rds-aurora/variables.tf +++ b/modules/aws-rds-aurora/variables.tf @@ -540,6 +540,11 @@ variable "ad_domain_auth_secret_arn" { description = "AD Domain Secret ARN for RDS SQL Server" } +variable "db_group_name" { + type = string + description = "DB parameter and option group name prefix" +} + variable "option_group" { type = list(object({ option_name = string diff --git a/modules/aws-rds-sql-server-read-replica/sql-server.tf b/modules/aws-rds-sql-server-read-replica/sql-server.tf new file mode 100644 index 0000000..a1b9506 --- /dev/null +++ b/modules/aws-rds-sql-server-read-replica/sql-server.tf @@ -0,0 +1,187 @@ + +locals { + port = coalesce(var.port, (var.engine == "aurora-postgresql" ? 5432 : 1433)) +} + + + +################################################################################ +# Security Group +################################################################################ + +resource "aws_security_group" "this" { + count = var.create_security_group ? 1 : 0 + + name = var.security_group_use_name_prefix ? null : var.name + name_prefix = var.security_group_use_name_prefix ? "${var.name}-sql-server" : null + vpc_id = var.vpc_id + description = coalesce(var.security_group_description, "Control traffic to/from RDS Aurora ${var.name}") + + tags = merge(var.tags, var.security_group_tags, { Name = var.name }) + + lifecycle { + create_before_destroy = true + } +} + +# TODO - change to map of ingress rules under one resource at next breaking change +resource "aws_security_group_rule" "default_ingress" { + count = var.create_security_group ? length(var.allowed_security_groups) : 0 + + description = "From allowed SGs" + + type = "ingress" + from_port = local.port + to_port = local.port + protocol = "tcp" + source_security_group_id = element(var.allowed_security_groups, count.index) + security_group_id = aws_security_group.this[0].id +} + +# TODO - change to map of ingress rules under one resource at next breaking change +resource "aws_security_group_rule" "cidr_ingress" { + count = var.create_security_group && length(var.allowed_cidr_blocks) > 0 ? 1 : 0 + + description = "From allowed CIDRs" + + type = "ingress" + from_port = local.port + to_port = local.port + protocol = "tcp" + cidr_blocks = var.allowed_cidr_blocks + security_group_id = aws_security_group.this[0].id +} + +resource "aws_security_group_rule" "egress" { + for_each = var.create_security_group ? var.security_group_egress_rules : {} + + # required + type = "egress" + from_port = try(each.value.from_port, local.port) + to_port = try(each.value.to_port, local.port) + protocol = try(each.value.protocol, null) + security_group_id = aws_security_group.this[0].id + + # optional + cidr_blocks = try(each.value.cidr_blocks, null) + description = try(each.value.description, null) + ipv6_cidr_blocks = try(each.value.ipv6_cidr_blocks, null) + prefix_list_ids = try(each.value.prefix_list_ids, null) + source_security_group_id = try(each.value.source_security_group_id, null) +} + + +############################# +# Amazon RDS for SQL Server # +############################# + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com", "monitoring.rds.amazonaws.com"] + } + + actions = ["sts:AssumeRole"] + } +} + +resource "aws_iam_role" "monitoring_role" { + name = "${var.name}-monitoring-role" + assume_role_policy = data.aws_iam_policy_document.assume_role.json + managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"] +} + + +resource "aws_db_option_group" "this" { + count = var.enable_custom_option_group ? 1 : 0 + name = "${var.db_group_name}-option-group" + option_group_description = "RDS SSRS and SSIS Option Group" + engine_name = var.engine + major_engine_version = var.option_group_engine_version + + option { + option_name = var.option_name + } + + dynamic "option" { + for_each = var.enable_custom_option_group ? var.option_group : [] + + content { + option_name = option.value.option_name + vpc_security_group_memberships = var.allowed_security_groups + #db_security_group_memberships = var.allowed_security_groups + dynamic "option_settings" { + for_each = can(option.value.option_rule_names[*]) ? option.value.option_rule_names : null + content { + name = option_settings.value.rule_name + value = option_settings.value.option_rule_value + } + } + } + } +} + + +resource "aws_db_parameter_group" "sql_server" { + count = var.enable_custom_parameter_group ? 1 : 0 + name = "${var.db_group_name}-paramater-group" + family = var.db_parameter_group_family + + dynamic "parameter" { + for_each = var.enable_custom_parameter_group ? var.parameter_group : [] + content { + name = parameter.value.parameter_name + value = parameter.value.parameter_value + apply_method = parameter.value.parameter_apply_method + } + } +} + +resource "aws_db_instance" "rds_sql_server_read_replica" { + + engine = var.engine + engine_version = var.engine_version + port = 1433 + + identifier = var.instances_use_identifier_prefix ? null : "${var.name}-sql-server" + + allow_major_version_upgrade = var.allow_major_version_upgrade + apply_immediately = var.apply_immediately + + + maintenance_window = var.preferred_maintenance_window + deletion_protection = var.deletion_protection + + copy_tags_to_snapshot = var.copy_tags_to_snapshot + skip_final_snapshot = var.skip_final_snapshot + + instance_class = var.instance_class + kms_key_id = var.kms_key_id + parameter_group_name = var.enable_custom_parameter_group ? aws_db_parameter_group.sql_server[0].name : var.db_parameter_group_name + option_group_name = var.enable_custom_option_group ? aws_db_option_group.this[0].name : var.db_parameter_group_name + + storage_type = var.storage_type + storage_encrypted = var.storage_encrypted + max_allocated_storage = var.max_allocated_storage + + monitoring_interval = var.monitoring_interval + monitoring_role_arn = aws_iam_role.monitoring_role.arn + performance_insights_enabled = var.performance_insights_enabled + enabled_cloudwatch_logs_exports = var.logs_exports + + + + vpc_security_group_ids = compact(concat([try(aws_security_group.this[0].id, "")], var.vpc_security_group_ids)) + + replicate_source_db = var.replication_source_identifier + + timeouts { + create = "80m" + } + + tags = var.tags +} + diff --git a/modules/aws-rds-sql-server-read-replica/variables.tf b/modules/aws-rds-sql-server-read-replica/variables.tf new file mode 100644 index 0000000..9e6ee5d --- /dev/null +++ b/modules/aws-rds-sql-server-read-replica/variables.tf @@ -0,0 +1,457 @@ +variable "name" { + description = "Name used across resources created" + type = string + default = "" +} + +variable "tags" { + description = "A map of tags to add to all resources" + type = map(string) + default = {} +} + +################################################################################ +# Random Password & Snapshot ID +################################################################################ + +variable "create_random_password" { + description = "Determines whether to create random password for RDS primary cluster" + type = bool + default = false +} + +variable "random_password_length" { + description = "Length of random password to create. Defaults to `10`" + type = number + default = 10 +} + + +################################################################################ +# Replica +################################################################################ + +variable "allocated_storage" { + description = "The amount of storage in gibibytes (GiB) to allocate to each DB instance in the Multi-AZ DB cluster. (This setting is required to create a Multi-AZ DB cluster)" + type = number + default = null +} + +variable "allow_major_version_upgrade" { + description = "Enable to allow major engine version upgrades when changing engine versions. Defaults to `false`" + type = bool + default = false +} + +variable "apply_immediately" { + description = "Specifies whether any cluster modifications are applied immediately, or during the next maintenance window. Default is `false`" + type = bool + default = null +} + + +variable "backup_retention_period" { + description = "The days to retain backups for. Default `7`" + type = number + default = 7 +} + +variable "deletion_protection" { + description = "If the DB instance should have deletion protection enabled. The database can't be deleted when this value is set to `true`. The default is `false`" + type = bool + default = true +} + +variable "engine" { + description = "The name of the database engine to be used for this DB cluster. Defaults to `aurora`. Valid Values: `aurora`, `aurora-mysql`, `aurora-postgresql`" + type = string + default = null +} + +variable "engine_mode" { + description = "The database engine mode. Valid values: `global`, `multimaster`, `parallelquery`, `provisioned`, `serverless`. Defaults to: `provisioned`" + type = string + default = null +} + +variable "engine_version" { + description = "The database engine version. Updating this argument results in an outage" + type = string + default = null +} + +variable "master_password" { + description = "Password for the master DB user. Note - when specifying a value here, 'create_random_password' should be set to `false`" + type = string + default = null +} + +variable "master_username" { + description = "Username for the master DB user" + type = string + default = "root" +} + +variable "port" { + description = "The port on which the DB accepts connections" + type = string + default = null +} + +variable "preferred_backup_window" { + description = "The daily time range during which automated backups are created if automated backups are enabled using the `backup_retention_period` parameter. Time in UTC" + type = string + default = "02:00-03:00" +} + +variable "preferred_maintenance_window" { + description = "The weekly time range during which system maintenance can occur, in (UTC)" + type = string + default = "sun:05:00-sun:06:00" +} + +variable "replication_source_identifier" { + description = "ARN of a source DB cluster or DB instance if this DB cluster is to be created as a Read Replica" + type = string + default = null +} + +variable "skip_final_snapshot" { + description = "Determines whether a final snapshot is created before the cluster is deleted. If true is specified, no snapshot is created" + type = bool + default = null +} + +variable "snapshot_identifier" { + description = "Specifies whether or not to create this cluster from a snapshot. You can use either the name or ARN when specifying a DB cluster snapshot, or the ARN when specifying a DB snapshot" + type = string + default = null +} + +variable "storage_encrypted" { + description = "Specifies whether the DB cluster is encrypted. The default is `true`" + type = bool + default = true +} + +variable "storage_type" { + description = "Specifies the storage type to be associated with the DB cluster. (This setting is required to create a Multi-AZ DB cluster). Valid values: `io1`, Default: `io1`" + type = string + default = null +} + +variable "vpc_security_group_ids" { + description = "List of VPC security groups to associate to the cluster in addition to the SG we create in this module" + type = list(string) + default = [] +} + + +################################################################################ +# Cluster Instance(s) +################################################################################ + +variable "db_parameter_group_name" { + description = "The name of the DB parameter group" + type = string + default = null +} + +variable "instances_use_identifier_prefix" { + description = "Determines whether cluster instance identifiers are used as prefixes" + type = bool + default = false +} + +variable "instance_class" { + description = "Instance type to use at master instance. Note: if `autoscaling_enabled` is `true`, this will be the same instance class used on instances created by autoscaling" + type = string + default = "" +} + + +################################################################################ +# Enhanced Monitoring +################################################################################ + +variable "create_monitoring_role" { + description = "Determines whether to create the IAM role for RDS enhanced monitoring" + type = bool + default = true +} + +variable "monitoring_role_arn" { + description = "IAM role used by RDS to send enhanced monitoring metrics to CloudWatch" + type = string + default = "" +} + +variable "iam_role_name" { + description = "Friendly name of the monitoring role" + type = string + default = null +} + +variable "iam_role_use_name_prefix" { + description = "Determines whether to use `iam_role_name` as is or create a unique name beginning with the `iam_role_name` as the prefix" + type = bool + default = false +} + +variable "iam_role_description" { + description = "Description of the monitoring role" + type = string + default = null +} + +variable "iam_role_path" { + description = "Path for the monitoring role" + type = string + default = null +} + +variable "iam_role_managed_policy_arns" { + description = "Set of exclusive IAM managed policy ARNs to attach to the monitoring role" + type = list(string) + default = null +} + +variable "iam_role_permissions_boundary" { + description = "The ARN of the policy that is used to set the permissions boundary for the monitoring role" + type = string + default = null +} + +variable "iam_role_force_detach_policies" { + description = "Whether to force detaching any policies the monitoring role has before destroying it" + type = bool + default = null +} + +variable "monitoring_interval" { + description = "Monitoring interval second" + type = number + default = 60 +} + +variable "performance_insights_enabled" { + description = "performance enablement " + type = bool + default = true +} + +variable "logs_exports" { + description = "Log exports" + type = list(string) + default = ["error"] +} + +variable "iam_role_max_session_duration" { + description = "Maximum session duration (in seconds) that you want to set for the monitoring role" + type = number + default = null +} + +############################# +# Amazon RDS for SQL Server # +############################# + +variable "rds_sql" { + type = bool + description = "this is value to enable RDS SQL" + default = false +} + +variable "custom_db_paramater_group_name" { + type = string + description = "the paramater group name" + default = "" +} + +variable "custom_db_option_group_name" { + type = string + description = "the option group name" + default = "" +} + +variable "multi_az" { + type = bool + default = false + description = "Multi Availibity Zone" +} + +variable "read_replica" { + type = bool + default = false + description = "Read replica for RDS" +} + +variable "db_group_name" { + type = string + description = "DB parameter and option group name prefix" + default = null +} + +variable "option_group" { + type = list(object({ + option_name = string + option_rule_names = optional(list(object({ + rule_name = string + option_rule_value = any + }))) + })) + default = null +} + +variable "parameter_group" { + type = list(object({ + parameter_name = string + parameter_value = any + parameter_apply_method = string + })) + default = null +} + +variable "enable_custom_option_group" { + type = bool + default = false + description = "Custom Option Group Creation" +} + +variable "enable_custom_parameter_group" { + type = bool + default = false + description = "Custom Paramater Group Creation" +} + +variable "max_allocated_storage" { + description = "The amount of storage in gibibytes (GiB) to allocate to each DB instance in the Multi-AZ DB cluster. (This setting is required to create a Multi-AZ DB cluster)" + type = number + default = null +} + +variable "option_group_engine_version" { + type = string + default = "16.00" + description = "Option Group Major engine version" +} + +variable "option_name" { + type = string + description = "Option name for without option settings of ptions" + default = "" +} + +variable "copy_tags_to_snapshot" { + description = "Copy all Cluster `tags` to snapshots" + type = bool + default = true +} + +################################################################################ +# Security Group +################################################################################ + +variable "create_security_group" { + description = "Determines whether to create security group for RDS cluster" + type = bool + default = true +} + +variable "security_group_use_name_prefix" { + description = "Determines whether the security group name (`name`) is used as a prefix" + type = bool + default = true +} + +variable "security_group_description" { + description = "The description of the security group. If value is set to empty string it will contain cluster name in the description" + type = string + default = null +} + +variable "vpc_id" { + description = "ID of the VPC where to create security group" + type = string + default = "" +} + +variable "allowed_security_groups" { + description = "A list of Security Group ID's to allow access to" + type = list(string) + default = [] +} + +variable "allowed_cidr_blocks" { + description = "A list of CIDR blocks which are allowed to access the database" + type = list(string) + default = [] +} + +variable "security_group_egress_rules" { + description = "A map of security group egress rule definitions to add to the security group created" + type = map(any) + default = {} +} + +variable "security_group_tags" { + description = "Additional tags for the security group" + type = map(string) + default = {} +} + +################################################################################ +# DB Subnet Group +################################################################################ + +variable "subnet_id_names" { + description = "name of subnet ID's" + type = string + default = "*" +} + +################################################################################ +# DB Parameter Group +################################################################################ + + +variable "create_db_parameter_group" { + description = "Determines whether a DB parameter should be created or use existing" + type = bool + default = false +} + +variable "db_parameter_group_use_name_prefix" { + description = "Determines whether the DB parameter group name is used as a prefix" + type = bool + default = true +} + +variable "db_parameter_group_description" { + description = "The description of the DB parameter group. Defaults to \"Managed by Terraform\"" + type = string + default = null +} + +variable "db_parameter_group_family" { + description = "The family of the DB parameter group" + type = string + default = "" +} + +variable "db_parameter_group_parameters" { + description = "A list of DB parameters to apply. Note that parameters may differ from a family to an other" + type = list(map(string)) + default = [] +} + +variable "kms_key_id" { + description = "The key ID of the KMS key" + default = null +} + +variable "kms_multi_region" { + description = "Determine whether the KMS key is multi region support" + type = bool + default = false +}