

# Usar o AWS Lambda com o Amazon RDS
<a name="services-rds"></a>

É possível conectar uma função do Lambda a um banco de dados do Amazon Relational Database Service (Amazon RDS) diretamente e por meio de um Amazon RDS Proxy. As conexões diretas são úteis em cenários simples e os proxies são recomendados para produção. Um proxy de banco de dados gerencia um pool de conexões de banco de dados compartilhadas, o que permite que sua função atinja altos níveis de simultaneidade sem esgotar as conexões de banco de dados.

Recomendamos o uso do Amazon RDS Proxy para funções do Lambda que fazem conexões curtas e frequentes com o banco de dados ou que abrem e fecham um grande número de conexões de banco de dados. Para obter mais informações, consulte [Conectar automaticamente uma função do Lambda e uma instância de banco de dados](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/lambda-rds-connect.html) no Guia do desenvolvedor do Amazon Relational Database Service.

**dica**  
Para conectar uma função do Lambda rapidamente a um banco de dados do Amazon RDS, é possível usar o assistente guiado no console. Para abrir o assistente, faça o seguinte:  
Abra a [página Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda.
Selecione a função à qual você deseja conectar um banco de dados.
Na guia **Configuração**, selecione **bancos de dados do RDS**.
Escolha **Conectar ao banco de dados do RDS**.
Depois de conectar a função a um banco de dados, você pode criar um proxy escolhendo **Adicionar proxy**.

## Configurar a função para funcionar com recursos do RDS
<a name="rds-configuration"></a>

No console do Lambda, você pode provisionar e configurar instâncias de banco de dados e recursos de proxy do Amazon RDS. É possível fazer isso navegando até **Bancos de dados do RDS** na guia **Configuração**. Como alternativa, você também pode criar e configurar conexões com funções do Lambda no console do Amazon RDS. Ao configurar uma instância de banco de dados do RDS para usar com o Lambda, observe os seguintes critérios:
+ Para se conectar a um banco de dados, a função deve estar na mesma Amazon VPC em que o banco de dados é executado.
+ É possível usar bancos de dados do Amazon RDS com mecanismos MySQL, MariaDB, PostgreSQL ou Microsoft SQL Server.
+ Também é possível usar clusters de banco de dados do Aurora com mecanismos MySQL ou PostgreSQL.
+ Você precisa fornecer um segredo do Secrets Manager para a autenticação do banco de dados.
+ Um perfil do IAM deve fornecer permissão para usar o segredo e uma política de confiança deve permitir que o Amazon RDS assuma o perfil.
+  A entidade principal do IAM que usa o console para configurar o recurso do Amazon RDS e conectá-lo à função deve ter as seguintes permissões:

### Exemplo de política de permissões
<a name="rds-lambda-permissions"></a>

**nota**  
 Você só precisa das permissões do Amazon RDS Proxy se configurar um Amazon RDS Proxy para gerenciar um pool de conexões de banco de dados. 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSecurityGroup",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSubnets",
        "ec2:DescribeVpcs",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:AuthorizeSecurityGroupEgress",
        "ec2:RevokeSecurityGroupEgress",
        "ec2:CreateNetworkInterface",
        "ec2:DeleteNetworkInterface",
        "ec2:DescribeNetworkInterfaces"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds-db:connect",
        "rds:CreateDBProxy",
        "rds:CreateDBInstance",
        "rds:CreateDBSubnetGroup",
        "rds:DescribeDBClusters",
        "rds:DescribeDBInstances",
        "rds:DescribeDBSubnetGroups",
        "rds:DescribeDBProxies",
        "rds:DescribeDBProxyTargets",
        "rds:DescribeDBProxyTargetGroups",
        "rds:RegisterDBProxyTargets",
        "rds:ModifyDBInstance",
        "rds:ModifyDBProxy"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "lambda:CreateFunction",
        "lambda:ListFunctions",
        "lambda:UpdateFunctionConfiguration"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:AttachRolePolicy",
        "iam:CreateRole",
        "iam:CreatePolicy"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetResourcePolicy",
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret",
        "secretsmanager:ListSecretVersionIds",
        "secretsmanager:CreateSecret"
      ],
      "Resource": "*"
    }
  ]
}
```

------

O Amazon RDS cobra uma taxa horária por proxies com base no tamanho da instância do banco de dados. Consulte [Preço do RDS Proxy](https://aws.amazon.com/rds/proxy/pricing/) para obter detalhes. Para obter mais informações sobre conexões de proxy, consulte [Usar o Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) no Guia do usuário do Amazon RDS.

### Requisitos de SSL/TLS para conexões do Amazon RDS
<a name="rds-lambda-certificates"></a>

Para fazer conexões SSL/TLS seguras com uma instância de banco de dados do Amazon RDS, a função do Lambda deverá verificar a identidade do servidor de banco de dados usando um certificado confiável. O Lambda lida com esses certificados de forma diferente dependendo do tipo de pacote de implantação:
+ [Arquivamentos de arquivos .zip](configuration-function-zip.md): o tratamento de certificados varia de acordo com o runtime:
  + **Node.js 18 e versões anteriores**: o Lambda inclui certificados CA e certificados do RDS automaticamente.
  + **Node.js 20 e posteriores**: o Lambda não carrega mais certificados CA adicionais por padrão. Defina a variável de ambiente `NODE_EXTRA_CA_CERTS` como `/var/runtime/ca-cert.pem`.

  Até 4 semanas podem ser necessárias para que os certificados do Amazon RDS para novos Regiões da AWS sejam adicionados aos runtimes gerenciados do Lambda.
+ [Imagens de contêiner](images-create.md): as imagens base da AWS incluem apenas certificados de CA. Se sua função se conectar a uma instância de banco de dados do Amazon RDS, será necessário incluir os certificados apropriados na imagem do seu contêiner. Em seu Dockerfile, baixe o [pacote de certificados que corresponde à Região da AWS em que você hospeda seu banco de dados.](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificatesDownload) Exemplo:

  ```
  RUN curl https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem -o /us-east-1-bundle.pem
  ```

Esse comando baixa o pacote de certificados do Amazon RDS e o salva no caminho absoluto `/us-east-1-bundle.pem` no diretório raiz do seu contêiner. Ao configurar a conexão do banco de dados no código da função, você deve referenciar esse caminho exato. Exemplo:

------
#### [ Node.js ]

A função `readFileSync` é necessária porque os clientes de banco de dados Node.js precisam do conteúdo real do certificado na memória, e não apenas do caminho para o arquivo do certificado. Sem `readFileSync`, o cliente interpreta a string do caminho como conteúdo do certificado, o que resulta em um erro de "certificado autoassinado na cadeia de certificados".

**Example Configuração de conexão Node.js para função OCI**  

```
import { readFileSync } from 'fs';

