Azure functionsからAWS Auroraにつないでみる

Azure functions(python)からIAMデータベース認証でAuroraに接続してみました。

# 必要なもの
* AWSのアカウント
* Azureのアカウント

# 作業概要
1. Auroraの作成
2. DBユーザーとIAMの作成
3. Azure functionsの作成
4. 動作確認

# 1. Auroraの作成

1. AWSマネジメントコンソールにログイン後、RDSを選択し、「Aurora(MySQL)を起動」をクリックする
　
2. 以下のパラメータを指定してAuroraを作成する

|パラメータ|値|
|--------------------|------------|
|DBインスタンスのクラス|db.t2.medium|
|マルチAZ配置|いいえ|
|VPC|デフォルトVPC|
|サブネットグループ|default|
|パブリックアクセス可能|はい|
|VPCセキュリティグループ|新しいセキュリティーグループの作成|
|IAMのDB認証を有効にする|はい|

※コスト重視の設定です。
　
3. セキュリティグループの編集

自動作成されたセキュリティグループは、自分のPCのグルーバルアドレスからアクセスのみ許可する設定になっているので、どこからのアクセスでも許可するように編集します。

3-1. 作成したAuroraインスタンスの詳細画面のセキュリティーグループをクリックする

<img width="387" alt="06_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/11e68a26-48d2-bd7b-2d4e-494fb93c0b93.png">

3-2. 「インバウンド」-「編集」をクリックし、ソースを「任意の場所」に変更し保存する

<img width="1021" alt="07_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/110886d1-4c9c-423a-0d15-6bcc9ffc45e8.png">
# 2. DBユーザーとIAMの作成

1. DBユーザーを作成する

作成したAuroraに接続して、下記SQLを実行します。

```sql
CREATE USER <<ユーザー名>> IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
```
　
2. IAMポリシーを作成する

AWSマネジメントコンソールでIAMを選択後、下記JSONを指定してIAMポリシーを作成します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1503756013000",
            "Effect": "Allow",
            "Action": [
                "rds-db:connect"
            ],
            "Resource": [
                "arn:aws:rds-db:<<リージョン>>:<<AWSのアカウントID>>:dbuser:<<クラスタのリソースID>>/<<DBユーザー名>>"
            ]
        }
    ]
}
```

*参考:http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html#UsingWithRDS.IAMDBAuth.Attaching*

*参考(リージョン):http://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html#rds_region*
　
3. IAMユーザーを作成し、上で作成したIAMポリシーをアタッチする

引き続きAWSマネジメントコンソール上でIAMユーザーを作成します。ユーザー名は利用しないので、ダミーで構いません。また作成するIAMユーザーはマネジメントコンソールへのログインには使わないので、AccessTypeは「Programmatic access」を指定します。
IAMユーザー作成後、アクセスキーとシークレットキーが表示されます。Azure functionsで利用するので、メモを取ります。(シークレットキーは作成時にしか確認できません。)

# 3. Azure functionsの作成

1. Azure Portalにログインして、functionsリソースを作成する

    <img width="293" alt="01_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/7d9a8f6d-a507-296b-a390-f0b1faf36d22.png">


2. テンプレート「HttpTrigger - Python」を選択して関数を作成する

    <img width="576" alt="02_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/30eb173c-f9ab-fef7-6800-8f4cf87c0c2f.png">

3. Kuduに接続し、Debug consoleを開く

    <img width="746" alt="03_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/063b0852-a74b-3fbe-8d01-46f06d8e23c9.png">

    <img width="653" alt="04_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/77451e8c-57eb-9c40-68f0-e6c4acc6dc00.png">

4. Azure functionsのPythonのバージョンを上げる

KuduのDebug consoleで以下を入力します。

```
D:\home>nuget.exe install -Source https://www.siteextensions.net/api/v2/ -OutputDirectory D:\home\site\tools python362x86
D:\home>mv /d/home/site/tools/python362x86.3.6.2/content/python362x86/* /d/home/site/tools/
```

Azure functionのpythonのバージョンは2.7.8(2017-08-30時点)ですが、そのバージョンだと今回利用するpymysqlが下記エラーを出力するため、バージョンを3.6.2に上げます。(やや黒魔術)
> AttributeError: 'module' object has no attribute 'SSLContext'

Azure functionsのpythonはまだExperimentalなので、正式リリース時にはここら辺は変わるかもしれません。
*参考:https://prmadi.com/running-python-code-on-azure-functions-app/*
　
5. Pythonのモジュールをインストールする

引き続き、KuduのDebug consoleで以下を入力します。

```
D:\home>cd /home/site/wwwroot/aurora
D:\home\site\wwwroot\aurora>python -m pip install boto3 -t .
D:\home\site\wwwroot\aurora>python -m pip install pymysql -t .
```
　
6. ルート証明書をダウンロードする

引き続き、KuduのDebug consoleで以下を入力します。

```
D:\home\site\wwwroot\aurora>curl -O https://s3.amazonaws.com/rds-downloads/rds-ca-2015-root.pem
```

*参考:http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html*
　
7. サンプルのpythonスクリプトを書き換える

```run.py
import os
import boto3
import pymysql

response = open(os.environ['res'], 'w')

host   = '<<Auroraのクラスタエンドポイント>>'
user   = '<<DBユーザー名>>'
dbname = '<<DB名>>'
region = '<<リージョン名>>' # 例) バージニアならus-east-1
cafile = 'rds-ca-2015-root.pem' # ルート証明書

client = boto3.client(
    'rds',
    aws_access_key_id     = '<<アクセスキー>>',
    aws_secret_access_key = '<<シークレットキー>>',
    region_name           = region
)

token = client.generate_db_auth_token(
    DBHostname = host,
    Port       = 3306,
    DBUsername = user,
    Region     = region
)

connection = pymysql.connect(
    host   = host,
    port   = 3306,
    user   = user,
    passwd = token,
    ssl    = {
        'ca': cafile
    },
    db     = dbname
)

try:
    with connection.cursor() as cursor:
        cursor.execute('select aurora_version();')
        result = cursor.fetchone()
        response.write("aurora version: "+result[0])
finally:
    connection.close()

response.close()
```
# 4. 動作確認

「実行」をクリックした結果が以下のようになればOKです。

<img width="439" alt="05_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/b746ad47-aa7d-8124-0745-e26395b4a0f4.png">


# 雑感
本当はC#で接続してみたかったのですが、Connector/NetがIAMデータベース認証に対応できないようで断念。。。pythonではバージョン周りで再びハマりましたが、Azure functionsの自由度(対AWS Lambda比)に助けられ無事Auroraに接続できました。

またIAM データベース認証を使わなければ、もっと簡単に接続できそうです。