AWS IAM 및 서명 V4로 GraphQL 요청에 서명

AWS AppSync는 GraphQL API를 구축하기 위한 관리형 서비스입니다. 자격 증명 풀(예: Cognito 사용자 풀, Google 로그인 등)에서 제공하는 API 키, AWS Identity and Access Management(IAM) 권한 또는 OpenID Connect 토큰과 같은 다양한authorization types을 통한 인증을 지원합니다.

API 키 인증은 클라이언트가 POST 요청에서 API 키를 x-api-key 헤더로 지정해야 하므로 매우 간단합니다. 반면에 AWS IAM을 통한 인증에는 AWS Signature Version 4 으로 요청 서명이 필요합니다. 이 프로세스는 오류가 발생하기 쉬울 수 있으므로 간단한 작업 예를 공유하고 싶습니다.

JavaScript v3용 AWS SDK를 사용한 서명 요청



항목을 생성하기 위해 GraphQL 변형을 실행하는 작은 Lambda 함수를 구현했습니다. 기본 HTTP 요청은 서명 V4로 서명됩니다. 이렇게 하면 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 헤더와 SignatureV4에 의해 추가된 다른 x-amz-* 헤더를 볼 수 있습니다.

{
  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'
  }
}


(민감한 정보가 유출되지 않도록 이 값을 수동으로 변경했습니다.)

추가 자료



Amplify 및 AppSync를 사용하는 GraphQL에 대한 유용한 정보article by Michael가 있습니다. Lambda에서 GraphQL 변형을 실행하는 방법에 대한 섹션이 포함되어 있습니다. 그의 예에서 그는 JS용 AWS SDK의 이전 버전 2를 사용하므로 그의 코드는 내 코드와 다릅니다. Amplify를 사용하는 경우 공식 문서에 Signing a request from Lambda에 대한 예제도 포함되어 있습니다.

좋은 웹페이지 즐겨찾기