Lambda 함수에서 Amazon RDS 데이터베이스에 연결하기
Lambda 함수에서 Amazon RDS 데이터베이스에 연결하기
다음 코드 예시는 RDS 데이터베이스에 연결하는 Lambda 함수를 구현하는 방법을 보여줘요. 함수는 간단한 데이터베이스 요청을 수행하고 결과를 반환해요.
본문
.NET
SDK for .NET GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. .NET을 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
using System.Data;
using System.Text.Json;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using MySql.Data.MySqlClient;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace aws_rds;
public class InputModel
{
public string key1 { get; set; }
public string key2 { get; set; }
}
public class Function
{
/// <summary>
// Handles the Lambda function execution for connecting to RDS using IAM authentication.
/// </summary>
/// <param name="input">The input event data passed to the Lambda function</param>
/// <param name="context">The Lambda execution context that provides runtime information</param>
/// <returns>A response object containing the execution result</returns>
public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
{
// Sample Input: {"body": "{\"key1\":\"20\", \"key2\":\"25\"}"}
var input = JsonSerializer.Deserialize<InputModel>(request.Body);
/// Obtain authentication token
var authToken = RDSAuthTokenGenerator.GenerateAuthToken(
Environment.GetEnvironmentVariable("RDS_ENDPOINT"),
Convert.ToInt32(Environment.GetEnvironmentVariable("RDS_PORT")),
Environment.GetEnvironmentVariable("RDS_USERNAME")
);
/// Build the Connection String with the Token
string connectionString = $"Server={Environment.GetEnvironmentVariable("RDS_ENDPOINT")};" +
$"Port={Environment.GetEnvironmentVariable("RDS_PORT")};" +
$"Uid={Environment.GetEnvironmentVariable("RDS_USERNAME")};" +
$"Pwd={authToken};";
try
{
await using var connection = new MySqlConnection(connectionString);
await connection.OpenAsync();
const string sql = "SELECT @param1 + @param2 AS Sum";
await using var command = new MySqlCommand(sql, connection);
command.Parameters.AddWithValue("@param1", int.Parse(input.key1 ?? "0"));
command.Parameters.AddWithValue("@param2", int.Parse(input.key2 ?? "0"));
await using var reader = await command.ExecuteReaderAsync();
if (await reader.ReadAsync())
{
int result = reader.GetInt32("Sum");
//Sample Response: {"statusCode":200,"body":"{\"message\":\"The sum is: 45\"}","isBase64Encoded":false}
return new APIGatewayProxyResponse
{
StatusCode = 200,
Body = JsonSerializer.Serialize(new { message = $"The sum is: {result}" })
};
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
return new APIGatewayProxyResponse
{
StatusCode = 500,
Body = JsonSerializer.Serialize(new { error = "Internal server error" })
};
}
}
Go
SDK for Go V2 GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. Go를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
/*
Golang v2 code here.
*/
package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"os"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
_ "github.com/go-sql-driver/mysql"
)
type MyEvent struct {
Name string `json:"name"`
}
func HandleRequest(event *MyEvent) (map[string]interface{}, error) {
var dbName string = os.Getenv("DatabaseName")
var dbUser string = os.Getenv("DatabaseUser")
var dbHost string = os.Getenv("DBHost") // Add hostname without https
var dbPort int = os.Getenv("Port") // Add port number
var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
var region string = os.Getenv("AWS_REGION")
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic("configuration error: " + err.Error())
}
authenticationToken, err := auth.BuildAuthToken(
context.TODO(), dbEndpoint, region, dbUser, cfg.Credentials)
if err != nil {
panic("failed to create authentication token: " + err.Error())
}
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=true&allowCleartextPasswords=true",
dbUser, authenticationToken, dbEndpoint, dbName,
)
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
defer db.Close()
var sum int
err = db.QueryRow("SELECT ?+? AS sum", 3, 2).Scan(&sum)
if err != nil {
panic(err)
}
s := fmt.Sprint(sum)
message := fmt.Sprintf("The selected sum is: %s", s)
messageBytes, err := json.Marshal(message)
if err != nil {
return nil, err
}
messageString := string(messageBytes)
return map[string]interface{}{
"statusCode": 200,
"headers": map[string]string{"Content-Type": "application/json"},
"body": messageString,
}, nil
}
func main() {
lambda.Start(HandleRequest)
}
Java
SDK for Java 2.x GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. Java를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rdsdata.RdsDataClient;
import software.amazon.awssdk.services.rdsdata.model.ExecuteStatementRequest;
import software.amazon.awssdk.services.rdsdata.model.ExecuteStatementResponse;
import software.amazon.awssdk.services.rdsdata.model.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class RdsLambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
try {
// Obtain auth token
String token = createAuthToken();
// Define connection configuration
String connectionString = String.format("jdbc:mysql://%s:%s/%s?useSSL=true&requireSSL=true",
System.getenv("ProxyHostName"),
System.getenv("Port"),
System.getenv("DBName"));
// Establish a connection to the database
try (Connection connection = DriverManager.getConnection(connectionString, System.getenv("DBUserName"), token);
PreparedStatement statement = connection.prepareStatement("SELECT ? + ? AS sum")) {
statement.setInt(1, 3);
statement.setInt(2, 2);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
int sum = resultSet.getInt("sum");
response.setStatusCode(200);
response.setBody("The selected sum is: " + sum);
}
}
}
} catch (Exception e) {
response.setStatusCode(500);
response.setBody("Error: " + e.getMessage());
}
return response;
}
private String createAuthToken() {
// Create RDS Data Service client
RdsDataClient rdsDataClient = RdsDataClient.builder()
.region(Region.of(System.getenv("AWS_REGION")))
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
// Define authentication request
ExecuteStatementRequest request = ExecuteStatementRequest.builder()
.resourceArn(System.getenv("ProxyHostName"))
.secretArn(System.getenv("DBUserName"))
.database(System.getenv("DBName"))
.sql("SELECT 'RDS IAM Authentication'")
.build();
// Execute request and obtain authentication token
ExecuteStatementResponse response = rdsDataClient.executeStatement(request);
Field tokenField = response.records().get(0).get(0);
return tokenField.stringValue();
}
}
JavaScript
SDK for JavaScript (v3) GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. JavaScript를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/*
Node.js code here.
*/
// ES6+ example
import { Signer } from "@aws-sdk/rds-signer";
import mysql from 'mysql2/promise';
async function createAuthToken() {
// Define connection authentication parameters
const dbinfo = {
hostname: process.env.ProxyHostName,
port: process.env.Port,
username: process.env.DBUserName,
region: process.env.AWS_REGION,
}
// Create RDS Signer object
const signer = new Signer(dbinfo);
// Request authorization token from RDS, specifying the username
const token = await signer.getAuthToken();
return token;
}
async function dbOps() {
// Obtain auth token
const token = await createAuthToken();
// Define connection configuration
let connectionConfig = {
host: process.env.ProxyHostName,
user: process.env.DBUserName,
password: token,
database: process.env.DBName,
ssl: 'Amazon RDS'
}
// Create the connection to the DB
const conn = await mysql.createConnection(connectionConfig);
// Obtain the result of the query
const [res,] = await conn.execute('select ?+? as sum', [3, 2]);
return res;
}
export const handler = async (event) => {
// Execute database flow
const result = await dbOps();
// Return result
return {
statusCode: 200,
body: JSON.stringify("The selected sum is: " + result[0].sum)
};
};
TypeScript를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
import { Signer } from "@aws-sdk/rds-signer";
import mysql from 'mysql2/promise';
// RDS settings
// Using '!' (non-null assertion operator) to tell the TypeScript compiler that the DB settings are not null or undefined,
const proxy_host_name = process.env.PROXY_HOST_NAME!
const port = parseInt(process.env.PORT!)
const db_name = process.env.DB_NAME!
const db_user_name = process.env.DB_USER_NAME!
const aws_region = process.env.AWS_REGION!
async function createAuthToken(): Promise<string> {
// Create RDS Signer object
const signer = new Signer({
hostname: proxy_host_name,
port: port,
region: aws_region,
username: db_user_name
});
// Request authorization token from RDS, specifying the username
const token = await signer.getAuthToken();
return token;
}
async function dbOps(): Promise<mysql.QueryResult | undefined> {
try {
// Obtain auth token
const token = await createAuthToken();
const conn = await mysql.createConnection({
host: proxy_host_name,
user: db_user_name,
password: token,
database: db_name,
ssl: 'Amazon RDS' // Ensure you have the CA bundle for SSL connection
});
const [rows, fields] = await conn.execute('SELECT ? + ? AS sum', [3, 2]);
console.log('result:', rows);
return rows;
}
catch (err) {
console.log(err);
}
}
export const lambdaHandler = async (event: any): Promise<{ statusCode: number; body: string }> => {
// Execute database flow
const result = await dbOps();
// Return error is result is undefined
if (result == undefined)
return {
statusCode: 500,
body: JSON.stringify(`Error with connection to DB host`)
}
// Return result
return {
statusCode: 200,
body: JSON.stringify(`The selected sum is: ${result[0].sum}`)
};
};
PHP
SDK for PHP GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. PHP를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
<?php
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
# using bref/bref and bref/logger for simplicity
use Bref\Context\Context;
use Bref\Event\Handler as StdHandler;
use Bref\Logger\StderrLogger;
use Aws\Rds\AuthTokenGenerator;
use Aws\Credentials\CredentialProvider;
require __DIR__ . '/vendor/autoload.php';
class Handler implements StdHandler
{
private StderrLogger $logger;
public function __construct(StderrLogger $logger)
{
$this->logger = $logger;
}
private function getAuthToken(): string {
// Define connection authentication parameters
$dbConnection = [
'hostname' => getenv('DB_HOSTNAME'),
'port' => getenv('DB_PORT'),
'username' => getenv('DB_USERNAME'),
'region' => getenv('AWS_REGION'),
];
// Create RDS AuthTokenGenerator object
$generator = new AuthTokenGenerator(CredentialProvider::defaultProvider());
// Request authorization token from RDS, specifying the username
return $generator->createToken(
$dbConnection['hostname'] . ':' . $dbConnection['port'],
$dbConnection['region'],
$dbConnection['username']
);
}
private function getQueryResults() {
// Obtain auth token
$token = $this->getAuthToken();
// Define connection configuration
$connectionConfig = [
'host' => getenv('DB_HOSTNAME'),
'user' => getenv('DB_USERNAME'),
'password' => $token,
'database' => getenv('DB_NAME'),
];
// Create the connection to the DB
$conn = new PDO(
"mysql:host={$connectionConfig['host']};dbname={$connectionConfig['database']}",
$connectionConfig['user'],
$connectionConfig['password'],
[
PDO::MYSQL_ATTR_SSL_CA => '/path/to/rds-ca-2019-root.pem',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true,
]
);
// Obtain the result of the query
$stmt = $conn->prepare('SELECT ?+? AS sum');
$stmt->execute([3, 2]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* @param mixed $event
* @param Context $context
* @return array
*/
public function handle(mixed $event, Context $context): array
{
$this->logger->info("Processing query");
// Execute database flow
$result = $this->getQueryResults();
return [
'sum' => $result['sum']
];
}
}
$logger = new StderrLogger();
return new Handler($logger);
Python
SDK for Python (Boto3) GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. Python을 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
import json
import os
import boto3
import pymysql
# RDS settings
proxy_host_name = os.environ['PROXY_HOST_NAME']
port = int(os.environ['PORT'])
db_name = os.environ['DB_NAME']
db_user_name = os.environ['DB_USER_NAME']
aws_region = os.environ['AWS_REGION']
# Fetch RDS Auth Token
def get_auth_token():
client = boto3.client('rds')
token = client.generate_db_auth_token(
DBHostname=proxy_host_name,
Port=port
DBUsername=db_user_name
Region=aws_region
)
return token
def lambda_handler(event, context):
token = get_auth_token()
try:
connection = pymysql.connect(
host=proxy_host_name,
user=db_user_name,
password=token,
db=db_name,
port=port,
ssl={'ca': 'Amazon RDS'} # Ensure you have the CA bundle for SSL connection
)
with connection.cursor() as cursor:
cursor.execute('SELECT %s + %s AS sum', (3, 2))
result = cursor.fetchone()
return result
except Exception as e:
return (f"Error: {str(e)}") # Return an error message if an exception occurs
Ruby
SDK for Ruby GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. Ruby를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
# Ruby code here.
require 'aws-sdk-rds'
require 'json'
require 'mysql2'
def lambda_handler(event:, context:)
endpoint = ENV['DBEndpoint'] # Add the endpoint without https"
port = ENV['Port'] # 3306
user = ENV['DBUser']
region = ENV['DBRegion'] # 'us-east-1'
db_name = ENV['DBName']
credentials = Aws::Credentials.new(
ENV['AWS_ACCESS_KEY_ID'],
ENV['AWS_SECRET_ACCESS_KEY'],
ENV['AWS_SESSION_TOKEN']
)
rds_client = Aws::RDS::AuthTokenGenerator.new(
region: region,
credentials: credentials
)
token = rds_client.auth_token(
endpoint: endpoint+ ':' + port,
user_name: user,
region: region
)
begin
conn = Mysql2::Client.new(
host: endpoint,
username: user,
password: token,
port: port,
database: db_name,
sslca: '/var/task/global-bundle.pem',
sslverify: true,
enable_cleartext_plugin: true
)
a = 3
b = 2
result = conn.query("SELECT #{a} + #{b} AS sum").first['sum']
puts result
conn.close
{
statusCode: 200,
body: result.to_json
}
rescue => e
puts "Database connection failed due to #{e}"
end
end
Rust
SDK for Rust GitHub에 더 많은 내용이 있어요. 전체 예시와 설정·실행 방법은 Serverless examples 저장소에서 확인하세요. Rust를 사용해서 Lambda 함수에서 Amazon RDS 데이터베이스에 연결해요.
use aws_config::BehaviorVersion;
use aws_credential_types::provider::ProvideCredentials;
use aws_sigv4::{
http_request::{sign, SignableBody, SignableRequest, SigningSettings},
sign::v4,
};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde_json::{json, Value};
use sqlx::postgres::PgConnectOptions;
use std::env;
use std::time::{Duration, SystemTime};
const RDS_CERTS: &[u8] = include_bytes!("global-bundle.pem");
async fn generate_rds_iam_token(
db_hostname: &str,
port: u16,
db_username: &str,
) -> Result<String, Error> {
let config = aws_config::load_defaults(BehaviorVersion::v2024_03_28()).await;
let credentials = config
.credentials_provider()
.expect("no credentials provider found")
.provide_credentials()
.await
.expect("unable to load credentials");
let identity = credentials.into();
let region = config.region().unwrap().to_string();
let mut signing_settings = SigningSettings::default();
signing_settings.expires_in = Some(Duration::from_secs(900));
signing_settings.signature_location = aws_sigv4::http_request::SignatureLocation::QueryParams;
let signing_params = v4::SigningParams::builder()
.identity(&identity)
.region(®ion)
.name("rds-db")
.time(SystemTime::now())
.settings(signing_settings)
.build()?;
let url = format!(
"https://{db_hostname}:{port}/?Action=connect&DBUser={db_user}",
db_hostname = db_hostname,
port = port,
db_user = db_username
);
let signable_request =
SignableRequest::new("GET", &url, std::iter::empty(), SignableBody::Bytes(&[]))
.expect("signable request");
let (signing_instructions, _signature) =
sign(signable_request, &signing_params.into())?.into_parts();
let mut url = url::Url::parse(&url).unwrap();
for (name, value) in signing_instructions.params() {
url.query_pairs_mut().append_pair(name, &value);
}
let response = url.to_string().split_off("https://".len());
Ok(response)
}
#[tokio::main]
async fn main() -> Result<(), Error> {
run(service_fn(handler)).await
}
async fn handler(_event: LambdaEvent<Value>) -> Result<Value, Error> {
let db_host = env::var("DB_HOSTNAME").expect("DB_HOSTNAME must be set");
let db_port = env::var("DB_PORT")
.expect("DB_PORT must be set")
.parse::<u16>()
.expect("PORT must be a valid number");
let db_name = env::var("DB_NAME").expect("DB_NAME must be set");
let db_user_name = env::var("DB_USERNAME").expect("DB_USERNAME must be set");
let token = generate_rds_iam_token(&db_host, db_port, &db_user_name).await?;
let opts = PgConnectOptions::new()
.host(&db_host)
.port(db_port)
.username(&db_user_name)
.password(&token)
.database(&db_name)
.ssl_root_cert_from_pem(RDS_CERTS.to_vec())
.ssl_mode(sqlx::postgres::PgSslMode::Require);
let pool = sqlx::postgres::PgPoolOptions::new()
.connect_with(opts)
.await?;
let result: i32 = sqlx::query_scalar("SELECT $1 + $2")
.bind(3)
.bind(2)
.fetch_one(&pool)
.await?;
println!("Result: {:?}", result);
Ok(json!({
"statusCode": 200,
"content-type": "text/plain",
"body": format!("The selected sum is: {result}")
}))
}
더 알아보기 (Learn more)
AWS SDK 개발자 안내서와 코드 예시의 전체 목록은 AWS SDK와 함께 Lambda 사용을 참고하세요. 이 주제에는 시작하기와 이전 SDK 버전에 대한 정보도 포함돼 있어요.