Shogo's Blog

Jan 13, 2019 - 1 minute read - go golang mysql aws

IAM認証でAWS RDSへ接続するMySQLドライバを作った

AWS RDS には IAM 認証を使って接続する機能があります。

これを使って接続するGo言語のSQLドライバを書いてみました。

使い方

IAMデータベース認証はデフォルトで無効になっているので、まずはこれを有効化します。 次に AWSAuthenticationPlugin を認証方式に指定して、新しいユーザーを作りましょう。

CREATE USER jane_doe IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';

他のSQLドライバはimportするだけで使えるのですが、 rdsmysqlではAWSへの権限情報を設定しなければならない都合上、 sql.Register を自前で呼び出す必要があります。 とは言っても、AWS SDKがいい感じに設定ファイルとか環境変数とか読んでくれるので、 rdsmysql.Driver にAWSセッションを渡すだけです。

c := aws.NewConfig().WithRegion("ap-northeast-1")
s := session.Must(session.NewSession(c))
d := &Driver{
    Session: s,
}
sql.Register("rdsmysql", d)

db, err := sql.Open("rdsmysql", "jane_doe:@tcp(db-foobar.ap-northeast-1.rds.amazonaws.com:3306)/")
if err != nil {
    log.Fatal(err)
}
defer db.Close()

あとは通常のMySQLドライバとして呼び出すだけです。 go-sql-driver/mysql のラッパーになっているので、 DNS等の書き方はこれに準じます。 認証部分は rdsmysql がやってくれるので、パスワードは空でOKです。 パスワードの管理から開放されて楽ですね!

なお、接続に使用するIAMユーザーもしくはロールには以下の権限が必要です。

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
             "rds-db:connect"
         ],
         "Resource": [
             "arn:aws:rds-db:ap-northeast-1:1234567890:dbuser:db-foobar/jane_doe"
         ]
      }
   ]
}

コマンドライン・インターフェイス

この方法、一応CLIからも行けるんですが、 aws rds generate-db-auth-token コマンドを叩いて、 数百の文字のトークンを頑張って mysql コマンドにわたす必要があって、かなり面倒くさい。

そこで、 mysql コマンドのラッパーも一緒に作りました。 いつもどおり go get でインストール可能です。

go get github.com/shogo82148/rdsmysql/cmd/rdsmysql
go get github.com/shogo82148/rdsmysql/cmd/rdsmysqldump

ユーザー名とホスト名を指定するだけでお手軽に接続できます。

rdsmysql -u jane_doe -h db-foobar.ap-northeast-1.rds.amazonaws.com

なお、 rdsmysqlmysql のラッパーなので、 mysql の事前インストールが必要です。

RDSクラスターに Public IP を割り振っておけば、踏み台サーバー等を経由せずとも、ローカルのPCから安全にアクセスが可能です。

まとめ

  • AWS RDS の IAM 認証を行うドライバを作った
  • IAM 認証用のCLIラッパーを作った

なおプロダクションへの投入はまだしてないです。 ちょっとしたユーティリティツールを書いただけで、バックエンドのリクエストをさばいたことはありません。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html#UsingWithRDS.IAMDBAuth.ConnectionsPerSecond MySQL で IAM データベース認証を使用する場合、1 秒あたりの新しい接続数は 20 までに制限されます。db.t2.micro インスタンスクラスを使用している場合、この制限は 1 秒あたり 10 接続に制限されます。

さて・・・Goの場合コネクションプールがあるので、たぶん問題ないとは思ってるんですが・・・・ この制限に引っかかった状況をまだ検証できてません。 人柱募集中。