1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SQSでCognitoユーザー一覧をS3に作成するキュー処理を行う関数とAPIをLambdaにSAMでデプロイする

Last updated at Posted at 2020-09-05

日本語が不自由なタイトルになりましたが順に設定していきます。

AWSのCognitoで管理されているユーザー一覧のCSVファイルをS3上に自動で作成する関数をLambda上に構築します。
そのLambdaを発動させるトリガーにSQSを設定し、SQSにメッセージキューを追加するAPIも別のLambdaに実装しAPI Gateway経由でHTTPリクエストを受け取るようにします。

  • Cognito: ユーザー管理サービス。多要素認証(MFA)やSNS連携などを簡単に実装できる。
  • S3: クラウドストレージ。バージョニングや一時的に利用可能なダウンロードURL作成などもできる。
  • SQS: AWS上でキューを管理する。非同期処理などに利用される。
  • Lambda: サーバーレスの関数実行環境
  • API Gateway: LambdaやEC2にAPIのインターフェースを提供する。

構成図は以下のとおりです。

image.png

AWS-CLIのインストールとIAMの設定

$ brew install awscli
$ aws configure
AWS Access Key ID [None]: ************
AWS Secret Access Key [None]: ************************
Default region name [None]: ap-northeast-1
Default output format [None]: json

SAMのインストール

※ Dockerも必要になるためインストールと起動をしてください。

$ brew tap aws/tap
$ brew install aws-sam-cli
$ sam --version
SAM CLI, version 1.0.0

SAMプロジェクトの初期化

今回はPython3.8でHello Worldテンプレートをベースに実装を進めます

% sam init
Which template source would you like to use?
	1 - AWS Quick Start Templates
	2 - Custom Template Location
Choice: 1

Which runtime would you like to use?
	1 - nodejs12.x
	2 - python3.8
	3 - ruby2.7
	・・・
Runtime: 2

Project name [sam-app]: sample-app

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

AWS quick start application templates:
	1 - Hello World Example
	2 - EventBridge Hello World
	・・・
Template selection: 1

-----------------------
Generating application:
-----------------------
Name: sample-app
Runtime: python3.8
Dependency Manager: pip
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./sample-app/README.md

Cognitoのユーザープールの作成

今回はひとまずデフォルト設定で作成して、適当なユーザーを一つ手動で追加しました。
作成したユーザープールIDをファイル作成時に利用します。

image.png

image.png

実装

主要なファイルを以下のように実装しました。

app.py
import json
import requests
import boto3
from datetime import datetime
import pandas as pd


def lambda_handler(event, context):

    try:
        sqs_client = boto3.client("sqs")
        # 一度SQSをデプロイすると自動でSQSにキューが作成されるのでそれを設定します
        queue_url = "https://sqs.ap-northeast-1.amazonaws.com/********/**********"
        print(queue_url)
        now = datetime.now()
        date_str = now.strftime('%Y/%m/%d-%H:%M:%S')
        sqs_response = sqs_client.send_message(
            QueueUrl=queue_url,
            MessageBody=json.dumps(date_str)
        )
    except requests.RequestException as e:
        # Send some context about this error to Lambda Logs
        print(e)

        raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world"
        }),
    }

def csv_create_handler(event, context):
    for record in event['Records']:
        payload=record["body"]

        date_str = str(payload)
        s3 = boto3.resource('s3')
        bucket = s3.Bucket('arkth-user-list-files')

        cognito_client = boto3.client('cognito-idp')

        response = cognito_client.list_users(
            UserPoolId = 'ap-northeast-***********',
            AttributesToGet = ['email','sub']
        )

        data = []
        for user in response["Users"]:
            data.append([user['Username'], user['Enabled']])

        Coulum = ['Username', 'Enabled']
        df = pd.DataFrame(data, columns=Coulum)

        df_csv = df.to_csv(index=None)
        objkey = 'user-list.csv'
        print(objkey)
        putobj = bucket.Object(objkey)
        putobj.put(Body=df_csv)

def support_datetime_default(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(repr(obj) + " is not JSON serializable")
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sample-app

  Sample SAM Template for sample-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3
    Runtime: python3.8

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

  UsersCsv:
    Type: AWS::SQS::Queue
    Properties:
      VisibilityTimeout: 60

  CsvCreateFunction:
    Properties:
      CodeUri: hello_world/
      Handler: app.csv_create_handler
      Events:
        MySQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt UsersCsv.Arn
            BatchSize: 10
    Type: AWS::Serverless::Function
requirement.txt
requests
boto3
pandas

SAMのビルド

$ sam build
Building function 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Building function 'CsvCreateFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

ローカルでSAMの起動

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-09-05 22:11:22  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

SQSのエンドポイントがダミーのためエラーになりますが、ブラウザから http://127.0.0.1:3000/hello にアクセスしてSyntax Errorなどがないか確かめます。

SAMのデプロイ

初回は --guided でデプロイすることで対話式で、samconfig.tomlが作成されます。

$ sam deploy --guided

Configuring SAM deploy
======================

	Looking for samconfig.toml :  Not found

	Setting default arguments for 'sam deploy'
	=========================================
	Stack Name [sam-app]: sample-app
	AWS Region [us-east-1]: ap-northeast-1
	#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
	Confirm changes before deploy [y/N]: y
	#SAM needs permission to be able to create roles to connect to the resources in your template
	Allow SAM CLI IAM role creation [Y/n]: Y
	HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
	Save arguments to samconfig.toml [Y/n]: Y
・・・・
・・・・
・・・・

少し時間がかかりますが、IAMやApi Gatewayなども適当に設定してデプロイしてくれます。

環境設定

  • app.py内のSQSのエンドポイントを、作成されたSQSのエンドポイントに書き換えます。

  • ファイル作成のLambda関数に割りてられているIAMのRoleにSQSとS3にアクセスする権限を付与します。

  • 以下のように、APIの方のLambda関数のDestinationに作成されたSQSを設定します。ここはSAMで設定できるのかもしれないのですが、今回は手動で行いました。

image.png

その後、再度build & deployします。

$ sam build
$ sam deploy

動作確認

HelloWorldの方のLambda関数に設定されているAPI Gatewayのエンドポイントにブラウザでアクセスします。

その後S3のBucketにアクセスすると、以下のようなCSVファイルが作成されています。

image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?