SageMakerノートブックインスタンスへのアクセスをPrivateLinkで制限する方法を経路別に検証してみた

SageMaker Jupyter Notebookインスタンスをプライベート接続で利用する方法を確認してみました。SageMakerはネットワークがやや特殊ですが、PrivateLinkの使い方も少し変わっているので、その使い方と実際の動作について様々な経路を想定して確認してみました。
2020.03.30

SageMakerでは簡単にJupyter Notebookを利用できる機能があります。
マネジメントコンソールからアクセスするのが簡単ですが、署名付きURLを使えば、マネジメントコンソールにログインすることなく、IAMユーザではない利用者が使うことも可能です。

VPC外から署名付きURLでアクセスする方法は下記で紹介しています。

さて今回は、ノートブックインスタンスへの接続を「VPN、Direct Connect、VPC内」に制限する方法をご紹介します。

目指す構成

下記のような構成で利用する想定とします。
(文字が潰れて見づらい場合は、画像だけ別タブにて表示してみてください)

ノートブックインスタンスは、SageMaker管理のVPCに作成することもできますし、ユーザ管理のVPCに作成することもできます。今回は、ユーザ管理のVPCに構築する前提として、下記図のような形で各経路からのアクセスに制限した環境を構築します。

00-image

構成の説明

ノートブックへのアクセス元は次の3種類を想定しています。

  • InternetVPN、Direct Connect経由のアクセス
  • ClientVPN経由のアクセス
  • 同じVPC上のリソース(EC2など)からのアクセス

拒否したいアクセスは下記になります。
(プライベートなアクセス以外はすべて拒否)

  • マネジメントコンソールを経由しないインターネットからのアクセス
    • IAM Userではない利用者を想定
  • マネジメントコンソール上からのアクセス
    • IAM Userである利用者を想定

今回のポイント

構築作業に入る前にポイントを押さえておきたいと思います。

インターフェイスエンドポイントから署名付きURLを発行

PrivateLinkでAWSサービスを利用する場合、そのエンドポイントURLを指定してアクセスすることが多いと思います。
SageMakerノートブックインスタンスの場合は、エンドポイントURLを指定して「署名付きURL」を発行します。そして発行された署名付きURLからJupyterノートブックにアクセスするという使い方になります。

IAMポリシーで署名付きURLへのアクセスを制限

Jupyterノートブックへの署名付きURLへのアクセス制限は、発行者のIAM権限、つまりポリシーの内容に依存します。
CreatePresignedNotebookInstanceUrlの権限を持っていて他の制限は特に無い場合、発行されるURLはインターネットに繋がる環境であればどこからでも接続可能です。

このとき、IP制限をしたい場合はConditionで許可IPを指定すると、そのIPからしかアクセスできないURLが発行されます。
下記はそのIAMポリシーの一例です。(上記ブログより引用)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": "sagemaker:CreatePresignedNotebookInstanceUrl",
            "Resource": "*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "<接続を許可するIPアドレス、またはIPアドレスレンジ>"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "sagemaker:CreatePresignedNotebookInstanceUrl",
            "Resource": "*"
        }
    ]
}

そのため、VPCからのアクセスに制限したい場合も同様に制限をすることで、制限のかかったURLを発行することができるようになります。
例えば、指定のVPCエンドポイント経由のアクセスだけを制限する場合は、aws:SourceVpceという条件を利用します。

"Condition": {
    "ForAnyValue:StringEquals": {
        "aws:sourceVpce": [
            "vpce-111bbccc",
            "vpce-111bbddd"
        ]
    }
}

上記の場合、エンドポイントが変わる度にポリシーの修正が必要となるので、対象VPC内のアクセスだけを許可したい場合は、次のような条件aws:sourceVpcを利用します。この場合は、ユーザー拠点からのInternet VPNやDirect Connectによる接続はできません。

"Condition": {
    "StringEquals": {
        "aws:SourceVpc": "vpc-111bbaaa"
    }
}

このようなIAMポリシーを持ったIAM UserやIAM Roleで生成されたURLは、インターネットからアクセスできません。ポリシー条件にマッチしたVPCやVPCエンドポイント経由に限りJupyterノートブックのURLにアクセスすることが可能になります。

