serverless aws構成でセキュアなspaを目指す
TRANSCRIPT
Copyright © 2016. All rights reserved.
Copyright © 2017 All rights reserved.
2017/01/17ハンズラボ 株式会社Serverless Meetup Tokyo #2
Serverless AWS構成でセキュアなSPAを⽬指す!
⾃⼰紹介
• 名前:加藤 雅之
• 所属:ハンズラボ株式会社
• 担当:「AWSチーム リーダー」
東急ハンズ- AWSインフラ、IT統制
ハンズラボ 外販- AWS構築運⽤⽀援
Copyright © 2017 All rights reserved.3
ハンズラボ株式会社
• 情シス部⾨Ø 東急ハンズの各種システムの内製開発と運⽤保守
• 外販Ø ⾃社開発の経験を活かした受託開発、内製⽀援
東急ハンズのシステム⼦会社
Copyright © 2017 All rights reserved.4
APNArchitectureoftheYear 2015受賞
• AWS Partner Networkの利用アーキテクチャが「最も先進的、または実用的、チャレンジングなもの」が選ばれる
Copyright © 2017 All rights reserved.5
東急ハンズ ポイントシステム
• ミッションクリティカルなポイントシステムを、AWSクラウドネイティブにて構築
Copyright © 2017 All rights reserved.6
AWSSamurai2015をCEO⻑⾕川が受賞
• AWSのユーザーコミュニティに貢献した方が選ばれる
Copyright © 2017 All rights reserved.7
今⽇お話する内容
Serverless AWS構成でセキュアなSPAを⽬指す!
Copyright © 2017 All rights reserved.8
今⽇お話する内容
過去に作成したSPAなServerlessシステムの知⾒をベースに、よりセキュリティを意識した、別バージョンのシステム
Serverless AWS構成でセキュアなSPAを⽬指す!
Copyright © 2017 All rights reserved.9
の紹介ではなく
東急ハンズの考え⽅「ここは、ヒント・マーケット」
何を売るところですか?とたずねられたら、「それはヒントです!」と言い切りたい。
そう、ここには「できあいの答え」は、ひとつも置いてありません。
全フロアが、何かをつくりたい人、はじめたい人にとっての
「きっかけ売り場」であり、「発想の一歩目」である。
モノ・コト・ヒトのすべてが出会い、すべての新しい価値がそこから生み出される、うれしい場所へ。
東急ハンズHP 「ここは、ヒント・マーケット」とは?https://www.tokyu-hands.co.jp/saiyo/shinsotsu/about/
そんな思いを Serverless Meetup Tokyo にも
Copyright © 2017 All rights reserved.10
今⽇お話する内容
Serverless AWS構成でセキュアなSPAを作成する様⼦を
順を追っていきます!
Copyright © 2017 All rights reserved.11
ちなみに過去に作成した Serverless PointSystem
Copyright © 2017 All rights reserved.12
それは唐突に起こった
ねぇねぇ加藤くん。ちょっといいかい?
n開発・テストも落ち着きつつある2015年 年末頃
忍び寄る大きな影
Copyright © 2017 All rights reserved.13
それは唐突に起こった
ねぇねぇ加藤くん。ちょっといいかい?
このプロジェクト中止ね
n開発・テストも落ち着きつつある2015年 年末頃
Copyright © 2017 All rights reserved.14
⼤⼈の事情により、使われる事がないポイントシステムが完成
Copyright © 2017 All rights reserved.15
システムに罪はない
Copyright © 2017 All rights reserved.16
気を取り直して
Let's cook !
Serverless AWS構成でセキュアなSPAを⽬指す!
そんなノウハウが詰まった
Copyright © 2017 All rights reserved.17
まずはSPAのベースとなる静的サイト
nHTMLやJavascript、画像ファイル等をS3へ設置
nより多くのアクセスに耐えられるようにCloudfrontでCDN化。同時にS3へのアクセスはCloudfrontからしか取得出来ない様に
Copyright © 2017 All rights reserved.18
ドメインの取得とSSL証明書の設置
nRoute 53を使⽤してドメインの取得とDNS登録
nAWS Certificate Managerにて証明書の作成とCloudfront への設置
Copyright © 2017 All rights reserved.19
静的なServerless の完成
これも⽴派なServerless!
Copyright © 2017 All rights reserved.20
次は動的な情報をJSONで返すAPIの⼊り⼝
nAPI GatewayからAPIを作成nCORS(Cross-OriginResourceSharing) 設定を忘れずに
l SPAとは異なるドメインになるのでCORSの有効化を⾏う
Copyright © 2017 All rights reserved.21
動的な情報を処理するFunction
nAPI Gatewayから呼び出されるバックエンドにはみんなが⼤好きなLambda
n実⾏権限(Role)は必要最低限
Copyright © 2017 All rights reserved.22
動的な情報を保持しているデータストア
nDynamoDBのテーブル作成nLambdaの実⾏RoleにDynamoDBへのRead/Write権
限を付与nDynamoDBからデータ取得するLambda、データを保
存するLambdaをそれぞれ作成。
Copyright © 2017 All rights reserved.23
API Gateway 周りをちまちまと
nAPI Gateway に適切なリソースやメソッドでLambdaを紐づけl RESTful APIな思想にて
nデプロイを⾏いJavascript のSDK⽣成を⾏うl SDKはSPAのS3へ保存
nSPA側でAPI呼び出しと⾮同期処理
Copyright © 2017 All rights reserved.24
XSS対策のためにAWS WAF
nAWS WAF をAPI Gateway の前に挟む※AWS WAFはAPI Gatewayに直接つかないので、
Cloudfront経由になる
Copyright © 2017 All rights reserved.25
動的でセキュアなServerless SPAの完成
らしくなって参りました
Copyright © 2017 All rights reserved.26
いよいよ個別ユーザー機能
nCognito で⽤意されているUser Pools(ユーザー認証基盤)を使⽤しても良いが、今回はFederated Identitiesについて
nFederated Identitiesには認証機能は付いておらず認可を⾏う。認可元はOpenIDやSAML等を選べるが、今回は⾃分で作成するCustum Provider(通称Developer authenticated identities )とする
Copyright © 2017 All rights reserved.27
DeveloperAuthenticatedIdentityの仕組み
n認証フローは複数あるが拡張認証フローを使⽤する。⾃作ユーザーとCognitoのユニークなIdentityが対になっていて、ユーザーは受け取ったTokenを使⽤してAWS STS からAWSリソースに対するCredentialを受け取る。
Copyright © 2017 All rights reserved.28
Cognitoの登録
nFederated identitiesよりidentity poolを作成l Authentication providersはcustumでユニークな
provider nameにするl 認証済みのRole auhenticated identitesをデフォルト
で作成
Copyright © 2017 All rights reserved.29
ユーザー登録Lambda
n ID/PASSのユーザー登録Lambdaを作るl DynamoDB ユーザーTableへIDとPassを保存
Copyright © 2017 All rights reserved.30
ユーザー認証Lambda
n登録ユーザーの認証を⾏うログイン処理Lambdaを作るl ID/Passの検証し、作成したCognito identity pool へ
getOpenIdTokenForDeveloperIdentityを⾏う。
Copyright © 2017 All rights reserved.31
クライアント処理とセンシティブなAPIの保護
n返却されたCognito Tokenをクライアントに保存ngetCredentialsForIdentityを使⽤して、AWS STSから
Credential(accessKey / secretKey / sessionToken)の取得して、apigClient.credentialに保存
nセンシティブなAPIのメソッドに対してAWS_IAMの認証設定
nCognitoのAuthenticateRoleに上記のメソッドarmを許可設定
Copyright © 2017 All rights reserved.32
ユーザー認証付きのセキュアなServerless
しかし問題が。。。
Copyright © 2017 All rights reserved.33
有効期限に注意
nSTSのCredential有効期限は最⼤1時間l Cognito Tokenで再取得
nCognito Tokenの有効期限は最⼤24時間l ID と パスワードを送れば再取得可能だが、クライアン
トに保管するわけにはいかない
nログインをそれ以上維持させたい場合l 独⾃認証部分の永続の為にToken化
Copyright © 2017 All rights reserved.34
ならば Json Web Token
nHeaderとPayloadとSignatureという3つのセグメントから構成される Token
1 Header署名アルゴリズムなどを含むJSON
2 Payload実際に送信したいJSONデータそのもの
3 SignatureHeaderとPayloadをBase64エンコードしたのちに、“.” で連結した文字列に対して、
Headerに指定されたアルゴリズムで署名
Copyright © 2017 All rights reserved.35
JWTの何が良いのか?
nセッションや単なるTokenとの⼤きな違いは、 Payloadにクライアントに渡しても良いデータ(ユーザーID等)を記載するので、疎結合となっているServerlessにとってはデータ使い回しの勝⼿が良い。
nクライアントとAPI側でTokenのやり取りがあるが、もし悪意あるユーザーが書き換えを⾏なっても、 Signature部分にてチェックを⾏える。- 復号できなければ不正なTokenとなる
nCognitoのTokenもJWTで構成されているl クライアント側でのTokenの取り回しが共通化
Copyright © 2017 All rights reserved.36
実際のJWT(Cognito)
Copyright © 2017 All rights reserved.37
独⾃ Json Web Tokenの準備
nPayloadはユーザーに渡しても良い使い回す情報を⾃由(JSON形式)に記載
nHeaderはtyp:JWTのalg:HS512( SHA-512 hash )
nSignatureに使うキーは可能であれば別々にしたいl 漏れた場合に別のユーザーになり済ませてしまう- KMS(Key Management Service)を使⽤
Copyright © 2017 All rights reserved.38
Key Management Service
nマスターキーとデータキーがあるl 実際のデータを暗号/復号化するのはデータキーだが、
データキー⾃体の⽣成と復号化をできるのはマスターキーとなっている。マスターキーの⽣データは取得する事が出来ない。
nマスターキーはIDしか無いので、暗号/復号化するLambdaのRoleだけにデータキー操作の権限を付与すれば、マスターキーIDがあっても開発者でさえ復号化する事が出来ない。- データキーをJWTのsignatureで使⽤するハッシュ
キーとする
Copyright © 2017 All rights reserved.39
暗号化:ログイン処理LambdaにJWT作成追加
nマスターキーIDを元にgenerateDataKeyで、⽣データキーと暗号化データキーを取得する。
n準備していたJWTのHeaderとPayloadを、それぞれBase64エンコードしてピリオドでつなぎ、取得した⽣データキーをsha2ハッシュ値としてして暗号化したものがsignatureとなり独⾃JWTが完成
n該当Lambda RoleにKMSの実⾏権限を付与
n最終的にCognito Tokenと独⾃JWTが返却となる。独⾃JWTの有効期限についてはAPI側とクライアント側で⾃由に合わせる。
n⽣データキーは即時に削除し、暗号化データキーをユーザーと紐付けてDynamoDBに保存する
Copyright © 2017 All rights reserved.40
復号化:独⾃JWTの検証Lambdaの作成
n独⾃JWTの正当性を検証する為に、KMSへの復号化権限を持ったRoleがついたLambdaを作成
nTokenの有効期限内であれば、マスターキーIDとユーザーに紐付いている暗号化データーキーを元にkms.decryptを⾏い、⽣データキーを取得する。
nJWTの HeaderとPayloadを、それぞれBase64エンコードしてピリオドでつなぎ、取得した⽣データキーをハッシュ値としてして暗号化したものが、signatureと⼀致すれば正当なTokenとなる
Copyright © 2017 All rights reserved.41
認証を⾏いたいAPIへ実装
nAPI GatewayにてオーソライザーとしてLambdaを登録し、検証を⾏いたいメソッドにて認証として選択
n認証が必要なAPIを呼び出す際には、クライアントで保管している独⾃JWTをヘッダーに組み込んでコールする
Copyright © 2017 All rights reserved.42
セキュアなSPA で 良い感じなServerless
Copyright © 2017 All rights reserved.43
Cognitoでこんなセキュアな事も
n⾃分のデータにはアクセス出来るが、他の⼈のデータへはアクセス出来ない
nS3プレフィックスやDynamoDB ファイングレインアクセスにて、${cognito-identity.amazonaws.com:sub}変数が可能になる
Copyright © 2017 All rights reserved.44
ありがとうござました
何かのきっかけやヒントになればうれしいです
Copyright © 2017 All rights reserved.45
エンジニア募集中!
求むエンジニア!
ハンズラボは積極的に技術者採用中です。