GraphQL API を保護するための認可と認証の設定 - AWS AppSync

GraphQL API を保護するための認可と認証の設定

AWS AppSync では、GraphQL APIを保護するため、API キー、Lambda、IAM、OpenID Connect、および Cognito ユーザープールの認可タイプが用意されています。各オプションは、異なるセキュリティ方法を提供します。

  1. API キー認可: 認証されていない API のスロットリングを制御し、シンプルなセキュリティオプションを提供します。

  2. Lambda 認可: 関数の入力と出力を詳細に説明するカスタム認可ロジックを有効にします。

  3. IAM 認可: AWS の署名バージョン 4 の署名プロセスを使用し、IAM ポリシーによるきめ細かなアクセスコントロールを可能にします。

  4. OpenID Connect 認可: ユーザー認証のために OIDC 準拠のサービスと統合します。

  5. Cognito ユーザープール: Cognito のユーザー管理機能を使用して、グループベースのアクセスコントロールを実装します。

認可タイプ

AWS AppSync GraphQL API を操作するためにアプリケーションを認可するには、5 つの方法があります。AWS AppSync API または CLI コールで次のいずれかの認可タイプ値を指定することで、使用する認可タイプを指定します。

  • API_KEY

    API キーを使用する場合。

  • AWS_LAMBDA

    AWS Lambda 機能を使用する場合。

  • AWS_IAM

    AWS Identity and Access Management(IAM) アクセス許可を使用する場合。

  • OPENID_CONNECT

    OpenID Connect プロバイダーを使用する場合。

  • AMAZON_COGNITO_USER_POOLS

    Amazon Cognito ユーザープールを使用する場合。

これらの基本的な承認タイプは、ほとんどの開発者に有効です。より高度なユースケースでは、コンソール、CLI、AWS CloudFormation を使用してさらに承認モードを追加できます。追加の承認モード用に、AWS AppSync には上記の値 (API_KEYAWS_LAMBDAAWS_IAMOPENID_CONNECT、およびAMAZON_COGNITO_USER_POOLS) を受け取る承認タイプがあります。

メインまたはデフォルトの承認タイプとしてAPI_KEYAWS_LAMBDA、または AWS_IAM を指定した場合、それを追加の承認モードの 1 つとして再び指定することはできません。同様に、追加の承認モード間で API_KEYAWS_LAMBDA、または AWS_IAM を重複して使用することはできません。複数の Amazon Cognito ユーザープールと OpenID Connect プロバイダーを使用できます。ただし、デフォルトの承認モードと追加の承認モード間で Amazon Cognito ユーザープールまたは OpenID Connect プロバイダーを重複して使用することはできません。Amazon Cognito ユーザープールまたは OpenID Connect プロバイダーに異なる複数のクライアントを設定する場合、対応する正規表現を使用できます。

API_KEY 認可

認証されていない API は、認証された API よりも厳格なスロットリングが必要になります。認証されていない GraphQL エンドポイントに対してスロットリングを制御する方法の 1 つは API キーを使用します。API キーは、アプリケーションにハードコーディングされた値です。認証されていない GraphQL エンドポイントを作成するときに AWS AppSync サービスによって生成されます。コンソール、CLI、または AWS AppSync API リファレンスから API キーを更新できます。

Console
  1. AWS Management Console にサインインして、AppSync コンソールを開きます。

    1. API ダッシュボードで、GraphQL API を選択します。

    2. サイドバー[設定] を選択します。

  2. デフォルト認可モードで、API キー を選択します。

  3. [API キー] テーブルで、[API キーの追加] を選択します。

    新しい API キーがテーブルで生成されます。

    1. 古い API キーを削除するには、テーブル内で API キーを選択し、[削除] を選択します。

  4. ページの最下部で [保存] をクリックします。

