日本酒醸造管理ツールの技術仕様

以前公開した日本酒醸造管理ツールの技術仕様、主にCognitoの権限とかセキュリティに関して。
一般的に、ここまでセキュリティを高くする必要はないし、明らかにオーバースペックではある。

今回の記事は半年くらい前に書いていた文章。
自分用のメモみたいな。
時が経ちすぎて自分でも結構忘れてるしなんで公開してなかったのかも覚えてないからどこか書き直したいところがあったのかな、覚えてないけどとりあえず公開して供養。
セキュリティの要件ベースでまぁ面白みはないけど、セキュリティにカジュアルな面白みなんて存在しないし興味ある人だけどうぞ。
供養、ナムナム。

セキュリティこだわりポイント

サービスと認証をドメインレベルで完全に分離する

ユーザはサービス開発者が何か悪いことをするのではないかと疑ってサービスを利用すべき。
ユーザはサービス開発者を信じてはいけない。

Federated Identityで認証する場合、自ドメインで開発者が手の届く場所でID/Passを入力させることが出来る。
そのサービス開発者なら難しいことなくJavaScriptでID/Passをスッポ抜くことが出来てしまう。
仮にサービス開発者が善人だとしても、サイトの改ざんや、広告からの良からぬスクリプト実行なども想定するべき。

なので、この2つをしないようにした。
・サービスドメインでID/Passを入力させない。
・サービスドメインでログインボタンを押させない。

したがって、認証用の外部ドメインに飛びOpenIDでログインして、サービスドメインに戻ってくるようにした。
サービスドメインでは認証に関わる入力や操作を一切しない、させない。

一般に、Facebookログインボタンだけが置かれた外部ドメインに飛ぶ方が怪しいらしい。
しかしここは見た目の怪しさよりも実際のセキュリティの高さを優先し最良の方法をとった。

ユーザに必要以上の権限を与えない

サービス開発者はユーザが何か悪いことをするのではないかと疑ってサービスを提供すべき。
サービス開発者はユーザを信じてはいけない。

よくあるのがネイティブアプリだからってDynamoDBとかFirebaseとかの書き込み権限を与えてしまうパターン。
これは良くない。
いくら書き込み前にvalidateしても所詮はユーザの手元でのチェック。
ユーザに与えた権限は開発者の意図しない形で行使されるものと思うべき。

Androidアプリなんて逆コンパイルして再ビルドして実機にインストールするくらいのことは出来る。
特に危ないのがAndroidアプリで中身がC#で書かれてるアプリ、あんなもん完全に逆コンパイルしてくださいと言っているようなもの。

なのでFederated Identityで安易に権限を与えてはいけない。
権限を与えるにしてもポリシーでギチギチに固めるべき。

認証情報やアカウント情報など保護すべきデータを保持しない

認証情報はOpenID Connect IdP(今回はFacebook)が管理。
アカウント情報はCognito UserPoolが管理。
ApiGatewayの認証はCognito UserPoolで。
IoT(MQTT)の認証はCognito Federated Identity。
権限はCognito Federated Identityに紐づけてIAMロールとIoTポリシーで管理。

DynamoDBにはUserPoolのsubしか持たない。
なのでOpenID Connect IdPがクラックされない限り、認証情報や個人情報を抜くことも出来ないし、権限を得ることも出来ない。

WebAPIを実行する時の認証

Webアプリ/ネイティブアプリ共通。
Cognito UserPoolのJWTトークンで認証する。

構成:
ブラウザ ー(HTTPS)→ Cognito UserPool ー(OpenID Connect)→ Facebook

認証:
UserPoolで認証して、DynamoDBのAccountテーブル(UserPoolのsubがキー)でBreweryテーブルに対する権限をチェックする。

ネイティブアプリ:IoT Core(MQTT)でPub/Subする時の認証

前提となる問題点:
MQTTでの認証はFederated Identity。
UserPoolで認証できればBreweryとの紐付けチェックは簡単だけど、Federated Identityからチェックしなければいけない。

構成:
Cognito Federated Identity ー(統合)→ Cognito UserPool

事前準備:
Breweryが作成されたタイミングで、Brewery単位でIoTポリシーを作成。
AccountテーブルとBrewreyテーブルが紐づくタイミングで、Federated Identity IDに対してBrewery単位のIoTポリシーをattach。
これでFederated IdentityからIoTポリシーベースでBreweryに対して権限があるか否かを判定できる。

認証:
MQTTではFederated Identityで認証して、Accountテーブル(UserPool認証)を経由することなくBrewreyに対して権限があるものにのみConnect/Pub/Sub権限が与えられる。

DynamoDB Streams、冪等性を以て整合性を保証する

冪等性が保証されることで、テーブル間の整合性を保証する流儀について。
分散DBが当たり前のこのご時世、トランザクションを使ってAll or Nothingで整合性を取る時代は終わった。
Streamsでlambdaを起動することで、Push型のObserverパターンとしてlambdaでレコードを数珠つなぎに処理出来る。
今回の設計でいうとStreamsで仕込み配合の更新をトリガーして、仕込み単位の作業日程に展開して、複数の仕込みを集計して実作業用のレコードを作るということをしている。
Streamsのエラー制御により冪等性が保証されることで、最初のレコードの状態に対する後続テーブルの対応レコードの状態を保証出来る。