テレワーク環境から研究用のJupyter Notebook on EC2にセキュアかつなるべく管理コストを抑えた方法でアクセスしたい話

タイトルのような状況に出会ったので、自分なりの解決方法をまとめます。
2021.04.29

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

こんにちは。AWS事業本部のKyoです。

タイトル長いですね。タイトルのような状況に出会ったので、自分なりの解決方法をまとめます。

問題と回答、そして考え方

問題

データサイエンティストのチームがあります。このチームはテレワークを行っており、テレワーク環境からEC2上で稼働するJupyter notebookにセキュアにアクセスしたいと考えています。チームは10人程度のメンバーから成り、1人が複数のJupyter notebookを利用することもあります。また、AWSアカウントはチームに対して払い出されており、環境の管理は研究チーム内で行わなければなりません。そのため、可能な限り管理コストを低くしたいとも考えています。なお、今回はオンプレミスからのリフトであり、SageMakerの利用は想定していません。

回答

先に回答となる構成を述べます。Session Managerを利用したポートフォワードです。

ClientはローカルPC、ServerがJupyter notebookに相当します。

AWS Systems Managerセッションマネージャーの「ポートフォワーディング」をHTTPプロキシ経由で利用する (Linux編) より引用

考え方

まず特定のIPのみを許可した踏み台サーバーを立てることを考えました。しかし、テレワーク環境 = 自宅環境に限定されるというわけでもないので接続元IPを限定するのは難しいと判断しました。

次に考えたのは、Client VPNです。この方法であれば、接続元IPを限定する必要がなく、プライベートIPでEC2インスタンスに接続できます。一方で認証のためにActive Directoryもしくは証明書が必要になります。これらの管理コストが低いとは言えません。

そこで考えたのがSession Managerのポートフォワードです。

この方法であれば認証もIAMベースのため、管理コストは最小限であると言えると思います。また、Session Managerを利用すると、EC2側でsshなどで利用するポートを開放する必要がなくなるのもメリットです。

Session Managerを通した通信がセキュアなのか?ということについては、公式ドキュメントに以下の記載があります。

クライアントとマネージドインスタンスとの間のトラフィックは TLS 1.2 を使用して暗号化され、接続の作成リクエストは Sigv4 を使用して署名されます。

AWS Systems Manager Session Manager

なお、ポートフォワードにはCLI操作が必要ですが、ボリュームも少なく基本的なコマンドであるため、ユーザーであるデータサイエンティストにとっては問題ないと判断しました。

やってみる

以下の3ステップで実際にやってみました。

1. AWS環境へのJupyter Notebookのセットアップ

EC2上にJupyter Notebook(以下、Jupyter)をセットアップする基本的な方法は以下のエントリをご参照ください。また、後で利用しますので、構築時にはJupyterのログインパスワードEC2のインスタンスIDEC2のパブリックIPを控えておいてください。

また、Jupyterはパブリックサブネットへ構築しますが、気になるのであればプライベートサブネットに構築し、NAT Gateway等でインターネットへの通信経路を確保してください。その場合、NAT Gatewayの利用料金が必要となります。

以降でSession Managerを利用するための設定について述べます。

SSMエージェントのインストール

Session Managerでポートフォワードを行うためににはSSMエージェントのバージョン2.3.672.0以降が必要です。なお、本エントリの執筆時に利用したUbuntu 18.04 AMI (ami-0ef85cf6e604e5650)ではインストール済みでした。

IAMロール

検証のためマネージドポリシーであるAmazonEC2RoleforSSMを含むロールを対象のEC2インスタンスに付与しました。本番利用時は必要に応じて権限を絞ってください。

セキュリティグループ

検証の上では必須ではない手順です。上記の方法ではセキュリティグループでSSH用の22番ポートとJupyterのデフォルトポートである8888番ポートを開放していますが、Session Managerのポートフォワードを利用するとどちらの開放も不要です。今回はインバウンドルールのないセキュリティグループを対象のEC2に付与しました。

2. ローカルマシンへのAWS CLI + Session Manager pluginのセットアップ

セットアップの方法はドキュメントをご参照ください。

検証時は以下の環境で行いました。

  • Mac OS 10.15.7
  • aws-cli/2.1.34 Python/3.8.8 Darwin/19.6.0 exe/x86_64 prompt/off

3. ポートフォワードでの接続

ローカルマシンのターミナル等で以下のコマンドを実行します。

--parametersで指定しているportNumberはJupyterのポート番号(デフォルトでは8888)、localPortNumberはローカルマシン側で空いている任意のポート番号(今回は58888)です。

 aws ssm start-session \
 --target 【インスタンスID】 \
 --document-name AWS-StartPortForwardingSession \
 --parameters '{"portNumber":["8888"],"localPortNumber":["58888"]}'

実行後、ターミナルには以下が表示されます。

Starting session with SessionId: botocore-session-1619659935-0362be49c20594fad
Port 58888 opened for sessionId botocore-session-1619659935-0362be49c20594fad.
Waiting for connections...

http://localhost:58888でブラウザからアクセスしてみます。

控えておいたJupyterのログインパスワードでログインしてみます。

無事にログインできました!

おわりに

本エントリでは、Session Managerおよびポートフォワードを利用することで、拠点IPを気にすることなくEC2上のJupyter Notebookにセキュアにアクセスすることができました。

今回は行いませんでしたが、IAMグループのポリシーで接続先インスタンスを絞ることで、チームごとにアクセス制限を行いたいといった要望にも対応可能だと思います。

また、StartSession APIの呼び出しを利用して、ポートフォワードのアクティビティを監視することも可能です。

今回はJupyter Notebookを例に挙げましたが、他のアプリケーションに対しても本構成は有効であると考えられます。テレワーク環境の構築に悩んだら一度検討してみてはいかがでしょうか。

以上、何かのお役に立てれば幸いです。