さわらブログ

さわら(@xhiroga)の技術ブログ

データで振り返る、Cognito屋さんとしてサークル初参加した #技術書典 7

2019-09-22、 #技術書典 7にCognito屋さんとしてサークル参加しました。
初めて技術同人誌を執筆・販売し、嬉しかったことから反省していることまで様々な思いがあるので、まとめます。

f:id:hiroga_cc:20190923092125p:plain

なお、「Cognito UserPool 実践入門」はBOOTHで頒布中です!
hiroga.booth.pm

振り返って

サークルとして #技術書典 に参加したのは楽しかったですが、本気で実用書を届けたかった。それには中途半端に終わったのが残念でした。
もともとAuth屋さんのススメもあり、ふらっと応募したところから始まった #技術書典 。Cognitoについて語れる方がたくさんいて、とっても嬉しかったです。
一方で、「Cognito UserPool 実践入門」は、UserPoolのユーザーグループやMFAまでカバーして、UserPoolに困っている人の実用書でありたかったな、という思いがあります。私にとって実用書とは、「困っている時に、すぐに逆引きできる本」です。

実はもともと1,000円で頒布予定だったのを、前日に500円に値下げした経緯があります。本当にUserPoolの入門と言えるのか不安になったので...かっこ悪いですね。とはいえ、ユースケースがハマれば役に立つ本なのは間違いないと思っています。
決められるところでしっかり決める人として認知されていこう(本のクオリティでも、仕事でもなんでも)と思いました。

Cognito UserPool 実践入門について

  • ページ数: 27ページ
  • 図版数: 6点
  • 執筆開始(リポジトリ作成日): 2019-07-14
  • 体験版の頒布開始: 2019-09-14
  • 執筆終了(技術書典7以前の最終編集日時): 2019-09-21
  • 総執期間: 70日
  • 執筆時間(Wakatimeで算出)(表紙・図版等作成時間を除く): 28時間48分
  • 販売価格: 500円

頒布について

経費

  • DLカード印刷数: 300枚
  • DLカード印刷費用: 5,054円
  • その他経費(見本印刷、ポップ印刷、ホワイトボード、売り子謝礼): 約8,500円

※ 物理本は初めからスコープ外でした。

売上

  • 非チェック数: 120名
  • 技術書典7購入数: 108冊
    • 技術書典7 現金購入: 43冊
    • 技術書典7 かんたん後払い購入: 65冊
  • BOOTH購入数(2019-09-23まで): 18冊
  • 総売上: 63,000円

利益

  • かんたん後払い手数料: 650円
  • 利益:約48,850円

フィードバック

来場者の方の声

  • Cognitoにこれから触る方(学習)、Cognitoへの乗り換えを検討している方(業務)、すでに触っていて知識の整理がしたい方、で 2: 1: 2、くらいでしょうか。実際にユーザー移行を検討している方の手元に届いたのは嬉しかったです。
  • カスタム認証について知りたい、という方が2人いました。カバー外で申し訳ないです。
  • ユーザーグループとアクセストークンの権限について知りたい、という方が2人いました。カバー外で申し訳ないです。

読者の方の感想

ぶっちゃけ私の本だけで入門はできないよなぁ...とは薄々感じていました。(ごめんなさい。でも一読の価値はあるはずです)
全範囲をカバーしてしまうと公式ドキュメントの再発明になるので、副読本アピールをしたかったです。そういえば中学校の教科書って、図版がメインの副読本ありましたよね。理科とか社会とか。

反省

  • 販売に必要なグッズの購入をサボってたので当日の朝ドンキで頑張って探したのですが、事前にAmazonでポチっておけばスムーズだった
  • 感想ツイートどんどんしてほしいですね。おまけ本をプレゼントするとかの代わりに。
  • 書くのが大変ではないところだけ書いて体験版としてリリースしちゃうのが良さそう。

その他嬉しかったこと

  • Cognito利用されている方とお話できたことですね!
  • ちょまどさんのサインを再びいただけたこと!今後もっと自分が強くなって、ちょまどさんはこんな強い人からも支持されているんだ!と言われるようにしたいですね!!!!!

Cognito UserPool 実践入門 では書けなかった闇をブログに記す #技術書典

#技術書典 で "Cognito UserPool実践入門" という本を販売します。

BOOTHでも取り扱っています。 hiroga.booth.pm

これ、元々プロジェクトで経験したUserPool移行の苦労話を書こうと思って始めたのですが、いつの間にか入門書を書いていました。
なので苦労話の方はお蔵入りにしたのですが、もったいないのでここに記します。

Cognito UserPool 実践ユーザー移行 UserPool to UserPool with Federated Identity編

悲劇の始まり

