

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon OpenSearch Service におけるマルチテナントサーバーレスアーキテクチャの構築
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service"></a>

*Tabby Ward、Nisha Gambhir (Amazon Web Services)*

## 概要
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-summary"></a>

Amazon OpenSearch Service は、ポピュラーなオープンソース検索および分析エンジンである Elasticsearch を簡単にデプロイ、運用、スケールするためのマネージド型サービスです。OpenSearch Service は、ログやメトリクスなどのストリーミングデータの自由なテキスト検索や、ほぼリアルタイムの取り込みやダッシュボードを提供します。

Software as a Service (SaaS) プロバイダーは、複雑さとダウンタイムを軽減しながら、スケーラブルかつセキュアな方法で顧客インサイトを得るなど、幅広いユースケースに対応するために、OpenSearch Service を頻繁に利用しています。

OpenSearch Service をマルチテナント環境で使用する場合、SaaS ソリューションのパーティショニング、隔離、デプロイ、および管理に影響を与えるさまざまな考慮事項が発生します。SaaS プロバイダーは、絶えず変化するワークロードに合わせて Elasticsearch クラスターを効果的にスケールする方法を検討する必要があります。また、階層化やノイズの多い隣接条件が、パーティショニングモデルにどのような影響を与えるかを考慮する必要があります。

このパターンでは、Elasticsearch コンストラクトを使用して、テナントデータを表現および隔離するために使用されるモデルを検討します。さらに、このパターンでは、マルチテナント環境で OpenSearch Service を使用してインデックス作成と検索を実演する例として、シンプルなサーバーレスリファレンスアーキテクチャに焦点を当てています。これにより、すべてのテナント間で同じインデックスを共有しながら、テナントのデータ分離を維持するプールデータパーティショニングのモデルが実現されます。このパターンでは、 AWS Amazon API Gateway、Amazon Simple Storage Service (Amazon S3) AWS Lambda、OpenSearch Service の各サービスを使用します。

プールモデルとその他のデータパーティショニングモデルの詳細については、「[追加情報](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)」セクションを参照してください。

## 前提条件と制限事項
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-prereqs"></a>