// ...

let connectionConfig = {
    host: process.env.ProxyHostName,
    user: process.env.DBUserName,
    password: token,
    database: process.env.DBName,
    ssl: {
        ca: readFileSync('/us-east-1-bundle.pem') // Load RDS certificate content from file into memory
    }
};
```

------
#### [ Python ]

**Example Configuração de conexão Python para função OCI**  

```
connection = pymysql.connect(
    host=proxy_host_name,
    user=db_username,
    password=token,
    db=db_name,
    port=port,
    ssl={'ca': '/us-east-1-bundle.pem'}  #Path to the certificate in container
)
```

------
#### [ Java ]

Para funções Java que usam conexões JDBC, a string de conexão deve incluir:
+ `useSSL=true`
+ `requireSSL=true`
+ Um parâmetro `sslCA` que aponta para a localização do certificado do Amazon RDS na imagem do contêiner

**Example String de conexão Java para função OCI**  

```
// Define connection string
String connectionString = String.format("jdbc:mysql://%s:%s/%s?useSSL=true&requireSSL=true&sslCA=/us-east-1-bundle.pem", // Path to the certificate in container
        System.getenv("ProxyHostName"),
        System.getenv("Port"),
        System.getenv("DBName"));
```

------
#### [ .NET ]

**Example String de conexão .NET para conexão MySQL em função OCI**  

```
/// 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};" +
                         "SslMode=Required;" +
                         "SslCa=/us-east-1-bundle.pem";  // Path to the certificate in container
```

------
#### [ Go ]

Para funções em Go que usam conexões MySQL, carregue o certificado do Amazon RDS em um pool de certificados e registre-o com o driver do MySQL. A string de conexão deve então referenciar essa configuração usando o parâmetro `tls`.

**Example Código Go para conexão MySQL em função OCI**  

```
import (
    "crypto/tls"
    "crypto/x509"
    "os"
    "github.com/go-sql-driver/mysql"
)

...

