> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rds default ports remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are the console-based steps to move an RDS instance off its default port (e.g., 3306 for MySQL, 5432 for PostgreSQL, 1433 for SQL Server, 1521 for Oracle):

        ***

        ### 1. Plan the New Port

        1. Choose a non-default, unused port in the allowed range for your engine:
           * MySQL/MariaDB/PostgreSQL: 1150–65535 (except ports reserved by AWS)
           * SQL Server: 1150–65535
           * Oracle: 1150–65535
        2. Ensure your network/security team approves the port.

        ***

        ### 2. Update the RDS Instance Port

        1. Sign in to the **AWS Management Console**.
        2. Open **RDS** service.
        3. In the left menu, select **Databases**.
        4. Click the DB instance you want to change.
        5. Click **Modify** (top-right).
        6. In the **Connectivity** or **Additional configuration** section (varies by engine), find **Port**.
        7. Change it from the default (e.g., 3306/5432/1433/1521) to your chosen custom port.
        8. At the bottom:
           * Under **Scheduling of modifications**, choose:
             * **Apply immediately** (causes a brief downtime)\
               or
             * **Apply during the next scheduled maintenance window** (less disruptive but delayed).
        9. Click **Continue**, review changes, then click **Modify DB instance**.

        The instance will go into **modifying** then **available** status once complete.

        ***

        ### 3. Update the Security Group Rules

        1. Still in the RDS instance details page, in the **Connectivity & security** tab, find **Security group rules**.
        2. Click the linked **VPC security group** name to open it in the EC2 console.
        3. On the **Inbound rules** tab:
           * Edit the rule that allowed the old port (e.g., 3306).
           * Either:
             * Change the **Port range** to the new port, **or**
             * Add a new rule for the new port and remove the old port rule afterward.
           * Keep the same **Source** (CIDR, security group, etc.) so the same clients can still connect.
        4. Save the inbound rule changes.

        If required, update **Outbound rules** similarly, though usually outbound is already open.

        ***

        ### 4. Update Application Configurations

        1. Find all applications, scripts, and tools that connect to this RDS instance.
        2. Update their DB connection strings:
           * Change the `port` value to the new port.
           * Hostname (endpoint) stays the same; only the port changes (unless you also changed anything else).
        3. Redeploy or restart applications if needed so they use the new configuration.

        ***

        ### 5. Validate Connectivity

        1. Use a DB client (e.g., `psql`, `mysql`, SQL Server Management Studio, etc.) and specify the new port:
           * Example (MySQL):
             ```bash theme={null}
             mysql -h <rds-endpoint> -P <new-port> -u <user> -p
             ```
        2. Confirm that applications can successfully connect and operate.
        3. Once confirmed, verify that the old port is:
           * No longer open in security groups.
           * No longer referenced in any configs or scripts.

        ***

        ### 6. (Optional) Enforce via Baseline/Standards

        * Document the required non-default port in your internal standards.
        * Use AWS Config or a security tool to:
          * Detect RDS instances using default ports.
          * Alert or block non-compliant deployments.
      </Accordion>

      <Accordion title="Using CLI">
        Below are concise, CLI-focused steps to move RDS off default ports.

        ***

        ## 1. Identify RDS instances using default ports

        Common default ports (AWS RDS engines):

        * MySQL / MariaDB / Aurora MySQL: `3306`
        * PostgreSQL / Aurora PostgreSQL: `5432`
        * Oracle: `1521`
        * SQL Server: `1433`

        List all DB instances with their ports:

        ```bash theme={null}
        aws rds describe-db-instances \
          --query 'DBInstances[*].[DBInstanceIdentifier,Engine,Endpoint.Port]' \
          --output table
        ```

        (Optional) Filter by a specific default port, e.g. MySQL’s 3306:

        ```bash theme={null}
        aws rds describe-db-instances \
          --query "DBInstances[?Endpoint.Port==\`3306\`].[DBInstanceIdentifier,Engine,Endpoint.Port]" \
          --output table
        ```

        ***

        ## 2. Choose a non-default port

        Pick a port that:

        * Is not in use by other services in your environment.
        * Is allowed by your organization’s security policy.
          Example: `13306` for MySQL, `15432` for PostgreSQL, etc.

        ***

        ## 3. Update security groups *before* changing the port

        Find the security groups used by the instance:

        ```bash theme={null}
        aws rds describe-db-instances \
          --db-instance-identifier <DB_INSTANCE_ID> \
          --query 'DBInstances[0].VpcSecurityGroups[*].VpcSecurityGroupId' \
          --output text
        ```

        For each security group, add an inbound rule for the new port (example: 13306/TCP, CIDR 10.0.0.0/16):

        ```bash theme={null}
        aws ec2 authorize-security-group-ingress \
          --group-id <SG_ID> \
          --protocol tcp \
          --port 13306 \
          --cidr 10.0.0.0/16
        ```

        After cutover, you can remove the old-port rule.

        ***

        ## 4. Change the RDS instance port

        Changing `--db-port` causes a reboot/outage. Schedule a maintenance window.

        ```bash theme={null}
        aws rds modify-db-instance \
          --db-instance-identifier <DB_INSTANCE_ID> \
          --db-port 13306 \
          --apply-immediately
        ```

        If you prefer to apply during the next maintenance window, omit `--apply-immediately`.

        Check status until it’s `available`:

        ```bash theme={null}
        aws rds describe-db-instances \
          --db-instance-identifier <DB_INSTANCE_ID> \
          --query 'DBInstances[0].DBInstanceStatus' \
          --output text
        ```

        Confirm new port:

        ```bash theme={null}
        aws rds describe-db-instances \
          --db-instance-identifier <DB_INSTANCE_ID> \
          --query 'DBInstances[0].Endpoint.Port' \
          --output text
        ```

        ***

        ## 5. For Aurora (cluster) setups

        For Aurora, you typically change each instance:

        ```bash theme={null}
        aws rds modify-db-instance \
          --db-instance-identifier <AURORA_INSTANCE_ID> \
          --db-port 13306 \
          --apply-immediately
        ```

        Repeat for all instances in the cluster.\
        Verify via:

        ```bash theme={null}
        aws rds describe-db-instances \
          --query 'DBInstances[*].[DBInstanceIdentifier,Engine,Endpoint.Port]' \
          --output table
        ```

        ***

        ## 6. Update application configurations

        Update application connection strings to use the new port:

        * JDBC: `jdbc:mysql://host:13306/dbname`
        * psql: `psql -h host -p 15432 -d dbname -U user`
        * Any connection libraries: adjust `port` field.

        Test connectivity from your app environment.

        ***

        ## 7. Remove old port from security groups

        Once apps successfully use the new port, remove the old-port inbound rules:

        ```bash theme={null}
        aws ec2 revoke-security-group-ingress \
          --group-id <SG_ID> \
          --protocol tcp \
          --port 3306 \
          --cidr 10.0.0.0/16
        ```

        Repeat for all affected SGs.
      </Accordion>

      <Accordion title="Using Python">
        Below is one way to do this programmatically using Python and boto3:

        ## 1. Decide which ports are “default” and what to change them to

        Common default ports (per engine):

        ```python theme={null}
        DEFAULT_PORTS = {
            "mysql": 3306,
            "mariadb": 3306,
            "aurora": 3306,
            "aurora-mysql": 3306,
            "postgres": 5432,
            "aurora-postgresql": 5432,
            "oracle-se2": 1521,
            "oracle-se1": 1521,
            "oracle-se": 1521,
            "oracle-ee": 1521,
            "sqlserver-ee": 1433,
            "sqlserver-se": 1433,
            "sqlserver-ex": 1433,
            "sqlserver-web": 1433,
            "redshift": 5439,  # for Redshift, you'd use redshift client, not rds
        }
        ```

        You also must pick **non-default** target ports (coordinate with your app & security teams first):

        ```python theme={null}
        TARGET_PORTS = {
            "mysql": 3307,
            "mariadb": 3307,
            "aurora": 3307,
            "aurora-mysql": 3307,
            "postgres": 5433,
            "aurora-postgresql": 5433,
            "oracle-se2": 1522,
            "oracle-se1": 1522,
            "oracle-se": 1522,
            "oracle-ee": 1522,
            "sqlserver-ee": 14330,
            "sqlserver-se": 14330,
            "sqlserver-ex": 14330,
            "sqlserver-web": 14330,
        }
        ```

        > Adjust the target ports to your standards and ensure corresponding security group rules and client configs will be updated.

        ***

        ## 2. Python script to find and remediate RDS instances on default ports

        ```python theme={null}
        import boto3

        rds = boto3.client("rds")

        DEFAULT_PORTS = {
            "mysql": 3306,
            "mariadb": 3306,
            "aurora": 3306,
            "aurora-mysql": 3306,
            "postgres": 5432,
            "aurora-postgresql": 5432,
            "oracle-se2": 1521,
            "oracle-se1": 1521,
            "oracle-se": 1521,
            "oracle-ee": 1521,
            "sqlserver-ee": 1433,
            "sqlserver-se": 1433,
            "sqlserver-ex": 1433,
            "sqlserver-web": 1433,
        }

        TARGET_PORTS = {
            "mysql": 3307,
            "mariadb": 3307,
            "aurora": 3307,
            "aurora-mysql": 3307,
            "postgres": 5433,
            "aurora-postgresql": 5433,
            "oracle-se2": 1522,
            "oracle-se1": 1522,
            "oracle-se": 1522,
            "oracle-ee": 1522,
            "sqlserver-ee": 14330,
            "sqlserver-se": 14330,
            "sqlserver-ex": 14330,
            "sqlserver-web": 14330,
        }

        def list_rds_instances():
            instances = []
            paginator = rds.get_paginator("describe_db_instances")
            for page in paginator.paginate():
                instances.extend(page["DBInstances"])
            return instances

        def find_instances_on_default_port():
            instances = list_rds_instances()
            to_change = []
            for inst in instances:
                engine = inst["Engine"]
                port = inst["Endpoint"]["Port"]
                db_id = inst["DBInstanceIdentifier"]

                default_port = DEFAULT_PORTS.get(engine)
                if default_port is None:
                    # Engine not in our mapping; skip or handle separately
                    continue

                if port == default_port:
                    to_change.append({
                        "DBInstanceIdentifier": db_id,
                        "Engine": engine,
                        "CurrentPort": port,
                        "TargetPort": TARGET_PORTS.get(engine)
                    })
            return to_change

        def modify_rds_port(db_identifier, new_port, apply_immediately=False):
            print(f"Modifying {db_identifier} to port {new_port} (apply_immediately={apply_immediately})")
            resp = rds.modify_db_instance(
                DBInstanceIdentifier=db_identifier,
                Port=new_port,
                ApplyImmediately=apply_immediately
            )
            return resp

        if __name__ == "__main__":
            # 1. Find instances using default ports
            instances_needing_change = find_instances_on_default_port()

            if not instances_needing_change:
                print("No RDS instances using a default port (per our mapping).")
                exit(0)

            print("Instances using default ports:")
            for item in instances_needing_change:
                print(f"- {item['DBInstanceIdentifier']} | engine={item['Engine']} | "
                      f"current_port={item['CurrentPort']} -> target_port={item['TargetPort']}")

            # 2. Safety step: confirm before changing
            confirm = input("Proceed with port modification? (yes/no): ").strip().lower()
            if confirm != "yes":
                print("Aborting.")
                exit(0)

            # 3. Modify the instances
            for item in instances_needing_change:
                if not item["TargetPort"]:
                    print(f"Skipping {item['DBInstanceIdentifier']} (no target port configured).")
                    continue

                # WARNING: ApplyImmediately=True can cause downtime; set to False to apply in maintenance window
                modify_rds_port(
                    db_identifier=item["DBInstanceIdentifier"],
                    new_port=item["TargetPort"],
                    apply_immediately=False,  # change to True if you explicitly want immediate change
                )
        ```

        ***

        ## 3. Operational steps to follow

        1. **Test in non-production first.**
        2. **Ensure security groups allow the new port**:
           * Add inbound rules for the new port before changing RDS.
           * Optionally remove old port after app migration.
        3. **Update application connection strings**:
           * Most drivers accept `host:port` or a separate `port` parameter.
           * Coordinate a maintenance window if `ApplyImmediately=False` is used or if app restart is required.
        4. **Monitor after change**:
           * Check RDS instance status until it becomes `available`.
           * Test app connectivity and logs.

        If you want, I can adapt the script to:

        * Only target specific tags/instances.
        * Write changes to a “dry-run” report instead of modifying.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_db_instance" "example" {
          identifier = "NON_DEFAULT_PORT_DB_IDENTIFIER" # replace with your DB identifier

          engine               = "DB_ENGINE"            # e.g. "mysql", "postgres", "oracle-ee"
          engine_version       = "DB_ENGINE_VERSION"    # e.g. "15.3"
          instance_class       = "DB_INSTANCE_CLASS"    # e.g. "db.t3.medium"
          allocated_storage    = 20
          username             = "DB_USERNAME"
          password             = "DB_PASSWORD"
          db_subnet_group_name = aws_db_subnet_group.example.name
          vpc_security_group_ids = [
            aws_security_group.db_sg.id,
          ]

          # Remediation: move off the engine default port
          # e.g. MySQL default 3306 -> 3307, PostgreSQL default 5432 -> 5433
          port = 5433 # set to a non-default port for your engine

          # Other required settings as per your environment
          skip_final_snapshot = false
          final_snapshot_identifier = "FINAL_SNAPSHOT_ID" # choose a snapshot name
        }

        resource "aws_db_subnet_group" "example" {
          name       = "DB_SUBNET_GROUP_NAME"
          subnet_ids = [SUBNET_ID_1, SUBNET_ID_2] # replace with subnet IDs
        }

        resource "aws_security_group" "db_sg" {
          name        = "DB_SG_NAME"
          description = "Security group for RDS on non-default port"
          vpc_id      = VPC_ID # replace with your VPC ID

          ingress {
            description = "DB access on non-default port"
            from_port   = 5433                         # must match aws_db_instance.port
            to_port     = 5433                         # must match aws_db_instance.port
            protocol    = "tcp"
            cidr_blocks = ["ALLOWED_CIDR_BLOCK"]       # replace with allowed CIDR(s)
          }

          egress {
            from_port   = 0
            to_port     = 0
            protocol    = "-1"
            cidr_blocks = ["0.0.0.0/0"]
          }
        }
        ```

        Changing the `port` on an existing `aws_db_instance` forces replacement of the database instance, which causes downtime and requires updating all clients to use the new port.

        For verification, `terraform plan` should show the `port` argument on the `aws_db_instance` (and matching security group rules) changing from the default (for example, `~ port: "5432" => "5433"`) and planning to replace the instance if it already exists.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
