AWAIAMと署名V 4によるGraphSQLリクエストに署名してください


AWAppAppSyncは、GraphSQL APIを構築するための管理サービスです.様々な認証をサポートauthorization types APIキー、AWSアイデンティティとアクセス管理(IAM)許可またはOpenID Connectトークンがアイデンティティプール(例えばCognitoユーザープール、Google Sign Inなど)によって提供されるように.
APIキー認証はクライアントがAPIキーを指定しなければならないので、単純ですx-api-key POSTリクエストのヘッダ.他方、AWS IAMを通しての認証は、要求による署名を必要としますAWS Signature Version 4 . このプロセスは非常にエラーがちなので、簡単な作業例を共有したいと思います.

JavaScript V 3用のAWS SDKでのリクエスト


私は、項目を作成するためにGraphSQL突然変異を実行する小さなラムダ関数を実装しました.基本的なHTTPリクエストは署名v 4で署名されます.これはAuthorization ヘッダおよび他のAWS特定のリクエストヘッダ.私は、新しいものを使いましたAWS SDK for JavaScript v3 を実装します.これは、モジュールの構造を持っているので、各サービスのパッケージをインストールする必要があります@aws-sdk/<service> の代わりに別の代わりにaws-sdk パッケージ.
import { Sha256 } from '@aws-crypto/sha256-js';
import { defaultProvider } from '@aws-sdk/credential-provider-node';
import { HttpRequest } from '@aws-sdk/protocol-http';
import { SignatureV4 } from '@aws-sdk/signature-v4';
import { Handler } from 'aws-lambda';
import fetch from 'cross-fetch';

export const createTest: Handler<{ name: string }> = async (event) => {
  const { name } = event;

  // AppSync URL is provided as an environment variable
  const appsyncUrl = process.env.APPSYNC_GRAPHQL_ENDPOINT!;

  // specify GraphQL request POST body or import from an extenal GraphQL document
  const createItemBody = {
    query: `
      mutation CreateItem($input: CreateItemInput!) {
        createItem(input: $input) {
          id
          createdAt
          updatedAt
          name
        }
      }
    `,
    operationName: 'CreateItem',
    variables: {
      input: {
        name,
      },
    },
  };

  // parse URL into its portions such as hostname, pathname, query string, etc.
  const url = new URL(appsyncUrl);

  // set up the HTTP request
  const request = new HttpRequest({
    hostname: url.hostname,
    path: url.pathname,
    body: JSON.stringify(createItemBody),
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      host: url.hostname,
    },
  });

  // create a signer object with the credentials, the service name and the region
  const signer = new SignatureV4({
    credentials: defaultProvider(),
    service: 'appsync',
    region: 'eu-west-1',
    sha256: Sha256,
  });

  // sign the request and extract the signed headers, body and method
  const { headers, body, method } = await signer.sign(request);

  // send the signed request and extract the response as JSON
  const result = await fetch(appsyncUrl, {
    headers,
    body,
    method,
  }).then((res) => res.json());

  return result;
};
実際の署名はsigner.sign(request) メソッド呼び出し.元のHTTPリクエストオブジェクトを受け取り、新しい符号付きリクエストオブジェクトを返します.署名者calculates the signature リクエストヘッダーと本体に基づきます.署名されたヘッダを印刷することができますAuthorization ヘッダーと他x-amz-* signaturev 4で追加されたヘッダ
{
  headers: {
    'Content-Type': 'application/json',
    host: '7lscqyczxhllijx7hy2nzu6toe.appsync-api.eu-west-1.amazonaws.com',
    'x-amz-date': '20220402T073125Z',
    'x-amz-security-token': 'IQoJb3JpZ2luX2VjEKj//////////wEaCWV1LXdlc3QtMSJGMEQCIC7sO4bZwXjo1mDJTKVHbIeXXwE6oB1xNgO7rA3xbhlJAiAlZ3KlfEYSsuk6F/vjybV6s...',
    'x-amz-content-sha256': '6a09087b5788499bb95583ad1ef55dcf03720ef6dab2e46d901abb381e588e48',
    authorization: 'AWS4-HMAC-SHA256 Credential=ASAIQVW5ULWVHHSLHGZ/20220402/eu-west-1/appsync/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=7949e3a4d99666ee6676ab29437a7da4a6c2d963f3f26a82eda3bda96fc947c9'
  }
}
(これらの値を手動で変更して、機密情報を漏らすことを避ける)

更なる読書


すばらしいarticle by Michael AppSyncとAppSyncとGraphSQLについて.これは、ラムダからのgraphql突然変異を実行する上でのセクションが含まれます.彼の例では、彼はJSのためにAWS SDKの古いバージョン2を使います、したがって、彼のコードは私のコードと異なります.あなたがAmplifyを使用しているならば、公式ドキュメンテーションはまた、上に例を含みますSigning a request from Lambda .