Cognito初心者が絶対つまづく(と私が思っている)設定として、エイリアス属性(IDの代わりにログインに利用できる属性)があとから変更できないことがあります。

f:id:hiroga_cc:20190921161501p:plain
デフォルトで設定されるエイリアス属性

デフォルト設定だとメールアドレス・電話番号でのログインは不可能ですが、この設定は後から変更不可能です

私が関わっているプロジェクトもUserPoolを利用していたのですが、エイリアス属性に設定されていたのはメールアドレスだけでした。
そこにきて、「電話番号でログインできるようにしたい」という要件が登場したわけです。

初めはちゃちゃっと対応できると思ってましたが...Federated Identityを併用していたことで話が大変になります。

堅牢なFederated Identity

正直言ってUserPoolからUserPoolにデータを移行するだけなら話は簡単でした。
恐ろしいのは Federated Identityとの連携を維持しなければいけないことです。

f:id:hiroga_cc:20190921162412p:plain
⑤アプリケーションが利用するユーザーの一意識別子はFederated IdentityのIdentity ID

UserPoolとFederated Identityを連携している場合、バックエンドのアプリケーションで利用するユーザー識別子には Federated IdentityのIdentity IDを利用しなくてはいけません(じゃないと、OpenID Provider → Federaed Identityでも利用している場合に困りますよね?)

ところが!Federated IdentityのIdentity IDに対して、管理者権限で任意のログイン情報を紐付けることは不可能なのです
(それ自体はセキュリティの観点からあるべき姿だと思いますが...。)

f:id:hiroga_cc:20190921163333p:plain
古いUserPoolのユーザープロファイルとFederated IdentityのIdentity IDが紐付いている。管理者が勝手に新しいUserPoolのIdentity IDを連携することはできない。

これを解決するための、たった一つだけ許されたやり方...それは、管理者がユーザーの代わりにログインすることです。
それならユーザー移行Lambdaトリガーで余裕じゃん!と思われるかもしれませんが、余裕ではありませんでした

たったひとつの冴えないやり方

結論から言えば、ユーザー移行Lambdaトリガーを以下のように実装すれば対応可能です。

f:id:hiroga_cc:20190921170014p:plain
UserPool to UserPool with Federated Identity のユーザー移行

  1. クライアントは新UserPoolにログインを試行
  2. 新UserPoolはユーザーが見つからないのでユーザー移行Lambdaトリガーを起動
  3. Lambdaはユーザーの代わりに旧UserPoolにログイン。この際にIdToken(旧)を受け取る。
  4. Lambdaは新UserPoolに対して AdminCreateUser アクションを実行し、ユーザー移行Lambdaトリガー内でユーザーを作成 ※1
  5. Lambdaは新UserPoolに作成したユーザーとしてログイン。IdToken(新)を受け取る。
  6. 新旧のIdTokenを使って、 Federated IdentityにgetOpenIdToken アクションを実行。結果、旧のユーザーで取得したIdentity IDが新のユーザーに紐付く
  7. LambdaはエラーをThrow(自爆)(そうしないと、UserPoolが後続処理でユーザーを作成しようとし、そのユーザーはStep2で作成済みでエラーになるため)
  8. UserPoolはクライアントにエラーを返す ※2

※1 ユーザー移行Lambdaトリガーは、その返り値でUserPoolにユーザー作成のための情報を渡すLambda。これはバッドハックです。
※2 クライアント側もエラーを握りつぶすように修正しました。

なお、これに加えてパスワードリセット時は旧のUserPoolのパスワードをリセットするように設定する必要があります。

参考までに、通常のユーザー移行Lambdaトリガーのフローも載せておきます。

f:id:hiroga_cc:20190921171501p:plain
通常のユーザー移行Lambdaトリガーのフロー

シンプル!!!!!

しんどさ

検証のためにUserPoolになんどもユーザーを作成するのが一番大変でした。
その結果生まれたのが cognito-cli です。

github.com 注意: ちょっとバグってます。後で直す。

CLIでUserPoolの非管理者用APIを立たけるようになったことで生産性が爆上がりました。

それからデプロイもしんどかったです。Cognito UserPool 実践入門 でも書きましたが、ユーザー移行Lambdaトリガーは 2019-09-21時点でCloudFormation非対応なので...。
たぶん世の中的にCognitoをCloudFormationで管理している人が稀なのですが(だってそんなに更新しないでしょ?)

でもやってよかった

同じ問題にぶち当たる人は二度と現れてほしくないですが(だから執筆したんです!)、私個人はとても勉強になりました。

  • OpenID ConnectのIdTokenの中身を見たり...
  • Cognitoの仕様にちょっとだけ詳しくなったり...
  • 初の技術書典サークル参加につながったり...

人間必要になったときが一番勉強するんで、認証認可について学びを深められたのは良かったです。

最後に...

