

# 使用 IAM 身份验证连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting"></a>

对于 IAM 数据库身份验证，您可以在连接到数据库实例时使用身份验证令牌。*身份验证令牌* 是您使用的一个字符串而不是密码。在生成身份验证令牌后，将在 15 分钟后失效。如果您尝试使用过期的令牌进行连接，则连接请求将被拒绝。

必须使用 AWS 签名版本 4 为每个身份验证令牌附带一个有效签名。（有关更多信息，请参阅《AWS 一般参考》**中的[签名版本 4 签名流程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。） AWS CLI 和 AWS 软件开发工具包（例如 适用于 Java 的 AWS SDK 或者 适用于 Python (Boto3) 的 AWS SDK）可以自动对您创建的每个令牌进行签名。

从其他AWS服务（如 AWS Lambda）连接到 Amazon RDS 时，您可以使用身份验证令牌。通过使用令牌，可以避免在代码中放置密码。或者，您可以使用 AWS 开发工具包以编程方式创建身份验证令牌并为其签名。

在获得签名的 IAM 身份验证令牌后，您可以连接到 Amazon RDS 数据库实例。在下文中，您可以了解如何使用命令行工具或 AWS 开发工具包（例如 适用于 Java 的 AWS SDK 或 适用于 Python (Boto3) 的 AWS SDK）执行该操作。

有关更多信息，请参阅以下博客文章：
+ [使用 IAM 身份验证通过 SQL Workbench/J 连接到 Aurora MySQL 或 Amazon RDS for MySQL](https://aws.amazon.com/blogs/database/use-iam-authentication-to-connect-with-sql-workbenchj-to-amazon-aurora-mysql-or-amazon-rds-for-mysql/)
+ [使用 IAM 身份验证通过 pgAdmin Amazon Aurora PostgreSQL 或 Amazon RDS for PostgreSQL 进行连接](https://aws.amazon.com/blogs/database/using-iam-authentication-to-connect-with-pgadmin-amazon-aurora-postgresql-or-amazon-rds-for-postgresql/)

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

**Topics**
+ [使用 IAM 身份验证和 AWS 驱动程序连接到数据库实例](IAMDBAuth.Connecting.Drivers.md)
+ [通过命令行 AWS CLI 和 mysql 客户端，使用 IAM 身份验证连接到数据库实例](UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.md)
+ [通过命令行使用 IAM 身份验证连接到数据库实例：AWS CLI 和 psql 客户端](UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.PostgreSQL.md)
+ [使用 IAM 身份验证和 适用于 .NET 的 AWS SDK 连接到数据库实例](UsingWithRDS.IAMDBAuth.Connecting.NET.md)
+ [使用 IAM 身份验证和 适用于 Go 的 AWS SDK 连接到数据库实例](UsingWithRDS.IAMDBAuth.Connecting.Go.md)
+ [使用 IAM 身份验证和 适用于 Java 的 AWS SDK 连接到数据库实例](UsingWithRDS.IAMDBAuth.Connecting.Java.md)
+ [使用 IAM 身份验证和 适用于 Python (Boto3) 的 AWS SDK 连接到数据库实例](UsingWithRDS.IAMDBAuth.Connecting.Python.md)

# 使用 IAM 身份验证和 AWS 驱动程序连接到数据库实例
<a name="IAMDBAuth.Connecting.Drivers"></a>

借助 AWS 驱动程序套件，可显著缩短切换和故障转移时间，并支持使用 AWS Secrets Manager、AWS Identity and Access Management（IAM）和联合身份进行身份验证。AWS 驱动程序依靠监控数据库实例状态以及了解实例拓扑，来确定新的写入器。这种方法将切换和故障转移时间缩短到几秒钟，而开源驱动程序的切换和故障转移时间则为几十秒。

有关 AWS 驱动程序的更多信息，请参阅 [RDS for MariaDB](MariaDB.Connecting.Drivers.md#MariaDB.Connecting.JDBCDriver)、[RDS for MySQL](MySQL.Connecting.Drivers.md#MySQL.Connecting.JDBCDriver) 或 [RDS for PostgreSQL](PostgreSQL.Connecting.JDBCDriver.md) 数据库实例的相应语言驱动程序。

**注意**  
RDS for MariaDB 支持的唯一功能是使用 AWS Secrets Manager、AWS Identity and Access Management（IAM）和联合身份进行身份验证。

# 通过命令行 AWS CLI 和 mysql 客户端，使用 IAM 身份验证连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI"></a>

可以使用 AWS CLI 和 `mysql` 命令行工具从命令行连接到 Amazon RDS 数据库实例，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

**注意**  
有关使用具有 IAM 身份验证的 SQL WorkBench/J 连接到数据库的信息，请参阅博客文章[使用 IAM 身份验证通过 SQL WorkBench/J 连接到 Aurora MySQL 或 Amazon RDS for MySQL](https://aws.amazon.com/blogs/database/use-iam-authentication-to-connect-with-sql-workbenchj-to-amazon-aurora-mysql-or-amazon-rds-for-mysql/)。

**Topics**
+ [生成 IAM 身份验证令牌](#UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.AuthToken)
+ [连接到数据库实例](#UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.Connect)

## 生成 IAM 身份验证令牌
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.AuthToken"></a>

以下示例说明了如何使用 AWS CLI 获取签名的身份验证令牌。

```
aws rds generate-db-auth-token \
   --hostname rdsmysql.123456789012.us-west-2.rds.amazonaws.com \
   --port 3306 \
   --region us-west-2 \
   --username jane_doe
```

在该示例中，参数如下所示：
+ `--hostname` – 要访问的数据库实例的主机名
+ `--port` – 用于连接到数据库实例的端口号
+ `--region` – 在其中运行数据库实例的 AWS 区域
+ `--username` – 要访问的数据库账户

令牌的前几个字符与以下内容类似。

```
rdsmysql.123456789012.us-west-2.rds.amazonaws.com:3306/?Action=connect&DBUser=jane_doe&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900...
```

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

## 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.Connect"></a>

通用连接格式如下所示。

```
mysql --host=hostName --port=portNumber --ssl-ca=full_path_to_ssl_certificate --enable-cleartext-plugin --user=userName --password=authToken
```

参数如下所示：
+ `--host` – 要访问的数据库实例的主机名
+ `--port` – 用于连接到数据库实例的端口号
+ `--ssl-ca` – 包含公有密钥的 SSL 证书文件的完整路径

  有关 MariaDB 的 SSL/TLS 支持的更多信息，请参阅 [Amazon RDS 上 MariaDB 数据库实例的 SSL/TLS 支持](MariaDB.Concepts.SSLSupport.md)。

  有关 MySQL 的 SSL/TLS 支持的更多信息，请参阅 [Amazon RDS 上 MySQL 数据库实例的 SSL/TLS 支持](MySQL.Concepts.SSLSupport.md)。

  要下载 SSL 证书，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。
+ `--enable-cleartext-plugin` – 一个指定 `AWSAuthenticationPlugin` 必须用于此连接的值

  如果您使用 MariaDB 客户端，则无需 `--enable-cleartext-plugin` 选项。
+ `--user` – 要访问的数据库账户
+ `--password` – 已签名的 IAM 身份验证令牌

身份验证令牌包含几百个字符。很难使用命令行对其进行处理。该问题的解决方式是，将令牌保存到一个环境变量中，然后在连接时使用此变量。以下示例说明了一种执行此解决方法的方式。在该示例中，*/sample\$1dir/* 是包含公有密钥的 SSL 证书文件的完整路径。

```
RDSHOST="mysqldb.123456789012.us-east-1.rds.amazonaws.com"
TOKEN="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 3306 --region us-west-2 --username jane_doe )"

mysql --host=$RDSHOST --port=3306 --ssl-ca=/sample_dir/global-bundle.pem --enable-cleartext-plugin --user=jane_doe --password=$TOKEN
```

在使用 `AWSAuthenticationPlugin` 进行连接时，将使用 SSL 保护连接。要进行验证，请在 `mysql>` 命令提示符处键入以下内容。

```
show status like 'Ssl%';
```

输出中的以下行显示了更多详细信息。

```
+---------------+-------------+
| Variable_name | Value                                                                                                                                                                                                                                |
+---------------+-------------+
| ...           | ...
| Ssl_cipher    | AES256-SHA                                                                                                                                                                                                                           |
| ...           | ...
| Ssl_version   | TLSv1.1                                                                                                                                                                                                                              |
| ...           | ...
+-----------------------------+
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

# 通过命令行使用 IAM 身份验证连接到数据库实例：AWS CLI 和 psql 客户端
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.PostgreSQL"></a>

可以使用 AWS CLI 和 psql 命令行工具从命令行连接到 Amazon RDS for PostgreSQL 数据库实例，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

**注意**  
有关使用具有 IAM 身份验证的 pgAdmin 连接到数据库的信息，请参阅博客文章[使用 IAM 身份验证通过 pgAdmin Amazon Aurora PostgreSQL 或 Amazon RDS for PostgreSQL 进行连接](https://aws.amazon.com/blogs/database/using-iam-authentication-to-connect-with-pgadmin-amazon-aurora-postgresql-or-amazon-rds-for-postgresql/)。

**Topics**
+ [生成 IAM 身份验证令牌](#UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.AuthToken.PostgreSQL)
+ [连接到 Amazon RDS PostgreSQL 实例](#UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.Connect.PostgreSQL)

## 生成 IAM 身份验证令牌
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.AuthToken.PostgreSQL"></a>

身份验证令牌包含几百个字符，因此，很难使用命令行对其进行处理。该问题的解决方式是，将令牌保存到一个环境变量中，然后在连接时使用此变量。以下示例说明了如何使用 AWS CLI 通过 `generate-db-auth-token` 命令获取签名的身份验证令牌，并将其存储在 `PGPASSWORD` 环境变量中。

```
export RDSHOST="rdspostgres.123456789012.us-west-2.rds.amazonaws.com"
export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region us-west-2 --username jane_doe )"
```

在该示例中，`generate-db-auth-token` 命令的参数如下所示：
+ `--hostname` – 要访问的数据库实例（集群终端节点）的主机名。
+ `--port` – 用于连接到数据库实例的端口号
+ `--region` – 在其中运行数据库实例的 AWS 区域
+ `--username` – 要访问的数据库账户

生成的令牌的前几个字符与以下内容类似。

```
rdspostgres.123456789012.us-west-2.rds.amazonaws.com:5432/?Action=connect&DBUser=jane_doe&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900...
```

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

## 连接到 Amazon RDS PostgreSQL 实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.Connect.PostgreSQL"></a>

使用 psql 进行连接的一般格式如下所示。

```
psql "host=hostName port=portNumber sslmode=verify-full sslrootcert=full_path_to_ssl_certificate dbname=DBName user=userName password=authToken"
```

参数如下所示：
+ `host` – 要访问的数据库实例（集群终端节点）的主机名。
+ `port` – 用于连接到数据库实例的端口号
+ `sslmode` – 要使用的 SSL 模式

  当您使用 `sslmode=verify-full` 时，SSL 连接将针对 SSL 证书中的终端节点验证数据库实例终端节点。
+ `sslrootcert` – 包含公有密钥的 SSL 证书文件的完整路径

  有关更多信息，请参阅 [将 SSL 与 PostgreSQL 数据库实例结合使用](PostgreSQL.Concepts.General.SSL.md)。

  要下载 SSL 证书，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。
+ `dbname` – 要访问的数据库
+ `user` – 要访问的数据库账户
+ `password` – 已签名的 IAM 身份验证令牌

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

以下示例演示了使用 psql 进行连接。在该示例中，psql 将环境变量 `RDSHOST` 用于主机，将环境变量 `PGPASSWORD` 用于生产的令牌。*/sample\$1dir/* 则是包含公有密钥的 SSL 证书文件的完整路径。

```
export RDSHOST="rdspostgres.123456789012.us-west-2.rds.amazonaws.com"
export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region us-west-2 --username jane_doe )"
                    
psql "host=$RDSHOST port=5432 sslmode=verify-full sslrootcert=/sample_dir/global-bundle.pem dbname=DBName user=jane_doe password=$PGPASSWORD"
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

# 使用 IAM 身份验证和 适用于 .NET 的 AWS SDK 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.NET"></a>

您可以使用 适用于 .NET 的 AWS SDK 连接到 RRDS for MariaDB、MySQL 或 PostgreSQL 数据库实例 ，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

**示例**  
以下代码示例演示如何生成身份验证令牌，然后使用该令牌连接到数据库实例。

要运行该代码示例，您需要使用 适用于 .NET 的 AWS SDK 网站上提供的 [AWS](https://aws.amazon.com/sdk-for-net/)。`AWSSDK.CORE` 和 `AWSSDK.RDS` 程序包是必需的。要连接到数据库实例，请使用用于数据库引擎的 .NET 数据库连接器，例如 MySqlConnector for MariaDB 或 MySQL，或 Npgsql for PostgreSQL。

此代码连接到 MariaDB 或 MySQL 数据库实例。根据需要修改以下变量的值：
+ `server` – 要访问的数据库实例的终端节点。
+ `user` – 要访问的数据库账户
+ `database` – 要访问的数据库
+ `port` – 用于连接到数据库实例的端口号
+ `SslMode` – 要使用的 SSL 模式

  当您使用 `SslMode=Required` 时，SSL 连接将针对 SSL 证书中的终端节点验证数据库实例终端节点。
+ `SslCa` – Amazon RDS 的 SSL 证书的完整路径

  要下载证书，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

```
using System;
using System.Data;
using MySql.Data;
using MySql.Data.MySqlClient;
using Amazon;

namespace ubuntu
{
  class Program
  {
    static void Main(string[] args)
    {
      var pwd = Amazon.RDS.Util.RDSAuthTokenGenerator.GenerateAuthToken(RegionEndpoint.USEast1, "mysqldb.123456789012.us-east-1.rds.amazonaws.com", 3306, "jane_doe");
      // for debug only Console.Write("{0}\n", pwd);  //this verifies the token is generated

      MySqlConnection conn = new MySqlConnection($"server=mysqldb.123456789012.us-east-1.rds.amazonaws.com;user=jane_doe;database=mydB;port=3306;password={pwd};SslMode=Required;SslCa=full_path_to_ssl_certificate");
      conn.Open();

      // Define a query
      MySqlCommand sampleCommand = new MySqlCommand("SHOW DATABASES;", conn);

      // Execute a query
      MySqlDataReader mysqlDataRdr = sampleCommand.ExecuteReader();

      // Read all rows and output the first column in each row
      while (mysqlDataRdr.Read())
        Console.WriteLine(mysqlDataRdr[0]);

      mysqlDataRdr.Close();
      // Close connection
      conn.Close();
    }
  }
}
```

此代码连接到 PostgreSQL 数据库实例。

根据需要修改以下变量的值：
+ `Server` – 要访问的数据库实例的终端节点。
+ `User ID` – 要访问的数据库账户
+ `Database` – 要访问的数据库
+ `Port` – 用于连接到数据库实例的端口号
+ `SSL Mode` – 要使用的 SSL 模式

  当您使用 `SSL Mode=Required` 时，SSL 连接将针对 SSL 证书中的终端节点验证数据库实例终端节点。
+ `Root Certificate` – Amazon RDS 的 SSL 证书的完整路径

  要下载证书，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

```
using System;
using Npgsql;
using Amazon.RDS.Util;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var pwd = RDSAuthTokenGenerator.GenerateAuthToken("postgresmydb.123456789012.us-east-1.rds.amazonaws.com", 5432, "jane_doe");
// for debug only Console.Write("{0}\n", pwd);  //this verifies the token is generated

            NpgsqlConnection conn = new NpgsqlConnection($"Server=postgresmydb.123456789012.us-east-1.rds.amazonaws.com;User Id=jane_doe;Password={pwd};Database=mydb;SSL Mode=Require;Root Certificate=full_path_to_ssl_certificate");
            conn.Open();

            // Define a query
                   NpgsqlCommand cmd = new NpgsqlCommand("select count(*) FROM pg_user", conn);

            // Execute a query
            NpgsqlDataReader dr = cmd.ExecuteReader();

            // Read all rows and output the first column in each row
            while (dr.Read())
                Console.Write("{0}\n", dr[0]);

            // Close connection
            conn.Close();
        }
    }
}
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

# 使用 IAM 身份验证和 适用于 Go 的 AWS SDK 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.Go"></a>

您可以使用 适用于 Go 的 AWS SDK 连接到 RRDS for MariaDB、MySQL 或 PostgreSQL 数据库实例 ，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

**示例**  
要运行上述代码示例，您需要使用 适用于 Go 的 AWS SDK 网站上提供的 [AWS](https://aws.amazon.com/sdk-for-go/)。

根据需要修改以下变量的值：
+ `dbName` – 要访问的数据库
+ `dbUser` – 要访问的数据库账户
+ `dbHost` – 要访问的数据库实例的终端节点。
**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。
+ `dbPort` – 用于连接到数据库实例的端口号
+ `region` – 在其中运行数据库实例的 AWS 区域

此外，请确保示例代码中的导入库存在于您的系统中。

**重要**  
本节中的示例使用以下代码提供从本地环境访问数据库的凭证：  
`creds := credentials.NewEnvCredentials()`  
如果要从AWS服务（如 Amazon EC2 或 Amazon ECS）访问数据库，则可以用以下代码替换：  
`sess := session.Must(session.NewSession())`  
`creds := sess.Config.Credentials`  
如果您进行此更改，请确保添加以下导入：  
`"github.com/aws/aws-sdk-go/aws/session"`

**Topics**
+ [使用 IAM 身份验证和 适用于 Go 的 AWS SDK V2 进行连接](#UsingWithRDS.IAMDBAuth.Connecting.GoV2)
+ [使用 IAM 身份验证和 适用于 Go 的 AWS SDK V1 进行连接](#UsingWithRDS.IAMDBAuth.Connecting.GoV1)

## 使用 IAM 身份验证和 适用于 Go 的 AWS SDK V2 进行连接
<a name="UsingWithRDS.IAMDBAuth.Connecting.GoV2"></a>

您可以使用 IAM 身份验证和 适用于 Go 的 AWS SDK V2 连接到数据库实例

以下代码示例演示如何生成身份验证令牌，然后使用该令牌连接到数据库实例。

此代码连接到 MariaDB 或 MySQL 数据库实例。

```
package main
                
import (
     "context"
     "database/sql"
     "fmt"

     "github.com/aws/aws-sdk-go-v2/config"
     "github.com/aws/aws-sdk-go-v2/feature/rds/auth"
     _ "github.com/go-sql-driver/mysql"
)

func main() {

     var dbName string = "DatabaseName"
     var dbUser string = "DatabaseUser"
     var dbHost string = "mysqldb.123456789012.us-east-1.rds.amazonaws.com"
     var dbPort int = 3306
     var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
     var region string = "us-east-1"

    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)
    }

    err = db.Ping()
    if err != nil {
        panic(err)
    }
}
```

此代码连接到 PostgreSQL 数据库实例。

```
package main

import (
     "context"
     "database/sql"
     "fmt"

     "github.com/aws/aws-sdk-go-v2/config"
     "github.com/aws/aws-sdk-go-v2/feature/rds/auth"
     _ "github.com/lib/pq"
)

func main() {

     var dbName string = "DatabaseName"
     var dbUser string = "DatabaseUser"
     var dbHost string = "postgresmydb.123456789012.us-east-1.rds.amazonaws.com"
     var dbPort int = 5432
     var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
     var region string = "us-east-1"

    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("host=%s port=%d user=%s password=%s dbname=%s",
        dbHost, dbPort, dbUser, authenticationToken, dbName,
    )

    db, err := sql.Open("postgres", dsn)
    if err != nil {
        panic(err)
    }

    err = db.Ping()
    if err != nil {
        panic(err)
    }
}
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

## 使用 IAM 身份验证和 适用于 Go 的 AWS SDK V1 进行连接
<a name="UsingWithRDS.IAMDBAuth.Connecting.GoV1"></a>

使用 IAM 身份验证和 适用于 Go 的 AWS SDK V1 连接到数据库实例

以下代码示例演示如何生成身份验证令牌，然后使用该令牌连接到数据库实例。

此代码连接到 MariaDB 或 MySQL 数据库实例。

```
package main
         
import (
    "database/sql"
    "fmt"
    "log"

    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/service/rds/rdsutils"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    dbName := "app"
    dbUser := "jane_doe"
    dbHost := "mysqldb.123456789012.us-east-1.rds.amazonaws.com"
    dbPort := 3306
    dbEndpoint := fmt.Sprintf("%s:%d", dbHost, dbPort)
    region := "us-east-1"

    creds := credentials.NewEnvCredentials()
    authToken, err := rdsutils.BuildAuthToken(dbEndpoint, region, dbUser, creds)
    if err != nil {
        panic(err)
    }

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

    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }

    err = db.Ping()
    if err != nil {
        panic(err)
    }
}
```

此代码连接到 PostgreSQL 数据库实例。

```
package main

import (
	"database/sql"
	"fmt"

	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/rds/rdsutils"
	_ "github.com/lib/pq"
)

func main() {
    dbName := "app"
    dbUser := "jane_doe"
    dbHost := "postgresmydb.123456789012.us-east-1.rds.amazonaws.com"
    dbPort := 5432
    dbEndpoint := fmt.Sprintf("%s:%d", dbHost, dbPort)
    region := "us-east-1"

    creds := credentials.NewEnvCredentials()
    authToken, err := rdsutils.BuildAuthToken(dbEndpoint, region, dbUser, creds)
    if err != nil {
        panic(err)
    }

    dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s",
        dbHost, dbPort, dbUser, authToken, dbName,
    )

    db, err := sql.Open("postgres", dsn)
    if err != nil {
        panic(err)
    }

    err = db.Ping()
    if err != nil {
        panic(err)
    }
}
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

# 使用 IAM 身份验证和 适用于 Java 的 AWS SDK 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.Java"></a>

您可以使用 适用于 Java 的 AWS SDK 连接到 RRDS for MariaDB、MySQL 或 PostgreSQL 数据库实例 ，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)
+ [设置适用于 Java 的AWS开发工具包](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-install.html)

有关如何使用 SDK for Java 2.x 的示例，请参阅 [Amazon RDS examples using SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html)。也可以使用 AWS 高级 JDBC 包装器，请参阅 [AWS Advanced JDBC Wrapper documentation](https://github.com/aws/aws-advanced-jdbc-wrapper/blob/main/docs/Documentation.md)。

**Topics**
+ [生成 IAM 身份验证令牌](#UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken)
+ [手动构造 IAM 身份验证令牌](#UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken2)
+ [连接到数据库实例](#UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken.Connect)

## 生成 IAM 身份验证令牌
<a name="UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken"></a>

如果您使用适用于 Java 的 AWS SDK编写程序，则可使用 `RdsIamAuthTokenGenerator` 类获取已签名的身份验证令牌。使用此类需要提供 AWS 凭证。为此，创建 `DefaultAWSCredentialsProviderChain` 类的实例。`DefaultAWSCredentialsProviderChain` 使用它在[默认凭证提供程序链](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default)中找到的第一个 AWS 访问密钥和私有密钥。有关 AWS 访问密钥的更多信息，请参阅[管理用户的访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)。

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

在创建一个 `RdsIamAuthTokenGenerator` 实例后，您可调用 `getAuthToken` 方法以获取已签名的令牌。提供 AWS 区域、主机名、端口号和用户名。以下代码示例说明了如何执行该操作。

```
package com.amazonaws.codesamples;

import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.rds.auth.GetIamAuthTokenRequest;
import com.amazonaws.services.rds.auth.RdsIamAuthTokenGenerator;

public class GenerateRDSAuthToken {

    public static void main(String[] args) {

	    String region = "us-west-2";
	    String hostname = "rdsmysql.123456789012.us-west-2.rds.amazonaws.com";
	    String port = "3306";
	    String username = "jane_doe";
	
	    System.out.println(generateAuthToken(region, hostname, port, username));
    }

    static String generateAuthToken(String region, String hostName, String port, String username) {

	    RdsIamAuthTokenGenerator generator = RdsIamAuthTokenGenerator.builder()
		    .credentials(new DefaultAWSCredentialsProviderChain())
		    .region(region)
		    .build();

	    String authToken = generator.getAuthToken(
		    GetIamAuthTokenRequest.builder()
		    .hostname(hostName)
		    .port(Integer.parseInt(port))
		    .userName(username)
		    .build());
	    
	    return authToken;
    }

}
```

## 手动构造 IAM 身份验证令牌
<a name="UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken2"></a>

在 Java 中，生成身份验证令牌的最简单方式是使用 `RdsIamAuthTokenGenerator`。此类将为您创建一个身份验证令牌，然后使用 AWS 签名版本 4 为该令牌签名。有关更多信息，请参阅《AWS 一般参考》**中的[签名版本 4 签名流程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。

不过，您也可以手动构造身份验证令牌并为之签名，如以下代码示例中所示。

```
package com.amazonaws.codesamples;

import com.amazonaws.SdkClientException;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.SigningAlgorithm;
import com.amazonaws.util.BinaryUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SortedMap;
import java.util.TreeMap;

import static com.amazonaws.auth.internal.SignerConstants.AWS4_TERMINATOR;
import static com.amazonaws.util.StringUtils.UTF8;

public class CreateRDSAuthTokenManually {
    public static String httpMethod = "GET";
    public static String action = "connect";
    public static String canonicalURIParameter = "/";
    public static SortedMap<String, String> canonicalQueryParameters = new TreeMap();
    public static String payload = StringUtils.EMPTY;
    public static String signedHeader = "host";
    public static String algorithm = "AWS4-HMAC-SHA256";
    public static String serviceName = "rds-db";
    public static String requestWithoutSignature;

    public static void main(String[] args) throws Exception {

        String region = "us-west-2";
        String instanceName = "rdsmysql.123456789012.us-west-2.rds.amazonaws.com";
        String port = "3306";
        String username = "jane_doe";
	
        Date now = new Date();
        String date = new SimpleDateFormat("yyyyMMdd").format(now);
        String dateTimeStamp = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'").format(now);
        DefaultAWSCredentialsProviderChain creds = new DefaultAWSCredentialsProviderChain();
	    String awsAccessKey = creds.getCredentials().getAWSAccessKeyId();
	    String awsSecretKey = creds.getCredentials().getAWSSecretKey();
        String expiryMinutes = "900";
        
        System.out.println("Step 1:  Create a canonical request:");
        String canonicalString = createCanonicalString(username, awsAccessKey, date, dateTimeStamp, region, expiryMinutes, instanceName, port);
        System.out.println(canonicalString);
        System.out.println();

        System.out.println("Step 2:  Create a string to sign:");        
        String stringToSign = createStringToSign(dateTimeStamp, canonicalString, awsAccessKey, date, region);
        System.out.println(stringToSign);
        System.out.println();

        System.out.println("Step 3:  Calculate the signature:");        
        String signature = BinaryUtils.toHex(calculateSignature(stringToSign, newSigningKey(awsSecretKey, date, region, serviceName)));
        System.out.println(signature);
        System.out.println();

        System.out.println("Step 4:  Add the signing info to the request");                
        System.out.println(appendSignature(signature));
        System.out.println();
        
    }

    //Step 1: Create a canonical request date should be in format YYYYMMDD and dateTime should be in format YYYYMMDDTHHMMSSZ
    public static String createCanonicalString(String user, String accessKey, String date, String dateTime, String region, String expiryPeriod, String hostName, String port) throws Exception {
        canonicalQueryParameters.put("Action", action);
        canonicalQueryParameters.put("DBUser", user);
        canonicalQueryParameters.put("X-Amz-Algorithm", "AWS4-HMAC-SHA256");
        canonicalQueryParameters.put("X-Amz-Credential", accessKey + "%2F" + date + "%2F" + region + "%2F" + serviceName + "%2Faws4_request");
        canonicalQueryParameters.put("X-Amz-Date", dateTime);
        canonicalQueryParameters.put("X-Amz-Expires", expiryPeriod);
        canonicalQueryParameters.put("X-Amz-SignedHeaders", signedHeader);
        String canonicalQueryString = "";
        while(!canonicalQueryParameters.isEmpty()) {
            String currentQueryParameter = canonicalQueryParameters.firstKey();
            String currentQueryParameterValue = canonicalQueryParameters.remove(currentQueryParameter);
            canonicalQueryString = canonicalQueryString + currentQueryParameter + "=" + currentQueryParameterValue;
            if (!currentQueryParameter.equals("X-Amz-SignedHeaders")) {
                canonicalQueryString += "&";
            }
        }
        String canonicalHeaders = "host:" + hostName + ":" + port + '\n';
        requestWithoutSignature = hostName + ":" + port + "/?" + canonicalQueryString;

        String hashedPayload = BinaryUtils.toHex(hash(payload));
        return httpMethod + '\n' + canonicalURIParameter + '\n' + canonicalQueryString + '\n' + canonicalHeaders + '\n' + signedHeader + '\n' + hashedPayload;

    }

    //Step 2: Create a string to sign using sig v4
    public static String createStringToSign(String dateTime, String canonicalRequest, String accessKey, String date, String region) throws Exception {
        String credentialScope = date + "/" + region + "/" + serviceName + "/aws4_request";
        return algorithm + '\n' + dateTime + '\n' + credentialScope + '\n' + BinaryUtils.toHex(hash(canonicalRequest));

    }

    //Step 3: Calculate signature
    /**
     * Step 3 of the &AWS; Signature version 4 calculation. It involves deriving
     * the signing key and computing the signature. Refer to
     * http://docs.aws.amazon
     * .com/general/latest/gr/sigv4-calculate-signature.html
     */
    public static byte[] calculateSignature(String stringToSign,
                                            byte[] signingKey) {
        return sign(stringToSign.getBytes(Charset.forName("UTF-8")), signingKey,
                SigningAlgorithm.HmacSHA256);
    }

    public static byte[] sign(byte[] data, byte[] key,
                          SigningAlgorithm algorithm) throws SdkClientException {
        try {
            Mac mac = algorithm.getMac();
            mac.init(new SecretKeySpec(key, algorithm.toString()));
            return mac.doFinal(data);
        } catch (Exception e) {
            throw new SdkClientException(
                    "Unable to calculate a request signature: "
                            + e.getMessage(), e);
        }
    }

    public static byte[] newSigningKey(String secretKey,
                                   String dateStamp, String regionName, String serviceName) {
        byte[] kSecret = ("AWS4" + secretKey).getBytes(Charset.forName("UTF-8"));
        byte[] kDate = sign(dateStamp, kSecret, SigningAlgorithm.HmacSHA256);
        byte[] kRegion = sign(regionName, kDate, SigningAlgorithm.HmacSHA256);
        byte[] kService = sign(serviceName, kRegion,
                SigningAlgorithm.HmacSHA256);
        return sign(AWS4_TERMINATOR, kService, SigningAlgorithm.HmacSHA256);
    }

    public static byte[] sign(String stringData, byte[] key,
                       SigningAlgorithm algorithm) throws SdkClientException {
        try {
            byte[] data = stringData.getBytes(UTF8);
            return sign(data, key, algorithm);
        } catch (Exception e) {
            throw new SdkClientException(
                    "Unable to calculate a request signature: "
                            + e.getMessage(), e);
        }
    }

    //Step 4: append the signature
    public static String appendSignature(String signature) {
        return requestWithoutSignature + "&X-Amz-Signature=" + signature;
    }

    public static byte[] hash(String s) throws Exception {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(s.getBytes(UTF8));
            return md.digest();
        } catch (Exception e) {
            throw new SdkClientException(
                    "Unable to compute hash while signing request: "
                            + e.getMessage(), e);
        }
    }
}
```

## 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.Java.AuthToken.Connect"></a>

以下代码示例演示如何生成一个身份验证令牌，然后使用该令牌连接到运行 MariaDB 或 MySQL 的实例。

要运行该代码示例，您需要使用 适用于 Java 的 AWS SDK 网站上提供的 [AWS](https://aws.amazon.com/sdk-for-java/)。此外，您需要：
+ MySQL Connector/J。此代码示例已使用 `mysql-connector-java-5.1.33-bin.jar` 进行测试。
+ 特定于AWS区域的 Amazon RDS 的中间证书。（有关更多信息，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。） 在运行时，类加载程序会在与此 Java 代码示例相同的目录中查找证书以便可以找到它。
+ 根据需要修改以下变量的值：
  + `RDS_INSTANCE_HOSTNAME` – 要访问的数据库实例的主机名。
  + `RDS_INSTANCE_PORT` – 用于连接到 PostgreSQL 数据库实例的端口号。
  + `REGION_NAME` – 在其中运行数据库实例的AWS区域。
  + `DB_USER` – 要访问的数据库账户
  + `SSL_CERTIFICATE` – 特定于AWS区域的 Amazon RDS 的中间证书。

    要为AWS区域下载证书，请参阅[使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。将 SSL 证书放置在此 Java 程序文件所在的同一目录中，以便类加载程序可在运行时找到此证书。

此代码示例将从[默认凭证提供程序链](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default)获取 AWS 凭证。

**注意**  
作为安全最佳实践，请为 `DEFAULT_KEY_STORE_PASSWORD` 指定除此处所示提示以外的密码。

```
package com.amazonaws.samples;

import com.amazonaws.services.rds.auth.RdsIamAuthTokenGenerator;
import com.amazonaws.services.rds.auth.GetIamAuthTokenRequest;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.AWSStaticCredentialsProvider;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

import java.net.URL;

public class IAMDatabaseAuthenticationTester {
    //&AWS; Credentials of the IAM user with policy enabling IAM Database Authenticated access to the db by the db user.
    private static final DefaultAWSCredentialsProviderChain creds = new DefaultAWSCredentialsProviderChain();
    private static final String AWS_ACCESS_KEY = creds.getCredentials().getAWSAccessKeyId();
    private static final String AWS_SECRET_KEY = creds.getCredentials().getAWSSecretKey();

    //Configuration parameters for the generation of the IAM Database Authentication token
    private static final String RDS_INSTANCE_HOSTNAME = "rdsmysql.123456789012.us-west-2.rds.amazonaws.com";
    private static final int RDS_INSTANCE_PORT = 3306;
    private static final String REGION_NAME = "us-west-2";
    private static final String DB_USER = "jane_doe";
    private static final String JDBC_URL = "jdbc:mysql://" + RDS_INSTANCE_HOSTNAME + ":" + RDS_INSTANCE_PORT;

    private static final String SSL_CERTIFICATE = "rds-ca-2019-us-west-2.pem";

    private static final String KEY_STORE_TYPE = "JKS";
    private static final String KEY_STORE_PROVIDER = "SUN";
    private static final String KEY_STORE_FILE_PREFIX = "sys-connect-via-ssl-test-cacerts";
    private static final String KEY_STORE_FILE_SUFFIX = ".jks";
    private static final String DEFAULT_KEY_STORE_PASSWORD = "changeit";

    public static void main(String[] args) throws Exception {
        //get the connection
        Connection connection = getDBConnectionUsingIam();

        //verify the connection is successful
        Statement stmt= connection.createStatement();
        ResultSet rs=stmt.executeQuery("SELECT 'Success!' FROM DUAL;");
        while (rs.next()) {
        	    String id = rs.getString(1);
            System.out.println(id); //Should print "Success!"
        }

        //close the connection
        stmt.close();
        connection.close();
        
        clearSslProperties();
        
    }

    /**
     * This method returns a connection to the db instance authenticated using IAM Database Authentication
     * @return
     * @throws Exception
     */
    private static Connection getDBConnectionUsingIam() throws Exception {
        setSslProperties();
        return DriverManager.getConnection(JDBC_URL, setMySqlConnectionProperties());
    }

    /**
     * This method sets the mysql connection properties which includes the IAM Database Authentication token
     * as the password. It also specifies that SSL verification is required.
     * @return
     */
    private static Properties setMySqlConnectionProperties() {
        Properties mysqlConnectionProperties = new Properties();
        mysqlConnectionProperties.setProperty("verifyServerCertificate","true");
        mysqlConnectionProperties.setProperty("useSSL", "true");
        mysqlConnectionProperties.setProperty("user",DB_USER);
        mysqlConnectionProperties.setProperty("password",generateAuthToken());
        return mysqlConnectionProperties;
    }

    /**
     * This method generates the IAM Auth Token.
     * An example IAM Auth Token would look like follows:
     * btusi123---cmz7kenwo2ye---rds---cn-north-1.amazonaws.com.rproxy.goskope.com.cn:3306/?Action=connect&DBUser=iamtestuser&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20171003T010726Z&X-Amz-SignedHeaders=host&X-Amz-Expires=899&X-Amz-Credential=AKIAPFXHGVDI5RNFO4AQ%2F20171003%2Fcn-north-1%2Frds-db%2Faws4_request&X-Amz-Signature=f9f45ef96c1f770cdad11a53e33ffa4c3730bc03fdee820cfdf1322eed15483b
     * @return
     */
    private static String generateAuthToken() {
        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);

        RdsIamAuthTokenGenerator generator = RdsIamAuthTokenGenerator.builder()
                .credentials(new AWSStaticCredentialsProvider(awsCredentials)).region(REGION_NAME).build();
        return generator.getAuthToken(GetIamAuthTokenRequest.builder()
                .hostname(RDS_INSTANCE_HOSTNAME).port(RDS_INSTANCE_PORT).userName(DB_USER).build());
    }

    /**
     * This method sets the SSL properties which specify the key store file, its type and password:
     * @throws Exception
     */
    private static void setSslProperties() throws Exception {
        System.setProperty("javax.net.ssl.trustStore", createKeyStoreFile());
        System.setProperty("javax.net.ssl.trustStoreType", KEY_STORE_TYPE);
        System.setProperty("javax.net.ssl.trustStorePassword", DEFAULT_KEY_STORE_PASSWORD);
    }

    /**
     * This method returns the path of the Key Store File needed for the SSL verification during the IAM Database Authentication to
     * the db instance.
     * @return
     * @throws Exception
     */
    private static String createKeyStoreFile() throws Exception {
        return createKeyStoreFile(createCertificate()).getPath();
    }

    /**
     *  This method generates the SSL certificate
     * @return
     * @throws Exception
     */
    private static X509Certificate createCertificate() throws Exception {
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        URL url = new File(SSL_CERTIFICATE).toURI().toURL();
        if (url == null) {
            throw new Exception();
        }
        try (InputStream certInputStream = url.openStream()) {
            return (X509Certificate) certFactory.generateCertificate(certInputStream);
        }
    }

    /**
     * This method creates the Key Store File
     * @param rootX509Certificate - the SSL certificate to be stored in the KeyStore
     * @return
     * @throws Exception
     */
    private static File createKeyStoreFile(X509Certificate rootX509Certificate) throws Exception {
        File keyStoreFile = File.createTempFile(KEY_STORE_FILE_PREFIX, KEY_STORE_FILE_SUFFIX);
        try (FileOutputStream fos = new FileOutputStream(keyStoreFile.getPath())) {
            KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE, KEY_STORE_PROVIDER);
            ks.load(null);
            ks.setCertificateEntry("rootCaCertificate", rootX509Certificate);
            ks.store(fos, DEFAULT_KEY_STORE_PASSWORD.toCharArray());
        }
        return keyStoreFile;
    }
    
    /**
     * This method clears the SSL properties.
     * @throws Exception
     */
    private static void clearSslProperties() throws Exception {
           System.clearProperty("javax.net.ssl.trustStore");
           System.clearProperty("javax.net.ssl.trustStoreType");
           System.clearProperty("javax.net.ssl.trustStorePassword"); 
    }
    
}
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。

# 使用 IAM 身份验证和 适用于 Python (Boto3) 的 AWS SDK 连接到数据库实例
<a name="UsingWithRDS.IAMDBAuth.Connecting.Python"></a>

您可以使用 适用于 Python (Boto3) 的 AWS SDK 连接到 RRDS for MariaDB、MySQL 或 PostgreSQL 数据库实例 ，如下所述。

**先决条件**  
以下是使用 IAM 身份验证连接到数据库实例的先决条件：
+ [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)
+ [创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)
+ [使用 IAM 身份验证创建数据库账户](UsingWithRDS.IAMDBAuth.DBAccounts.md)

此外，请确保示例代码中的导入库存在于您的系统中。

**示例**  
该代码示例将配置文件用于共享凭证。有关指定凭证的信息，请参阅 适用于 Python (Boto3) 的 AWS SDK 文档中的[凭证](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)。

以下代码示例演示如何生成身份验证令牌，然后使用该令牌连接到数据库实例。

要运行该代码示例，您需要使用 适用于 Python (Boto3) 的 AWS SDK 网站上提供的 [AWS](https://aws.amazon.com/sdk-for-python/)。

根据需要修改以下变量的值：
+ `ENDPOINT` – 要访问的数据库实例的终端节点。
+ `PORT` – 用于连接到数据库实例的端口号
+ `USER` – 要访问的数据库账户
+ `REGION` – 在其中运行数据库实例的 AWS 区域
+ `DBNAME` – 要访问的数据库
+ `SSLCERTIFICATE` – Amazon RDS 的 SSL 证书的完整路径

  对于 `ssl_ca`，请指定 SSL 证书。要下载 SSL 证书，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。

**注意**  
不能使用自定义 Route 53 DNS 记录代替数据库实例端点来生成身份验证令牌。

此代码连接到 MariaDB 或 MySQL 数据库实例。

在运行此代码之前，请按照 [Python 包索引](https://pypi.org/project/PyMySQL/)中的说明安装 PyMySQL 驱动程序。

```
import pymysql
import sys
import boto3
import os

ENDPOINT="mysqldb.123456789012.us-east-1.rds.amazonaws.com"
PORT="3306"
USER="jane_doe"
REGION="us-east-1"
DBNAME="mydb"
os.environ['LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN'] = '1'

#gets the credentials from .aws/credentials
session = boto3.Session(profile_name='default')
client = session.client('rds')

token = client.generate_db_auth_token(DBHostname=ENDPOINT, Port=PORT, DBUsername=USER, Region=REGION)

try:
    conn =  pymysql.connect(auth_plugin_map={'mysql_clear_password':None},host=ENDPOINT, user=USER, password=token, port=PORT, database=DBNAME, ssl_ca='SSLCERTIFICATE', ssl_verify_identity=True, ssl_verify_cert=True)
    cur = conn.cursor()
    cur.execute("""SELECT now()""")
    query_results = cur.fetchall()
    print(query_results)
except Exception as e:
    print("Database connection failed due to {}".format(e))
```

此代码连接到 PostgreSQL 数据库实例。

在运行此代码之前，请按照 [Psycopg 文档](https://pypi.org/project/psycopg2/)中的说明安装 `psycopg2`。

```
import psycopg2
import sys
import boto3
import os

ENDPOINT="postgresmydb.123456789012.us-east-1.rds.amazonaws.com"
PORT="5432"
USER="jane_doe"
REGION="us-east-1"
DBNAME="mydb"

#gets the credentials from .aws/credentials
session = boto3.Session(profile_name='RDSCreds')
client = session.client('rds')

token = client.generate_db_auth_token(DBHostname=ENDPOINT, Port=PORT, DBUsername=USER, Region=REGION)

try:
    conn = psycopg2.connect(host=ENDPOINT, port=PORT, database=DBNAME, user=USER, password=token, sslrootcert="SSLCERTIFICATE")
    cur = conn.cursor()
    cur.execute("""SELECT now()""")
    query_results = cur.fetchall()
    print(query_results)
except Exception as e:
    print("Database connection failed due to {}".format(e))
```

如果您想通过代理连接到数据库实例，请参阅[使用 IAM 身份验证连接到数据库](rds-proxy-connecting.md#rds-proxy-connecting-iam)。