**前提条件**
+ アクティブな AWS アカウント
+ [AWS Command Line Interface (AWS CLI) バージョン 2.x](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)、macOS、Linux、または Windows にインストールおよび設定
+ [Python バージョン 3.9](https://www.python.org/downloads/release/python-3921/)
+ [pip3](https://pip.pypa.io/en/stable/) — Python ソースコードは .zip ファイルとして提供され、Lambda 関数にデプロイされます。コードをローカルで使用またはカスタマイズする場合は、次の手順に従ってソースコードを開発して再コンパイルします。

  1. Python スクリプトと同じディレクトリでコマンド `pip3 freeze > requirements.txt` を実行して `requirements.txt` ファイルを生成します。

  1. 依存関係 `pip3 install -r requirements.txt` をインストールします。

**制限事項**
+ このコードは Python で実行され、現在、他のプログラミング言語はサポートされていません。 
+ サンプルアプリケーションには、 AWS クロスリージョンまたはディザスタリカバリ (DR) サポートは含まれません。 
+ このパターンは、デモンストレーションのみを目的としています。実稼働環境では使用しないでください。

## アーキテクチャ
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-architecture"></a>

以下の図に、このパターンのアーキテクチャについて概要を示します。このアーキテクチャには、以下の項目が含まれます。
+ コンテンツのインデックス作成とクエリを実行する Lambda 
+ 検索を実行する OpenSearch Service 
+ ユーザーとの API インタラクションを提供する API Gateway
+ (インデックスが付いていない) 未処理のデータを保存するための Amazon S3
+ ログをモニタリングする Amazon CloudWatch
+ AWS Identity and Access Management テナントロールとポリシーを作成するための (IAM)

![高レベルのマルチテナントのサーバーレスアーキテクチャ](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/1a8501e7-0776-4aca-aed3-28e3ada1d15d.png)


**自動化とスケール**

わかりやすく AWS CLI するために、このパターンでは を使用してインフラストラクチャをプロビジョニングし、サンプルコードをデプロイします。 CloudFormation テンプレートまたは AWS Cloud Development Kit (AWS CDK) スクリプトを作成して、パターンを自動化できます。

## ツール
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-tools"></a>

**AWS のサービス**
+ [AWS CLI](https://aws.amazon.com/cli/) は、コマンドラインシェルでコマンドを使用して AWS のサービス および リソースを管理するための統合ツールです。
+ [Lambda](https://aws.amazon.com/lambda/) はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。Lambda は必要に応じてコードを実行し、1 日あたり数個のリクエストから 1 秒あたり数千のリクエストまで自動的にスケールします。
+ [API Gateway](https://aws.amazon.com/api-gateway/) は、REST、HTTP、WebSocket APIsで作成、公開、保守、モニタリング、保護 AWS のサービス するための です。
+ [Amazon S3](https://aws.amazon.com/s3/) は、ウェブ上のどこからでも、任意の量のデータをいつでも保存して取得できるようにするオブジェクトストレージサービスです。
+ [OpenSearch Service](https://aws.amazon.com/opensearch-service/) は、大規模かつコスト効率の高い方法で、Elasticsearch のデプロイ、セキュリティ保護、実行を簡単に行えるフルマネージドサービスです。

**コード**

添付ファイルには、このパターンのサンプルが記載されています。具体的には次のとおりです。
+ `index_lambda_package.zip` — プールモデルを使用して OpenSearch Service のデータにインデックスを付けるための Lambda 関数。
+ `search_lambda_package.zip` — OpenSearch Service 内のデータを検索するための Lambda 関数。
+ `Tenant-1-data` — Tenant-1 の (インデックスが付いていない) 未処理のデータをサンプリングします。
+ `Tenant-2-data` — Tenant-2 の (インデックスが付いていない) 未処理のデータをサンプリングします。

**重要**  
このパターンのストーリーには、Unix、Linux、macOS 用にフォーマットされた AWS CLI コマンド例が含まれています。Windows の場合は、各行末のバックスラッシュ (\\) Unix 連結文字をキャレット (^) に置き換えてください。

**注記**  
 AWS CLI コマンドで、角括弧 (<>) 内のすべての値を正しい値に置き換えます。

## エピック
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-epics"></a>

### S3 バケットの作成と設定
<a name="create-and-configure-an-s3-bucket"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| S3 バケットを作成する。 | に S3 バケットを作成します AWS リージョン。このバケットには、インデックスが付いていないサンプルアプリケーションのテナントデータが格納されます。　 名前空間はすべての によって共有されるため、S3 バケットの名前がグローバルに一意であることを確認してください AWS アカウント。<br />S3 バケットを作成するには、次のように AWS CLI [create-bucket](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-bucket.html) コマンドを使用します。<pre>aws s3api create-bucket \<br />  --bucket <tenantrawdata> \<br />  --region <your-AWS-Region></pre><br />`tenantrawdata` は S3 バケット名です。(「[バケット命名ガイドライン](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)」に従った任意の一意の名前を使用できます)。 | クラウドアーキテクト、クラウド管理者 | 

### Elasticsearch クラスターの作成と設定
<a name="create-and-configure-an-elasticsearch-cluster"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| OpenSearch Service ドメインを作成します。 |  AWS CLI [create-elasticsearch-domain](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/es/create-elasticsearch-domain.html) コマンドを実行して、OpenSearch Service ドメインを作成します。<pre>aws es create-elasticsearch-domain \<br />  --domain-name vpc-cli-example \<br />  --elasticsearch-version 7.10 \<br />  --elasticsearch-cluster-config InstanceType=t3.medium.elasticsearch,InstanceCount=1 \<br />  --ebs-options EBSEnabled=true,VolumeType=gp2,VolumeSize=10 \<br />  --domain-endpoint-options "{\"EnforceHTTPS\": true}" \<br />  --encryption-at-rest-options "{\"Enabled\": true}" \<br />  --node-to-node-encryption-options "{\"Enabled\": true}" \<br />  --advanced-security-options "{\"Enabled\": true, \"InternalUserDatabaseEnabled\": true, \<br />    \"MasterUserOptions\": {\"MasterUserName\": \"KibanaUser\", \<br />    \"MasterUserPassword\": \"NewKibanaPassword@123\"}}" \<br />  --vpc-options "{\"SubnetIds\": [\"<subnet-id>\"], \"SecurityGroupIds\": [\"<sg-id>\"]}" \<br />  --access-policies "{\"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \ <br />    \"Principal\": {\"AWS\": \"*\" }, \"Action\":\"es:*\", \<br />    \"Resource\": \"arn:aws:es:<region>:<account-id>:domain\/vpc-cli-example\/*\" } ] }"</pre><br />テスト用ドメインであるため、インスタンス数は 1 に設定されています。ドメインの作成後は、詳細を変更できないため、`advanced-security-options` パラメータを使用してきめ細かいアクセス制御を有効にする必要があります。 <br />このコマンドは、Kibana コンソールにログインできるマスターユーザー名 (`KibanaUser`) とパスワードを作成します。<br />このドメインは仮想プライベートクラウド (VPC) の一部であるため、使用するアクセスポリシーを指定して、必ず Elasticsearch インスタンスにアクセスする必要があります。<br />詳細については、 AWS ドキュメント[の「VPC 内での Amazon OpenSearch Service ドメインの起動](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)」を参照してください。 | クラウドアーキテクト、クラウド管理者 | 
| 踏み台ホストをセットアップします。 | Kibana コンソールにアクセスするための踏み台ホストとして、Amazon Elastic Compute Cloud (Amazon EC2) Windows インスタンスをセットアップします。Elasticsearch セキュリティグループは、Amazon EC2 セキュリティグループからのトラフィックを許可する必要があります。　 手順については、ブログ記事「[踏み台サーバーを使用して EC2 インスタンスへのネットワークアクセスを制御する](https://aws.amazon.com/blogs/security/controlling-network-access-to-ec2-instances-using-a-bastion-server/)」を参照してください。<br />踏み台ホストが設定され、インスタンスに関連付けられているセキュリティグループが使用可能になったら、 AWS CLI [authorize-security-group-ingress](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/authorize-security-group-ingress.html) コマンドを使用して Elasticsearch セキュリティグループにアクセス許可を追加して、Amazon EC2 (踏み台ホスト) セキュリティグループからのポート 443 を許可します。<pre>aws ec2 authorize-security-group-ingress \<br />  --group-id <SecurityGroupIdfElasticSearch> \ <br />  --protocol tcp \<br />  --port 443 \<br />  --source-group <SecurityGroupIdfBashionHostEC2></pre> | クラウドアーキテクト、クラウド管理者 | 

### Lambda 関数の作成と設定
<a name="create-and-configure-the-lam-index-function"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| Lambda 実行ロールを作成する |  AWS CLI [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) コマンドを実行して、Lambda インデックス関数に AWS のサービス および リソースへのアクセスを許可します。<pre>aws iam create-role \<br />  --role-name index-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre><br />ここで、`lambda_assume_role.json` は JSON ドキュメントで、以下のように Lambda 関数に `AssumeRole` 権限を付与します。<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | クラウドアーキテクト、クラウド管理者 | 
| マネージドポリシーを Lambda ロールにアタッチする |  AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) コマンドを実行して、前のステップで作成したロールに管理ポリシーをアタッチします。これらの 2 つのポリシーは、Elastic Network Interface を作成し、CloudWatch Logs にログを書き込む権限をロールに与えます。<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | クラウドアーキテクト、クラウド管理者 | 
| Lambda インデックス関数に、S3 オブジェクトの読み取り権限を与えるポリシーを作成する |  AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) コマンドを に実行して、Lambda インデックス関数に S3 バケット内のオブジェクトを読み取る`s3:GetObject`アクセス許可を付与します。<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3-policy.json</pre><br />ファイル `s3-policy.json` は次に示す JSON ドキュメントで、S3 オブジェクトへの読み取りアクセスを許可する `s3:GetObject` 権限を付与します。S3 バケットを作成するときに別の名前を使用した場合は、`Resource ` セクションで正しいバケット名を指定します。<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />           "Effect": "Allow",<br />           "Action": "s3:GetObject",<br />           "Resource": "arn:aws:s3:::<tenantrawdata>/*"<br />        }<br />    ]<br />}</pre> | クラウドアーキテクト、クラウド管理者 | 
| Amazon S3 のアクセス許可ポリシーを Lambda 実行ロールにアタッチする |  AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) コマンドを実行して、前のステップで作成した Amazon S3 アクセス許可ポリシーを Lambda 実行ロールにアタッチします。<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn <PolicyARN></pre><br />ここで、`PolicyARN` は Amazon S3 のアクセス許可ポリシーの Amazon リソースネーム (ARN) です。前のコマンド出力からこの値を取得できます。 | クラウドアーキテクト、クラウド管理者 | 
| Lambda インデックス関数の作成 |  AWS CLI [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) コマンドを実行して、OpenSearch Service にアクセスする Lambda インデックス関数を作成します。<pre>aws lambda create-function \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip \<br />  --handler lambda_index.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/index-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | クラウドアーキテクト、クラウド管理者 | 
| Amazon S3 が Lambda インデックス関数を呼び出すことを許可する |  AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) コマンドを実行して、Lambda インデックス関数を呼び出すアクセス許可を Amazon S3 に付与します。<pre>aws lambda add-permission \<br />  --function-name index-lambda-function \<br />  --statement-id s3-permissions \<br />  --action lambda:InvokeFunction \<br />  --principal s3.amazonaws.com \<br />  --source-arn "arn:aws:s3:::<tenantrawdata>" \<br />  --source-account "<account-id>" </pre> | クラウドアーキテクト、クラウド管理者 | 
| Amazon S3 イベントの Lambda トリガーを追加する | Amazon S3 `ObjectCreated`イベントが検出されたときに Lambda インデックス関数 に通知を送信するには、 AWS CLI [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html) コマンドを実行します。インデックス関数は、オブジェクトが S3 バケットにアップロードされるたびに実行されます。　 <pre>aws s3api put-bucket-notification-configuration \<br />  --bucket <tenantrawdata> \<br />  --notification-configuration file://s3-trigger.json</pre><br />ファイル `s3-trigger.json` は現在のフォルダにある JSON ドキュメントで、Amazon S3 `ObjectCreated` イベントが発生したときにリソースポリシーを Lambda 関数に追加します。 | クラウドアーキテクト、クラウド管理者 | 

### Lambda 検索関数の作成と設定
<a name="create-and-configure-the-lam-search-function"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| Lambda 実行ロールを作成する |  AWS CLI [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) コマンドを実行して、Lambda 検索関数に AWS のサービス および リソースへのアクセスを許可します。<pre>aws iam create-role \<br />  --role-name search-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre><br />ここで、`lambda_assume_role.json` は現在フォルダ内にある JSON ドキュメントで、以下のように、Lambda 関数に `AssumeRole` の権限を付与します。<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | クラウドアーキテクト、クラウド管理者 | 
| マネージドポリシーを Lambda ロールにアタッチする |  AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) コマンドを実行して、前のステップで作成したロールに管理ポリシーをアタッチします。これらの 2 つのポリシーは、Elastic Network Interface を作成し、CloudWatch Logs にログを書き込む権限をロールに与えます。<pre>aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | クラウドアーキテクト、クラウド管理者 | 
| Lambda 検索関数を作成する |  AWS CLI [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) コマンドを実行して、OpenSearch Service にアクセスする Lambda 検索関数を作成します。<pre>aws lambda create-function \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip \<br />  --handler lambda_search.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/search-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | クラウドアーキテクト、クラウド管理者 | 