// Create certificate pool and register TLS config
rootCertPool := x509.NewCertPool()
pem, err := os.ReadFile("/us-east-1-bundle.pem")  // Path to the certificate in container
if err != nil {
    panic("failed to read certificate file: " + err.Error())
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
    panic("failed to append PEM")
}

mysql.RegisterTLSConfig("custom", &tls.Config{
    RootCAs: rootCertPool,
})

dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?allowCleartextPasswords=true&tls=custom",
    dbUser, authenticationToken, dbEndpoint, dbName,
)
```

------
#### [ Ruby ]

**Example Configuração de conexão Ruby para função OCI**  

```
conn = Mysql2::Client.new(
    host: endpoint,
    username: user,
    password: token,
    port: port,
    database: db_name,
    sslca: '/us-east-1-bundle.pem',  # Path to the certificate in container
    sslverify: true
)
```

------

## Como se conectar a um banco de dados do Amazon RDS em uma função do Lambda
<a name="rds-connection"></a>

Os exemplos de código a seguir mostram como implementar uma função do Lambda que se conecta a um banco de dados do Amazon RDS. A função faz uma solicitação simples ao banco de dados e exibe o resultado.

**nota**  
Esses exemplos de código são válidos somente para [pacotes de implantação .zip](configuration-function-zip.md). Se você estiver implantando sua função usando uma [imagem de contêiner](images-create.md), será necessário especificar o arquivo de certificado do Amazon RDS no código da sua função, conforme explicado na [seção anterior](#oci-certificate).

------
#### [ .NET ]

**SDK para .NET**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando .NET.  

```
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 para Go V2**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando Go.  

```
/*
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 para Java 2.x**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando Java.  

```
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 para JavaScript (v3)**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando JavaScript.  

```
// 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)
  }
};
```
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando TypeScript.  

```
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 para PHP**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando PHP.  

```
<?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 para Python (Boto3).**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando Python.  

```
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 para Ruby**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando Ruby.  

```
# 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 para Rust**  
 Há mais no GitHub. Encontre o exemplo completo e saiba como configurar e executar no repositório dos [Exemplos sem servidor](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam). 
Conectar-se a um banco de dados do Amazon RDS em uma função do Lambda usando Rust.  

```
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(&region)
        .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}")
    }))
}
```

------

## Processar notificações de eventos vindas do Amazon RDS
<a name="rds-events"></a>

É possível usar o Lambda para processar notificações de eventos em um banco de dados do Amazon RDS. O Amazon RDS envia notificações para um tópico do Amazon Simple Notification Service (Amazon SNS), que você pode configurar para invocar uma função do Lambda. O Amazon SNS envolve a mensagem do Amazon RDS em seu próprio documento de evento e a envia para sua função.

Para obter mais informações sobre como configurar um banco de dados do Amazon RDS para enviar notificações, consulte [Trabalhar com a notificação de eventos do Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html). 

**Example Mensagem do Amazon RDS em um evento do Amazon SNS**  

```
{
        "Records": [
          {
            "EventVersion": "1.0",
            "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:rds-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
            "EventSource": "aws:sns",
            "Sns": {
              "SignatureVersion": "1",
              "Timestamp": "2023-01-02T12:45:07.000Z",
              "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
              "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
              "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
              "Message": "{\"Event Source\":\"db-instance\",\"Event Time\":\"2023-01-02 12:45:06.000\",\"Identifier Link\":\"https://console.aws.amazon.com/rds/home?region=eu-west-1#dbinstance:id=dbinstanceid\",\"Source ID\":\"dbinstanceid\",\"Event ID\":\"http://docs.amazonwebservices.com/AmazonRDS/latest/UserGuide/USER_Events.html#RDS-EVENT-0002\",\"Event Message\":\"Finished DB Instance backup\"}",
              "MessageAttributes": {},
              "Type": "Notification",
              "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
              "TopicArn":"arn:aws:sns:us-east-2:123456789012:sns-lambda",
              "Subject": "RDS Notification Message"
            }
          }
        ]
      }
```

## Tutorial do Lambda e do Amazon RDS
<a name="rds-database-samples"></a>
+ [Usar uma função do Lambda para acessar um banco de dados do Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html): no Guia do usuário do Amazon RDS, aprenda a usar uma função do Lambda para gravar dados em um banco de dados do Amazon RDS usando um Amazon RDS Proxy. A função do Lambda lerá registros de uma fila do Amazon SQS e gravará novos itens em uma tabela no banco de dados sempre que uma mensagem for adicionada.

