BLOG

AWS AppSync 다중 인증 유형으로 백엔드 및 내부 프로세스 지원
작성일: 2019-09-06

AWS AppSync 및 Amazon DynamoDB 테이블 위에 구축된 GraphQL API를 사용하여 모바일 또는 웹 애플리케이션을 생성했다고 가정해보겠습니다. 이 경우엔 AWS Lambda함수와 같은 다른 백엔드 또는 내부 프로세스는 이제 백엔드 테이블의 데이터를 업데이트해야 합니다. 이제 AWS AppSync의 새로운 기능을 통해 Lambda 함수 액세스 권한을 부여하여 통합된 AppSync API 엔드 포인트를 통해 안전한 GraphQL API 호출을 수행할 수 있습니다.

 

오늘 게시 글에서는 다중 인증 유형 기능을 사용하여 해당 목표를 달성하는 방법을 살펴볼 예정입니다.

 

개요

다음 과정을 구현하는 애플리케이션이 있다고 가정해보겠습니다. 사용자는 Amazon Cognito사용자 풀을 통해 인증합니다.

  1. 사용자는 AWS AppSync API를 쿼리하여 앱에서 데이터를 봅니다.
  2. 데이터는 DynamoDB 테이블에 저장됩니다.
  3. GraphQL 구독은 데이터 변경 사항을 사용자에게 다시 반영합니다.

 

앱이 훌륭하게 잘 작동한다고 해도, DynamoDB 테이블의 데이터를 백그라운드에서 업데이트하려는 다른 백엔드 또는 내부 프로세스가 있을 수 있습니다.

예를 들자면 다음과 같습니다.

  • Amazon S3 버킷에 대한 외부 데이터 처리 프로세스
  • Amazon Kinesis Data Streams를 통해 수집 된 실시간 데이터
  • 외부 이벤트에 응답하는 Amazon SNS 메시지

 

이러한 각 시나리오에 대해 Lambda 함수를 사용하여 통합 API 엔드 포인트를 통해 DynamoDB 테이블의 데이터를 업데이트 하려고 합니다. AWS AppSync는 이 기능을 제공하기 위해 적절한 중간 계층 역할을 할 수 있습니다.

 

연습해 보기

Amazon Cognito 사용자 풀은 API를 인증하고 권한을 부여합니다. 안전한 AWS AppSync API 호출을 위한 Lambda 기능 액세스 권한을 부여하는 가장 좋은 방법을 고려할 때 이 점을 명심하십시오.

 

인증 모드 선택

AWS AppSync는 다음 네 가지 인증 유형을 지원합니다.

 

  • API_KEY : API 키 사용
  • AMAZON_COGNITO_USER_POOLS : Amazon Cognito 사용자 풀 사용
  • AWS_IAM : IAM 권한 사용
  • OPENID_CONNECT : OpenID Connect 제공자 사용

 

다중 인증 유형의 기능을 시작하기 전에 이러한 인증 유형 중 한번에 하나만 사용할 수 있습니다. 이제 더 나은 액세스 제어 수준을 제공하기 위해 이들을 혼합하고 일치시킬 수 있습니다.

 

추가 권한 부여 유형을 설정하려면 다음 스키마 지시문을 사용하십시오.

 

  • @aws_api_key — 필드는 권한 부여를 위해 API_KEY를 사용합니다.
  • @aws_cognito_user_pools — 필드는 권한 부여에 AMAZON_COGNITO_USER_POOLS를 사용합니다.
  • @aws_iam — 필드는 권한 부여를 위해 AWS_IAM을 사용합니다.
  • @aws_oidc — 필드는 권한 부여를 위해 OPENID_CONNECT를 사용합니다.

 