CLI
  1. まだ AWS CLI へのアクセスを設定していない場合は、設定します。詳細については、「設定の基本」を参照してください。

  2. update-graphql-api コマンドを実行して GraphQL API オブジェクトを作成します。

    この特定のコマンドには次の 2 つのパラメータを入力する必要があります。

    1. GraphQL API の api-id

    2. API の新しい name。同じ name を使用できます。

    3. API_KEY となる authentication-type

    注記

    Region など、設定する必要のあるパラメータは他にもありますが、通常はデフォルトで CLI 設定値になります。

    コマンドの例は、次のようになります。

    aws appsync update-graphql-api --api-id abcdefghijklmnopqrstuvwxyz --name TestAPI --authentication-type API_KEY

    出力は CLI に返されます。以下に JSON の例を示します。

    { "graphqlApi": { "xrayEnabled": false, "name": "TestAPI", "authenticationType": "API_KEY", "tags": {}, "apiId": "abcdefghijklmnopqrstuvwxyz", "uris": { "GRAPHQL": "https://s8i3kk3ufhe9034ujnv73r513e.appsync-api.us-west-2.amazonaws.com/graphql", "REALTIME": "wss://s8i3kk3ufhe9034ujnv73r513e.appsync-realtime-api.us-west-2.amazonaws.com/graphql" }, "arn": "arn:aws:appsync:us-west-2:348581070237:apis/abcdefghijklmnopqrstuvwxyz" } }

API キーは、最大 365 日間有効に設定可能で、該当日からさらに最大 365 日、既存の有効期限を延長できます。API キーは、パブリック API の公開が安全であるユースケース、または開発目的での使用が推奨されます。

クライアントでは、API キーをヘッダー x-api-key で指定します。

たとえば、API_KEY'ABC123' である場合、次のように curl 経由で GraphQL クエリを送信できます。

$ curl -XPOST -H "Content-Type:application/graphql" -H "x-api-key:ABC123" -d '{ "query": "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql

AWS_LAMBDA 認可

AWS Lambda 機能を使用して、独自の API 認可ロジックを実装できます。Lambda 関数をプライマリオーソライザーまたはセカンダリオーソライザーに使用できますが、API ごとに Lambda 認可関数は 1 つしかありません。Lambda 関数を認可に使用する場合、次のことが適用されます。

  • API で AWS_LAMBDA および AWS_IAM 認可モードが有効になっている場合、SigV4 署名を AWS_LAMBDA 認可トークンとして使用することはできません。

  • API で AWS_LAMBDA および OPENID_CONNECT 認可モードまたは AMAZON_COGNITO_USER_POOLS 認可モードが有効になっている場合、OIDC 署名を AWS_LAMBDA 認可トークンとして使用することはできません。OIDC トークンはベアラースキームにすることができます。

  • Lambda 関数は、リゾルバーに対して 5MB を超えるコンテキストデータを返してはいけません。

例えば、認可トークン が 'ABC123' である場合、次のように curl 経由で GraphQL クエリを送信できます。

$ curl -XPOST -H "Content-Type:application/graphql" -H "Authorization:ABC123" -d '{ "query": "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql

Lambda 関数は、各クエリまたはミューテーションの前に呼び出されます。戻り値は API ID と認証トークンに基づいてキャッシュできます。デフォルトでは、キャッシュは有効になっていませんが、これは API レベルで、または関数の戻り値の ttlOverride の値を設定することで有効にすることができます。

必要に応じて、関数が呼び出される前に認可トークンを検証する正規表現を指定できます。これらの正規表現は、関数が呼び出される前に、認可トークンが正しい形式であることを検証するために使用されます。この正規表現と一致しないトークンを使用したリクエストは、自動的に拒否されます。

認可に使用する Lambda 関数には、appsync.amazonaws.com がその Lambda 関数を呼び出すのを許可するために適用される AWS AppSync 用のプリンシパルポリシーが必要です。この操作は、AWS AppSync コンソールで自動的におこなわれます。AWS AppSync コンソールはポリシーを削除しません。Lambda 関数へのポリシーの添付に関する詳細については、AWS Lambdaデベロッパーガイドの「リソースベースのポリシー」を参照ください。

指定した Lambda 関数は次の形状のイベントを受け取ります。

{ "authorizationToken": "ExampleAUTHtoken123123123", "requestContext": { "apiId": "aaaaaa123123123example123", "accountId": "111122223333", "requestId": "f4081827-1111-4444-5555-5cf4695f339f", "queryString": "mutation CreateEvent {...}\n\nquery MyQuery {...}\n", "operationName": "MyQuery", "variables": {} } "requestHeaders": { application request headers } }

event オブジェクトには、アプリケーションクライアントから AWS AppSync にリクエストで送信されたヘッダーが含まれています。

