はじめに

みなさん、こんにちは!

アジャイル事業部の土井田です。

この記事は「もくもく会ブログリレー」 30日目 の記事です。

今回飛び入りでブログリレーに参加させていただきました。

6/20(木)、6/21(金)に幕張メッセで開催された『AWS Summit Japan 2024』のアイレットブースで、産業用ロボットを使った工場IoTのデモを展示しました。

実はデモ環境の構築で、地味に苦労したところがありましたので今回これをご紹介します。

苦労したところ

展示会では産業用ロボットから収集したIoTデータに加え、ロボットの動画をKinesis Video Streamで配信し、Amazon Managed Grafanaのダッシュボードに稼働状況とライブ動画を表示しました。

また、ロボットの運転開始/停止等のイベントが発生した時、イベント前後の動画をポップアップで確認できる様にしました。

以下はデモ環境の構成図です。(主要な構成要素のみ記載しています。)

イベント前後の動画はAWS LambdaAmazon Kinesis Video Streamから切り出してAmazon S3に格納していますが、苦労したポイントは、「Amazon S3に格納されたイベント動画をどの様にしてサインインしているユーザーのみ取得可能とするか」という所です。

解決方法

Amazon S3に格納されたコンテンツをセキュアに配信する方法として、以下を考えました。

方法 メリット デメリット
アクセスするファイルの期限付きURLを利用する AWSが提供するドメインを使用するため、ドメインやSSL証明書をを用意しなくて済む 期限付きURLを発行するためのアプリケーションが必要となる。
期限の長さを考慮する必要がある。
Application Load Balancer (ALB)経由でAmazon S3へ接続し、ALBとAmazon Cognitoを連携し認証する コーディング無しで実現可能
サインインしたユーザーのみアクセス可能
ドメイン、SSL証明書を用意する必要がある。

Amazon Managed GrafanaにはAWS IAM Identity Centerで認証しSSOでアクセスしていますが、色々調べる中、AWS IAM Identity CenterからAmazon CognitoへSAMLでフェデレーションサインインできることが判り、今回は後者の方法で解決しました。

認証周りの構成は以下のとおりです。

 

構築方法

構築方法を以下に示します。

ドメイン・SSL証明書の取得

インターネットから静的コンテンツへhttpsでアクセスできるようにするため、Amazon Route 53でドメインを取得し、AWS Certificate ManagerSSL証明書を発行しました。

VPCの作成

以下の条件でVPCを作成しました。

  • 名前タグ:自動生成
  • IPv4 CIDR ブロック:192.168.0.0/24
  • AZの数:2
  • パブリックサブネットの数:2
  • プライベートサブネットの数:0

AWSマネジメントコンソールでVPCを作成すると、プレビューを見ながら名前タグやサブネットの設定も行えるため、便利です。

セキュリティグループの設定

VPCにはALBとAmazon S3のエンドポイントを構築しますが、各々に設定する以下のセキュリティグループを用意しました。

  • ALBに設定するセキュリティグループ:全てのIPアドレスから443ポート(https)へのアクセスを許可
  • Amazon S3のエンドポイント設定するセキュリティグループ:VPCのセグメントから80ポート(http)へのアクセスを許可

Amazon S3エンドポイントの構築

VPCに以下のエンドポイントを構築し、上で作成した80ポート(http)へのアクセスを許可するセキュリティグループを設定しました。

  • サービス名:com.amazonaws.ap-northeast-1.s3
  • タイプ:Interface

ALBを構築する時に、エンドポイントのIPアドレスを設定する必要があるため、エンドポイントを構築後、各サブネットのIPアドレスを控えておくと良いです。

Amazon S3 バケットの設定

インターネットからALB経由でAmazon S3のコンテンツにアクセスできる様にするためには、バケット名をサブドメイン(例:sub.domain.com)と一致させる必要がありました。
また、バケットポリシーには以下を設定し、S3エンドポイントからのみアクセス可能としました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::バケット名",
                "arn:aws:s3:::バケット名/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:SourceVpce": "S3のVPCエンドポイントのID"
                }
            }
        }
    ]
}

ALBの構築

まず、ALBの配信先となるターゲットグループを設定します。

  • グループの詳細の指定
    ターゲットタイプの選択:IPアドレス
    プロトコル・ポート:HTTP 80
    成功コード:200, 307, 405
  • ターゲットを登録
    IPアドレス:Amazon S3 VPCエンドポイントのIPアドレス(2つ)

