A Comprehensive Guide to IAM Authentication for Amazon RDS Instances

--

Photo by Campaign Creators on Unsplash

AWS Identity and Access Management (IAM) is a powerful service that allows you to manage access to various AWS resources, including Amazon RDS (Relational Database Service) instances. IAM authentication provides an additional layer of security for your RDS instances by enabling you to authenticate using AWS IAM credentials instead of traditional database credentials. This blog will take you through the process of setting up IAM authentication for Amazon RDS instances, explaining the benefits and providing a step-by-step guide.

Why use IAM Authentication for RDS Instances?

IAM authentication offers several advantages over traditional database authentication:

a. Enhanced Security: IAM authentication allows you to manage user access using AWS IAM policies, which offer fine-grained control and are easier to manage than database-level users and passwords.

b. No Need for Database Credentials: With IAM authentication, you can eliminate the need to store and manage database credentials, reducing the risk of unauthorized access and potential credential leakage.

c. Seamless Integration with AWS Services: IAM authentication integrates seamlessly with other AWS services, such as Amazon Redshift, Amazon S3, and AWS Glue, allowing you to leverage IAM roles for a consistent authentication approach.

d. Multi-Factor Authentication (MFA) Support: IAM authentication supports MFA, providing an additional layer of security for your RDS instances.

Prerequisites:

Before you begin configuring IAM authentication for your RDS instances, ensure you have the following:

  1. Configuring IAM Roles and Policies:

Step 1: Create an IAM Role

The following example policy allows a user to connect to a DB instance using IAM database authentication.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:<region>:<Account ID>:dbuser:<Database Resouce ID>/db_user"
]
}
]
}

Step 2: Modify RDS DB Instance

  • In the RDS Management Console, locate and select the RDS instance you want to enable IAM authentication for.
  • Click on “Modify.”
  • Scroll down to the “Database Authentication” section and choose “IAM DB authentication.”
  • In the “IAM Roles” dropdown, select the IAM role you created in Step 1.
  • Click “Continue” and then “Modify DB Instance.”
  1. Connecting to the RDS Instance Using IAM Authentication:

Once IAM authentication is enabled for your RDS instance, you can connect to it using various methods.

Create a database user account that uses an AWS authentication token

CREATE USER <username> IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
GRANT ALL PRIVILEGES ON dbname.* TO '<username>'@'%';
ALTER USER <username> REQUIRE SSL;
FLUSH PRIVILEGES;

Generate an AWS authentication token to identify the IAM role

wget https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem
RDSHOST="db-host.ap-south-1.rds.amazonaws.com"
TOKEN="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 3306 --region ap-south-1 --username username)"
mysql --host=$RDSHOST --port=3306 --ssl-ca=/opt/aws/rds-combined-ca-bundle.pem --enable-cleartext-plugin --user=username --password=$TOKEN

Confused Still not working

AWS Identity and Access Management (IAM) is a powerful service that allows you to manage access to various AWS resources, including Amazon RDS (Relational Database Service) instances. IAM authentication provides an additional layer of security for your RDS instances by enabling you to authenticate using AWS IAM credentials instead of traditional database credentials. This blog will take you through the process of setting up IAM authentication for Amazon RDS instances, explaining the benefits and
Photo by Nathan Dumlao on Unsplash

Note if this isn’t working for your mysql database then you may have to make a change in the Database Parameter group. Change skip_name_resolve value from 0 to 1

AWS RDS — IAM Database Authentication with Rails

require 'aws-sdk-rds'
require 'mysql2'

Aws.config.update(
region: 'region',
)

class RdsIamPasswordGenerator
def self.generate(region, host, user, port)
cred = Aws::ECSCredentials.new rescue Aws::InstanceProfileCredentials.new
Aws::RDS::AuthTokenGenerator
.new(credentials: cred)
.auth_token(
region: region,
endpoint: host.to_s + ':' + port.to_s,
user_name: user
)
end
end

module MysqlClientIamMonkeyPatch
def initialize(opts = {})
opts = opts.dup
aws_iam_auth = opts.delete(:aws_iam_auth)

if aws_iam_auth
raise ArgumentError, 'reconnect must be false if aws_iam_auth is true' if opts[:reconnect]

user = opts[:username] || opts[:user]
host = opts[:host]
port = opts[:port] || 3306

raise ArgumentError, 'username/user and host/hostname must be present' if user.nil? || host.nil?

opts.delete(:pass)
opts.delete(:password)

opts[:password] = RdsIamPasswordGenerator.generate(Aws.config[:region], host, user, port)
opts[:enable_cleartext_plugin] = true # Necessary for IAM auth
end

super(opts)
end
end

Mysql2::Client.prepend(MysqlClientIamMonkeyPatch)
# config/boot.rb
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
require_relative './database' # Handles patching in IAM auth

# config/database.yml
production:
adapter: mysql2
database: production
ssl_mode: verify_identity
sslverify: true
sslca: /opt/aws/rds-combined-ca-bundle.pem
aws_iam_auth: true
host: db_host
username: db_user
password: null

AWS RDS — IAM Database Authentication with Node

import AWS, { Credentials } from 'aws-sdk';
import config from '../config'
import fs from 'fs';
import knex from 'knex'
import { Signer } from "@aws-sdk/rds-signer";
const sslCA = fs.readFileSync('/opt/aws/rds-combined-ca-bundle.pem');

const getRDSAuthToken = async () => {
const signer = new Signer({
region: 'region',
hostname: config.get('host'),
port: config.get('port'),
username: config.get('user'),
})

const token = await signer.getAuthToken()
return {token:token,tokenExpiration:Date.now() + (14 * 60 * 1000)}
}

const Database = knex({
client: 'mysql2',
connection: async () => {
const {
token,
tokenExpiration
} = await getRDSAuthToken();
return {
host: config.get('host'),
port: config.get('port'),
user: config.get('user'),
password: token,
database: config.get('websiteDb.database'),
pool: { min: 3, max: 10 },
// ssl:true,
ssl: {
ca: sslCA,
},
expirationChecker: () => {
return tokenExpiration <= Date.now();
}
}
}
});

export default Database

And it’s Done

Photo by Fuu J on Unsplash

Conclusion:

IAM authentication provides a robust and secure method for managing access to your Amazon RDS instances. By leveraging IAM roles and policies, you can eliminate the need for database credentials and gain greater control over access to your RDS databases. Implementing IAM authentication is a best practice for any AWS environment and is well worth the effort to enhance the security posture of your infrastructure.

Remember to always follow AWS security best practices, regularly review IAM policies, and stay informed about the latest AWS security features and updates to keep your RDS instances and other AWS resources protected.

References:-

https://stackoverflow.com/a/58794305

--

--

THE HOW TO BLOG |Siddhanth Dwivedi

Siddhanth Dwivedi | Senior Security Engineer & AWS Community Builder 👨🏾‍💻