### IAM ロールを作成および設定
<a name="create-and-configure-tenant-roles"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| テナントの IAM ロールを作成する |  AWS CLI [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) コマンドを実行して、検索機能のテストに使用される 2 つのテナントロールを作成します。<pre>aws iam create-role \<br />  --role-name Tenant-1-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre><pre>aws iam create-role \<br />  --role-name Tenant-2-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre><br />この `assume-role-policy.json` ファイルは、現在のフォルダ内にある JSON ドキュメントで、Lambda 実行ロールに `AssumeRole` のアクセス権限を付与します。<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Principal": {<br />                 "AWS": "<Lambda execution role for index function>",<br />                 "AWS": "<Lambda execution role for search function>"<br />             },<br />            "Action": "sts:AssumeRole"<br />        }<br />    ]<br />}</pre> | クラウドアーキテクト、クラウド管理者 | 
| 新規 IAM ポリシーを作成する |  AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) コマンドを実行して、Elasticsearch オペレーションへのアクセスを許可するテナントポリシーを作成します。<pre>aws iam create-policy \<br />  --policy-name tenant-policy \<br />  --policy-document file://policy.json</pre><br />この `policy.json` ファイルは、現在のフォルダ内の JSON ドキュメントで、Elasticsearch にアクセス権限を付与します。<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": [<br />                "es:ESHttpDelete",<br />                "es:ESHttpGet",<br />                "es:ESHttpHead",<br />                "es:ESHttpPost",<br />                "es:ESHttpPut",<br />                "es:ESHttpPatch"<br />            ],<br />            "Resource": [<br />                "<ARN of Elasticsearch domain created earlier>"<br />            ]<br />        }<br />    ]<br />}</pre> | クラウドアーキテクト、クラウド管理者 | 
| テナント IAM ポリシーをテナントロールにアタッチする |  AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) コマンドを実行して、前のステップで作成した 2 つのテナントロールにテナント IAM ポリシーをアタッチします。<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-1-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-2-role</pre><br />ポリシー ARN は、前のステップの出力から取得されます。 | クラウドアーキテクト、クラウド管理者 | 
| Lambda にロールを引き受ける権限を付与する IAM ポリシーを作成する |  AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) コマンドを実行して、Lambda がテナントロールを引き受けるためのポリシーを作成します。<pre>aws iam create-policy \<br />  --policy-name assume-tenant-role-policy \<br />  --policy-document file://lambda_policy.json</pre><br />この `lambda_policy.json` ファイルは、現在のフォルダ内にある JSON ドキュメントで、`AssumeRole` にアクセス権限を付与します。<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />       {<br />            "Effect": "Allow",<br />            "Action":  "sts:AssumeRole",<br />            "Resource": "<ARN of tenant role created earlier>"<br />       }<br />    ]<br />}</pre><br />`Resource` には、ワイルドカード文字を使用すると、テナントごとに新しいポリシーを作成する必要がなくなります。 | クラウドアーキテクト、クラウド管理者 | 
| Lambda インデックスロールに Amazon S3 へのアクセスを許可する IAM ポリシーを作成する |  AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) コマンドを実行して、Lambda インデックスロールに S3 バケット内のオブジェクトにアクセスするアクセス許可を付与します。<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3_lambda_policy.json</pre><br />この `s3_lambda_policy.json` ファイルは、現在のフォルダ内にある JSON ポリシードキュメントです。<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": "s3:GetObject",<br />            "Resource": "arn:aws:s3:::tenantrawdata/*"<br />        }<br />    ]<br />}</pre> | クラウドアーキテクト、クラウド管理者 | 
| ポリシーを Lambda 実行ロールにアタッチする |  AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) コマンドを実行して、前のステップで作成したポリシーを、前に作成した Lambda インデックスと検索実行ロールにアタッチします。<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name index-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name search-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/s3-permission-policy \<br />  --role-name index-lambda-role</pre><br />ポリシー ARN は、前のステップの出力から取得されます。 | クラウドアーキテクト、クラウド管理者 | 

### 検索ドメインを作成して設定する
<a name="create-and-configure-a-search-api"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| API ゲートウェイで REST API を作成する |  AWS CLI [create-rest-api](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-rest-api.html) コマンドを実行して REST API リソースを作成します。<pre>aws apigateway create-rest-api \<br />  --name Test-Api \<br />  --endpoint-configuration "{ \"types\": [\"REGIONAL\"] }"</pre><br />エンドポイント設定タイプでは、`REGIONAL` ではなく `EDGE` を指定して、特定の AWS リージョンではなくエッジロケーションを使用できます。<br />コマンド出力の `id` フィールドの値に注目してください。これは、以降のコマンドで使用する API ID です。 | クラウドアーキテクト、クラウド管理者 | 
| API リソースの検索を作成する | API リソースを検索し、Lambda 検索関数をリソース名 `search` で起動します。(Lambda インデックス関数の API は、オブジェクトが S3 バケットにアップロードされると自動的に実行されるため、作成する必要はありません)。[See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | クラウドアーキテクト、クラウド管理者 | 
| 検索 API の GET メソッドを作成する |  AWS CLI [put-method](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method.html) コマンドを実行して、検索 API の`GET `メソッドを作成します。<pre>aws apigateway put-method \<br />  --rest-api-id <API-ID> \<br />  --resource-id <ID from the previous command output> \<br />  --http-method GET \<br />  --authorization-type "NONE" \<br />  --no-api-key-required</pre><br />`resource-id` では、`create-resource` コマンドの ID を指定します。 | クラウドアーキテクト、クラウド管理者 | 
| 検索 API のメソッドレスポンスを作成する |  AWS CLI [put-method-response](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method-response.html) コマンドを実行して、検索 API のメソッドレスポンスを追加します。<pre>aws apigateway put-method-response \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --status-code 200 \<br />  --response-models "{\"application/json\": \"Empty\"}"</pre><br />`resource-id` には、前の `create-resource` コマンドから出力された ID を指定します。 | クラウドアーキテクト、クラウド管理者 | 
| 検索 API のプロキシ Lambda 統合を設定する |  AWS CLI [put-integration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-integration.html) コマンドを実行して、Lambda 検索関数との統合を設定します。<pre>aws apigateway put-integration \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --type AWS_PROXY \<br />  --integration-http-method GET \<br />  --uri arn:aws:apigateway:region:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account-id>:function:<function-name>/invocations</pre><br />`resource-id` では、前の `create-resource` コマンドの ID を指定します。 | クラウドアーキテクト、クラウド管理者 | 
| API ゲートウェイに Lambda 検索関数を呼び出す権限を付与する |  AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) コマンドを実行して、検索関数を使用するためのアクセス許可を API Gateway に付与します。<pre>aws lambda add-permission \<br />  --function-name <function-name> \<br />  --statement-id apigateway-get \<br />  --action lambda:InvokeFunction \<br />  --principal apigateway.amazonaws.com \<br />  --source-arn "arn:aws:execute-api:<region>:<account-id>:api-id/*/GET/search</pre><br />`search` ではなく別の API リソース名を使用している場合は、`source-arn` パスを変更します。 | クラウドアーキテクト、クラウド管理者 | 
| 検索 API をデプロイする |  AWS CLI [create-deployment](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-deployment.html) コマンドを実行して、 という名前のステージリソースを作成します`dev`。<pre>aws apigateway create-deployment \<br />  --rest-api-id <API-ID> \<br />  --stage-name dev</pre><br />API を更新する場合は、同じ AWS CLI コマンドを使用して同じステージに再デプロイできます。 | クラウドアーキテクト、クラウド管理者 | 