署名付きURLを発行できる環境

ここまでの内容で、IAMポリシーでアクセス制限されたURLを発行できることが分かりました。次にこのURLを発行できる条件について説明します。

署名付きURLはVPC外でもインターネットに繋がっていればCreatePresignedNotebookInstanceUrlというAPIを利用して発行することができます。この場合に発行されるURLは、(IAMポリシーで特に何も制限をかけていなければ)インターネットにつながる環境ならば、どこからでもノートブックにアクセス可能です。

しかし、「プライベートに閉じたアクセスに制限されたURL」を発行するには、そのVPCエンドポイントにアクセスできる必要があります。具体的には、「対象のVPCエンドポイントを指定してCreatePresignedNotebookInstanceUrlAPIで署名付きURLを生成」する必要があります。
逆に、そのエンドポイントにアクセスできない環境からは「制限された署名付きURL」を発行することができません。

先程の図で言うと、次のようになります。

  • プライベートに閉じた署名付きURLを発行できるユーザーやリソース
    • ClientVPNでVPN接続しているIAM User
    • Internet VPNまたはDirect Connectで接続しているIAM User
    • VPC内のリソース(同じポリシーのIAM RoleがあるEC2など)
  • プライベートに閉じた署名付きURLを発行できないユーザーやリソース
    • VPC外(インターネット)にいる「非IAM User」
    • マネジメントコンソールからJupyter Notebookインスタンスを利用するIAM User

やや冗長的に記載してきましたが、このポイントを押さえることで、後で紹介する手順の意味がより理解できると思います。

やってみる

それでは実際に環境を作る手順を追っていきたいと思います。

VPCエンドポイントの作成

まずはVPCエンドポイントを作成します。作成するエンドポイントは2種類あります。

  • SageMaker Notebookエンドポイント
    • プライベートにNotebookインスタンスにアクセスするためのエンドポイント
  • SageMaker APIエンドポイント
    • プライベートアクセスに制限された署名付きURLを発行するエンドポイント

下記は、「SageMaker Notebookエンドポイント」を作成する画面です。
(notebookという名前が付いたエンドポイントを選択します)

  • VPCは環境に合わせて適当なものを選択してください。
  • セキュリティグループは「HTTPS」に対してアクセスを想定するIPのみ許可するように設定します。
    • 「VPC内のIP」
    • 「Internet VPNやDirectConnetで接続するオンプレ側のIP」
    • 今回は2つのエンドポイントとも同じセキュリティグループに設定しました。必要に応じて分けるなりしてください。

10-make-endpoint

同様に「AageMaker API」のエンドポイントも作成しておきましょう。この場合は「sagemaker.api」というサービス名を選択します。

プライベート接続の構築

ClientVPNの場合

次にいずれかのプライベート接続環境を構築します。今回は構築が簡単なClientVPNにします。
ポイントは「カスタムDNSサーバー」を設定している点です。今回はAmazon DNSを利用したかったので、エンドポイントのあるVPC CIDR(10.60.0.0/16)の2番目のIPアドレス(10.60.0.2)を設定しました。

11-clientvpn-endpoint

ClientVPNでカスタムDNSサーバーを使う理由

署名付きURLとして発行されるURLのドメインは「sagemaker.aws」になりますが、VPC外のDNSサーバ(例えば契約プロバイダのDNSなど)で名前解決させるとグローバルIPが返ってきます。
ClientVPNで接続できていてもDNSが外部のものだとパブリックIPに対してアクセスすることになりますが、発行されるURLはアクセス制限がかかっているので、ノートブックにアクセスできません。

そのため、VPC内の名前解決を行うためにカスタムDNSサーバーを設定しています。
手元で試してみたところ、私の設定ではMacのOpenVPNクライアントで接続すると、すべての名前解決がカスタムDNSサーバーを向くようになりました。

Windowsの場合は、VPNインタフェースのみAmazon DNSのIPが設定されていたので、Windowsのネットワーク設定でDNSサーバをAmazon DNSに指定してアクセスするようにしました。

Internet VPN / Direct Connectの場合

次にオンプレからの接続環境を作ります。(必要に応じて作成してください)

