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
サイバー捜査員研修(前半)
nomizone
1
1.9k
Data Hubグループ 紹介資料
sansan33
PRO
0
3.2k
猫付きpingコマンドを自作
uyuki234
0
150
ガバメント AI 源内を地方自治体は活用できるのか可能性と課題、期待について
takeda_h
1
390
『三匹の子ぶた』から学ぶネットワークセキュリティの昔と今 / Network Security: Then and Now Through the Lens of The Three Little Pigs
nttcom
1
1.8k
侵入は突然に 〜 IoTマルウェアと悪用される家庭の機器 ~ / When Intrusion Strikes: IoT Malware and the Abuse of Home Devices
nttcom
0
1.6k
え?フロントエンドエンジニアの ワイがインフラも!?
puku0x
1
480
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
19k
モバイルアプリ開発概論2026
recruitengineers
PRO
5
540
Software Supply Chain Attackからクラウド環境を守るためにできること
lhazy
2
240
SO-101×VLAによる3色キューブのピック&プレース
abeja
0
180
TypeScript入門 2026
recruitengineers
PRO
3
530
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.3k
GraphQLとの向き合い方2022年版
quramy
50
15k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
450
From π to Pie charts
rasagy
0
260
The Spectacular Lies of Maps
axbom
PRO
1
900
Darren the Foodie - Storyboard
khoart
PRO
3
3.6k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
660
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Utilizing Notion as your number one productivity tool
mfonobong
4
530
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