AWS_IAM람다 함수는 IAM 실행 역할에 바인딩 되어 있어, 이 람다 함수가 가질 수 있는 액세스 허가를 규정 가능하기 때문에, 이 타입은 람다 기능에 이상적입니다. API_KEY인증 모드를 사용하지 마십시오. API 키는 개발 목적 또는 공개 API를 공개하는 것이 안전한 사용에만 권장됩니다.

 

아키텍처 이해

로깅 데이터를 볼 수 있는 로그 뷰어 웹의 앱이 있다고 가정해 보겠습니다.

 

  • Amazon Cognito 사용자 풀을 사용하여 사용자를 인증하고 “Log” DynamoDB 테이블에서 데이터를 읽기 위해 AWS AppSync API 엔드 포인트에 액세스합니다.
  • 일부 백엔드 프로세스는 로그 이벤트 및 세부 사항을 SNS 토픽에 공개합니다.
  • Lambda 함수는 토픽을 구독하고 AWS AppSync API를 호출하여 백엔드 데이터 저장소를 업데이트합니다.

 

다음 다이어그램은 웹 앱 아키텍처를 보여줍니다.

 

 

다음 코드는 권한 부여 지시문이 없는 AWS AppSync GraphQL 스키마입니다.

 

type Log {

  id: ID!

  event: String

  detail: String

}

 

input CreateLogInput {

  id: ID

  event: String

  detail: String

}

 

input UpdateLogInput {

  id: ID!

  event: String

  detail: String

}

 

input DeleteLogInput {

  id: ID!

}

 

type ModelLogConnection {

  items: [Log]

  nextToken: String

}

 

type Mutation {

  createLog(input: CreateLogInput!): Log

  updateLog(input: UpdateLogInput!): Log

  deleteLog(input: DeleteLogInput!): Log

}

 

type Query {

  getLog(id: ID!): Log

  listLogs: ModelLogConnection

}

 

type Subscription {

  onCreateLog: Log

    @aws_subscribe(mutations: [“createLog”])

  onUpdateLog: Log

    @aws_subscribe(mutations: [“updateLog”])

  onDeleteLog: Log

    @aws_subscribe(mutations: [“deleteLog”])

}

 

 

AWS AppSync API 구성하기

먼저 새로운 인증 모드를 추가하도록 AWS AppSync API를 구성하십시오.

 

  • AWS AppSync에서 콘솔 및 당신의 API를 선택합니다.
  • API 이름에서 설정을 선택 하십시오.
  • 기본 인증 모드에서 Amazon Cognito user pool을 설정 하십시오.
  • 추가 권한 제공자 우측의 신규를 선택 하십시오.
  • 인증 모드에서 AWS ID 및 액세스 관리 (IAM)를 선택하고, 제출을 선택 하십시오.
  • 저장을 선택 하십시오.

 

추가 인증 제공자를 설정 했으므로 createLog에 @aws_iam을 추가하여 AWS_IAM 인증을 허용하도록 스키마를 수정하십시오. 새 스키마는 다음 코드와 같습니다.

 

input CreateLogInput {

  id: ID

  event: String

  detail: String

}

 

input UpdateLogInput {

  id: ID!

  event: String

  detail: String

}

 

input DeleteLogInput {

  id: ID!

}

 

type ModelLogConnection {

  items: [Log]

  nextToken: String

}

 

type Mutation {

  createLog(input: CreateLogInput!): Log

    @aws_iam

  updateLog(input: UpdateLogInput!): Log

  deleteLog(input: DeleteLogInput!): Log

}

 

type Query {

  getLog(id: ID!): Log

  listLogs: ModelLogConnection

}

 

type Subscription {

  onCreateLog: Log

    @aws_subscribe(mutations: [“createLog”])

  onUpdateLog: Log

    @aws_subscribe(mutations: [“updateLog”])

  onDeleteLog: Log

    @aws_subscribe(mutations: [“deleteLog”])

}

 

type Log @aws_iam {

  id: ID!

  event: String

  detail: String

}