色々書きましたが、認証・認可をマネージドに済ませてアプリに集中するには、Cognitoはとてもいいサービスだと思っています。
もしCognito検討する人がいたら、公式ドキュメントに加えて私の本もチラッと見ていただければ幸いです!!!!!
hiroga.booth.pm

「あとで読む」を読む - DNSの勉強法、Istio、jlink、Bluetooth

f:id:hiroga_cc:20190529163402p:plain

夏休みで時間ができたので、日々のPocketの積ん読を消化していきました。

Auth0 Ebooks

Identity Resources - Webinars, eBooks, Case Studies - Auth0

Auth0の資料が認証認可の基本の理解のためにかなり良さそう、という話。
Etheriumについての解説まであるんだね。Auth0とEtherium...?

情報セキュリティ白書 2019

情報セキュリティ白書2019:IPA 独立行政法人 情報処理推進機構

無料なのでどんなものかと思って読んでみた。実装レベルの話ではなく、国内外のセキュリティ動向を概観したいときに読む本だ。

DNS Study

DNS Study

DNSの仕組み、どこかでちゃんと抑えなきゃ...と思ってた。
ふわっと本を読もうと思っていたら「本に書いてあることはだいたい間違っています」と来た...そうなのかもしれないけどさ、その言い方って怪しい健康食品と変わらないよね...

マイクロサービスアーキテクチャ向けにサービスメッシュを提供する「Istio」の概要と環境構築、トラフィックルーティング設定

マイクロサービスアーキテクチャ向けにサービスメッシュを提供する「Istio」の概要と環境構築、トラフィックルーティング設定 | さくらのナレッジ

サービスメッシュについて頭の中が整理されてきた。
マイクロサービスの場合には通信先のサービスのIPアドレスを事前に知ることができない、という制約でどうするか。
AWSのCloudMapやKubernetesのServiceのようにサービスディスカバリを用いることもできるし、各コンテナにサイドカーとしてのプロキシサーバー(データプレーン)を置く、という選択もできる。後者のほうが多機能なものが多い、ということのようだ。

アプリケーション配布用に小さなJREを作る

アプリケーション配布用に小さなJREを作る

JRE入のコンテナイメージが重い!って問題に対処できるらしい。
全然分かってなかったんだけど、つまり、
JREJVMJavaの標準ライブラリから成る
Javaの標準ライブラリにはたくさん機能があるが、そこまで使わないことのほうが多い
・だからカスタムJRE(=自分が使うライブラリとJVMだけのJRE)を作ってしまおう!
ということらしい。

Bluetoothで山手線の乗降パターンを追跡してみた

高木浩光@自宅の日記 - Bluetoothで山手線の乗降パターンを追跡してみた , ユビキタス社会の歩き方(6) Bluetoothの「デバイスの公開」「検出可能にする」..

面白い!これを追いかけるだけで、例えば店頭で「あなたは何回目の来訪です」というのが言えちゃうわけか。
(あなた、が誰かはわからないとしても)

NASA Books

NASA e-Books | NASA

NASAの無料公開している電子書籍システム開発に関する本があったのでダウンロードしました。

Amazon EventBridge

Amazon EventBridge入門 PagerDuty連携を試してみた | DevelopersIO

AWS版のZapierってことかな?

20日間fish体験記

macOSのデフォルトのログインシェルがbashからzshになるってことで、せっかくなら予めzsh慣れておこう → いや、zshでなくてもいいよね?
ということでfishにしてみましたが...。

ちなみにこんな設定でやってます。
github.com

感想

メリット

・fishにしたことで、生産性意識の高い人の情報が自然と流れてくるようになった。
(例えばghq, peco, z, etc...) ・シンタックスハイライトが賢い!
・promptが関数でできてる思い切りが分かりやすくて好き。

デメリット

bash文法非互換なので、仕事用のシェルを検証するときにいちいちbashに切り替えが必要
・たまにVSCodeのコンソールの表示がバグる(超ダサフォントになる)
・nvmの設定がbashで書かれているので使えない...こういうの他にもありそう。 ・環境変数の設定をbashと共有するのがしんどい

使いこなせていないと感じるところ

・コマンド履歴が賢い、というかおせっかいに感じる。もっと慣れれば違いそう... ・POSIX互換の文法よりはスッキリしている...らしいけど、シェルってそんな毎日書くものでもないし多少文法おかしくてもいいじゃん...?

今後について

bash非互換はつらいので、互換性のある拡張をいれつつ、もしかしたらzshに移るかもしれません。
うーん。

自分的Dockerのユースケースをまとめてみた

ふだん雰囲気でDocker使っているのですが、もっと自由にDockerを使えるようになりたい!
ということで、自分的なDockerのユースケースを振り返ってまとめてみました。