# Selecione um serviço de banco de dados para suas aplicações baseadas em Lambda
<a name="ddb-rds-database-decision"></a>

Muitas aplicações com tecnologia sem servidor precisam armazenar e recuperar dados. A AWS oferece várias opções de banco de dados que funcionam com funções do Lambda. Duas das opções mais populares são o Amazon DynamoDB, um serviço de banco de dados NoSQL, e o Amazon RDS, uma solução tradicional de banco de dados relacional. As seções a seguir explicam as principais diferenças entre esses serviços ao usá-los com o Lambda e ajudam você a selecionar o serviço de banco de dados certo para sua aplicação com tecnologia sem servidor.

Para saber mais sobre os outros serviços de banco de dados oferecidos pela AWS e entender seus casos de uso e suas desvantagens de forma mais geral, consulte [Como escolher um serviço de banco de dados da AWS](https://docs.aws.amazon.com/decision-guides/latest/databases-on-aws-how-to-choose/databases-on-aws-how-to-choose.html). Todos os serviços de banco de dados da AWS são compatíveis com o Lambda, mas nem todos podem ser adequados ao seu caso de uso específico.

## Quais são suas opções ao selecionar um serviço de banco de dados com o Lambda?
<a name="w2aad101d101c19b9"></a>

A AWS oferece vários serviços de banco de dados. Para aplicações com tecnologia sem servidor, duas das opções mais populares são o DynamoDB e o Amazon RDS.
+ O **DynamoDB** é um serviço de banco de dados NoSQL totalmente gerenciado e otimizado para aplicações com tecnologia sem servidor. Ele fornece ajuste de escala perfeita e performance consistente de milissegundos de um dígito em qualquer escala.
+ O **Amazon RDS** é um serviço gerenciado de banco de dados relacional que oferece suporte a vários mecanismos de banco de dados, incluindo MySQL e PostgreSQL. Ele fornece recursos SQL familiares com infraestrutura gerenciada.

## Recomendações se você já conhece seus requisitos
<a name="w2aad101d101c19c11"></a>

Se você já sabe quais são seus requisitos, estas são as nossas recomendações básicas:

Recomendamos o [DynamoDB](with-ddb.md) para aplicações com tecnologia sem servidor que precisam de performance consistente de baixa latência, ajuste de escala automática e não exigem junções ou transações complexas. É especialmente adequado para aplicações baseadas em Lambda devido à sua natureza com tecnologia sem servidor.

O [Amazon RDS](services-rds.md) é a melhor opção quando você precisa de consultas SQL complexas, junções ou tem aplicações existentes usando bancos de dados relacionais. No entanto, esteja ciente de que conectar as funções do Lambda ao Amazon RDS requer configuração adicional e pode afetar os horários de inicialização a frio.

## O que considerar ao selecionar um serviço de banco de dados
<a name="w2aad101d101c19c13"></a>

Ao escolher entre o DynamoDB e o Amazon RDS para suas aplicações Lambda, considere estes fatores:
+ Gerenciamento de conexões e inicializações a frio
+ Padrões de acesso aos dados
+ Complexidade das consultas
+ Requisitos de consistência de dados.
+ Características de ajuste de escala
+ Modelo de custo

Ao compreender esses fatores, você pode selecionar a opção que melhor atenda às necessidades do seu caso de uso específico.

### Gerenciamento de conexões e inicializações a frio
<a name="w2aad101d101c19c13b9b1"></a>
+ O DynamoDB usa uma API HTTP para todas as operações. As funções do Lambda podem fazer solicitações imediatas sem manter conexões, resultando em melhor performance de inicialização a frio. Cada solicitação é autenticada usando credenciais da AWS sem sobrecarga de conexão.
+ O Amazon RDS exige o gerenciamento de pools de conexões, pois usa conexões de banco de dados tradicionais. Isso pode impactar as inicializações a frio, pois novas instâncias do Lambda precisam estabelecer conexões. Você precisará implementar estratégias de agrupamento de conexões e, potencialmente, usar o [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) para gerenciar conexões de forma eficaz. Observe que o uso do Amazon RDS Proxy incorre em custos adicionais.

### Padrões de acesso a dados
<a name="w2aad101d101c19c13b9b3"></a>
+ O DynamoDB funciona melhor com padrões de acesso conhecidos e designs de tabela única. É ideal para aplicações do Lambda que precisam de acesso consistente de baixa latência aos dados com base em chaves primárias ou índices secundários.
+ O Amazon RDS oferece flexibilidade para consultas complexas e padrões de acesso variáveis. É mais adequado quando suas funções do Lambda precisam realizar consultas exclusivas e personalizadas ou junções complexas em várias tabelas.

### Complexidade das consultas
<a name="w2aad101d101c19c13b9b5"></a>
+ O DynamoDB se destaca em operações simples baseadas em chaves e padrões de acesso predefinidos. As consultas complexas devem ser projetadas em torno de estruturas de índice, e as junções devem ser tratadas no código da aplicação.
+ O Amazon RDS oferece suporte a consultas SQL complexas com junções, subconsultas e agregações. Isso pode simplificar o código da sua função do Lambda quando operações de dados complexas são necessárias.

### Requisitos de consistência de dados.
<a name="w2aad101d101c19c13b9b7"></a>
+ O DynamoDB oferece opções de consistência eventual e forte, com consistência forte disponível para leituras de um único item. As transações são aceitas, mas com algumas limitações.
+ O Amazon RDS fornece conformidade total com atomicidade, consistência, isolamento e durabilidade (ACID) e suporte a transações complexas. Se suas funções do Lambda exigirem transações complexas ou consistência forte em vários registros, o Amazon RDS pode ser mais adequado.

### Características de ajuste de escala
<a name="w2aad101d101c19c13b9b9"></a>
+ O DynamoDB escala automaticamente com sua workload. Ele pode lidar com picos repentinos no tráfego das funções do Lambda sem pré-provisionamento. É possível usar o modo de capacidade sob demanda para pagar somente o que usar, combinando perfeitamente com o modelo de ajuste de escala do Lambda.
+ O Amazon RDS tem capacidade fixa com base no tamanho da instância que você escolher. Se várias funções do Lambda tentarem se conectar simultaneamente, você poderá exceder sua cota de conexão. Você precisa gerenciar cuidadosamente os pools de conexões e, potencialmente, implementar a lógica de novas tentativas.

### Modelo de custo
<a name="w2aad101d101c19c13b9c11"></a>
+ Os preços do DynamoDB se alinham bem com aplicações com tecnologia sem servidor. Com a capacidade sob demanda, você paga somente pelas leituras e gravações reais executadas pelas funções do Lambda. Não há cobranças por tempo ocioso.
+ O Amazon RDS cobra pela instância em execução, independentemente do uso. Isso pode ser menos econômico para workloads esporádicas que podem ser comuns em aplicações com tecnologia sem servidor. No entanto, pode ser mais econômico para workloads de alto throughput com uso consistente.

## Introdução ao serviço de banco de dados escolhido
<a name="w2aad101d101c19c15"></a>

Agora que você conhece os critérios para escolher entre o DynamoDB e o Amazon RDS, bem como as principais diferenças entre eles, poderá selecionar a opção que melhor atende às suas necessidades e usar os recursos a seguir para ajudar a começar a usá-lo.

------
#### [ DynamoDB ]

**Conceitos básicos para usar o DynamoDB com os recursos abaixo**
+ Para uma introdução ao serviço DynamoDB, leia [O que é o DynamoDB?](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) no *Guia do desenvolvedor do Amazon DynamoDB*.
+ Siga o tutorial [Uso do Lambda com API Gateway](services-apigateway-tutorial.md) para ver um exemplo do uso de uma função do Lambda para realizar operações CRUD em uma tabela do DynamoDB em resposta a uma solicitação de API.
+ Leia [Programação com o DynamoDB e os AWS SDKs](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.html) no *Guia do desenvolvedor do Amazon DynamoDB* para saber mais sobre como acessar o DynamoDB de dentro da sua função do Lambda usando um dos SDKs da AWS.

------
#### [ Amazon RDS ]

**Conceitos básicos para usar o Amazon RDS com os recursos abaixo**
+ Para uma introdução ao serviço Amazon RDS, leia [O que é o Amazon Relational Database Service (Amazon RDS)?](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html) no *Guia do usuário do Amazon Relational Database Service*.
+ Siga o tutorial [Usar uma função do Lambda para acessar um banco de dados Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html) no *Guia do usuário do Amazon Relational Database Service*.
+ Saiba mais sobre o uso do Lambda com o Amazon RDS lendo o [Usar o AWS Lambda com o Amazon RDS](services-rds.md).

------