diff --git a/README.md b/README.md
index 35cd4f5..6da452c 100644
--- a/README.md
+++ b/README.md
@@ -25,9 +25,14 @@ Terraform modules that provide a consistent interface for provisioning AWS cloud
- **Lambda** - Serverless functions with container support and VPC integration
- **Fargate** - Container orchestration with ECS and load balancer integration
+### Database
+- **RDS Instance** - Managed PostgreSQL database instances with automated backups
+- **RDS Database** - PostgreSQL database and role provisioning within RDS instances
+
### Networking
- **VPC** - Virtual private clouds with public/private subnets and NAT gateways
- **Load Balancer** - Application and network load balancers for traffic distribution
+- **Security Group Rule** - Firewall rules for controlling inbound and outbound traffic
### Identity
- **IAM Role** - Identity and access management roles with trust policies
diff --git a/rds-database/icon.svg b/rds-database/icon.svg
new file mode 100644
index 0000000..1b5712b
--- /dev/null
+++ b/rds-database/icon.svg
@@ -0,0 +1,17 @@
+
+
diff --git a/rds-database/manifest.yaml b/rds-database/manifest.yaml
new file mode 100644
index 0000000..6d5ee1a
--- /dev/null
+++ b/rds-database/manifest.yaml
@@ -0,0 +1,45 @@
+name: rds-database
+display_name: RDS PostgreSQL Database
+type: database
+description: "Creates a PostgreSQL database on an existing RDS instance with automatic credential generation and service injection"
+icon: ./icon.svg
+deployment:
+ terraform: ./module
+
+inputs:
+ rds_instance_endpoint:
+ type: string
+ required: true
+ description: "Connection endpoint of the RDS instance in format hostname:port (e.g. `mydb.abc123.us-east-1.rds.amazonaws.com:5432`)"
+
+ codebuild_project_name:
+ type: string
+ required: true
+ description: "Name of the CodeBuild project for database operations (from RDS instance)"
+
+ database_name:
+ type: string
+ required: false
+ description: "Name of the database to create. If not specified, uses stack_id and resource name (e.g. `myapp_db`)"
+
+ database_owner:
+ type: string
+ required: false
+ description: "Username for the database owner role. If not specified, a unique role is created (e.g. `myapp_user`)"
+
+outputs:
+ database_name:
+ type: string
+ description: "Name of the created database"
+
+ database_owner:
+ type: string
+ description: "Username of the database owner"
+
+ database_password:
+ type: string
+ description: "Password for the database owner (sensitive)"
+
+ connection_string:
+ type: string
+ description: "PostgreSQL connection string for the database"
diff --git a/rds-database/module/main.tf b/rds-database/module/main.tf
new file mode 100644
index 0000000..b6beec8
--- /dev/null
+++ b/rds-database/module/main.tf
@@ -0,0 +1,70 @@
+# Get the current AWS region
+data "aws_region" "current" {
+}
+
+# Local variables
+locals {
+ database_name = var.database_name != null ? var.database_name : replace("${var.suga.stack_id}_${var.suga.name}", "-", "_")
+ database_owner = var.database_owner != null ? var.database_owner : replace("${var.suga.stack_id}_${var.suga.name}_user", "-", "_")
+
+ # Build PostgreSQL connection string
+ connection_string = "postgresql://${local.database_owner}:${random_password.db_password.result}@${var.rds_instance_endpoint}/${local.database_name}?sslmode=require"
+
+ # Output service export map
+ service_outputs = {
+ for name, service in var.suga.services : name => {
+ env = {
+ (var.suga.env_var_key) = local.connection_string
+ }
+ }
+ }
+}
+
+# Generate a random password for the database owner role
+resource "random_password" "db_password" {
+ length = 32
+ special = false
+}
+
+# Trigger CodeBuild to create the database and role
+resource "null_resource" "create_database" {
+ triggers = {
+ database_name = local.database_name
+ database_owner = local.database_owner
+ rds_endpoint = var.rds_instance_endpoint
+ codebuild_project = var.codebuild_project_name
+ }
+
+ provisioner "local-exec" {
+ interpreter = ["bash", "-c"]
+ command = <
+
diff --git a/rds-instance/manifest.yaml b/rds-instance/manifest.yaml
new file mode 100644
index 0000000..b570902
--- /dev/null
+++ b/rds-instance/manifest.yaml
@@ -0,0 +1,224 @@
+name: rds-instance
+display_name: RDS PostgreSQL Instance
+type: infra
+description: "Provisions an AWS RDS PostgreSQL instance with optional automated backups, encryption, and multi-AZ support. Use with rds-database plugin to create individual databases."
+icon: ./icon.svg
+deployment:
+ terraform: ./module
+
+inputs:
+ identifier:
+ type: string
+ required: true
+ description: "Unique identifier for the RDS instance (e.g. `myapp-db`)"
+
+ engine_version:
+ type: string
+ required: false
+ description: "PostgreSQL engine version (e.g. `15.4`, `16.1`). If not specified, uses the latest version"
+
+ instance_class:
+ type: string
+ description: "Compute and memory capacity - `db.t3.micro` (free tier, 2vCPU, 1GB RAM), `db.t3.small` (2vCPU, 2GB), `db.t3.medium` (2vCPU, 4GB), `db.m5.large` (2vCPU, 8GB), `db.m5.xlarge` (4vCPU, 16GB) (e.g. `db.t3.small`)"
+
+ allocated_storage:
+ type: number
+ required: false
+ description: "Initial storage size in GB, 20-65536. Can grow with max_allocated_storage (e.g. `20`)"
+
+ max_allocated_storage:
+ type: number
+ required: false
+ description: "Maximum storage autoscaling limit in GB. Set higher than allocated_storage to enable autoscaling (e.g. `100`)"
+
+ storage_type:
+ type: string
+ required: false
+ description: 'Storage type: `gp2` (general SSD, legacy), `gp3` (newer SSD with better performance), `io1` (provisioned IOPS) (e.g. `gp3`)'
+
+ storage_encrypted:
+ type: bool
+ required: false
+ description: "`true` (recommended) encrypts database storage at rest using AWS KMS. `false` leaves data unencrypted"
+
+ kms_key_id:
+ type: string
+ required: false
+ description: "ARN of AWS KMS key for encryption. If storage_encrypted is true and this is not set, uses default AWS RDS key (e.g. `arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012`)"
+
+ database_name:
+ type: string
+ required: false
+ description: "Initial database name to create. At least one database must exist for PostgreSQL provider to connect (e.g. `postgres`)"
+
+ master_username:
+ type: string
+ description: "Master username for database access (e.g. `postgres`)"
+
+ port:
+ type: number
+ required: false
+ description: "TCP port for database connections (default: 5432)"
+
+ multi_az:
+ type: bool
+ required: false
+ description: "`false` (default) single AZ deployment for dev/test. `true` enables multi-AZ with automatic failover for production high availability"
+
+ publicly_accessible:
+ type: bool
+ required: false
+ description: "`false` (recommended) keeps database private within VPC. `true` assigns public IP - use only for development, not production"
+
+ vpc_id:
+ type: string
+ required: true
+ description: "VPC ID where RDS will be deployed (e.g. `vpc-0123456789abcdef0`)"
+
+ subnet_ids:
+ type: list(string)
+ required: true
+ description: 'List of subnet IDs for RDS subnet group, must span at least 2 availability zones (e.g. `["subnet-abc123", "subnet-def456"]`)'
+
+ allowed_security_group_ids:
+ type: list(string)
+ required: false
+ description: 'Security group IDs allowed to connect to the database (e.g. `["sg-lambda-app", "sg-fargate-backend"]`)'
+
+ allowed_cidr_blocks:
+ type: list(string)
+ required: false
+ description: 'CIDR blocks allowed to connect to the database (e.g. `["10.0.1.0/24", "10.0.2.0/24"]`)'
+
+ backup_retention_period:
+ type: number
+ required: false
+ description: "Days to retain automated backups, 0-35. 0 disables backups (not recommended). 7+ required for point-in-time recovery (e.g. `7`)"
+
+ backup_window:
+ type: string
+ required: false
+ description: 'Daily backup time window in UTC format HH:MM-HH:MM, must be at least 30 minutes (e.g. `03:00-04:00`)'
+
+ maintenance_window:
+ type: string
+ required: false
+ description: 'Weekly maintenance window in UTC format ddd:HH:MM-ddd:HH:MM, must not overlap backup_window (e.g. `mon:04:00-mon:05:00`)'
+
+ skip_final_snapshot:
+ type: bool
+ required: false
+ description: "`false` (recommended) creates final snapshot before deletion. `true` skips snapshot - use only for dev/test databases"
+
+ final_snapshot_identifier:
+ type: string
+ required: false
+ description: "Name for final snapshot when database is deleted. Required if skip_final_snapshot is false (e.g. `myapp-db-final-snapshot`)"
+
+ deletion_protection:
+ type: bool
+ required: false
+ description: "`false` (default) allows database deletion. `true` prevents accidental deletion - recommended for production databases"
+
+ enabled_cloudwatch_logs_exports:
+ type: list(string)
+ required: false
+ description: 'PostgreSQL log types to export to CloudWatch (e.g. `["postgresql"]` for general logs, `["postgresql", "upgrade"]` for logs and upgrade logs)'
+
+ monitoring_interval:
+ type: number
+ required: false
+ description: "Enhanced monitoring interval in seconds: 0 (disabled), 1, 5, 10, 15, 30, 60. Values >0 require monitoring_role_arn (e.g. `60`)"
+
+ monitoring_role_arn:
+ type: string
+ required: false
+ description: "IAM role ARN for enhanced monitoring. Required if monitoring_interval > 0 (e.g. `arn:aws:iam::123456789012:role/rds-monitoring-role`)"
+
+ performance_insights_enabled:
+ type: bool
+ required: false
+ description: "`false` (default) disables performance insights. `true` enables advanced performance monitoring (additional costs apply)"
+
+ performance_insights_retention_period:
+ type: number
+ required: false
+ description: "Days to retain performance insights data: 7 (free tier) or 731 (2 years, additional cost). Only applies if performance_insights_enabled is true (e.g. `7`)"
+
+ auto_minor_version_upgrade:
+ type: bool
+ required: false
+ description: "`true` (default) automatically applies minor engine upgrades during maintenance window. `false` requires manual upgrades"
+
+ apply_immediately:
+ type: bool
+ required: false
+ description: "`false` (default) applies changes during maintenance window. `true` applies changes immediately (may cause downtime)"
+
+ parameter_group_name:
+ type: string
+ required: false
+ description: "Custom DB parameter group name for PostgreSQL configuration. If not specified, uses default parameter group (e.g. `custom-postgres15-params`)"
+
+ tags:
+ type: map(string)
+ required: false
+ description: 'Resource tags for organization and cost tracking (e.g. `{"Environment": "production", "Application": "web-api"}`)'
+
+ enable_ssm_bastion_access:
+ type: bool
+ required: false
+ description: "`false` (default) disables SSM bastion resources. `true` creates a security group and IAM instance profile that users can attach to their own EC2 instances for SSM Session Manager port forwarding access to the database"
+
+outputs:
+ db_instance_id:
+ type: string
+ description: "Unique identifier of the RDS instance"
+
+ db_instance_arn:
+ type: string
+ description: "Amazon Resource Name (ARN) of the RDS instance"
+
+ db_instance_endpoint:
+ type: string
+ description: "Connection endpoint in format hostname:port (e.g. mydb.abc123.us-east-1.rds.amazonaws.com:5432)"
+
+ db_instance_name:
+ type: string
+ description: "Name of the initial database created"
+
+ db_instance_username:
+ type: string
+ description: "Master username for database access"
+
+ db_instance_resource_id:
+ type: string
+ description: "Resource ID of the RDS instance (format: db-ABCDEFGHIJKLMNOPQRS)"
+
+ db_subnet_group_id:
+ type: string
+ description: "ID of the DB subnet group"
+
+ db_security_group_id:
+ type: string
+ description: "ID of the security group attached to the RDS instance"
+
+ db_master_password:
+ type: string
+ description: "Master password for the RDS instance (sensitive)"
+
+ codebuild_project_name:
+ type: string
+ description: "Name of the CodeBuild project for database operations"
+
+ codebuild_project_arn:
+ type: string
+ description: "ARN of the CodeBuild project for database operations"
+
+ bastion_security_group_id:
+ type: string
+ description: "Security group ID for SSM bastion instances (only created if enable_ssm_bastion_access is true). Attach this to EC2 instances that need database access via SSM port forwarding"
+
+ bastion_instance_profile_name:
+ type: string
+ description: "IAM instance profile name for SSM bastion instances (only created if enable_ssm_bastion_access is true). Attach this to EC2 instances to enable SSM Session Manager access"
diff --git a/rds-instance/module/main.tf b/rds-instance/module/main.tf
new file mode 100644
index 0000000..1bfb148
--- /dev/null
+++ b/rds-instance/module/main.tf
@@ -0,0 +1,373 @@
+# Generate a random password for the master user
+resource "random_password" "master_password" {
+ length = 32
+ special = false
+}
+
+# DB Subnet Group
+resource "aws_db_subnet_group" "this" {
+ name = "${var.identifier}-subnet-group"
+ subnet_ids = var.subnet_ids
+
+ tags = merge(
+ var.tags,
+ {
+ Name = "${var.identifier}-subnet-group"
+ }
+ )
+}
+
+# Security Group for RDS
+resource "aws_security_group" "this" {
+ name = "${var.identifier}-sg"
+ description = "Security group for RDS PostgreSQL instance ${var.identifier}"
+ vpc_id = var.vpc_id
+
+ tags = merge(
+ var.tags,
+ {
+ Name = "${var.identifier}-sg"
+ }
+ )
+}
+
+# Allow ingress from specified security groups
+resource "aws_security_group_rule" "from_security_groups" {
+ count = length(var.allowed_security_group_ids)
+
+ type = "ingress"
+ from_port = local.db_port
+ to_port = local.db_port
+ protocol = "tcp"
+ source_security_group_id = var.allowed_security_group_ids[count.index]
+ security_group_id = aws_security_group.this.id
+ description = "Allow PostgreSQL access from security group ${var.allowed_security_group_ids[count.index]}"
+}
+
+# Allow ingress from specified CIDR blocks
+resource "aws_security_group_rule" "from_cidr_blocks" {
+ count = length(var.allowed_cidr_blocks) > 0 ? 1 : 0
+
+ type = "ingress"
+ from_port = local.db_port
+ to_port = local.db_port
+ protocol = "tcp"
+ cidr_blocks = var.allowed_cidr_blocks
+ security_group_id = aws_security_group.this.id
+ description = "Allow PostgreSQL access from specified CIDR blocks"
+}
+
+# Self-referential rule (allows resources in the same SG to communicate)
+resource "aws_security_group_rule" "self" {
+ type = "ingress"
+ from_port = local.db_port
+ to_port = local.db_port
+ protocol = "tcp"
+ self = true
+ security_group_id = aws_security_group.this.id
+ description = "Allow PostgreSQL access within security group"
+}
+
+# Allows codebuild job to pull images and updates
+# More open to allow overriding job externally for additional work/image runs in future
+# e.g. if a user wants to run containerised migrations in the same CodeBuild project
+# trivy:ignore:avd-aws-0104
+resource "aws_security_group_rule" "egress" {
+ type = "egress"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ security_group_id = aws_security_group.this.id
+ description = "Allow all outbound traffic"
+}
+
+# Security Group for SSM Bastion instances (optional)
+resource "aws_security_group" "bastion" {
+ count = var.enable_ssm_bastion_access ? 1 : 0
+
+ name = "${var.identifier}-bastion-sg"
+ description = "Security group for SSM bastion instances to access RDS ${var.identifier}"
+ vpc_id = var.vpc_id
+
+ # Allow all outbound traffic (needed for SSM Session Manager)
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ description = "Allow all outbound traffic for SSM"
+ }
+
+ tags = merge(
+ var.tags,
+ {
+ Name = "${var.identifier}-bastion-sg"
+ }
+ )
+}
+
+# Allow ingress from bastion security group to RDS
+resource "aws_security_group_rule" "from_bastion" {
+ count = var.enable_ssm_bastion_access ? 1 : 0
+
+ type = "ingress"
+ from_port = local.db_port
+ to_port = local.db_port
+ protocol = "tcp"
+ source_security_group_id = aws_security_group.bastion[0].id
+ security_group_id = aws_security_group.this.id
+ description = "Allow PostgreSQL access from SSM bastion instances"
+}
+
+# Local variables
+locals {
+ db_port = var.port != null ? var.port : 5432
+}
+
+# RDS PostgreSQL Instance
+resource "aws_db_instance" "this" {
+ identifier = var.identifier
+
+ # Engine configuration
+ engine = "postgres"
+ engine_version = var.engine_version
+ instance_class = var.instance_class
+
+ # Storage configuration
+ allocated_storage = var.allocated_storage
+ max_allocated_storage = var.max_allocated_storage
+ storage_type = var.storage_type
+ storage_encrypted = var.storage_encrypted
+ kms_key_id = var.kms_key_id
+
+ # Database configuration
+ db_name = var.database_name
+ username = var.master_username
+ password = random_password.master_password.result
+ port = local.db_port
+
+ # Network configuration
+ db_subnet_group_name = aws_db_subnet_group.this.name
+ vpc_security_group_ids = [aws_security_group.this.id]
+ publicly_accessible = var.publicly_accessible
+ multi_az = var.multi_az
+
+ # Backup configuration
+ backup_retention_period = var.backup_retention_period
+ backup_window = var.backup_window
+ maintenance_window = var.maintenance_window
+ skip_final_snapshot = var.skip_final_snapshot
+ final_snapshot_identifier = var.skip_final_snapshot == false ? (
+ var.final_snapshot_identifier != null ? var.final_snapshot_identifier : "${var.identifier}-final-snapshot"
+ ) : null
+
+ # Deletion protection
+ deletion_protection = var.deletion_protection
+
+ # Monitoring and logging
+ enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports
+ monitoring_interval = var.monitoring_interval
+ monitoring_role_arn = var.monitoring_role_arn
+
+ # Performance Insights
+ performance_insights_enabled = var.performance_insights_enabled
+ performance_insights_retention_period = var.performance_insights_enabled ? var.performance_insights_retention_period : null
+
+ # Maintenance and upgrades
+ auto_minor_version_upgrade = var.auto_minor_version_upgrade
+ apply_immediately = var.apply_immediately
+
+ # Parameter group
+ parameter_group_name = var.parameter_group_name
+
+ # Tags
+ tags = merge(
+ var.tags,
+ {
+ Name = var.identifier
+ }
+ )
+
+}
+
+# IAM Role for CodeBuild
+resource "aws_iam_role" "codebuild" {
+ name = "${var.identifier}-codebuild-role"
+
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "codebuild.amazonaws.com"
+ }
+ }
+ ]
+ })
+
+ tags = var.tags
+}
+
+# IAM Policy for CodeBuild
+resource "aws_iam_role_policy" "codebuild" {
+ role = aws_iam_role.codebuild.name
+
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Effect = "Allow"
+ Action = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents"
+ ]
+ Resource = "arn:aws:logs:*:*:*"
+ },
+ {
+ Effect = "Allow"
+ Action = [
+ "ec2:CreateNetworkInterface",
+ "ec2:DescribeNetworkInterfaces",
+ "ec2:DeleteNetworkInterface",
+ "ec2:DescribeSubnets",
+ "ec2:DescribeSecurityGroups",
+ "ec2:DescribeDhcpOptions",
+ "ec2:DescribeVpcs",
+ "ec2:CreateNetworkInterfacePermission"
+ ]
+ Resource = "*"
+ }
+ ]
+ })
+}
+
+# CodeBuild Project for Database Operations
+resource "aws_codebuild_project" "db_operations" {
+ name = "${var.identifier}-db-operations"
+ description = "CodeBuild project for creating databases and roles on RDS instance"
+ service_role = aws_iam_role.codebuild.arn
+ build_timeout = 10
+
+ artifacts {
+ type = "NO_ARTIFACTS"
+ }
+
+ environment {
+ compute_type = "BUILD_GENERAL1_SMALL"
+ image = "postgres:16-alpine"
+ type = "LINUX_CONTAINER"
+ image_pull_credentials_type = "CODEBUILD"
+
+ environment_variable {
+ name = "DB_HOST"
+ value = aws_db_instance.this.address
+ }
+
+ environment_variable {
+ name = "DB_PORT"
+ value = tostring(aws_db_instance.this.port)
+ }
+
+ environment_variable {
+ name = "DB_MASTER_USER"
+ value = var.master_username
+ }
+
+ environment_variable {
+ name = "DB_PASSWORD"
+ value = random_password.master_password.result
+ }
+ }
+
+ vpc_config {
+ vpc_id = var.vpc_id
+ subnets = var.subnet_ids
+ security_group_ids = [aws_security_group.this.id]
+ }
+
+ source {
+ type = "NO_SOURCE"
+ buildspec = <<-EOT
+ version: 0.2
+ phases:
+ build:
+ commands:
+ - echo "Running database operations..."
+ - |
+ export PGPASSWORD="$DB_PASSWORD"
+
+ # Create role if it doesn't exist
+ if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_MASTER_USER" -d postgres -tc \
+ "SELECT 1 FROM pg_roles WHERE rolname='$DB_ROLE'" | grep -q 1; then
+ psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_MASTER_USER" -d postgres -c \
+ "CREATE ROLE \"$DB_ROLE\" WITH LOGIN PASSWORD '$DB_ROLE_PASSWORD';"
+ psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_MASTER_USER" -d postgres -c \
+ "GRANT \"$DB_ROLE\" TO \"$DB_MASTER_USER\";"
+ fi
+
+ # Create database if it doesn't exist
+ psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_MASTER_USER" -d postgres -tc \
+ "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1 || \
+ psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_MASTER_USER" -d postgres -c \
+ "CREATE DATABASE \"$DB_NAME\" OWNER \"$DB_ROLE\";"
+
+ echo "Database operations completed successfully"
+ EOT
+ }
+
+ tags = var.tags
+}
+
+# IAM Role for SSM Bastion instances (optional)
+resource "aws_iam_role" "bastion" {
+ count = var.enable_ssm_bastion_access ? 1 : 0
+
+ name = "${var.identifier}-bastion-role"
+
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "ec2.amazonaws.com"
+ }
+ }
+ ]
+ })
+
+ tags = merge(
+ var.tags,
+ {
+ Name = "${var.identifier}-bastion-role"
+ }
+ )
+}
+
+# Attach AWS managed policy for SSM
+resource "aws_iam_role_policy_attachment" "bastion_ssm" {
+ count = var.enable_ssm_bastion_access ? 1 : 0
+
+ role = aws_iam_role.bastion[0].name
+ policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
+}
+
+# IAM Instance Profile for SSM Bastion instances
+resource "aws_iam_instance_profile" "bastion" {
+ count = var.enable_ssm_bastion_access ? 1 : 0
+
+ name = "${var.identifier}-bastion-profile"
+ role = aws_iam_role.bastion[0].name
+
+ tags = merge(
+ var.tags,
+ {
+ Name = "${var.identifier}-bastion-profile"
+ }
+ )
+}
diff --git a/rds-instance/module/outputs.tf b/rds-instance/module/outputs.tf
new file mode 100644
index 0000000..e917918
--- /dev/null
+++ b/rds-instance/module/outputs.tf
@@ -0,0 +1,65 @@
+output "db_instance_id" {
+ description = "Unique identifier of the RDS instance"
+ value = aws_db_instance.this.id
+}
+
+output "db_instance_arn" {
+ description = "Amazon Resource Name (ARN) of the RDS instance"
+ value = aws_db_instance.this.arn
+}
+
+output "db_instance_endpoint" {
+ description = "Connection endpoint in format hostname:port"
+ value = aws_db_instance.this.endpoint
+}
+
+output "db_instance_name" {
+ description = "Name of the initial database created"
+ value = aws_db_instance.this.db_name
+}
+
+output "db_instance_username" {
+ description = "Master username for database access"
+ value = aws_db_instance.this.username
+}
+
+output "db_instance_resource_id" {
+ description = "Resource ID of the RDS instance"
+ value = aws_db_instance.this.resource_id
+}
+
+output "db_subnet_group_id" {
+ description = "ID of the DB subnet group"
+ value = aws_db_subnet_group.this.id
+}
+
+output "db_security_group_id" {
+ description = "ID of the security group attached to the RDS instance"
+ value = aws_security_group.this.id
+}
+
+output "db_master_password" {
+ description = "Master password for the RDS instance"
+ value = random_password.master_password.result
+ sensitive = true
+}
+
+output "codebuild_project_name" {
+ description = "Name of the CodeBuild project for database operations"
+ value = aws_codebuild_project.db_operations.name
+}
+
+output "codebuild_project_arn" {
+ description = "ARN of the CodeBuild project for database operations"
+ value = aws_codebuild_project.db_operations.arn
+}
+
+output "bastion_security_group_id" {
+ description = "Security group ID for SSM bastion instances (empty if enable_ssm_bastion_access is false)"
+ value = var.enable_ssm_bastion_access ? aws_security_group.bastion[0].id : ""
+}
+
+output "bastion_instance_profile_name" {
+ description = "IAM instance profile name for SSM bastion instances (empty if enable_ssm_bastion_access is false)"
+ value = var.enable_ssm_bastion_access ? aws_iam_instance_profile.bastion[0].name : ""
+}
diff --git a/rds-instance/module/variables.tf b/rds-instance/module/variables.tf
new file mode 100644
index 0000000..45f480a
--- /dev/null
+++ b/rds-instance/module/variables.tf
@@ -0,0 +1,194 @@
+variable "identifier" {
+ type = string
+ description = "Unique identifier for the RDS instance"
+}
+
+variable "engine_version" {
+ type = string
+ description = "PostgreSQL engine version"
+ default = null
+}
+
+variable "instance_class" {
+ type = string
+ description = "Compute and memory capacity for the RDS instance"
+ default = "db.t3.micro"
+}
+
+variable "allocated_storage" {
+ type = number
+ description = "Initial storage size in GB"
+ default = 20
+}
+
+variable "max_allocated_storage" {
+ type = number
+ description = "Maximum storage autoscaling limit in GB"
+ default = null
+}
+
+variable "storage_type" {
+ type = string
+ description = "Storage type (gp2, gp3, io1)"
+ default = "gp3"
+}
+
+variable "storage_encrypted" {
+ type = bool
+ description = "Enable storage encryption at rest"
+ default = true
+}
+
+variable "kms_key_id" {
+ type = string
+ description = "ARN of AWS KMS key for encryption"
+ default = null
+}
+
+variable "database_name" {
+ type = string
+ description = "Initial database name to create"
+ default = null
+}
+
+variable "master_username" {
+ type = string
+ description = "Master username for database access"
+ default = "postgres"
+}
+
+variable "port" {
+ type = number
+ description = "TCP port for database connections"
+ default = null
+}
+
+variable "multi_az" {
+ type = bool
+ description = "Enable multi-AZ deployment"
+ default = false
+}
+
+variable "publicly_accessible" {
+ type = bool
+ description = "Allow public access to the database"
+ default = false
+}
+
+variable "vpc_id" {
+ type = string
+ description = "VPC ID where RDS will be deployed"
+}
+
+variable "subnet_ids" {
+ type = list(string)
+ description = "List of subnet IDs for RDS subnet group"
+}
+
+variable "allowed_security_group_ids" {
+ type = list(string)
+ description = "Security group IDs allowed to connect to the database"
+ default = []
+}
+
+variable "allowed_cidr_blocks" {
+ type = list(string)
+ description = "CIDR blocks allowed to connect to the database"
+ default = []
+}
+
+variable "backup_retention_period" {
+ type = number
+ description = "Days to retain automated backups"
+ default = 7
+}
+
+variable "backup_window" {
+ type = string
+ description = "Daily backup time window in UTC"
+ default = null
+}
+
+variable "maintenance_window" {
+ type = string
+ description = "Weekly maintenance window in UTC"
+ default = null
+}
+
+variable "skip_final_snapshot" {
+ type = bool
+ description = "Skip final snapshot before deletion"
+ default = false
+}
+
+variable "final_snapshot_identifier" {
+ type = string
+ description = "Name for final snapshot when database is deleted"
+ default = null
+}
+
+variable "deletion_protection" {
+ type = bool
+ description = "Prevent accidental deletion"
+ default = false
+}
+
+variable "enabled_cloudwatch_logs_exports" {
+ type = list(string)
+ description = "PostgreSQL log types to export to CloudWatch"
+ default = []
+}
+
+variable "monitoring_interval" {
+ type = number
+ description = "Enhanced monitoring interval in seconds"
+ default = 0
+}
+
+variable "monitoring_role_arn" {
+ type = string
+ description = "IAM role ARN for enhanced monitoring"
+ default = null
+}
+
+variable "performance_insights_enabled" {
+ type = bool
+ description = "Enable performance insights"
+ default = false
+}
+
+variable "performance_insights_retention_period" {
+ type = number
+ description = "Days to retain performance insights data"
+ default = 7
+}
+
+variable "auto_minor_version_upgrade" {
+ type = bool
+ description = "Automatically apply minor engine upgrades"
+ default = true
+}
+
+variable "apply_immediately" {
+ type = bool
+ description = "Apply changes immediately instead of during maintenance window"
+ default = false
+}
+
+variable "parameter_group_name" {
+ type = string
+ description = "Custom DB parameter group name"
+ default = null
+}
+
+variable "tags" {
+ type = map(string)
+ description = "Resource tags"
+ default = {}
+}
+
+variable "enable_ssm_bastion_access" {
+ type = bool
+ description = "Enable creation of security group and IAM instance profile for SSM bastion access"
+ default = false
+}