日本語が不自由なタイトルになりましたが順に設定していきます。
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のインターフェースを提供する。
構成図は以下のとおりです。
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をファイル作成時に利用します。
実装
主要なファイルを以下のように実装しました。
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")
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
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で設定できるのかもしれないのですが、今回は手動で行いました。
その後、再度build & deployします。
$ sam build
$ sam deploy
動作確認
HelloWorldの方のLambda関数に設定されているAPI Gatewayのエンドポイントにブラウザでアクセスします。
その後S3のBucketにアクセスすると、以下のようなCSVファイルが作成されています。