特に変わった設定は必要ありませんが、Amazon DNSはVPC外からは利用できないので「Route53 Resolver」を使ってAmazon DNSを利用できるようにしておきましょう。

特別な設定は特に無いので、作業内容は割愛致します。
また、同じVPC上のEC2からのアクセスについても説明を割愛させていただきます。

IAMの設定

次にIAMポリシーを作成します。署名付きURLはauthTokenが付帯しただけのものでポリシーの内容はURLから推測することはできませんが、ポリシーの内容が反映されたURLとして発行されます。

ポリシーの説明自体は、冒頭の「ポイント」で行いましたので詳細は割愛致します。
今回は、指定のVPCエンドポイント経由のアクセスのみに制限をしてみたいと思うので、下記のようなポリシーを作成しました。
VPCエンドポイントには、作成した2つのエンドポイントIDを記載します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sagemaker:CreatePresignedNotebookInstanceUrl",
                "sagemaker:DescribeNotebookInstance"
            ],
            "Resource": "*",
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "aws:SourceVpce": [
                        "vpce-xxxxxxxxxxxxxxxxx",
                        "vpce-yyyyyyyyyyyyyyyyy"
                    ]
                }
            }
        }
    ]
}

このポリシーを、署名付きURLを発行するIAM UserやEC2のIAM Roleにアタッチします。

ちなみに、ノートブックにはブラウザでアクセスするので、ノートブックにアクセスする端末(ユーザ)は、上記のVPCエンドポイントにアクセスさえできればJupyter Notebookを利用することができます(IAM権限はURL発行者だけが持っていればOKです)

ノートブックインスタンス作成

署名付きURLの作成には、アクセスしたいノートブックインスタンスを指定する必要があります。
このとき、対象のノートブックインスタンスが起動している必要があるので、リソースを作成しておきましょう。

今回はSageMakerのコンソールから作成してみました。
また、自分のVPCを利用させる構成にしたかったので、ネットワークオプションでVPCやサブネットなどを指定します。ネットワーク構成の指定は構成図のとおりです。

また、今回の話とはあまり関係ありませんが、ノートブックインスタンスからのインターネットアクセスも自分のVPC経由としたかったので、「直接インターネットアクセス」の設定は「無効化」を選択しています。
(「有効化」を選択するとSageMakerサービスが管理するVPCからインターネットに出ていく形になります。参考リンク

12-make-notebook-instance

署名付きURLの発行

ようやく署名付きURLを発行します。
先程作成したIAMポリシーを持ったIAM User、EC2のいずれでも構いませんので、署名付きURLを発行してみます。

ここでは下記の点を確認することを念頭に置きながら作業すると分かりやすいと思います。
IAMポリシーの内容はすべて同じとします。)

  • URL発行者A,B,CのいずれかのIAM権限にて署名付きURLが発行可能になっている。
    • A:同じVPC上のEC2インスタンス
    • B:ClientVPNで接続しているIAM User
    • C:InternetVPN / DirectConnectで接続しているIAM User
  • 次のユーザは署名付きURLを発行できない
    • D:URL発行権限を持っているがプライベート接続できないIAM User
    • E:URL発行権限を持っていてマネジメントコンソールを利用するるIAM User

20-image-presined-urls

署名付きURLを発行するコマンドの書式は下記のようになります。
繰り返しになりますが、VPNなどでVPCエンドポイントにアクセスできていることが前提になります。
(VPCエンドポイントにアクセスできない環境だとコマンド実行に失敗します)

「ノートブックインスタンスの名前」には先程作成したインスタンスの名前を指定します。

aws --endpoint https://[VPC_Endpoint_ID].api.sagemaker.[Region].vpce.amazonaws.com sagemaker create-presigned-notebook-instance-url \
--notebook-instance-name [ノートブックインスタンスの名前]

19-sagemaker-endpoint

なお、エンドポイントの指定は、VPCエンドポイントで「Private DNS names enabled」が有効であれば必要ありません。
(エンドポイントにアクセスできない環境で、エンドポイントを省略してもコマンド実行者のIAMポリシーでCondition条件にマッチしないので、この場合もコマンドの実行に失敗します)

