Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ユースケースで学ぶ!API Gateway + Lambda Authorizer 実践入門(...
Search
Shiraishi
July 26, 2022
Technology
2.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ユースケースで学ぶ!API Gateway + Lambda Authorizer 実践入門(CDK)
Shiraishi
July 26, 2022
Other Decks in Technology
See All in Technology
しぶいSRE: サーバから見えない障害にどう向き合うか。ラストワンマイルのデバッグ実践 / Shibui SRE
kanny
13
6.5k
Control Planeで育てるBtoB SaaSの認証基盤 - SRE NEXT 2026
pokohide
1
2.6k
DMM.com 購入改善推進チーム におけるCodeRabbitを用いた レビューフロー改善の一例
ysknsid25
2
660
型は壁、Rustでもバグを直すな、表現できなくせよ
nwiizo
14
2.1k
AIが実装を自走する時代の認知負債との戦い
lycorptech_jp
PRO
0
140
2年前に削除したPHPクラスが、 ある日突然決済をエラーにした
ykagano
1
280
シンガポールで登壇してきます
yama3133
0
240
非定型なドキュメントを効率よくリファクタする 〜えぇ!?仕様書27本の移行が1日で終わったって!?〜
subroh0508
2
550
ZOZOTOWNの進化と信頼性を両立する負荷試験
zozotech
PRO
2
190
10年目を迎えた「ABEMA」がどのように AI 活用を推進して、AI 駆動開発にシフトしているのか / How ABEMA, entering its 10th year, is promoting the use of AI and shifting toward AI-driven development
miyukki
0
260
AIコード生成×サプライチェーン攻撃 — PHPが直面する“二重の信頼問題
shinyasaita
0
190
AIと共生する開発者プラットフォーム:バクラクのモノレポ×マイクロサービス基盤
sakajunquality
2
3.7k
Featured
See All Featured
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.7k
Bash Introduction
62gerente
615
220k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
810
BBQ
matthewcrist
89
10k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
450
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
180
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
270
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.6k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Transcript
ϢʔεέʔεͰֶͿʂ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ೖʢ$%,ʣ "84ࣄۀຊ෦ίϯαϧςΟϯά෦നੴҰ
ࣗݾհ w"84ࣄۀຊ෦ίϯαϧς Οϯά෦ w"84ΤϯδχΞ ϑϩϯτ ΤϯυΤϯδχΞ w8FCडୗ4&4$. w"84 )5.-
$44 +BWB4DSJQU 5ZQF4DSJQU 1)1 1FSM $ 1ZUIPO നੴҰʢShiraishi Seiichiʣ
ΞδΣϯμ ຊηογϣϯʹ͍ͭͯ ࣮֓ཁʢ8FCIPPL #BTJDೝূར༻ʣ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ ·ͱΊ
ΞδΣϯμ ຊηογϣϯʹ͍ͭͯ ࣮֓ཁʢ8FCIPPL #BTJDೝূར༻ʣ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ ·ͱΊ
ຊηογϣϯʹ͍ͭͯ ରࢹௌऀ w"1*։ൃॳֶऀ w"1*(BUFXBZ -BNCEB"VUIPSJ[FSॳֶऀ ΰʔϧ w8FCIPPLΛड͚͚ΔͨΊͷ"1*(BUFXBZΛ࣮͠·͢ɻ"1* (BUFXBZʹ#BTJDೝূΛ࣮͠·͢ɻ w͜ͷྫΛ௨ͯ͠ɺԿ͔ಘΔͷ͕͋Γ·͢ͱ͍Ͱ͢ɻ
ຊηογϣϯʹೖΔલʹ લఏ݅ wຊηογϣϯͰɺ;FOEFTLʹͯ8FCIPPLͷઃఆΛߦ͍ɺ 8FCIPPLΛड͚͚Δ"1*Λ࡞͢Δํ๏Λ͝հ͠·͢ɻ w;FOEFTLଆͷઃఆऔΓѻΘͣɺࢀߟϒϩάͷ͝հͷΈͱͤͯ͞ ͍͖ͨͩ·͢ɻ ༻͢Δٕज़ w"1*(BUFXBZ -BNCEB"VUIPSJ[FS
w"84$%,W
ΞδΣϯμ ຊηογϣϯʹ͍ͭͯ ࣮֓ཁʢ8FCIPPL #BTJDೝূར༻ʣ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ ·ͱΊ
࣮֓ཁ w;FOEFTLͷ8FCIPPLઃఆ w;FOEFTLͷ#BTJDೝূઃఆ w8FCIPPLΛड͚͚Δ"1*ͷ࡞ w"1*(BUFXBZͷ࡞ w-BNCEB"VUIPSJ[FSͷ࡞
࣮֓ཁ w;FOEFTLͱ w;FOEFTLɺʮ͓٬༷͕৺Α͍ͱײ͡ΔΤΫεϖϦΤϯεʯΛ࣮ ݱ͢ΔΧελϚʔαʔϏεϓϥοτϑΥʔϜΛఏڙ͍ͯ͠·͢ɻ ϝʔϧ͔Βͷ͓͍߹Θͤɺνϟοτ͔Βͷ͓͍߹ΘͤҰݩ ཧͰ͖ΔͨΊɺΧελϚʔαʔϏεۀ͕ܶతʹεϜʔζʹͳΔ ͱͱʹɺސ٬ͱͷΑΓྑ͍ؔΛங͘͜ͱ͕ՄೳʹͳΓ·͢ɻ wҾ༻ɿIUUQTXXX[FOEFTLDPKQBCPVU
࣮֓ཁ w"1*(BUFXBZͱ w"NB[PO"1*(BUFXBZɺ͋ΒΏΔنͷ3&45ɺ)551ɺ͓Α ͼ8FC4PDLFU"1*Λ࡞ɺެ։ɺҡ࣋ɺϞχλϦϯάɺ͓Αͼη ΩϡΞԽ͢ΔͨΊͷ"84ͷαʔϏεͰ͢ɻ wҾ༻ɿIUUQTEPDTBXTBNB[PODPNKB@KQBQJHBUFXBZ MBUFTUEFWFMPQFSHVJEFXFMDPNFIUNM
࣮֓ཁ w-BNCEB"VUIPSJ[FSͱ w-BNCEBؔΛ༻ͯ͠)551"1*ͷΞΫηεΛ੍ޚ͢Δ ΈͰ͢ɻ wҾ༻ɿIUUQTEPDTBXTBNB[PODPNKB@KQBQJHBUFXBZ MBUFTUEFWFMPQFSHVJEFIUUQBQJMBNCEBBVUIPSJ[FSIUNM
ΞʔΩςΫνϟ
ΞδΣϯμ ຊηογϣϯʹ͍ͭͯ ࣮֓ཁʢ8FCIPPL #BTJDೝূར༻ʣ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ ·ͱΊ
;FOEFTLଆઃఆ https://dev.classmethod.jp/ articles/zendesk-attachments- to-s3/ wʮ;FOEFTLͷ8FCIPPLͱ τϦΨʔͷઃఆʯͷষΛࢀߟ
"1*(BUFXBZ࣮ import { IdentitySource, LambdaIntegration, RequestAuthorizer, RestApi } from
‘aws-cdk-lib/aws-apigateway'; const api = new RestApi(this, 'zendesk-webhook-api', { deployOptions: { stageName: ‘v1’ // default Ͱ prod ͕ੜ͞ΕΔ } }) const auth = new RequestAuthorizer(this, 'zendeskWebhookAuthorizer', { handler: authorizerFunction, // LambdaAuthorizer ࣮ identitySources: [ IdentitySource.header(‘Authorization'), IdentitySource.header(‘X-Request-Id’) ] })
"1*(BUFXBZ࣮ const webhookApi = api.root.addResource('resource'); webhookApi.addMethod( 'POST', new LambdaIntegration(postResourceFunction),
{ authorizer: auth } ) webhookApi.addCorsPreflight({ statusCode: 200, allowOrigins: Cors.ALL_ORIGINS, allowMethods: Cors.ALL_METHODS, allowHeaders: Cors.DEFAULT_HEADERS, })
-BNCEB"VUIPSJ[FS࣮ import { ManagedPolicy, Effect, PolicyStatement, Role, ServicePrincipal }
from ‘aws-cdk-lib/aws-iam'; // policy ͷ࣮ const authorizerFunctionPolicy = new ManagedPolicy(this, "authorizer-function-policy", { managedPolicyName: "authorizer-function-policy", statements: [ new PolicyStatement({ effect: Effect.ALLOW, actions: [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", ], resources: ["arn:aws:logs:*:*:*"], }), ] }); const authorizerFunctionRole = new Role(this, "authorizer-function-role", { roleName: "authorizer-function-role", assumedBy: new ServicePrincipal("lambda.amazonaws.com"), managedPolicies: [authorizerFunctionPolicy] });
-BNCEB"VUIPSJ[FS࣮ // policy ͷ࣮ const authorizerInvokePolicy = new ManagedPolicy(this,
"authorizer-invoke-policy", { managedPolicyName: "authorizer-invoke-policy", statements: [ new PolicyStatement({ effect: Effect.ALLOW, actions: [ "sts:AssumeRole", ], resources: ['*'], }) ] }) const authorizerInvokeRole = new Role(this, 'authorizer-invoke-role', { roleName: "authorizer-invoke-role", assumedBy: new ServicePrincipal('apigateway.amazonaws.com'), managedPolicies: [authorizerInvokePolicy] });
-BNCEB"VUIPSJ[FS࣮ const authorizerFunction = new Function(this, ‘authorizer-function', { functionName:
'authorizer-function', description: ‘Zendesk WebhookͷBasicೝূΛݕূ͢Δ', code: new AssetCode(“resources"), // ҙͷύεΛઃఆ handler: “auth/authorizer.handler", // ҙͷύεΛઃఆ runtime: Runtime.PYTHON_3_9, role: authorizerFunctionRole, environment: { // parameter store Λར༻ SSM_ZENDESK_USERNAME: "/zendesk/username", SSM_ZENDESK_PASSWORD: "/zendesk/password", } }); // API Gateway ͕ Lambda Λ࣮ߦ͢ΔͨΊͷݖݶ authorizerFunction.grantInvoke(authorizerInvokeRole);
-BNCEB"VUIPSJ[FS࣮ import base64 import json import logging import os
from hooks.utils import common TOKYO = "ap-northeast-1" logger = logging.getLogger() logger.setLevel(logging.INFO) zendesk_username = os.environ['SSM_ZENDESK_USERNAME'] zendesk_password = os.environ['SSM_ZENDESK_PASSWORD'] def handler(event, context): try: basic_header = event[“headers"]["Authorization"] req_id = event["headers"]["X-Request-Id"] result = is_valid(basic_header, common.get_parameter_value(zendesk_username), common.get_parameter_value(zendesk_password)) if result is True: return gen_policy(req_id, "Allow") return gen_policy(req_id, "Deny") except Exception as e: logger.error(e) raise Exception("Unauthorized") authorizer.py
-BNCEB"VUIPSJ[FS࣮ def is_valid(basic_header, username, password): basic_username_and_pasword = base64.b64encode( f"{username}:{password}".encode("utf-8")
) sig = f"Basic {basic_username_and_pasword.decode('utf-8')}" if basic_header == sig: return True return False def gen_policy(principal_id, effect: str): return { "principalId": principal_id, "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": effect, "Resource": '*', } ], }, } authorizer.py
-BNCEB"VUIPSJ[FS࣮ import boto3 def get_parameter_value(param_key): ssm = boto3.client('ssm') return
ssm.get_parameter(Name=param_key, WithDecryption=True)['Parameter']['Value'] common.py
ʢ͓·͚ʣ8FCIPPLॺ໊ݕূ common.py https://dev.classmethod.jp/ articles/zendesk-webhook- signature-veri fi cation-in-python/ wηΩϡϦςΟରࡦͱͯ͠ 8FCIPPL͕ຊʹ;FOEFTL
͔ΒͷͷͰ͋Δ͔Ͳ͏͔Λ֬ ೝɾݕূ͢Δ
ΞδΣϯμ ຊηογϣϯʹ͍ͭͯ ࣮֓ཁʢ8FCIPPL #BTJDೝূར༻ʣ "1*(BUFXBZ -BNCEB"VUIPSJ[FS࣮ ·ͱΊ
·ͱΊ w$%, -BNCEB"VUIPSJ[FSϦϑΝϨϯεΛಡΈ࣮͠·͠ΐ͏ wIUUQTEPDTBXTBNB[PODPNKB@KQBQJHBUFXBZMBUFTU EFWFMPQFSHVJEFBQJHBUFXBZVTFMBNCEBBVUIPSJ[FSIUNM w8FCIPPLΛར༻࣮ͨ͠ɺ;FOEFTLʹݶΒͣଞͷαʔϏεͰΑ ͋͘ΔͨΊྲྀ༻Ͱ͖Δʢ4MBDL %JTDPSE -*/&FUDʣ
wૉৼΓͱͯ͠ɺ͓खܰͳϢʔεέʔε
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
None