認可関数は少なくとも、リクエストが認可されたかどうかを示すブール型の isAuthorized を返す必要があります。AWS AppSync は、Lambda 認可関数から返される次のキーを認識します。

注記

WebSocket 接続オペレーションの requestContextoperationName の値は、AWS AppSync によって「DeepDish:Connect」に設定されます。

isAuthorized (boolean、必須)

GraphQL API への呼び出しをおこなうために authorizationToken の値が認証されるかどうかを示すブール値。

この値が true の場合、GraphQL API の実行が継続されます。この値が false の場合、UnauthorizedException が生成されます。

deniedFields (文字列のリスト、オプション)

リゾルバーから値が返された場合でも、そのリストは強制的に null に変更されます。

各項目は、arn:aws:appsync:us-east-1:111122223333:apis/GraphQLApiId/types/TypeName/fields/FieldName の形式、または TypeName.FieldName の短い形式の完全修飾フィールド ARN です。2 つの API が Lambda 関数のオーソライザーを共有し、2 つの API の間に共通の型とフィールドの間にあいまいさがある可能性がある場合は、完全な ARN 形式を使用する必要があります。

resolverContext (JSON オブジェクト、オプション)

リゾルバーテンプレート内の $ctx.identity.resolverContext として可視化されるJSON オブジェクト。たとえば、リゾルバーによって次の構造体が返されたとします。

{ "isAuthorized":true "resolverContext": { "banana":"very yellow", "apple":"very green" } }

リゾルバーテンプレート内の値 ctx.identity.resolverContext.apple は「very green」になります。resolverContext オブジェクト はキーと値のペアのみをサポートします。ネストされたキーはサポートされません。

警告

この JSON オブジェクトの合計サイズは 5 MB を超えないようにしてください。

ttlOverride (integer、オプション)

応答をキャッシュする秒数。値が返されない場合は、API からの値が使用されます。これが 0 の場合、応答はキャッシュされません。

Lambda オーソライザーのタイムアウトは 10 秒です。API のパフォーマンスをスケールするために、できるだけ短い時間で実行する関数を設計することをお勧めします。

複数 AWS AppSync API は単一の認証 Lambda 関数を共有できます。クロスアカウントオーソライザーの使用は許可されていません。

複数の API 間で認可関数を共有する場合は、短い形式のフィールド名 (typename.fieldname) が誤ってフィールドを隠すことがあります。deniedFields のフィールドを明確化するには、明確なフィールド ARN を arn:aws:appsync:region:accountId:apis/GraphQLApiId/types/typeName/fields/fieldName の形式で指定できます。

AWS AppSyncで Lambda 関数をデフォルトの認可モードとして追加するには、

Console
  1. AWS AppSync コンソールにログインして、更新する API に移動します。

  2. API の設定ページに移動します。

    API レベルの認可をAWS Lambdaに変更します。

  3. AWS リージョンと Lambda ARN を選択して API 呼び出しを承認します。

    注記

    適切なプリンシパルポリシーが自動的に追加され、AWS AppSync Lambda 関数を呼び出します。

  4. 必要に応じて、レスポンス TTL とトークン検証の正規表現を設定します。

AWS CLI
  1. 使用中の Lambda 関数に次のポリシーをアタッチします。

    aws lambda add-permission --function-name "my-function" --statement-id "appsync" --principal appsync.amazonaws.com --action lambda:InvokeFunction --output text
    重要

    関数のポリシーを単一の GraphQL API にロックする場合は、次のコマンドを実行できます。

    aws lambda add-permission --function-name “my-function” --statement-id “appsync” --principal appsync.amazonaws.com --action lambda:InvokeFunction --source-arn “<my AppSync API ARN>” --output text
  2. AWS AppSync API をアップデートして、指定された Lambda 関数 ARN をオーソライザーとして使用します。

    aws appsync update-graphql-api --api-id example2f0ur2oid7acexample --name exampleAPI --authentication-type AWS_LAMBDA --lambda-authorizer-config authorizerUri="arn:aws:lambda:us-east-2:111122223333:function:my-function"
    注記

    トークンの正規表現など、他の設定オプションを含めることもできます。

次の例では、Lambda 関数が AWS AppSync 認可メカニズムとして使用されたとき、その Lambda 関数が持つさまざまな認証状態および認証失敗状態を示しています。

