冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

Serverless Framework + API Gatewayのアプリケーションに認可を追加する

しばらく合同勉強会の資料準備とシュバルツバース探索など優先順位が高いタスクが積まれていて、手をつけておりませんでしたが、ようやく再開。今回は完全に備忘録的なレベルです。

で、今回は、表題の通り認可を追加してみたいと思います。今回仮で組んだものとは違いますが、最終的な構成のイメージとしては以下の様な感じ。

  1. 認証のプロバイダはアプリケーション外
  2. アプリケーションは認証されていることを前提に個別に認可

つまり、アプリケーションは「その人が本人であること」を確認する責任をおいませんが、「その人がアプリケーションを使う権限をもつこと」を確認する責任はおいます。これが、Serverless SPAであればアプリケーション内に認証プロバイダを持ってもいいと思います。用途次第ということで。

いつもの如く、具体的なコードはこちらのリポジトリをご査収ください。

github.com

CognitoでUserPoolをつくる

とは言え、いくつもサービスが乱立してしまうのもまだ面倒いので、とりあえず認証プロバイダはアプリケーションのリソースに突っ込んで設定、アプリケーションのデプロイと同様にUserPoolもデプロイされる様にしました。認証プロバイダの切り離しはまたあとでやってみたいと思います。肥大しがちなserverless.ymlの分割とかも、プロジェクトのファイル構成の観点からやってみときたいし。

api.wp-kyoto.net

この記事を参考にしました。特に問題なくデプロイまで出来ます。その前にAWS Glueの検証してたのをすっかり忘れてて、違うリージョンみながら「デプロイされねーな」とか思ってた無駄な時間があったくらいです。

なお、記事にはクライアント側が書かれていませんが、私はクライアントのページを用意するのも面倒いので(フロントエンド苦手)、認証用のLambda関数を追加で作りました。sign_upとconfirmとsign_inとrefresh_tokenができる様にしあります。認可という観点でいうと、トークンがあれば作れるはずなので、このあたりがちょっと雑なのは否めません。

ただ、boto3での認証をどのAPIを使えばいいのかいまいちよくわからなかったので、すこしググりました。で、参考にしたのはイカです。Pythonの場合はクライアントサイドで動く訳ではないので、admin_initiate_authを使う、という解釈ですが、あってるのかな?

qiita.com

閑話:UserPool IDについて

認証系のLambda関数から読み出している COGNITO_POOL_CLIENT_ID は作成したUserPoolのIDで、このサンプルを使う場合はデプロイ後に設定しておいてあげる必要があります。その意味で面倒な構成にはなっているのですが、認可の部分のコードをみていただければ分かる通り、認可に必要なのはトークンのみです。そのため、実際に認証プロバイダを切り離して構成する場合にはこのあたりの面倒くささはなくなるとおもいます。

閑話休題:認可を追加する

で、認可。認可ロジックをLambda関数として実装して、対象となるLambda関数のhttpイベントに authorizer を追加すればいいだけでした。

blog.naoshihoshi.com

認可ロジックでは、トークンからユーザ情報にアクセスできるか確認して、エラーがなければ対象となるLambda関数に実行権限を与えるためのJSONオブジェクトを返しています。このJSONオブジェクトをうけてAPI Gatewayがよしなにしてくれる模様。

実行する

認証プロバイダから彫られた認証済みトークンを Authorization ヘッダに渡して、API GatewayのURLを叩くだけです。

curl -H "Authorization: xxx" -d '{"event": "今日はカポエイラに行く", "insight": "首が少し痛いので心配"}' -X POST https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/my-assistant/life_log

Authorization ヘッダがない場合は以下のエラーメッセージが返ります。

{"message":"Unauthorized"}

ちなみに、この認可はAPI Gatewayを通る場合に有効です。認可対象のLambda関数を直接実行する場合( sls invoke コマンドなど)は、認可なしに実行可能となっています。

まとめ

Serverless FrameworkもAPI Gatewayもかなりよしなにしてくれるので、認証・認可周りは非常に楽に開始できるな、と感じました。まあ、認証基盤はそれだけで一大プロジェクトになる要素を持っているのですが、そこまで突っ込んでやるのが目的ではないですし。今回検証したかったことは認可の追加が楽かどうか、という観点なので、その点では知りたいことを確認できた感じです。

2017/10に読んだ本

シュバルツバース探索がマジ忙しいです。

先月読んだ本

印象的な本

フィクション系

ランドの新刊をようやくフォローしたところですが、これはまだ終わってないので、なんとも評価し難いところです。ワクワクはしておりますが。それよりも、今月はすごく力のある作品に出会えたことが印象的でした。

