クロスアカウントでVPCピアリング先のEC2(MySQL)へLambdaからアクセスしてみる

クロスアカウントでVPCピアリングしている環境の中で、プライベートに配置したEC2へ別アカウントのLambda関数からアクセスしてみました。
2021.01.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、鈴木(純)です。

クロスアカウントでVPCピアリングした環境で、LambdaからEC2内にインストールしたMySQLへアクセスしてみました。

はじめに

以下のような環境を想定しています。EC2インスタンス側のセキュリティグループでアカウントBのLambdaからのみアクセスを許可するようにインバウンドを絞っていきます。

LambdaからMySQLに登録したテーブルの情報をSELECTすることをゴールとします。

前提

今回はVPCピアリングの細かい話はしません。以下の記事みてもらえるとルーティングまで設定できるかと思います。

VPCピアリングした状態で、ルートテーブルが設定済の前提で進めます。

EC2(MySQL)へサンプルデータを用意する

まず最初にEC2(Amazon Linux2)を用意してMySQLをインストールします。

以下を参考にMySQLをインストール。

無事MySQLへログインできたら、サンプル用のnameテーブルを作成していきます。

$ use mysql;
$ create table name (name varchar(10));

とりあえず、以下のような5つのデータを挿入。

insert into name values ('Suzuki');
insert into name values ('Satou');
insert into name values ('Kimura');
insert into name values ('Toda');
insert into name values ('Goto');
$ select * from name;
+--------+
| name   |
+--------+
| Suzuki |
| Satou  |
| Kimura |
| Toda   |
| Goto   |
+--------+

上記のように表示されれば、サンプル用のテーブル作成は完了です。

Lambdaを作成する

次に先ほど作成したテーブルを読み取るLambdaを作成していきます。今回はpython3.7で作成していきます。

下へスクロールして詳細設定を開くとネットワークを設定することができるので、Lambda関数に紐づけるVPC、サブネット、セキュリティグループを設定します。ここでネットワークを設定することで、Lambda関数がプライベートサブネットへ接続できるようVPC内にENIが作成されます。詳しくは以下ドキュメントをご参照下さい。

Lambda関数に設定したセキュリティグループはインバウンド設定なし、アウトバウンドは制限をかけずにオープンにしてます。

Lambda用のコードを作成する

ここからはAWSのコンソールではなく、ローカルで作業して下さい。理由はMySQLへの接続で使用するパッケージをインストールする必要があり、ZIPの形式でLambdaへアップロードする必要があるためです。

任意のフォルダを作成します。

$ mkdir function
$ cd function

以下のコードをlambda_function.pyとして保存します。接続先については適宜変更して下さい。

$ vi lambda_function.py
import json
import mysql.connector
import traceback
import sys

def lambda_handler(event, context):

    names = ""

    conn = mysql.connector.connect(user='[ユーザー名]', password='[パスワード]', host='[接続先EC2のプライベートIP]', database='[DB名]')
    cur = None
    try:
        cur = conn.cursor(dictionary=True)
        cur.execute("select * from name;")
        for row in cur.fetchall():
            names += row['name'] + "," 
        cur.close
    except:
        traceback.print_exc()
        print(sys.exc_info())
        names = "error!"  
    finally:
        cur.close
        conn.close       
    return {
        'statusCode': 200,
        'body': json.dumps('name : ' + names)
    }

MySQLへ接続するために、ライブラリをインストールします。

$ pip install mysql-connector-python -t .
Collecting mysql-connector-python
  Using cached https://files.pythonhosted.org/packages/91/c3/d06afc12fb811e62732b5d0332648bb8a92f253eb45585042852156d3236/mysql_connector_python-8.0.23-cp36-cp36m-macosx_10_14_x86_64.whl
Collecting protobuf>=3.0.0 (from mysql-connector-python)
  Using cached https://files.pythonhosted.org/packages/a7/04/82599fbac6f1e047242bb6e7a4fac76cb2a94a38968af30ee55a4179be31/protobuf-3.14.0-cp36-cp36m-macosx_10_9_x86_64.whl
Collecting six>=1.9 (from protobuf>=3.0.0->mysql-connector-python)
  Using cached https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl
Installing collected packages: six, protobuf, mysql-connector-python
Successfully installed mysql-connector-python-8.0.23 protobuf-3.14.0 six-1.15.0

インストールが完了したらlambda_function.py含めまとめて以下コマンドでZIPにします。

$ zip -r9 ../function.zip .

ZIPファイルの作成が完了したら、function.zipをそのままコンソールからアップロードします。

これでLambda側の設定は完了です。

EC2のセキュリティグループを編集する

作成したLambda関数からのアクセスを許可するため、EC2のセキュリティグループのインバウンドルールを編集します。

EC2に紐づけたセキュリティグループのインバウンドルールにLambdaのセキュリティグループIDを入力します。クロスアカウントのため見つかりませんと表示されていますが、Enterを押すとしっかりと認識してくれますのでご安心下さい。MySQLのポート3306ポートを指定してルールを保存します。

Lambdaを実行してみる

セキュリティグループの設定が完了したら、Lambdaを実行してみます。

テストを実行してみると、設定が正しければname : Suzuki,Satou,Kimura,Toda,Gotoとサンプルで作成した名前が結果として確認できるはずです。

まとめ

クロスアカウント上でVPCピアリングした環境でLambdaを実行したことがなかったのでやってみました。クロスアカウント先のLambdaでもしっかりセキュリティグループで接続元を指定できるのはいいですね。