次に以下を指定してVPCにALBを構築しました。

  • 基本的な設定
    スキーム:インターネット向け
  • ネットワークマッピング
    マッピング:VPCのAZ、サブネットを全て選択
  • セキュリティグループ:「セキュリティグループの設定」でALB用に作成したもの
  • リスナーとルーティング
    リスナー プロトコル:HTTPS
    デフォルトアクション:上で作成したターゲットグループを選択
    デフォルトSSL /TLSサーバー証明書:「ACMから」を選択し、ACMに設定された証明書を選択

Route 53のAレコード追加

以下を指定してドメインにレコードを追加しました。

  • レコード名:S3バケット名に設定したサブドメインの先頭
  • レコードタイプ:A
  • エイリアス:ON
  • トラフィックルーティング先:以下を選択
    Application Load BalancerとClassic Load Balancerへのエイリアス
    アジアパシフィック(東京)
    上で作成したALBのURLを指定

この段階で、認証無しでブラウザからS3の静的コンテンツにアクセスできます。S3にテスト用のhtmlファイルを置いて動作確認しました。

IAM Identity Centerのアプリケーション追加・Amazon Cognitoユーザープールの作成

IAM Identity CenterのAmazon Cognitoの設定では相互に設定内容を反映する箇所があり、2つのタブで各々の画面を開いて設定しました。

設定内容は以下のとおりです。

IAM Identity Centerのアプリケーション追加

以下を指定してアプリケーションを追加します。最後のアプリケーションメタデータにはユーザープールの値を設定する必要があるため、Amazon Cognitoでユーザープール作成後入力します。

  • セットアップリファレンス:設定するアプリケーションがある
  • アプリケーションタイプ:SAML 2.0
  • IAM Identity Center SAML メタデータファイル」のリンクをクリックし、ファイルをダウンロード(Amazon Cognitoの設定で使用します)
  • アプリケーションメタデータ:「メタデータ値をマニュアルで入力する」を選択し、以下を設定
    アプリケーションACS URL:https://ユーザープールのCognito ドメイン/saml2/idpresponse
    アプリケーション SAML 対象者:urn:amazon:cognito:sp:ユーザープールのID

作成したアプリケーションを選択し、以下のとおり属性マッピングを設定します。

形式
Subject ${user:subject} persistent
email ${user:email} basic

アプリケーション作成後、このアプリケーションにアクセスできるユーザーを追加します。

Amazon Cognitoユーザープールの作成

以下を指定してユーザープールを作成します。

  • プロバイダーのタイプ:フェデレーティッドアイデンティティプロバイダー
  • Cognito ユーザープールのサインインオプション:Eメールのみ選択
  • フェデレーティッドサインインのオプション:SAML
  • 多要素認証:MFAなし
  • セルフサービスのアカウントの復旧:OFF
  • セルフサービスのサインアップ:OFF
  • Cognitoアシスト型の検証および確認:メッセージを自動的に送信しない
  • Eメールプロバイダー:CognitoでEメールを送信
  • SAMLプロバイダー名:任意の名称
  • SAMLメタデータドキュメント:IAM Identity Centerの設定画面でダウンロードしたファイルをアップロード
  • SAMLプロバイダーとユーザープールの間で属性をマッピング:以下を入力
    ユーザープール属性:email SAML属性:email
  • ユーザープール名:任意の名称
  • ドメインタイプ:Cognitoドメインを使用する
  • Cognitoドメイン:任意(ユーザープールのサブドメイン)を設定
  • 最初のアプリケーションクライアント:パブリッククライアント
  • アプリケーションクライアント名:任意の名称
  • クライアントシークレット:クライアントのシークレットを生成する
  • 許可されているコールバックURL:https://S3のバケット名に設定したサブドメイン/oauth2/idpresponse
  • 認証フロー:ALLOW_REFRESH_TOKEN_AUTHのみ指定
  • ID プロバイダー:Cognitoユーザープールを削除
  • OpenID Connect のスコープ:OpenID、Eメールのみ指定

ALBのAmazon Cognito認証ルールの設定

ALBリスナーのルールに上で作成したAmazon Cognitoのユーザープールによる認証の設定を追加します。

 

参考にした記事

ALB、S3、PrivateLinkによる内部HTTPS静的ウェブサイトのホスティング

IAM Identity CenterとCognitoユーザープールの統合

 

まとめ

IAM Identity Center、Amazon Cognito、ALB、Amazon S3を連携することで、SSOによるセキュアな静的コンテンツ配信を実現できました。これにより、Amazon Managed Grafanaのみで実現が難しい部分を補うことが可能です。

次は動的なWebアプリケーションのSSO連携にもチャレンジしたいと思ってます。

明日の記事は、西田さんの「フロントエンドが苦手でも! StreamlitGeminiで簡単生成AIチャットボット開発 」です。楽しみです。