いや、絵の好き嫌いはあるんですけど(割と苦手なタイプの濃い絵)、それをぶっちぎる良いセリフがあったんですよ。 ストーリーは雑にまとめると「アポカリプス + 火星の人」という感じです。こっちはワトニーとちがって仲間がいますが。で、「火星の人」を例えにだすからには、科学への視点というかスタンスが素晴らしいわけです。それでいて少年漫画っぽさも溢れているんですね。この作品の魅力はこのセリフに集約されるんじゃないかと思います。

「科学ではわからないこともある」じゃねえ
わからねえことにルールを探す
そのクッソ地道な努力を
科学って呼んでるだけだ……!!

早く2巻買おう。

黄昏のブッシャリオン (カドカワBOOKS)

黄昏のブッシャリオン (カドカワBOOKS)

タイプブッダのプラモが欲しいです、誰かキット作ってください。 とまあ戯言はともかく、なんだろう、設定の濃さの割には表現もストーリーも硬派だし、なんかUSJの読後感みたいなものを感じさせる作品です。わりかし無茶な設定だとは思うんですけど、説明はほどほどに言い切ってしまうというのが表現の力強さに繋がって、一気に読めてしまいました。 まだ、ストーリーとしては終わってないし、仕掛けもあるようなので続きに期待ということで。

ノンフィクション系

10月はこっちのジャンルが少なめだったんですよね。その中でも割と厳選して読めたと思います。

「まちづくり」から「まち直し」へ/パタンランゲージと「修復の原理」

「まちづくり」から「まち直し」へ/パタンランゲージと「修復の原理」

中埜博(ナカノ ヒロシ) – やわらかいパタンランゲージ

「やわらかいパターンランゲージ」で出版された本。中埜博さんの本で、以前は小冊子のような形でオンデマンドで売り出されていたように記憶していますが、Kindle Unlimitedにこのシリーズの冊子が全てラインナップされていました。アレグザンダーの関連原著に当たるのは、書籍の金額からして割とハードル高いので、こういう実際的な本があるのは非常に良いことではないかと思います。建築家ではなく、パターンランゲージの活動に参加する市民を対象に書かれているので、重要なエッセンスのみ抽出されていてサクッと読めます。 他の冊子も順次読んでいきたいと思います。

目からうろこの線形代数

目からうろこの線形代数

数学の本はやはり読んでいるだけでは難しいところがあるのですが、この本はなかなか食らいついて行けるように書かれてました。高校の時にベクトルの問題は割と得点源だった記憶があるので、もしかしたら少しは線形代数への苦手意識はないのかもしれません。無料のセール中に押さえておいてよかった。今度ノート片手に読み返してみようと思います。

2017年9月に読了した本

やっぱり本はいいですね。最近は業が深そうな作品も割と

今月読んだ本

印象的な本

フィクション系

今月は何と言っても「皆川亮二本」ですね。

スプリガンで厨二ごころをくすぐられ、ARMSでそれを開花させられ、これを読むためだけに毎週サンデーを購入してたと私にとって、皆川亮二という漫画家は青春そのものと言っても過言ではない訳です。そんな皆川亮二についてのアレヤコレヤをじっくり堪能できる本とか、もう買うしかないですよね?ARMS読み返したい、ADAMAS読みたい。

エヴォリューションがーるず

エヴォリューションがーるず

安定の草野原々ですね。脳の作りが知りたい作家の一人です(他は酉島伝法と小林泰三)。オススメしたいんですが、作品が読まないとわからない類の読後感を持っているため、ビブリオバトルなどのフォーマットに向かないという致命的な欠点を持っています。

「俺はこういう正解するカドが見たかったんだよ?」という感じで物申したくなる作品。ここまで最初の構想の中に入っていての作品だとしたら大したものです。余談ですが、描かれている舞台が地元に非常に近くて、場所的に友人が住んでいる地域なのではないかと思ってます。また、作中に出てくる作家名で読書遍歴が私に近そうな感じがして、ちょっと同類相憐れむのような感触。

ノンフィクション系

読もう読もうと思っていた名著をようやく読みました。

失敗の本質―日本軍の組織論的研究 (中公文庫)

失敗の本質―日本軍の組織論的研究 (中公文庫)

買ったときのキャンペーンカバーに某都知事が出ていて、今となってはかなり失笑を買いそうな印象になっているのはご愛嬌。この本の価値が下がるものではありませんね。よく野村克也が言っている「負けに不思議の負けなし」というのがよくわかります。これで負けなかったら相手のチョンボがよほどだったんだな、と思うレベルでやらかしまくっている。分析もわかりやすく、やはり一度は読むべきだったな、と思いました。

悟らなくたって、いいじゃないか 普通の人のための仏教・瞑想入門 (幻冬舎新書)

悟らなくたって、いいじゃないか 普通の人のための仏教・瞑想入門 (幻冬舎新書)

以前、「ブッタとシッタカブッタ」という本に触れたことがありましたが、同じような印象を持った本です。出家するのではなく、在家として現実の物語に関わりながら、どうやって心の平穏を保つのか、そこに仏教がどう関わっていくかというのがわかりやすく書かれていました。瞑想難民という言葉がすごくわかりやすい。早速、瞑想のやり方を変えました。

