Common Fate’s AWS RDS integration allows your end users to request Just-In-Time (JIT) access to RDS databases. Common Fate will provision an ephemeral EC2 instance used to proxy network access to the database. The proxy instance captures audit logs of all SQL commands executed by the user during their session. Users connect to the proxy instance using AWS SSM Session Manager.

Using this integration mitigates the need to run long-lived proxy infrastructure for privileged access to RDS databases. Common Fate continuously scans for RDS resources across your AWS organization, so new databases can become available for access without requiring additional configuration.

This guide will walk you through integrating Common Fate with AWS RDS. By the end of this guide, you’ll have a functioning integration with Common Fate, allowing it to read RDS Instances and VPCs from selected accounts and regions and provision access to entitlements.

AWS RDS Setup

The AWS RDS integration is deployed in conjunction with the AWS IDC integration. The AWS IDC integration will handle discovery of database instances and the provisioner will grant access to them by deploying an ephemeral ec2 bastion host.

The following terraform will deploy the required IAM role for reading RDS instances and provisioning access, deploy this role into each account containing databases you wish to access

  module "common-fate-aws-rds-roles" {
    common_fate_aws_account_id = "<The AWS account id where Common Fate is deployed>"
    organizational_unit_ids = "<The organization root ID or organizational unit (OU) IDs to which StackSets deploys the rds provisioning role into>"
  }

  module "common-fate-aws-audit-roles" {
    common_fate_aws_account_id = "<The AWS account id where Common Fate is deployed>"
    organizational_unit_ids = "<The organization root ID or organizational unit (OU) IDs to which StackSets deploys the rds provisioning role into>"
  }

Configuring Common Fate

In this section, you will update your AWS IDC integration to enable the RDS feature. At the end of this section, you should have Common Fate reading AWS RDS resources and see them inside the web dashboard. You’ll need to have set up the Common Fate Application Configuration repository using our Terraform provider.

Inside your Application Configuration repository, update the following module:

resource "commonfate_aws_idc_integration" "example" {
  ... existing config
+  audit_role_name = module.common-fate-aws-audit-roles.audit_role_name
+  resource_regions = ["<each region to discover databases in"]
}

Apply the changes. If the apply succeeds, you should see AWS RDS resources should populate within 10 minutes.

If after 10 minutes you do not see resources appear, check the logs of the common-fate-prod-control-plane service in ECS. You can search for aws_rds_sync to filter for structured logs containing data about the AWS integration.

Provisioning access to AWS RDS instances

To grant and revoke access to AWS, Common Fate uses a service called the Provisioner. The Provisioner is an internal service and is not user-facing. In default deployments, there is a provisioner builtin to the main stack which can be configured using blocks.

To configure the builtin Provisioner for AWS RDS, add the provisioner_aws_rds_config config block as per the example below:

By default, the provisioner will attempt to find a security group in the same VPC as your database which already has access to the database. It will look for a security group tagged with should_provision_security_groups=true. You can alternatively allow the provisioner to create it’s own security group and attach it to the database as required by setting should_provision_security_groups to true on the provisioner config.

module "common-fate-deployment" {
  source = "common-fate/common-fate-deployment/aws"
  version = "1.22.0"

  aws_rds_config = {
    idc_instance_arn                  = "<Your Identity Center Instance ARN>"
    idc_region                        = "<Your Identity Center Region>"
    idc_role_arn                      = "<ARN of the IDC Management IAM role>"
    infra_role_name                   = module.common-fate-aws-rds-roles.rds_provisioning_role_name
    should_provision_security_groups  = "<(Optional) whether or not to provision security groups for database access>"
  }
}

You’ll additionally need to add the following Provisioner registration inside your Application Configuration repository:

resource "commonfate_webhook_provisioner" "aws" {
  url = "http://common-fate-prod-builtin-provisioner.common-fate-prod-builtin.internal:9999"
  capabilities = [
    {
      target_type = "AWS::RDS::Instance"
      role_type   = "CF::Database::Role"
      belonging_to = {
        type = "AWS::Organization"
        id   = "<Your AWS Organization ID>"
      }
    },
  ]
}

You can now create an access workflow and availabilities:


resource "commonfate_access_workflow" "rds" {
  name                     = "RDS"
  access_duration_seconds  = 60
  try_extend_after_seconds = 5
  priority                 = 3
}

resource "commonfate_aws_rds_selector" "select_all" {
  id                  = "select_all_aws_rds"
  name                = "Select All Databases"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = "true"
}


resource "commonfate_aws_rds_availabilities" "demo" {
  workflow_id           = commonfate_access_workflow.rds.id
  aws_rds_selector_id   = commonfate_aws_rds_selector.select_all.id
  aws_identity_store_id = "<Your Identity Store ID>"
}


AWS RDS database selectors

To make AWS RDS databases available for Just-In-Time (JIT) access you can add a commonfate_aws_rds_selector Selector resource to your Common Fate application Terraform code. As shown below, the when clause in the resource is a Cedar expression. You can use any Cedar operator in the when clause, such as && and || to combine conditions.

You’ll need to use the commonfate_aws_rds_selector in conjunction with a commonfate_aws_rds_availabilities and commonfate_access_workflow resources, as shown above.

We’ve included some examples below.

Select a database by ID

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource == AWS::RDS::Database::"example-instance-identifier"
  EOT
}

Select multiple databases by ID

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource == AWS::RDS::Database::"example-instance-identifier" ||  AWS::RDS::Database::"another-example-instance-identifier"
  EOT
}

Select a database based on a naming pattern

Select databases with a name ending in -prod:

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource.name like "*-prod"
  EOT
}

Select databases with a name beginning with Develop:

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource.name like "Develop*"
  EOT
}

Select databases belonging to a particular Organizational Unit (OU)

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource in AWS::OrgUnit::"ou-123abc"
  EOT
}

Select an account containing a tag key

Selects AWS databases which have a tag with a key of production:

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource.tag_keys.contains("production")
  EOT
}

Select an account containing a tag key and value

Selects AWS databases which have a tag with key department and value engineering (department=engineering):

resource "commonfate_aws_rds_selector" "example" {
  id                  = "example"
  name                = "Example"
  aws_organization_id = "<Your AWS Organization ID>"
  when                = <<EOT
  resource.tags.contains({key: "department", value: "engineering"})
  EOT
}