@aws_iam지시문은 현재 createLog변화에 구현되어 있습니다. 지시문을 로그 유형에 추가합니다. 지시문은 필드 수준에서 작동하므로 AWS_IAM에 로그 유형에 대한 액세스 권한도 부여하십시오. 이렇게 하려면 지시문으로 로그 유형의 각 필드를 표시하거나 로그타입을 @aws_iam 지시문으로 표시합니다.

 

@aws_cognito_user_pools지시문은 기본 인증 유형이므로 명시 적으로 지정하지 않아도 됩니다. 다른 지시문 으로 표시되지 않은 필드는 Amazon Cognito 사용자 풀을 사용하여 보호됩니다.

 

 

Lambda 함수 생성하기

AWS AppSync 백엔드가 설정되었으므로 Lambda 함수를 생성하십시오. 이 기능은 SNS주제에 발행 된 이벤트에 의해 트리거 됩니다. 이 이벤트에는 메시지 본문에 이벤트와 상세 정보의 로깅이 포함 됩니다.

 

다음 코드 예제는 Lambda 함수가 Node.js로 작성되는 방법을 보여줍니다.

 

require(‘isomorphic-fetch’);

const AWS = require(‘aws-sdk/global’);

const AUTH_TYPE = require(‘aws-appsync/lib/link/auth-link’).AUTH_TYPE;

const AWSAppSyncClient = require(‘aws-appsync’).default;

const gql = require(‘graphql-tag’);

 

const config = {

  url: process.env.APPSYNC_ENDPOINT,

  region: process.env.AWS_REGION,

  auth: {

    type: AUTH_TYPE.AWS_IAM,

    credentials: AWS.config.credentials,

  },

  disableOffline: true

};

 

const createLogMutation =

`mutation createLog($input: CreateLogInput!) {

  createLog(input: $input) {

    id

    event

    detail

  }

}`;

 

const client = new AWSAppSyncClient(config);

 

exports.handler = (event, context, callback) => {

 

  // An expected payload has the following format:

  // {

  //   “event”: “sample event”,

  //   “detail”: “sample detail”

  // }

 

  const payload = event[‘Records’][0][“Sns”][‘Message’];

 

  if (!payload[‘event’]) {

    callback(Error(“event must be provided in the message body”));

    return;

  }

 

  const logDetails = {

    event: payload[‘event’],

    detail: payload[‘detail’]

  };

 

  (async () => {

    try {

      const result = await client.mutate({

        mutation: gql(createLogMutation),

        variables: {input: logDetails}

      });

      console.log(result.data);

      callback(null, result.data);

    } catch (e) {

      console.warn(‘Error sending mutation: ‘,  e);

      callback(Error(e));

    }

  })();

};

 

Lambda 함수는 createLogAWS_IAM 권한 부여 유형을 사용하여 AWS AppSync SDK를 통해 변경 호출을 수행합니다.

 

 

IAM 역할 정의하기

다음으로 이 Lambda 함수가 가정할 수 있는 IAM 역할을 정의합니다. API에 대한 Lambda 함수 appsync : GraphQL 권한과 Amazon CloudWatch Logs 권한을 부여합니다. 또 Lambda 함수가 SNS 주제에 의해 트리거 되도록 허용 해야 합니다.

 

Lambda 함수, 해당 IAM 권한 및 지원 리소스를 배포 하는 전체 AWS CloudFormation 템플릿을 볼 수 있습니다.

 

AWSTemplateFormatVersion: ‘2010-09-09’

Transform: AWS::Serverless-2016-10-31

Parameters:

  GraphQLApiEndpoint:

    Type: String

    Description: The https endpoint of an AppSync API

  GraphQLApiId:

    Type: String

    Description: The id of an AppSync API

  SnsTopicArn:

    Type: String

    Description: The ARN of the SNS topic that can trigger the Lambda function