不惑になります

とかさんざっぱらネタにしてたんですけどね、

数え年で四十歳のこと

らしいですよ!もう過ぎてました。人生は依然ラビリンス。

というわけで今年の誕生日から「さんじゅうさい」ネタが使えなくなって少々物足りなくなった誕生日を明日に控えております。まだ三十代。諸々環境の変化ややりたいことの変化はありつつ、そろそろ無駄な悩みは捨てて、どうやって楽しみを積み重ねていくか考えながら日々を過ごしていこうと思います。人生の責任は自分でしか取れませんのでね。

とりあえず来年は本厄なので、筋肉で回避できるように頑張ります。

いつものやつ、置いときますね。

http://amzn.asia/2kmu11A http://amzn.asia/gdCN30r

AWS Glueのお試し:JSONを扱う時に注意事項があるっぽい

本当はもっと先のところまでやりたかったんですが、ちょっといくつか引っかかっているポイントがあって、一つわかったことがあるのでそこだけ先出しします。AWS GlueとAthenaでJSONを取り扱う時の注意事項の話。というか現象はわかったけど、どのアプローチが仕様的に正しいんだっけ?というのは未だわからず。

JSONファイルのクローラは作れたがジョブでデータを扱えない

前々回のエントリで、JSONファイルのテーブル定義を取得するクローラを作ることはできました。

で、これを普通にParquet形式に受け流すだけのジョブを作って実行して見たんですが、以下のようなエラー吐いてこけます。

: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 4 times, most recent failure: Lost task 0.3 in stage 0.0 (TID 3, ip-172-31-19-251.ec2.internal, executor 1): com.fasterxml.jackson.core.JsonParseException: Unexpected character (',' (code 44)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')

カンマのパースでこけてますね。もともと適当にGithubを探していて見つけたJSONファイルで、クローラを作る時にもカンマ区切りのオブジェクトの羅列になるように手を入れています。このオブジェクトの区切り方がおかしいということらしいです。

というわけで、レコードのオブジェクトの区切りをなくす、具体的には }, から } に変えてみることでジョブを実行することができました。返還後のParquetファイルをAthenaで検索することもできています。Athenaに投げたDDLは以下の通り。

CREATE EXTERNAL TABLE IF NOT EXISTS flights.airport_target_test (
  iata string,
  lon string,
  iso string,
  status int,
  name string,
  continent string,
  type string,
  lat string,
  size string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://***/'

Athenaで元データを検索してみる

それはそうとAthenaで変換元のJSONファイルを検索しようとして見たら、

HIVE_CURSOR_ERROR: Row is not a valid JSON Object - JSONException: A JSONObject text must end with '}' at 2 [character 3 line 1]

というエラーになって検索できません。どうにもJSONオブジェクトは } で終われ、と言われているようですが、そうなってるんですよね。

で、色々試した結果、おそらくAthenaとGlueで使っているJSONパーサーが違うんじゃないかという挙動です。元データは、以下のように「人間にとって」可読性がある程度高くなるようにカラムごとの改行を入れたデータでした。これで、Glueのクローラとジョブは実行できます。ジョブで変換したParquetファイルを検索しても、データはきちんと認識している模様。

{
    "iata": "UTK",
    "lon": "169.86667",
    "iso": "MH",
    "status": 1,
    "name": "Utirik Airport",
    "continent": "OC",
    "type": "airport",
    "lat": "11.233333",
    "size": "small"
}
{
    "iata": "FIV",
    "iso": "US",
    "status": 1,
    "name": "Five Finger CG Heliport",
    "continent": "NA",
    "type": "heliport",
    "size": null
}
...

Athenaでも検索可能なJSONファイルは以下で、1行1レコードになっていないとエラーになるパーサのようです。

{"iata": "UTK", "lon": "169.86667", "iso": "MH", "status": 1, "name": "Utirik Airport", "continent": "OC", "type": "airport", "lat": "11.233333", "size": "small"}
{"iata": "FIV", "iso": "US", "status": 1, "name": "Five Finger CG Heliport", "continent": "NA", "type": "heliport", "size": null}
...

あー、面倒臭い。

まとめ

まずこういうケースでバルクデータっぽく使われる場合のJSONの仕様ってあったっけ?というのがドキュメント読んでもよくわからないのと、GlueとAthenaのパースの扱いが違うのとか割と問題に気づくまでが面倒臭いのとか考えると、特に強い理由がなければCSVでもいいんじゃないのかなあ?というのが正直な感想です。CSVにしたくなければそのままJDBCをデータソースやターゲットに使うという方法もありますし。バルクデータという観点で行けば、CSVの方がデータの構成上サイズは小さくなりそうなので。