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.2k
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
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
25k
[ホンマでっか SRE] あなたはなぜ SRE に?
_awache
0
550
bet_ai_day_2026_session02
agenticsec
0
140
The Django UUID Story - DjangoCon US 2026
pauloxnet
0
350
PdMをやめて、 "プロダクトビルダー"という 働き方に変えました / PdM to Product Builder
shikichee
2
560
EUDIWの枠組みを出発点に民間エコシステムの在り方を考える(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
410
Data Hubグループ 紹介資料
sansan33
PRO
0
3.2k
IHV like なユースケースへのOpenID Connect 関連仕様の適用事例
optim
0
420
みてねにおけるAI-DLC導入活動とAIドリブン開発の現在地/JAWS-UG AI-DLC #2
isaoshimizu
2
310
AIレビュー時代に必要なのは、SLOで引く撤退ライン
nobuoooo
0
160
MCPを待つな、パスキーを拡げよう(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
420
AI時代の「OAuth認証」にどう物申すか?(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
410
Featured
See All Featured
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
520
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Facilitating Awesome Meetings
lara
57
7.1k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
310
WCS-LA-2024
lcolladotor
0
810
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Darren the Foodie - Storyboard
khoart
PRO
3
3.8k
The agentic SEO stack - context over prompts
schlessera
0
880
The Cost Of JavaScript in 2023
addyosmani
55
10k
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