### Kibana ロールの作成と設定
<a name="create-and-configure-kibana-roles"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| Kibana コンソールにログインする | [See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | クラウドアーキテクト、クラウド管理者 | 
| Kibana ロールの作成と設定 | データを隔離し、あるテナントが別のテナントのデータを取得できないようにするには、ドキュメントセキュリティを使用する必要があります。ドキュメントセキュリティを使用すると、テナントがテナント ID を含むドキュメントのみにアクセスできるようになります。[See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | クラウドアーキテクト、クラウド管理者 | 
| ユーザーをロールにマッピングします。 | [See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)テナントのオンボーディング時に、テナントロールと Kibana ロールの作成を自動化することをお勧めします。 | クラウドアーキテクト、クラウド管理者 | 
| テナント-データ インデックスを作成します。 | ナビゲーションペインの **[管理]** で **[開発ツール]** を選択し、次のコマンドを実行します。このコマンドは、`TenantId` プロパティのマッピングを定義する `tenant-data` インデックスを作成します。<pre>PUT /tenant-data<br />{<br />  "mappings": {<br />    "properties": {<br />      "TenantId": { "type": "keyword"}<br />    }<br />  }<br />}</pre> | クラウドアーキテクト、クラウド管理者 | 

### Amazon S3 と の VPC エンドポイントを作成する AWS STS
<a name="create-vpc-endpoints-for-s3-and-sts"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| Amazon S3 の VPC エンドポイントを作成する |  AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) コマンドを実行して、Amazon S3 の VPC エンドポイントを作成します。エンドポイントにより、VPC の Lambda インデックス関数が Amazon S3 にアクセスできるようになります。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --service-name com.amazonaws.us-east-1.s3 \<br />  --route-table-ids <route-table-ID></pre><br />`vpc-id` には、Lambda インデックス関数に使用している VPC を指定します。`service-name` には、Amazon S3 エンドポイントの正しい URL を使用します。`route-table-ids` には、VPC エンドポイントに関連付けられているルートテーブルを指定します。 | クラウドアーキテクト、クラウド管理者 | 
| の VPC エンドポイントを作成します AWS STS。 |  AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) コマンドを実行して、 AWS Security Token Service () の VPC エンドポイントを作成しますAWS STS。エンドポイントにより、VPC の Lambda インデックス関数と Lambda 検索関数が AWS STSにアクセスできるようになります。関数は、IAM ロールを引き受ける AWS STS ときに を使用します。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --vpc-endpoint-type Interface \<br />  --service-name com.amazonaws.us-east-1.sts \<br />  --subnet-id <subnet-ID> \<br />  --security-group-id <security-group-ID></pre><br />`vpc-id` には、Lambda インデックス関数と Lambda 検索関数に使用している VPC を指定します。`subnet-id` には、このエンドポイントを作成するサブネットを指定します。`security-group-id` には、このエンドポイントを関連付けるセキュリティグループを指定します。(Lambda が使用するセキュリティグループと同じである可能性があります)。　 | クラウドアーキテクト、クラウド管理者 | 

