IAM認証を使用して、EC2(Linux)/LambdaからRDSに接続する
RDSが提供する機能の1つに、IAM認証があります。
AWS Identity and Access Management (IAM) データベース認証を使用して、DB インスタンスを認証できます。IAM データベース認証には、MariaDB、MySQL、および PostgreSQL を使用します。この認証方法では、DB インスタンスに接続するときにパスワードを使用する必要はありません。代わりに、認証トークンを使用します。
MariaDB、MySQL、および PostgreSQL の IAM データベース認証
本ページでは、EC2インスタンスおよびLambda関数から、IAM認証でRDSにアクセスする方法を確認します。
構築する環境
DBインスタンスを作成します。
IAM認証を有効化します。
エンジンはMySQLです。
プライベートサブネットにEC2インスタンスおよびLambda関数を作成します。
EC2インスタンスは最新版のAmazon Linux2、Lambda関数はPython3.8とします。
両リソースはDBインスタンスにIAM認証で接続するクライアントとして使用します。
CloudFormationカスタムリソースに関連づけるLambda関数を2種類作成します。
1種類目はLambda関数用のLambdaレイヤーを作成します。
2種類目はDBインスタンスの初期化処理を行います。
カスタムリソースに関連づけることによって、CloudFormationスタック作成時に、自動的に関数を実行するように設定します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/128
テンプレートファイルのポイント解説
RDS
DBインスタンス
Resources:
DBInstance:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: !Ref DBAllocatedStorage
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone}"
EnableIAMDatabaseAuthentication: true
DBInstanceClass: !Ref DBInstanceClass
DBInstanceIdentifier: !Sub "${Prefix}-dbinstance"
DBName: !Ref DBName
DBSubnetGroupName: !Ref DBSubnetGroup
Engine: !Ref DBEngine
EngineVersion: !Ref DBEngineVersion
MasterUsername: !Ref DBMasterUsername
MasterUserPassword: !Ref DBMasterUserPassword
VPCSecurityGroups:
- !Ref DBSecurityGroup
Code language: YAML (yaml)
ポイントはEnableIAMDatabaseAuthenticationプロパティです。
本プロパティに「true」を設定することで、DBインスタンスでIAM認証が有効化されます。
Lambda関数を使用した初期化処理
Resources:
SQLParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub "${Prefix}-customresource-03"
Type: String
Value: !Sub |
CREATE USER ${DBIamUsername} IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
GRANT SELECT ON *.* TO 'iamuser'@'%';
USE ${DBName};
CREATE TABLE ${DBTableName} (id INT UNSIGNED AUTO_INCREMENT, name VARCHAR(30), PRIMARY KEY(id));
INSERT INTO planet (name) VALUES ("Mercury");
INSERT INTO planet (name) VALUES ("Venus");
INSERT INTO planet (name) VALUES ("Earth");
INSERT INTO planet (name) VALUES ("Mars");
INSERT INTO planet (name) VALUES ("Jupiter");
INSERT INTO planet (name) VALUES ("Saturn");
INSERT INTO planet (name) VALUES ("Uranus");
INSERT INTO planet (name) VALUES ("Neptune");
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Environment:
Variables:
DB_ENDPOINT_ADDRESS: !Ref DBInstanceEndpointAddress
DB_ENDPOINT_PORT: !Ref MySQLPort
DB_PASSWORD: !Ref DBMasterUserPassword
DB_USER: !Ref DBMasterUsername
REGION: !Ref AWS::Region
SQL_PARAMETER: !Ref SQLParameter
Code:
ZipFile: |
import boto3
import cfnresponse
import mysql.connector
import os
db_endpoint_port = int(os.environ['DB_ENDPOINT_PORT'])
db_endpoint_address = os.environ['DB_ENDPOINT_ADDRESS']
db_password = os.environ['DB_PASSWORD']
db_user = os.environ['DB_USER']
region = os.environ['REGION']
sql_parameter = os.environ['SQL_PARAMETER']
CREATE = 'Create'
response_data = {}
def lambda_handler(event, context):
try:
if event['RequestType'] == CREATE:
client = boto3.client('ssm', region_name=region)
response = client.get_parameter(Name=sql_parameter)
sql_statements = response['Parameter']['Value']
conn = mysql.connector.connect(
host=db_endpoint_address,
port=db_endpoint_port,
user=db_user,
password=db_password
)
cur = conn.cursor()
for sql in sql_statements.splitlines():
print(sql)
cur.execute(sql)
cur.close()
conn.commit()
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
except Exception as e:
print(e)
cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
FunctionName: !Sub "${Prefix}-customresource-03"
Handler: !Ref Handler
Layers:
- !Ref LambdaLayer
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Timeout: !Ref Timeout
VpcConfig:
SecurityGroupIds:
- !Ref FunctionSecurityGroup
SubnetIds:
- !Ref FunctionSubnet
Code language: YAML (yaml)
Lambda関数で実行するコードをインライン表記で定義します。
詳細につきましては、以下のページをご確認ください。
VPC内に本関数を配置し、DBインスタンスにアクセスして、DBの初期化処理を行います。
詳細につきましては、以下のページをご確認ください。
実行するSQL文はSSMパラメータストアに保存し、これを関数が参照します。
SQL文の中で、特に1〜2行目がポイントです。
1行目はIAM認証によってDBインスタンスにアクセスするユーザを作成するコマンドです。
2行目は作成したユーザにデータベースを操作する権限を付与するコマンドです。
残りのコマンドはテストレコードを書き込む処理を行います。
以下のページの内容を参考にしました。
EC2インスタンス
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref InstanceSubnet
GroupSet:
- !Ref InstanceSecurityGroup
UserData: !Base64 |
#!/bin/bash -xe
yum update -y
yum install -y mariadb
curl -OL https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
Code language: YAML (yaml)
ユーザデータでインスタンスの初期化処理を定義します。
初期化処理に関する詳細は以下のページをご確認ください。
ポイントは3行目と4行目です。
前者はMySQLクライアントをインストールするコマンドです。
Amazon Linux 2において、各種RDSに接続する方法に関しては、以下のページをご確認ください。
後者はIAM認証に必要な証明書をダウンロードするコマンドです。
前提として、IAM認証を行う場合、SSL通信が必須となります。
データベースとの間で送受信されるネットワークトラフィックは、Secure Socket Layer (SSL) または Transport Layer Security (TLS) を使用して暗号化されます。
MariaDB、MySQL、および PostgreSQL の IAM データベース認証
そしてSSL通信を行うためには、証明書を用意する必要があります。
SSL/TLS 接続は、クライアントと DB インスタンスの間を移動するデータを暗号化することによって、1 つのセキュリティ層を提供します。サーバー証明書を使用すると、Amazon RDS DB インスタンスへの接続が確立されていることを検証することによって、追加のセキュリティレイヤーが提供されます。これを行うには、プロビジョニングしたすべての DB インスタンスに自動インストールされたサーバー証明書をチェックします。
SSL/TLS を使用した DB インスタンスへの接続の暗号化
使用可能な証明書は以下のページにまとめられています。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
今回は全リージョンの証明書バンドルであるglobal-bundle.pemを使用します。
以下が本インスタンス用のIAMロールです。
Resources:
InstanceRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Policies:
- PolicyName: RDSIamAthenticationPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- rds-db:connect
Resource:
- !Sub "arn:aws:rds-db:${AWS::Region}:${AWS::AccountId}:dbuser:${DBInstanceResourceId}/${DBIamUsername}"
Code language: YAML (yaml)
後述する動作確認時に、SSM Session Managerで本インスタンスに接続するため、AWS管理ポリシーAmazonSSMManagedInstanceCoreをアタッチします。
以下のページを参考にして、インラインポリシーにIAM認証用の設定を行います。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html
アクションにrds-db:connectを、リソースにDBインスタンス内のユーザ名を指定します。
Lambda関数
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Environment:
Variables:
DB_ENDPOINT_ADDRESS: !Ref DBInstanceEndpointAddress
DB_ENDPOINT_PORT: !Ref MySQLPort
DB_NAME: !Ref DBName
DB_TABLENAME: !Ref DBTableName
DB_USER: !Ref DBIamUsername
REGION: !Ref AWS::Region
SSL_CERTIFICATE: /opt/python/global-bundle.pem
Code:
ZipFile: |
import boto3
import datetime
import json
import mysql.connector
import os
db_endpoint_address = os.environ['DB_ENDPOINT_ADDRESS']
db_endpoint_port = int(os.environ['DB_ENDPOINT_PORT'])
db_name = os.environ['DB_NAME']
db_tablename = os.environ['DB_TABLENAME']
db_user = os.environ['DB_USER']
region = os.environ['REGION']
ssl_certificate = os.environ['SSL_CERTIFICATE']
os.environ['LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN'] = '1'
client = boto3.client('rds', region_name=region)
def lambda_handler(event, context):
token = client.generate_db_auth_token(
DBHostname=db_endpoint_address,
Port=db_endpoint_port,
DBUsername=db_user,
Region=region)
conn = mysql.connector.connect(
host=db_endpoint_address,
user=db_user,
password=token,
port=db_endpoint_port,
database=db_name,
ssl_ca=ssl_certificate)
cur = conn.cursor()
read_sql = 'select * from {tbl};'.format(tbl=db_tablename)
cur.execute(read_sql)
content = [record for record in cur]
cur.close()
conn.close()
return {
'statusCode': 200,
'body': json.dumps(content, indent=2)
}
FunctionName: !Sub "${Prefix}-function"
Handler: !Ref Handler
Layers:
- !Ref LambdaLayer1
- !Ref LambdaLayer2
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Timeout: !Ref Timeout
VpcConfig:
SecurityGroupIds:
- !Ref FunctionSecurityGroup
SubnetIds:
- !Ref FunctionSubnet
Code language: YAML (yaml)
Lambda関数で実行するコードをインライン表記で定義します。
詳細につきましては、以下のページをご確認ください。
今回の構成では、Lambda関数をVPC内に配置します。
VpcConfigプロパティで、関数を配置するサブネットや、適用するセキュリティグループを指定します。
実行するコードの内容ですが、以下の通りです。
- CloudFormationテンプレートで定義した環境変数を、os.environにアクセスして取得する。
- Boto3でRDS用クライアントオブジェクトを作成する。
- generate_db_auth_tokenメソッドを実行して、IAM認証用のトークンを取得する。
- mysql.connector.connectメソッドを実行して、IAM認証でDBインスタンスに接続する。
- SELECT文を実行して、テーブル内の全データを取得する。
ポイントはLambdaレイヤーです。
後述するCloudFormationカスタムリソースに関連づいたLambda関数で、自動的に作成します。
今回は2つのレイヤーを作成して、本関数に関連づけます。
一方はMySQL接続用パッケージ用で、もう一方はSSL通信用の証明書用のレイヤーです。
SSL通信用の証明書の設置場所もポイントです。
Lambda 関数にレイヤーを含めると、Lambda は関数実行環境で/optディレクトリにレイヤーコンテンツを抽出します。
関数からレイヤーコンテンツにアクセスする
そして本関数のランタイム環境はPython3.8ですから、/opt/pythonディレクトリに証明書が設置されることになります。
以下が本関数用のIAMロールです。
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Policies:
- PolicyName: RDSIamAthenticationPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- rds-db:connect
Resource:
- !Sub "arn:aws:rds-db:${AWS::Region}:${AWS::AccountId}:dbuser:${DBInstanceResourceId}/${DBIamUsername}"
Code language: YAML (yaml)
VPC内で本関数を実行するために、AWS管理ポリシーAWSLambdaVPCAccessExecutionRoleをアタッチします。
加えてEC2インスタンスと同様に、IAM認証用の設定を行います。
本関数のFunction URLを有効化します。
Resources:
FunctionUrl:
Type: AWS::Lambda::Url
Properties:
AuthType: NONE
TargetFunctionArn: !GetAtt Function.Arn
FunctionUrlPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunctionUrl
FunctionName: !GetAtt Function.Arn
FunctionUrlAuthType: NONE
Principal: "*"
Code language: YAML (yaml)
詳細は以下のページをご確認します。
Lambdaレイヤー
Pythonパッケージ用レイヤー
Resources:
RequirementsParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub "${Prefix}-customresource-01"
Type: String
Value: |
mysql-connector-python
LambdaLayer:
Type: AWS::Lambda::LayerVersion
DependsOn:
- CustomResource
Properties:
CompatibleArchitectures:
- !Ref Architecture
CompatibleRuntimes:
- !Ref Runtime
Content:
S3Bucket: !Ref CodeS3Bucket
S3Key: !Ref LayerS3Key
Description: !Ref Prefix
LayerName: !Sub "${Prefix}-customresource-01"
CustomResource:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt Function.Arn
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Environment:
Variables:
LAYER_PACKAGE: !Ref LayerPackage
REGION: !Ref AWS::Region
REQUIREMENTS_PARAMETER: !Ref RequirementsParameter
S3_BUCKET: !Ref CodeS3Bucket
S3_BUCKET_FOLDER: !Ref Prefix
Code:
ZipFile: |
import boto3
import cfnresponse
import os
import pip
import shutil
import subprocess
layer_package = os.environ['LAYER_PACKAGE']
region = os.environ['REGION']
requirements_parameter = os.environ['REQUIREMENTS_PARAMETER']
s3_bucket = os.environ['S3_BUCKET']
s3_bucket_folder = os.environ['S3_BUCKET_FOLDER']
CREATE = 'Create'
response_data = {}
work_dir = '/tmp'
requirements_file = 'requirements.txt'
package_dir = 'python'
requirements_path = os.path.join(work_dir, requirements_file)
package_dir_path = os.path.join(work_dir, package_dir)
layer_package_path = os.path.join(
work_dir,
layer_package
)
def lambda_handler(event, context):
try:
if event['RequestType'] == CREATE:
ssm_client = boto3.client('ssm', region_name=region)
ssm_response = ssm_client.get_parameter(Name=requirements_parameter)
requirements = ssm_response['Parameter']['Value']
#print(requirements)
with open(requirements_path, 'w') as file_data:
print(requirements, file=file_data)
pip.main(['install', '-t', package_dir_path, '-r', requirements_path])
shutil.make_archive(
os.path.splitext(layer_package_path)[0],
format='zip',
root_dir=work_dir,
base_dir=package_dir
)
s3_resource = boto3.resource('s3')
bucket = s3_resource.Bucket(s3_bucket)
bucket.upload_file(
layer_package_path,
'/'.join([s3_bucket_folder, layer_package])
)
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
except Exception as e:
print(e)
cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
EphemeralStorage:
Size: !Ref EphemeralStorageSize
FunctionName: !Sub "${Prefix}-customresource-01"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Timeout: !Ref Timeout
Code language: YAML (yaml)
先述の関数では、MySQLに接続するために、mysql(mysql-connector-python)パッケージを使用しましたが、これをLambdaレイヤーとして用意します。
今回はCloudFormationカスタムリソースに関連づくLambda関数を使用して、自動的にLambdaレイヤーを作成します。
SSM Parameter Storeにダウンロードするパッケージのリストを登録します。
先述のパッケージを登録します。
詳細は以下のページをご確認ください。
証明書用レイヤー
Resources:
UrlsParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub "${Prefix}-customresource-02"
Type: String
Value: |
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
LambdaLayer:
Type: AWS::Lambda::LayerVersion
DependsOn:
- CustomResource
Properties:
CompatibleArchitectures:
- !Ref Architecture
CompatibleRuntimes:
- !Ref Runtime
Content:
S3Bucket: !Ref CodeS3Bucket
S3Key: !Ref LayerS3Key
Description: !Ref Prefix
LayerName: !Sub "${Prefix}-customresource-02"
CustomResource:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt Function.Arn
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Environment:
Variables:
LAYER_PACKAGE: !Ref LayerPackage
REGION: !Ref AWS::Region
URLS_PARAMETER: !Ref UrlsParameter
S3_BUCKET: !Ref CodeS3Bucket
S3_BUCKET_FOLDER: !Ref Prefix
Code:
ZipFile: |
import boto3
import cfnresponse
import os
import shutil
import subprocess
import urllib
layer_package = os.environ['LAYER_PACKAGE']
region = os.environ['REGION']
urls_parameter = os.environ['URLS_PARAMETER']
s3_bucket = os.environ['S3_BUCKET']
s3_bucket_folder = os.environ['S3_BUCKET_FOLDER']
CREATE = 'Create'
response_data = {}
work_dir = '/tmp'
package_dir = 'python'
package_dir_path = os.path.join(work_dir, package_dir)
layer_package_path = os.path.join(
work_dir,
layer_package
)
ssm_client = boto3.client('ssm', region_name=region)
s3_client = boto3.client('s3', region_name=region)
def lambda_handler(event, context):
try:
if event['RequestType'] == CREATE:
ssm_response = ssm_client.get_parameter(Name=urls_parameter)
urls = ssm_response['Parameter']['Value']
result = subprocess.run(
['mkdir', package_dir_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
for url in urls.splitlines():
print(url)
file_name = os.path.basename(url)
download_path = os.path.join(package_dir_path, file_name)
data = urllib.request.urlopen(url).read()
with open(download_path, mode='wb') as f:
f.write(data)
shutil.make_archive(
os.path.splitext(layer_package_path)[0],
format='zip',
root_dir=work_dir,
base_dir=package_dir
)
s3_client.upload_file(
layer_package_path,
s3_bucket,
os.path.join(s3_bucket_folder, layer_package)
)
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
except Exception as e:
print(e)
cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
EphemeralStorage:
Size: !Ref EphemeralStorageSize
FunctionName: !Sub "${Prefix}-customresource-02"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Timeout: !Ref Timeout
Code language: YAML (yaml)
先述の関数では、IAM認証を行うために証明書を使用しました。
これをLambdaレイヤーとして用意します。
こちらもCloudFormationカスタムリソースに関連づくLambda関数を使用して、自動的にLambdaレイヤーを作成します。
SSM Parameter StoreにダウンロードするファイルのURLリストを登録します。
先述の証明書のURLを登録します。
詳細は以下のページをご確認ください。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- EC2インスタンス:i-0a625917a26ccc6ae
- Lambda関数:fa-128-function
- Lambda関数のFunction URL:https://wndut2cyprxccm4cxjpm5or7bm0takbo.lambda-url.ap-northeast-1.on.aws/
- Lambdaレイヤー1:fa-128-customresource-01
- Lambdaレイヤー2:fa-128-customresource-02
- DB初期化処理用Lambda関数:fa-128-customresource-03
- DBインスタンス:fa-128-dbinstance
- DBインスタンスのエンドポイント:fa-128-dbinstance.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
AWS Management Consoleから各リソースを確認します。
まずDBインスタンスを確認します。
正常にDBインスタンスが作成されています。
そしてIAM認証が有効化されていることも確認できます。
Lambdaレイヤーを確認します。
確かに2つのレイヤーが作成されていることがわかります。
DBインスタンスの初期化処理用のLambda関数の実行結果を確認します。
確かにCloudFormationカスタムリソースによって、本関数が実行されました。
そして本関数内でDBの初期化処理用のSQL文が実行されたことがわかります。
動作確認
準備が整いましたので、実際の動作を確認します。
EC2インスタンスからDBインスタンスにIAM認証でアクセス
まずEC2インタンスにアクセスします。
インスタンスへのアクセスはSSM Session Managerを使用します。
% aws ssm start-session --target i-0a625917a26ccc6ae
...
sh-4.2$
Code language: Bash (bash)
SSM Session Managerの詳細につきましては、以下のページをご確認ください。
ユーザーデータによるインスタンスの初期化処理の実行状況を確認します。
sh-4.2$ sudo yum list installed | grep mariadb
mariadb.aarch64 1:5.5.68-1.amzn2 @amzn2-core
mariadb-libs.aarch64 1:5.5.68-1.amzn2 installed
sh-4.2$ mysql -V
mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (aarch64) using readline 5.1
sh-4.2$ ls -l /*.pem
-rw-r--r-- 1 root root 174184 May 3 00:27 /global-bundle.pem
Code language: Bash (bash)
正常にMySQLクライアントパッケージがインストールされていることがわかります。
またSSL通信用の証明書についてもダウンロードされています。
確認が済みましたので、IAM認証でDBインスタンスにアクセスします。
sh-4.2$ mysql \
--host=fa-128-dbinstance.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com \
--port=3306 \
--ssl-ca=/global-bundle.pem \
--default-auth=mysql_clear_password \
--user=iamuser \
--password=`aws rds generate-db-auth-token \
--hostname fa-128-dbinstance.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com \
--port 3306 \
--username iamuser \
--region ap-northeast-1`
...
MySQL [(none)]>
Code language: Bash (bash)
正常にアクセスすることができました。
アクセス用のコマンドは以下のページを参考にしました。
なお今回はMariaDB用のクライアントパッケージを使用しているため、上記のページで言及されているenable-cleartext-pluginオプションが存在しません。
ですから代わりに「–default-auth=mysql_clear_password」オプションを使用します。
https://mariadb.com/kb/en/pluggable-authentication-overview/
試しにテストテーブルに対して、SELECT文を実行します。
MySQL [(none)]> use tutorial;
...
Database changed
MySQL [tutorial]> select * from planet;
+----+---------+
| id | name |
+----+---------+
| 1 | Mercury |
| 2 | Venus |
| 3 | Earth |
| 4 | Mars |
| 5 | Jupiter |
| 6 | Saturn |
| 7 | Uranus |
| 8 | Neptune |
+----+---------+
8 rows in set (0.01 sec)
Code language: SQL (Structured Query Language) (sql)
確かにSELECT文を実行することができました。
このようにIAM認証でEC2インスタンスからDBインスタンスにアクセスし、操作することができます。
Lambda関数からDBインスタンスにIAM認証でアクセス
上記の関数を実行して動作を確認します。
関数の実行は、Function URLにアクセスして行います。
$ curl https://wndut2cyprxccm4cxjpm5or7bm0takbo.lambda-url.ap-northeast-1.on.aws/
[
[
1,
"Mercury"
],
[
2,
"Venus"
],
[
3,
"Earth"
],
[
4,
"Mars"
],
[
5,
"Jupiter"
],
[
6,
"Saturn"
],
[
7,
"Uranus"
],
[
8,
"Neptune"
]
]
Code language: Bash (bash)
正常に応答がありました。
DBインスタンスのテストテーブルの内容が返ってきました。
このようにIAM認証でLambda関数からDBインスタンスにアクセスし、操作することができます。
まとめ
EC2インスタンスおよびLambda関数から、IAM認証でRDSにアクセスする方法を確認しました。