[CDK] RDS DatabaseClusterでgrantConnect()メソッドを試してみる
経緯
実はAdvent Calendarというイベントに今年初めて参加させていただきます。元々Qiitaのお祭りだと思っていた節があり「Zenn使っているしなぁ」と思っていましたが、何かの投稿を拝見してZENNで投稿して紐づけても良いという事を知り、申し込みドリブンで一枠いただいた次第です。
アドカレがスタートした際、読ませていただいた@rrrraaaaa6さんの以下記事が印象に残っていた事と、
以下、@konokenjさんのXの投稿を拝見して
これもそっち系かな?と思い、RDSのgrantConnect()触ってみようと思うに至りました。お詳しい方は「ん?」と思う所もあるかと思いますが、温かい目でご覧いただければ幸いです。
早速やっていきます。
準備
まずはCDKを最新verに。
$ npm install -g aws-cdk
changed 2 packages in 2s
npm notice
npm notice New major version of npm available! 9.8.0 -> 10.2.5
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.2.5
npm notice Run npm install -g npm@10.2.5 to update!
npm notice
個人的に最近は別に発生していた興味範囲ばかりで、暫く触れていなかった為9.8.0 -> 10.2.5の更新です。
$ mkdir grantConnectTest && cd grantConnectTest
$ cdk init --language typescript
Applying project template app for typescript
# Welcome to your CDK TypeScript project
This is a blank project for CDK development with TypeScript.
The `cdk.json` file tells the CDK Toolkit how to execute your app.
## Useful commands
* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `npx cdk deploy` deploy this stack to your default AWS account/region
* `npx cdk diff` compare deployed stack with current state
* `npx cdk synth` emits the synthesized CloudFormation template
Executing npm install...
✅ All done!
書いてみる
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';
import { readFileSync } from "fs";
export class GrantConnectTestStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, 'MyVPC', {
maxAzs: 2,
});
const rdsCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_05_0,
}),
vpc,
writer: rds.ClusterInstance.provisioned('writerInstance'),
defaultDatabaseName: 'MyDatabase',
subnetGroup: new rds.SubnetGroup(this, 'MySubnetGroup', {
description: 'description',
vpc,
vpcSubnets: { subnets: vpc.privateSubnets },
}),
iamAuthentication: true
});
const ec2Instance = new ec2.Instance(this, 'MyEC2Instance', {
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
vpc,
vpcSubnets: { subnets: [vpc.publicSubnets[0]] },
});
ec2Instance.connections.securityGroups[0].addIngressRule(
ec2.Peer.ipv4('0.0.0.0/0'),
ec2.Port.tcp(22),
'Allow SSH traffic from Internet Gateway'
);
ec2Instance.addUserData(readFileSync("./lib/resources/user-data.sh", "utf8"));
rdsCluster.connections.allowFrom(ec2Instance, ec2.Port.tcp(rdsCluster.clusterEndpoint.port));
rdsCluster.grantConnect(ec2Instance, 'iam_db_user');
new cdk.CfnOutput(this, 'EndPoint!', {
value: rdsCluster.clusterEndpoint.hostname
});
}
}
#!/bin/bash
sudo yum -y update
sudo dnf -y localinstall https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm
sudo dnf -y install mysql mysql-community-client
EC2に接続
今回はInstance Connectで接続してみます。
すっかり前提条件も忘れてしまいましたが(最後にいつ使ったかも忘却)ドキュメントを見て確認。
↓
ひとまず無事に鳥が飛びました。
Secrets ManagerコンソールでMaster User Passwordを確認
RDSへ接続
接続出来ました。
$ mysql -u admin -p -h [エンドポイント]
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 71
Server version: 8.0.32 Source distribution
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
ただ、これは以下で実現されているもので、じゃあgrantConnect()は?と言う所です。
rdsCluster.connections.allowFrom(ec2Instance, ec2.Port.tcp(rdsCluster.clusterEndpoint.port));
正直、この時点で私はこのメソッドを確り理解しておらず、grantConnect()で作成された権限を確認してみる事にしました。
grantConnect()が何の権限を付与するのか確認
それが以下です。(この時点ではadminですが先ほどのtsではiam_db_userに変更しています。)
ここにある「rds-db:connect」が何を意味するのかを調べる為にGoogleの検索窓で叩いてたり、ChatGPTに質問してみます。
利点も改めて調べてみます。
mysql内でIAM DB認証の準備をする
mysql> CREATE USER iam_db_user@'%' IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
Query OK, 0 rows affected (0.09 sec)
↓
mysql> select Host, User from mysql.user;
+-----------+-----------------------+
| Host | User |
+-----------+-----------------------+
| % | AWS_COMPREHEND_ACCESS |
| % | AWS_LAMBDA_ACCESS |
| % | AWS_LOAD_S3_ACCESS |
| % | AWS_SAGEMAKER_ACCESS |
| % | AWS_SELECT_S3_ACCESS |
| % | admin |
| % | iam_db_user |
| % | rds_superuser_role |
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | rdsadmin |
+-----------+-----------------------+
12 rows in set (0.00 sec)
↓
mysql> create database iam_db;
Query OK, 1 row affected (0.00 sec)
↓
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| MyDatabase |
| iam_db |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
↓
mysql> GRANT ALL PRIVILEGES ON iam_db.* TO 'iam_db_user '@'%';
Query OK, 0 rows affected (0.01 sec)
↓
一旦mysqlを抜けます
mysql> quit
アクセスしてみる
入る事が出来ました。
$ mysql -u [IAMデータベース認証ログインユーザ名] -h [RDSエンドポイント] -p`aws rds generate-db-auth-token --hostname [RDSエンドポイント] --port 3306 --username [IAMデータベース認証ログインユーザ名] --region [リージョン]` --enable-cleartext-plugin
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 602
Server version: 8.0.32 Source distribution
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
以上でした
有難うございました。
参考にした記事
Discussion