### マルチテナンシーとデータ隔離のテスト
<a name="test-multi-tenancy-and-data-isolation"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| インデックス関数と検索関数の Python ファイルを更新する | [See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)Elasticsearch エンドポイントは OpenSearch Service コンソールの **[概要]** タブから取得できます。これは、`<AWS-Region>.es.amazonaws.com` という形式です。 | クラウドアーキテクト、アプリ開発者 | 
| Lambda コードを作成する | Python ファイルに加えた変更で Lambda コードを更新するには、 AWS CLI [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) コマンドを使用します。<pre>aws lambda update-function-code \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip<br /><br />aws lambda update-function-code \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip</pre> | クラウドアーキテクト、アプリ開発者 | 
| S3 バケットに未処理のデータをアップロードする | Tenant-1 および Tenant-2 オブジェクトのデータを`tenantrawdata`バケットにアップロードするには、 AWS CLI [cp](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html) コマンドを使用します (この目的のために作成した S3 バケットの名前を指定します）。<pre>aws s3 cp tenant-1-data s3://tenantrawdata<br />aws s3 cp tenant-2-data s3://tenantrawdata</pre><br />S3 バケットは、データがアップロードされるたびに Lambda インデックス関数を実行するように設定されているため、ドキュメントには Elasticsearch でインデックスが付けられます。 | クラウドアーキテクト、クラウド管理者 | 
| Kibana コンソールからデータを検索する | Kibana コンソールで、以下のクエリを実行します。<pre>GET tenant-data/_search</pre><br />このクエリは、Elasticsearch でインデックスに登録されているすべてのドキュメントを表示します。この場合、Tenant-1 と Tenant-2 の 2 つのドキュメントが別々に表示されます。 | クラウドアーキテクト、クラウド管理者 | 
| API ゲートウェイ から検索 API をテストする | [See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)画面の図については、「[追加情報](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)」セクションを参照してください。 | クラウドアーキテクト、アプリ開発者 | 
| リソースをクリーンアップします。 | アカウントへの追加料金が発生しないように、作成したすべてのリソースをクリーンアップします。 | AWS DevOps、クラウドアーキテクト、クラウド管理者 | 

## 関連リソース
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-resources"></a>
+ [AWS SDK for Python (Boto)](https://aws.amazon.com/sdk-for-python/)
+ [AWS Lambda ドキュメント](https://docs.aws.amazon.com/lambda/)
+ [API Gateway ドキュメント](https://docs.aws.amazon.com/apigateway/)
+ 「[Amazon S3 ドキュメント](https://docs.aws.amazon.com/s3/)」
+ 「[Amazon OpenSearch Service](https://docs.aws.amazon.com/elasticsearch-service/)」
  + 「[Amazon OpenSearch Service のきめ細かなアクセスコントロール](https://docs.amazonaws.cn/en_us/elasticsearch-service/latest/developerguide/fgac.html)」
  + 「[Amazon OpenSearch Service を用いて検索アプリケーションを作成する](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/search-example.html)」
  + 「[VPC 内で Amazon OpenSearch Service ドメインを起動する](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)」

## 追加情報
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional"></a>

**データパーティショニングのモデル**

マルチテナントシステムで使用される一般的なデータパーティショニングモデルには、サイロ、プール、ハイブリッドの 3 つがあります。選択するモデルは、環境のコンプライアンス、ノイジーネイバー、運用、隔離の要件によって異なります。

サイロモデル

サイロモデルでは、各テナントのデータをテナントデータが混在しない個別のストレージエリアに保存します。OpenSearch Service のサイロモデルを実装するには、「テナントごとのドメイン」と「テナントごとのインデックス」という 2 つの方法があります。
+ **テナントごとのドメイン** — テナントごとに個別の OpenSearch Service ドメイン (Elasticsearch クラスターと同義) を使用できます。各テナントを独自のドメインに配置することで、データをスタンドアロンコンストラクトに配置することに関連するすべてのメリットが得られます。しかし、このアプローチでは、管理とアジリティの面で課題が生じています。隔離型であるため、テナントの運営状況や活動を集計して評価することが難しくなっています。これはコストのかかるオプションであり、各 OpenSearch Service ドメインには、実稼働環境のワークロード用に最低でも 3 つのマスターノードと 2 つのデータノードが必要です。

![マルチテナントのサーバーレスアーキテクチャのための「テナントごとのドメイン」サイロモデル](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2195f82-e5ed-40bb-b76a-3b0210bf1254.png)


 
+ **テナントごとのインデックス** — OpenSearch Service クラスター内の個別のインデックスにテナントデータを配置できます。このアプローチでは、テナント識別子をインデックス名にあらかじめ付けておくことで、インデックスを作成して名前を付けるときにテナント識別子を使用できます。テナントごとにインデックスを付けるアプローチでは、テナントごとに完全に分離したクラスターを導入しなくても、サイロの目標を達成できます。　 しかし、インデックスの数が増えると、このアプローチではより多くのシャードが必要になり、マスターノードがより多くの割り当てとリバランスを処理する必要があるため、メモリの負荷がかかる可能性があります。

![マルチテナントのサーバーレスアーキテクチャのための「テナントごとのインデックス」サイロモデル](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/354a9463-25bb-422b-84de-d4875a7c8ea2.png)


 

**サイロモデルでの隔離** — サイロモデルでは、IAM ポリシーを使用して、各テナントのデータを保持するドメインまたはインデックスを隔離します。これらのポリシーは、あるテナントが別のテナントのデータにアクセスすることを防止します。サイロ隔離モデルを実装するには、テナントリソースへのアクセスを制御するリソースベースのポリシーを作成できます。通常、これはドメインアクセスポリシーで、Elasticsearch インデックスや API など、プリンシパルがドメインのサブリソースに対して実行できるアクションを指定します。IAM アイデンティティベースのポリシーでは、OpenSearch Service 内のドメイン、インデックス、または API に対して*許可*または*拒否する*アクションを指定できます。IAM ポリシーの `Action` 要素は、ポリシーによって許可または拒否される特定のアクションを記述し、`Principal ` 要素は、影響を受けるアカウント、ユーザー、またはロールを指定します。

以下のサンプルポリシーは、`es:*` で指定された `tenant-1` ドメイン上のサブリソースへの完全なアクセス権を Tenant-1 にのみ付与します。`Resource` 要素の末尾に付いた `/*` は重要であり、このポリシーがドメイン自体ではなく、ドメインのサブリソースに適用されることを示します。このポリシーが有効な場合、テナントは新しいドメインの作成や、既存のドメイン設定を変更できません

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::<aws-account-id>:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/tenant-1/*"
      }
   ]
}
```

「インデックスごとのテナント」サイロモデルを実装するには、このサンプルポリシーを変更して、インデックス名を指定することで、Tenant-1 を指定された 1 つ以上のインデックスにさらに制限する必要があります。次のサンプルポリシーでは、Tenant-1 を `tenant-index-1` インデックスに制限しています。 

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::123456789012:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/test-domain/tenant-index-1/*"
      }
   ]
}
```

*プールモデル*

プールモデルでは、すべてのテナントデータが同じドメイン内のインデックスに保存されます。　 テナント識別子はデータ (ドキュメント) に含まれ、パーティションキーとして使用されるため、どのデータがどのテナントに属しているか判断できます。このモデルでは、管理オーバーヘッドが削減されます。プールインデックスの操作と管理は、複数のインデックスを管理するよりも容易で効率的です。しかし、テナントデータが同じインデックスに混在しているため、サイロモデルが提供する自然なテナント隔離が失われます。このアプローチでは、ノイジーネイバー効果によりパフォーマンスが低下する可能性もあります。

![マルチテナントのサーバーレスアーキテクチャのためのプールモデル](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2c3bb0f-6ccd-47a7-ab67-e7f3f8c7f289.png)


 

**プールモデルでのテナント隔離** — 一般的に、テナント隔離をプールモデルに実装するのは困難です。サイロモデルで使用されている IAM メカニズムでは、ドキュメントに保存されているテナント ID に基づいて隔離を記述することはできません。

代わりに、Open Distro for Elasticsearch で提供される[きめ細かなアクセス制御](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/fgac.html) (FGAC) サポートを使用する方法があります。FGAC では、インデックス、ドキュメント、またはフィールドレベルでアクセス許可を制御できます。　 FGAC は、リクエストごとに、ユーザーの認証情報を評価し、ユーザーを認証するか、アクセスを拒否します。FGAC がユーザーを認証すると、そのユーザーにマッピングされているすべてのロールを取得し、アクセス許可のセット一式を使用してリクエストの処理方法を決定します。 

プールされたモデルで必要な隔離を実現するには、「[ドキュメントレベルのセキュリティ](https://opendistro.github.io/for-elasticsearch-docs/docs/security/access-control/document-level-security/)」を使用できます。これにより、ロールをインデックス内のドキュメントのサブセットに制限できます。以下のサンプルロールは、クエリを Tenant-1 に制限します。このロールを Tenant-1 に適用することで、必要な隔離を実現できます。　 

```
{
   "bool": {
     "must": {
       "match": {
         "tenantId": "Tenant-1"
       }
     }
   }
 }
```

*ハイブリッドモデル*

ハイブリッドモデルでは、同じ環境でサイロモデルとプールモデルを組み合わせて、各テナントレイヤー (無料、標準、プレミアム階層など) に独自のエクスペリエンスを提供します。各層は、プールモデルで使用されているのと同じセキュリティプロファイルに従います。

 

![マルチテナントのサーバーレスアーキテクチャのためのハイブリッドモデル](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/e7def98a-38ef-435a-9881-7e95ae4d4940.png)


**ハイブリッドモデルでのテナント隔離** — ハイブリッドモデルでは、ドキュメントレベルで FGAC セキュリティモデルを使用することでテナントを隔離できるプールモデルと同じセキュリティプロファイルに従います。この戦略はクラスター管理を簡素化し、アジリティを提供しますが、アーキテクチャの他の側面が複雑になります。例えば、どのモデルを各テナントに関連付けるか決めるには、コードをさらに複雑化する必要があります。また、単一テナントのクエリによってドメイン全体が飽和状態になり、他のテナントのエクスペリエンスが低下しないようにする必要があります。 

**API ゲートウェイでのテスト**

*Tenant-1 クエリのテストウィンドウ*

![Tenant-1 クエリのテストウィンドウ](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/a6757d3f-977a-4ecc-90cb-83ab7f1c3588.png)


Tenant-2 クエリのテストウィンドウ

 

![Tenant-2 クエリのテストウィンドウ](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/31bfd656-33ca-4750-b6e6-da4d703c2071.png)


## アタッチメント
<a name="attachments-750196bb-03f6-4b6e-92cd-eb7141602547"></a>

このドキュメントに関連付けられている追加のコンテンツにアクセスするには、添付ファイルをダウンロードして解凍します。[zip](samples/p-attach/750196bb-03f6-4b6e-92cd-eb7141602547/attachments/attachment.zip)