1. リポジトリごとの開発環境の構築

リポジトリごとに開発で利用するPythonの環境を、Dockerを使って構築しています。

コマンド

`docker-compose run --rm python /bin/bash

version: '3'
services:
  python:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./src:/root/work

2. 開発用のデータベースの構築

command

(開発用のサーバーの起動前などに) docker-compose up -d dynamo

docker-compose.yml

version: '3'

services:
  dynamo:
    image: amazon/dynamodb-local:1.11.477
    ports:
      - "8001:8000"

3. ミドルウェアの実行

技術書典で出品するPDFファイルのビルドのために利用しています。 (Thanks for カウプラン機関極東支部 さん!)

コマンド

docker-compose run --rm review

docker-compose.yml

version: "3"
services:
  review:
    image:
      kauplan/review2.5
    volumes:
      - $PWD:/work
    entrypoint:
      /bin/bash -c "cd /work; rake pdf"

4. cliツールのバイナリを直接インストールする代わりにする

例えば jq のバイナリを直接ローカルに置かない。
alias jq="docker run -i --rm mbentley/jq"

jq以外にも、例えばβ版のcliツールを利用する場合なんかは安心して使えますね。

参考
hub.docker.com

反省

ブログを書くに当たり、改めてDockerについて学びがありました。

  • 基本的に docker-composeを利用すること。

  • docker-compose up には --build オプション、 docker-compose run には --rm オプションをつけること。
    ...しかし、どうして docker-compose run には --build オプションがないんだろう。一貫性が足りないよね。

github.com

  • Dockerの仕様として、ADD, COPYで取得したファイルのハッシュが代わっていたら、それ以降のRUNのキャッシュは利用されないこと(つまり、 package.json が変更されていれば npm install は再実行される)

個人のメールアドレスに届くGitHub・CircleCIの通知を会社のアドレスに転送する

justInCaseでは、リポジトリをBitBucketからGitHubに移行する計画があります。

そこで個人のGitHubアカウントを使って開発をしていますが、一つ問題が。
仕事のPRやビルドの失敗のメールが、個人のアドレスに流れてしまうのです。

GMailのメールの転送設定で解決できそうなので、やり方をメモしておきます。

1. 転送先のメールアドレスを設定

公式のガイドに従って特に躓かずに設定できました。

support.google.com

2. フィルタの作成

こちらも公式のガイドどおりに。
support.google.com

こんな感じのフィルタになりました。 f:id:hiroga_cc:20190727110931p:plain

以上、特別難しい手順はありませんが、誰かのお役に立てば幸いです。

ググって出てきたCognito UserPoolのベストプラクティスを雑にまとめる

(このブログは、 #技術書典7 で出展する「Cognito屋さん/ Cognito ユーザー移行入門(仮)」の下調べのために書いてます.)

タイトル通り、ググって出てきたCognito UserPoolのベストプラクティスを雑にまとめていきます。

Security / Best Practice for poolData (UserPoolId, ClientId) in a browser JS app

github.com

UserPoolIDとClientIDは、JSのコード内で公開していいの?という質問。
スレッドにある通り、これらの値は unauthenticated APIs のリクエストにしか使われないので大丈夫。

Cognito user pools, in my experience, are terrible to work with

www.reddit.com

ベストプラクティスじゃないけど...Cognito使うのしんどいよね、って話。
いっそ新しいサービス出したらいいんじゃない?って指摘には私も同意。
Cognito is a flawed product that should become redundant. AWS should either build a new service with a new name or build a backwards incompatible Cognito 2.0.

[レポート] サーバーレスアーキテクチャデザインパターンとベストプラクティス! #reinvent #ARC305

dev.classmethod.jp

たしかに、Cognito使いたい人ってAPI Gatewayを認証付きで提供したい人だよね。
1.一時的なAWS認証 or 2.UserPoolのトークン or 3.Lambdaオーソライザー。特に 1.と2. は混同しやすいのでは?

HOW TO USE NEW ADVANCED SECURITY FEATURES FOR AMAZON COGNITO USER POOLS

noise.getoto.net

せっかくだしMFAもちょっと触ってから本を書いたほうがいい気がしてきた

SaaS Identity and Isolation with Amazon Cognito on the AWS Cloud

https://aws-quickstart.s3.amazonaws.com/saas-identity-cognito/doc/saas-identity-and-isolation-with-cognito-on-the-aws-cloud.pdf

弊社(justInCase)のアーキテクチャじゃんこれ!!!知らずしてここにたどり着いたんだなあ...
CloudMapを使ってるとこだけが違う。

Are email addresses supposed to be case-sensitive?

https://forums.aws.amazon.com/forum.jspa?forumID=173&start=0

そうそう、メアドが大文字小文字違いで登録できちゃうんだよね。