# Using Secrets Manager to Authenticate with an RDS Database Using Lambda - Learning material: ACloudGURU ## Introduce AWS Secrets Manager assists in safeguarding the secrets required for accessing your applications, services, and IT resources. This service allows you to effortlessly rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle. In this lab, we establish a connection to a MySQL RDS database from an AWS Lambda function using a username and password, then we transfer credential management to AWS Secrets Manager. Subsequently, we utilize the Secrets Manager API to connect to the database, eliminating the need to hard-code credentials in our Lambda function. By the conclusion of this lab, we will comprehend how to store a secret in AWS Secrets Manager and access it from a Lambda function. ## Diagram ![image](https://hackmd.io/_uploads/HkbLHb15R.png) ## Steps - Go to RDS ![image](https://hackmd.io/_uploads/BkU_WWJ5C.png) - Find the endpoint ![image](https://hackmd.io/_uploads/B163WZyqA.png) ### Create a Lambda function and Create the MySQL Layer - Enable VPC for accessing VPC resources ![image](https://hackmd.io/_uploads/ryhPzZJ90.png) - Modify timeout ![image](https://hackmd.io/_uploads/Sk-x4byq0.png) - Create "mysql" layer because Lambda will call mysql ![image](https://hackmd.io/_uploads/r1UAubk5R.png) ### Create Table in the RDS Database Using Lambda to Check Connectivity - Go to the function you create ![image](https://hackmd.io/_uploads/ByY7YZJcC.png) - Add a layer ![image](https://hackmd.io/_uploads/ryNwt-k9C.png) - Modify the code, replacing the < RDS Endpoint > placeholder with your own RDS endpoint ![image](https://hackmd.io/_uploads/S1vWqWkcR.png) ```javascript= import mysql from 'mysql2/promise'; export const handler = async (event, context, callback) => { try { const connection = await mysql.createConnection({ host: "<RDS Endpoint>", user: "username", password: "password", database: "example", }); // Create 'pets' table await connection.execute(` CREATE TABLE IF NOT EXISTS pets ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, age INT NOT NULL ) `); console.log('Table created: pets'); // List all tables const [rows] = await connection.execute('SHOW TABLES'); console.log('Tables:'); rows.forEach((row) => { console.log(row[`Tables_in_example`]); }); connection.end(); callback(null, { statusCode: 200, body: 'Tables listed successfully', }); } catch (err) { console.error(err); callback(err, { statusCode: 500, body: 'Error listing tables', }); } }; ``` - Deploy - Test ![image](https://hackmd.io/_uploads/ByXMsWkqA.png) ![image](https://hackmd.io/_uploads/BkkBo-yqC.png) ![image](https://hackmd.io/_uploads/BJzPobyc0.png) ### Modify the Lambda IAM Role - Go to "Configuration" > "Permission" > link below "Role name" ![image](https://hackmd.io/_uploads/ByPrnWkcR.png) - Add new permission ![image](https://hackmd.io/_uploads/HyVA2-k9A.png) - Attach "SecretsManagerReadWrite", so the resources we can use with Lambda will be more ![image](https://hackmd.io/_uploads/ryCep-ycC.png) - Result ![image](https://hackmd.io/_uploads/r1kxC-1cR.png)![image](https://hackmd.io/_uploads/rJY-0bkcC.png) ### Create a Secret in Secrets Manager - Go to Secret manager ![image](https://hackmd.io/_uploads/rkuiRWJ5R.png) - ![image](https://hackmd.io/_uploads/SJ2AAZJcA.png) ![image](https://hackmd.io/_uploads/Hy6-yMJ9R.png) ![image](https://hackmd.io/_uploads/SkwYJz1c0.png) - Password has been changed ![image](https://hackmd.io/_uploads/rJr7ZzJ90.png) ### Test Connectivity from Lambda to RDS Using Credentials from AWS Secrets Manager - In the index.mjs, file replace the current code with the code shown below. Issue a deploy, and once deployed, issue a test. Ensure you replace the < RDS Endpoint > placeholder with the endpoint of your RDS MySQL database. - With this code, we can retrieve the RDS credential secret name from Secrets Manager. It will then open a connection to the MySQL RDS database using the host as the RDS endpoint and the user and password. ```javascript= import mysql from 'mysql2/promise'; import AWS from 'aws-sdk'; const secretName = 'RDScredentials'; const region = 'us-east-1'; const rdsEndpoint = '<RDS Endpoint>'; const databaseName = 'example'; AWS.config.update({ region: region }); const secretsManager = new AWS.SecretsManager(); export const handler = async (event, context) => { try { const data = await secretsManager.getSecretValue({ SecretId: secretName }).promise(); const secret = JSON.parse(data.SecretString || Buffer.from(data.SecretBinary, 'base64').toString('ascii')); const { username, password } = secret; const connection = await mysql.createConnection({ host: rdsEndpoint, user: username, password: password, database: databaseName, }); const [rows] = await connection.execute('SHOW TABLES'); console.log('Tables:'); rows.forEach((row) => { console.log(row[`Tables_in_${databaseName}`]); }); connection.end(); return { statusCode: 200, body: 'Tables listed successfully', }; } catch (err) { console.error('Error:', err.message); return { statusCode: 500, body: 'Error listing tables', }; } }; ``` - Test ![image](https://hackmd.io/_uploads/Hy7sXfJ9A.png) ## Conclusion User can use Lambda function to retrieve credential from Secret manager, then use the credential to get access to RDS.