個人的には、プライベートDNS名の設定に関わらずエンドポイントを指定するほうが不要なトラブルを回避するという意味でオススメかなと思います。
(プライベートDNS名の設定はデフォルトで有効です)

コマンドの実行が成功すれば下記のような結果が返ってきます。

{
    "AuthorizedUrl": "https://test-notebook.notebook.ap-northeast-1.sagemaker.aws?authToken=xxxxx"
}

動作確認

発行できたURLにアクセスしてみます。
VPNなどでVPCに接続している環境、もしくはVPC内のインスタンスなどからブラウザで確認して、Jupyterノートブックインスタンスにアクセスできれば成功です。

署名付きURLを貼り付けて・・・

14-access-notebook

VPC内、プライベート接続の環境でアクセスできました!

15-success-access

次に、VPN接続を切って同じURLにアクセスしてみます。接続できませんでした。
このとき、「sagemaker.aws」の名前解決はグローバルIPが返ってきていますが、署名付きURLの中でIAMポリシーが検証されます。その結果、指定のVPCエンドポイント経由ではないアクセスなので拒否されてしまいます。

18-ng-disconnect-vpn

最後にマネジメントコンソールからもアクセスしてみます。コンソールを利用するIAM Userの権限は先に作成したもの同じポリシーをアタッチしているものとします。

コンソールから「Jupyterを開く」をクリックしてアクセスすると・・・

16-open-jupyter-by-iam-user

マネジメントコンソール上からはアクセスできませんでした。

17-ng-access-nb-over-console

マネジメントコンソールからノートブックにアクセスされる際、裏側でCreatePresignedNotebookInstanceUrlのAPIが呼ばれて署名付きURLが発行されています。このURLに対して、「IAMポリシーで記載した制限(VPCエンドポイント経由のみ許可)が効いているためコンソールからはアクセスできなかった」ということになります。

SageMakerの全権限を持つIAM Userの場合は、ポリシーそのものが違うのでマネジメントコンソールからアクセスすることが可能です。
(この場合は、自分で制限のない署名付きURLを作成できるので、インターネットからでもアクセスすることができますが…)

下記の図は署名付きURLへのアクセスを経路別にまとめたものです。
発行されたURLへアクセスした際にポリシーで許可されたアクセスのみノートブックインスタンスにアクセスすることが可能です。

21-image-access-presined-urls

まとめ

ここまでの内容を(やや強引に)一つのイメージで図解すると次のようになります。ポイントは下記の2点です。

  • VPCエンドポイントにアクセスできる環境から、署名付きURLを発行できるIAM権限を持ったリソースからURLを発行
  • VPCエンドポイントにアクセスできる環境からのみ上記で発行した署名付きURLにアクセス可能

22-image-complete-updated

異なるVPCから同じノートブックインスタンスを利用したい場合は、そのVPC上で別途エンドポイントを作成し、そのエンドポイントに対してconditionで制限するポリシーを付与します。

すべて同じポリシーで運用したい場合は、すべてのエンドポイントを記載すればよいと思います。
(VPCが2つの場合、SageMaker APIとNotebookの2つずつで合計4つ)

"Condition": {
    "ForAnyValue:StringEquals": {
        "aws:SourceVpce": [
            "vpce-aaaaaaaaaaaaaaaaa",
            "vpce-bbbbbbbbbbbbbbbbb",
            "vpce-ccccccccccccccccc",
            "vpce-ddddddddddddddddd"

        ]
    }
}

念の為の余談ですが、別のユーザで発行したURLは他のユーザが利用することも当然可能です。例えば、ClientVPN接続したユーザで発行したURLをコピペして、VPC上のインスタンスやDirectConnect接続しているユーザが利用できます。
このとき、コピペで利用するユーザはIAM権限を持っていなくてもノートブックを利用可能です。

最後に

SageMakerのノートブックインスタンスに対する署名付きURLは、見た目からだと「想定したアクセス制限」がかかっているか判断できません。SageMakerのネットワークもやや特殊なので、各通信がどのように流れているのか最初は混乱しましたが、今回の検証を通して、その仕様をよく理解することができました。

イメージしやすいように図解を交えてみました。この記事がどなたかのお役に立てれば幸いです。

参考ページ