def handler(event, context): # This is the authorization token passed by the client token = event.get('authorizationToken') # If a lambda authorizer throws an exception, it will be treated as unauthorized. if 'Fail' in token: raise Exception('Purposefully thrown exception in Lambda Authorizer.') if 'Authorized' in token and 'ReturnContext' in token: return { 'isAuthorized': True, 'resolverContext': { 'key': 'value' } } # Authorized with no f if 'Authorized' in token: return { 'isAuthorized': True } # Partial authorization if 'Partial' in token: return { 'isAuthorized': True, 'deniedFields':['user.favoriteColor'] } if 'NeverCache' in token: return { 'isAuthorized': True, 'ttlOverride': 0 } if 'Unauthorized' in token: return { 'isAuthorized': False } # if nothing is returned, then the authorization fails. return {}

SigV4 と OIDC トークンの認可制限を回避する

以下の方法を使用すると、特定の認可モードが有効になっている場合に SigV4 署名または OIDC トークンを Lambda 認可トークンとして使用できないという問題を回避できます。

AWS AppSync の API に対して AWS_IAM および AWS_LAMBDA 認可モードが有効になっているとき、SigV4 署名を Lambda 認可トークンとして使用する場合は、次の操作を行います。

  • 新しい Lambda 認可トークンを作成するには、SigV4 署名にランダムなサフィックスおよび/またはプレフィックスを追加します。

  • 元の SigV4 署名を取得するには、Lambda 認可トークンからランダムなプレフィックスおよび/またはサフィックスを削除して、Lambda 関数を更新します。次に、元の SigV4 署名を認証に使用します。

AWS AppSync の API に対して OPENID_CONNECT 認可モード、または AMAZON_COGNITO_USER_POOLS および AWS_LAMBDA 認可モードが有効になっているとき、OIDC トークンを Lambda 認可トークンとして使用する場合は、次の操作を行います。

  • 新しい Lambda 認可トークンを作成するには、OIDC トークンにランダムなサフィックスおよび/またはプレフィックスを追加します。Lambda 認可トークンにはベアラースキームプレフィックスを含めないでください。

  • 元の OIDC トークンを取得するには、Lambda 認可トークンからランダムなプレフィックスおよび/またはサフィックスを削除して、Lambda 関数を更新します。次に、元の OIDC トークンを認証に使用します。

AWS_IAM 認可

この承認タイプでは、GraphQL API に対して AWS 署名バージョン 4 署名プロセスを使用する必要があります。Identity and Access Management (IAM) アクセスポリシーをこの承認タイプに関連付けることができます。アクセスキー (アクセスキー ID とシークレットアクセスキーで構成) または Amazon Cognito フェデレーティッドアイデンティティによって提供される有効期限の短い、一時的な認証情報を使用して、アプリケーションでこの関連付けを活用します。

すべてのデータオペレーションを実行できるアクセス権限を持つロールが必要な場合。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "appsync:GraphQL" ], "Resource": [ "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/*" ] } ] }

AppSync コンソールのメイン API リストページから、使用する API の名前の直下で、YourGraphQLApiId を確認できます。CLI aws appsync list-graphql-apis を使用して取得することもできます。

特定の GraphQL オペレーションのみにアクセスを制限するには、ルートの QueryMutationSubscription の各フィールドに対してこれを実行します。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "appsync:GraphQL" ], "Resource": [ "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-1>", "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-2>", "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Mutation/fields/<Field-1>", "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Subscription/fields/<Field-1>" ] } ] }

たとえば、以下のスキーマがあり、すべての投稿を取得するアクセスを制限する場合。

schema { query: Query mutation: Mutation } type Query { posts:[Post!]! } type Mutation { addPost(id:ID!, title:String!):Post! }

ロール (Amazon Cognito ID プールなどにアタッチできる) に対応する IAM ポリシーは次のようになります。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "appsync:GraphQL" ], "Resource": [ "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/posts" ] } ] }

OPENID_CONNECT 認可

この認可タイプは、OIDC 準拠サービスによって提供される OpenID Connect (OIDC) トークンを適用します。アプリケーションは、アクセス制御に対して、使用する OIDC プロバイダーによって定義されたユーザーと権限を活用できます。

