🐼

[CDK] RDS DatabaseClusterでgrantConnect()メソッドを試してみる

2023/12/19に公開

経緯

https://qiita.com/advent-calendar/2023/aws-cdk

実はAdvent Calendarというイベントに今年初めて参加させていただきます。元々Qiitaのお祭りだと思っていた節があり「Zenn使っているしなぁ」と思っていましたが、何かの投稿を拝見してZENNで投稿して紐づけても良いという事を知り、申し込みドリブンで一枠いただいた次第です。

アドカレがスタートした際、読ませていただいた@rrrraaaaa6さんの以下記事が印象に残っていた事と、
https://zenn.dev/rrrraaaaa6/articles/8f188c8e07378f

以下、@konokenjさんのXの投稿を拝見して
https://twitter.com/konokenj/status/1734114806280675405

これもそっち系かな?と思い、RDSのgrantConnect()触ってみようと思うに至りました。お詳しい方は「ん?」と思う所もあるかと思いますが、温かい目でご覧いただければ幸いです。

早速やっていきます。


準備

https://github.com/aws/aws-cdk/pull/28118

まずは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!

書いてみる

lib/grant_connect_test-stack.ts
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
    });
  }
}
lib/resources/user-data.sh
#!/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に質問してみます。

利点も改めて調べてみます。
https://note.com/ym202110/n/n724759c69885


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.

以上でした

有難うございました。


参考にした記事

https://qiita.com/leomaro7/items/18d0d13c39f5548ee4ce

Discussion