Resources:

  AppSyncSNSLambda:

    Type: ‘AWS::Serverless::Function’

    Properties:

      Description: A Lambda function that invokes an AppSync API endpoint

      Handler: index.handler

      Runtime: nodejs8.10

      MemorySize: 256

      Timeout: 10

      CodeUri: ./

      Role: !GetAtt AppSyncLambdaRole.Arn

      Environment:

        Variables:

          APPSYNC_ENDPOINT: !Ref GraphQLApiEndpoint

 

  AppSyncLambdaRole:

    Type: AWS::IAM::Role

    Properties:

      AssumeRolePolicyDocument:

        Version: ‘2012-10-17’

        Statement:

        – Effect: Allow

          Principal:

            Service: lambda.amazonaws.com

          Action: sts:AssumeRole

      Policies:

      – PolicyName: AppSyncLambdaPolicy

        PolicyDocument:

          Version: ‘2012-10-17’

          Statement:

          – Effect: Allow

            Resource: arn:aws:logs:*

            Action:

            – logs:CreateLogGroup

            – logs:CreateLogStream

            – logs:PutLogEvents

          – Effect: Allow

            Resource:

            – !Sub ‘arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${GraphQLApiId}*’

            Action:

            – appsync:GraphQL

 

  SnsSubscription:

    Type: AWS::SNS::Subscription

    Properties:

      Endpoint: !GetAtt AppSyncSNSLambda.Arn

      Protocol: Lambda

      TopicArn: !Ref SnsTopicArn

 

  LambdaInvokePermission:

    Type: AWS::Lambda::Permission

    Properties:

      FunctionName: !Ref AppSyncSNSLambda

      Action: lambda:InvokeFunction

      Principal: sns.amazonaws.com

      SourceArn: !Ref SnsTopicArn

 

 

AWS CloudFormation 템플릿 배포하기

다음 두 명령을 사용하여 AWS CloudFormation 템플릿을 배포하십시오. 모든 CAPS 필드를 AWS 계정에 특정한 값으로 바꾸십시오.

aws cloudformation package –template-file “cloudformation.yaml” \

  –s3-bucket “<YOUR S3 BUCKET>” \

  –output-template-file “out.yaml”

 

aws cloudformation deploy –template-file out.yaml \

    –stack-name appsync-lambda \

    –s3-bucket “<YOUR S3 BUCKET>” \

    –parameter-overrides GraphQLApiEndpoint=”<YOUR GRAPHQL ENDPOINT>” \

      GraphQLApiId=”<YOUR GRAPHQL API ID>” \

      SnsTopicArn=”<YOUR SNS TOPIC ARN>” \

    –capabilities CAPABILITY_IAM

 

 

솔루션 테스트하기

두 명령이 모두 성공하고 AWS CloudFormation 템플릿이 배포 된 후 다음을 수행하십시오.

 

  1. 콘솔을 열고 이전에 지정한 SNS 주제로 이동합니다.
  2. 메시지 공개를 선택 합니다.
  3. 로우 메시지 본문에 다음을 입력하십시오.

 

{

   “event”: “sample event”,

   “detail”: “sample detail”

}

  1. 메시지 게시를 선택합니다.

 

AWS AppSync API의 데이터 소스 인 Log DynamoDB 테이블로 이동합니다. CreateLog변경을 사용하여 생성된 새로운 “샘플 이벤트” 레코드가 표시됩니다.

 

 

결론

새로운 기능으로 AWS AppSync는 이제 여러 인증 유형을 지원할 수 있습니다. 이 기능은 AWS AppSync API가 여러 프로세스간에 강력한 중간 계층으로 작동하면서 최종 사용자를 위한, 안전한 API 라는 것을 보여줍니다.

 

 

원문 URL: https://aws.amazon.com/ko/blogs/mobile/supporting-backend-and-internal-processes-with-aws-appsync-multiple-authorization-types/

 

** 메가존 클라우드 TechBlog는 AWS BLOG 영문 게재 글 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.