発行者 URL は、AWS AppSyncに指定する唯一の必須設定値です (https://auth.example.com など)。この URL に HTTPS 経由でアクセスできる必要があります。AWSAppSync は /.well-known/openid-configuration を発行者 URL に追加し、https://auth.example.com/.well-known/openid-configuration (OpenID Connect Discovery 仕様ごとに) にある OpenID 設定を見つけます。この URL で RFC5785 準拠の JSON ドキュメントを取得するものとします。この JSON ドキュメントに jwks_uri キーが含まれている必要があります。これは JWKS JSON Web キー (JWKS) ドキュメントと署名キーを指します。AWS AppSync では kty および kid の JSON フィールドを含めるには、JWKS が必要です。

AWS AppSync では幅広い署名アルゴリズムをサポートしています。

署名アルゴリズム
RS256
RS384
RS512
PS256
PS384
PS512
HS256
HS384
HS512
ES256
ES384
ES512

RSA アルゴリズムを使用することをお勧めします。プロバイダーによって発行されたトークンに、トークンが発行された時刻 (iat) が含まれている必要があり、認証された時刻 (auth_time) が含まれる場合があります。発行時刻の TTL 値 (iatTTL) および認証時刻の TTL 値 (authTTL) を、追加の検証用に OpenID Connect 設定に入力できます。使用するプロバイダーが複数のアプリケーションを認可している場合は、クライアント ID で認可するために使用される正規表現を (clientId) も入力できます。clientId が OpenID Connect 構成に存在する場合、AWS AppSync は clientId に対してトークン内の aud または azp クレームと一致するように要求してクレームを検証します。

複数のクライアント ID を検証するには、正規表現で「or」であるパイプライン演算子 ("|") を使用します。例えば、OIDC アプリケーションに 4 つのクライアントがあり、そのクライアント ID が 0A1S2D、1F4G9H、1J6L4B、6GS5MG などである場合、最初の 3 つのクライアント ID のみを検証するには、クライアント ID フィールドに「1F4G9H|1J6L4B|6GS5MG」と入力します。

AMAZON_COGNITO_USER_POOLS 認可

この認可タイプでは、Amazon Cognito ユーザープールによって提供される OIDC トークンが使用されます。アプリケーションはさらに、ユーザープールおよび別の AWS アカウントからのユーザープール内のユーザーとグループを活用して、これらをアクセスをコントロールするための GraphQL フィールドに関連付けることができます。

Amazon Cognito ユーザープールを使用する場合、ユーザーが属するグループを作成できます。この情報は JWT トークンの中にエンコードされます。これはアプリケーションが、GraphQL オペレーションを送信するときに authorizaton ヘッダーで AWS AppSync に送信します。スキーマで GraphQL ディレクティブを使用して、フィールドでどのグループがどのリゾルバーを起動できるのかを制御します。したがってカスタマーのアクセスを細かく制御できます。

たとえば、以下の GraphQL スキーマがあるとします。

schema { query: Query mutation: Mutation } type Query { posts:[Post!]! } type Mutation { addPost(id:ID!, title:String!):Post! } ...

Amazon Cognito ユーザープールに 2 つのグループ (bloggers と readers) があり、readers が新しいエントリを追加できないように制限する場合、スキーマは次のようになります。

schema { query: Query mutation: Mutation }
type Query { posts:[Post!]! @aws_auth(cognito_groups: ["Bloggers", "Readers"]) } type Mutation { addPost(id:ID!, title:String!):Post! @aws_auth(cognito_groups: ["Bloggers"]) } ...

@aws_auth ディレクティブは、個別のアクセス許可/拒否戦略をデフォルトにする場合に省略できることに注意してください。コンソールまたは以下の CLI コマンド経由で GraphQL API を作成するときに、ユーザープール設定で許可/拒否戦略を指定できます。

$ aws appsync --region us-west-2 create-graphql-api --authentication-type AMAZON_COGNITO_USER_POOLS --name userpoolstest --user-pool-config '{ "userPoolId":"test", "defaultEffect":"ALLOW", "awsRegion":"us-west-2"}'

追加の承認モードの使用

追加の承認モードを追加するとき、AWS AppSync GraphQL API レベル (GraphqlApi オブジェクトで直接設定できる authenticationType フィールド) で、承認設定を直接定義できます。この設定はスキーマのデフォルトになります。つまり、特定のディレクティブのないタイプは API レベルの承認設定を渡す必要があります。

スキーマレベルでは、スキーマでディレクティブを使用して追加の承認モードを指定できます。スキーマの個々のフィールドに承認モードを指定できます。たとえば、API_KEY 承認の場合、スキーマオブジェクトタイプの定義/フィールドで @aws_api_key を使用します。以下のディレクティブは、スキーマフィールドおよびオブジェクトタイプ定義でサポートされています。

  • @aws_api_key - フィールドが API_KEY で承認されることを指定します。

  • @aws_iam - フィールドが AWS_IAM で承認されることを指定します。

  • @aws_oidc - フィールドが OPENID_CONNECT で承認されることを指定します。

  • @aws_cognito_user_pools - フィールドが AMAZON_COGNITO_USER_POOLS で承認されることを指定します。

  • @aws_lambda - フィールドが AWS_LAMBDA で承認されることを指定します。

@aws_auth ディレクティブを追加の承認モードと共に使用することはできません。@aws_auth は、追加の承認モードのない AMAZON_COGNITO_USER_POOLS 承認のコンテキストでのみ機能します。ただし、同じ引数で @aws_auth ディレクティブの代わりに @aws_cognito_user_pools ディレクティブを使用できます。2 つの主な違いは、フィールドとオブジェクトタイプの定義で @aws_cognito_user_pools を指定できることです。

追加の承認モードがどのように機能し、スキーマでどのように指定できるかを理解するために、以下のスキーマを見てみましょう。

schema { query: Query mutation: Mutation } type Query { getPost(id: ID): Post getAllPosts(): [Post] @aws_api_key } type Mutation { addPost( id: ID! author: String! title: String! content: String! url: String! ): Post! } type Post @aws_api_key @aws_iam { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! } ...

このスキーマでは、AWS_IAM が AWS AppSync GraphQL API のデフォルトの承認タイプであるとします。つまり、ディレクティブのないフィールドは AWS_IAM を使用して保護されます。たとえば、Query タイプの getPost フィールドの場合です。スキーマディレクティブにより、複数の承認モードを使用できます。たとえば、API_KEY を AWS AppSync GraphQL API での追加の承認モードとして設定し、@aws_api_key ディレクティブ (この例では getAllPosts) を使用してフィールドをマークできます。ディレクティブはフィールドレベルで機能するため、Post タイプへの API_KEY アクセスも許可する必要があります。そのためには、Post タイプの各フィールドをディレクティブでマークするか、Post タイプを @aws_api_key ディレクティブでマークします。

Post タイプのフィールドへのアクセスをさらに制限するには、以下に示すように、Post タイプの個々のフィールドに対してディレクティブを使用できます。

たとえば、restrictedContent フィールドを Post タイプに追加し、@aws_iam ディレクティブを使用してそのフィールドへのアクセスを制限できます。ただし restrictedContent に、AWS_IAM 認証済みリクエストからはアクセスできますが、API_KEY リクエストからはアクセスできません。

type Post @aws_api_key @aws_iam{ id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! restrictedContent: String! @aws_iam } ...

きめ細かなアクセスコントロール

前述の情報は、特定の GraphQL フィールドへのアクセスを制限または許可する方法を示しています。特定の条件に基づいて (たとえば、呼び出し元のユーザーがだれであるかや、そのユーザーがデータを所有しているかどうかに基づいて) データに対するアクセスコントロールを設定する場合は、リゾルバーでマッピングテンプレートを使用できます。より複雑なビジネスロジックも実行できます。「フィルタ処理情報」で説明します。

このセクションでは、DynamoDB リゾルバーマッピングテンプレート使用してデータのアクセスコントロールを設定する方法を示します。

さらに進む前に、AWS AppSync のマッピングテンプレートがよくわからない場合は、「リゾルバーのマッピングテンプレートリファレンス」と「DynamoDB のリゾルバーのマッピングテンプレートリファレンス」を参照してください。

DynamoDB を使用した次の例では、前述のブログ投稿スキーマを使用し、投稿を作成したユーザーのみが編集を許可されているものとします。評価プロセスは、Amazon Cognito ユーザープールなどを使用して、ユーザーがアプリケーションで認証情報を取得し、GraphQL オペレーションの一部として、これらの認証情報を渡すというものです。その後、マッピングテンプレートが、条件ステートメントで、認証情報 (username など) からの値を置き換えます。値はデータベースの値と比較されます。

Diagram showing authentication flow from user login to database operation using AWS のサービス.

この機能を追加するには、次のように editPost GraphQL フィールドを追加します。

schema { query: Query mutation: Mutation } type Query { posts:[Post!]! } type Mutation { editPost(id:ID!, title:String, content:String):Post addPost(id:ID!, title:String!):Post! } ...

editPost のリゾルバーマッピングテンプレート (このセクションの最後にある例) では、投稿を作成したユーザーのみが編集を許可されるように、データストアに対する論理チェックを実行する必要があります。これは編集オペレーションなので、DynamoDB の UpdateItem に対応します。ユーザー ID 検証に渡されるコンテキストを使用して、このアクションを実行する前に条件チェックを実行できます。これは次の値を持つ Identity オブジェクトに保存されます。

{ "accountId" : "12321434323", "cognitoIdentityPoolId" : "", "cognitoIdentityId" : "", "sourceIP" : "", "caller" : "ThisistheprincipalARN", "username" : "username", "userArn" : "Sameasabove" }

DynamoDB UpdateItem コールでこのオブジェクトを使用するには、比較用テーブルにユーザー ID 情報を保存する必要があります。まず、addPost ミューテーションは作成者を保存する必要があります。次に、更新する前に、editPost ミューテーションで条件チェックを実行する必要があります。

Author 列としてユーザー ID を保存する addPost のリゾルバーコードの例を次に示します。

import { util, Context } from '@aws-appsync/utils'; import { put } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { id: postId, ...item } = ctx.args; return put({ key: { postId }, item: { ...item, Author: ctx.identity.username }, condition: { postId: { attributeExists: false } }, }); } export const response = (ctx) => ctx.result;

Author 属性が、アプリケーションから得られた Identity オブジェクトから入力されていることに注意してください。

最後に、editPost のリゾルバーコードの例を次に示します。これは、投稿を作成したユーザーからリクエストが来た場合にのみ、ブログ投稿のコンテンツを更新します。

import { util, Context } from '@aws-appsync/utils'; import { put } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { id, ...item } = ctx.args; return put({ key: { id }, item, condition: { author: { contains: ctx.identity.username } }, }); } export const response = (ctx) => ctx.result;

この例では、UpdateItem ではなく、すべての値を上書きする PutItem を使用していますが、condition ステートメントブロックには同じ概念が適用されます。

フィルタ処理情報

データソースからのレスポンスを制御できないときに、データソースへの正常な書き込みまたは読み取りに対して、不必要な情報をクライアントに送信したくない場合があります。このような場合は、レスポンスマッピングテンプレートを使用して情報をフィルタリングすることができます。

たとえば、ブログ投稿 DynamoDB テーブルに適切なインデックス (Author のインデックスなど) がない場合を考えます。以下のリゾルバーを使用できます。

import { util, Context } from '@aws-appsync/utils'; import { get } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { return get({ key: { ctx.args.id } }); } export function response(ctx) { if (ctx.result.author === ctx.identity.username) { return ctx.result; } return null; }

リクエストハンドラは、呼び出し元が投稿の作成者でなくても、項目をフェッチします。これによってすべてのデータが返されるのを防ぐために、レスポンスハンドラは呼び出し元が項目の作成者と一致することを確認します。発信者がこのチェックに一致しない場合に、null レスポンスのみが返されます。

データソースへのアクセス

AWS AppSync は Identity and Access Management (IAM) のロールとアクセスポリシーを使用してデータソースと通信します。既存のロールを使用している場合、AWS AppSync がロールを引き受けるために信頼ポリシーを追加する必要があります。信頼関係は以下のようになります。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "appsync.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

必要な最小限のリソースについて作業を行うアクセス許可のみを持つように、ロールのアクセスポリシーを制限することが重要です。AppSync コンソールを使用してデータソースを作成し、ロールを作成したとき、これは自動的に行われます。IAM コンソールから組み込みのサンプルテンプレートを使用して AWS AppSync コンソールの外部でロールを作成している場合、アクセス許可はリソースに対して自動的に制限はされず、アプリケーションを本番環境に移行する前に、手動でこの処置を実施する必要があります。