AWS WAF を使用して IP ホワイトリストによるアクセス制限を行う方法

前回の記事では AWS 上に静的サイトをホスティングする構成について紹介しました。この記事では、CloudFront のディストリビューションに AWS WAF で作成した Web ACL を関連付け、IP ホワイトリストによるアクセス制限を行う方法についてお伝えしたいと思います。

例えば以下のようなコンテンツで、サイトを外部に公開したくない場合において有効です。

  • WebAPIの仕様、開発ドキュメント ※ Swagger UI など
  • 社内向けサイト
  • 開発中のウェブアプリ

この記事で紹介する構成



  • CloudFront のディストリビューションに AWS WAF を使用してアクセス制限をかけます。
  • クライアントによる S3 バケットへの直アクセスはできません。
  • AWS WAF は Origin の種類に関係なく関連付けることができます。

設定の手順

以下の一連の作業を行う必要があります。
まず、AWS WAF のコンソールを開き、「Go to AWS WAF」 を選択します。

Create web ACL を選択すると以下の画面が表示されます。

  • Web ACL name を入力します。
  • Region については、「Global(CloudFront)」を指定します。

※ AWS resources to associate で関連付ける AWS リソースを指定することができます。ここですでに作成済みの CloudFront ディストリビューションを指定しても OK ですが、この記事では別途 CloudFront のコンソールから指定することにします。

「Next」をクリックして次の設定に移ります。

ここでは「IP match conditions」を選択します。

ここで許可したい IP アドレスを登録します。名前・IP Version・Address を入力して、「Add IP address or range」をクリックします。複数のIPアドレスを登録することもできますので、許可したい IP アドレスがたくさんある場合はどんどん入れていきましょう。

登録が終わったら、画面下の「Next」をクリックします。

ルールの名前、Rule type、条件(Condition)を指定します。

先程作成した IP アドレスのリストが反映されていることを確認し、「Create」をクリックします。

作成したルールの Action は「Allow」を選択、Default action は「Block all requests that don’t match any rules」を選択します。これでこのルールにマッチしなかった IP アドレスはブロックする挙動になります。

準備ができたら「Review and create」をクリック、問題なければ「Confirm and create」します!

先程 AWS resources to associate を設定しておいた場合、このまましばらくすると反映されるようになります。AWS WAF のコンソールではなく CloudFront のコンソールで設定する場合は、ディストリビューションの設定にて「General」タブを選択、以下の場所から設定することができます。

修正してしばらくすると適用されます。WAFによってアクセスがブロックされた場合、以下のようなエラー画面が表示されます。

Web ACL のコンソールを見ると、どのようなリクエストがあったか確認することができます。便利ですね!

アクセスログを取得したい場合は Web ACL のコンソールから Logging タブを選択して有効化することもできますが、この記事では割愛させていただきます。

AWS WAF で作成する項目として 許可する IP アドレスのリスト・ルール・Web ACL の3点を押さえておくと分かりやすいと思います。Web ACL を削除する時、この順番で消していかないとエラーになりますのでご参考ください。

いかがだったでしょうか。

AWS WAF は、ALB(アプリケーションロードバランサー)と API Gateway にも関連付けることができます。ただし、その場合は Web ACL のリージョンを指定する必要があります。

IP アドレス制限のみならず、色んなルールを設定することができますので、是非試してみてください。

Go_SaaS 三種の神器オンボーディングセミナー 1 〜東京〜 参加レポート

2019年7月8日に開催された「#Go_SaaS 三種の神器 オンボーディングセミナー#1(東京)」に参加したのでレポートします。

今回参加したのは、日本における SaaS ビジネス、サブスクリプションビジネスを推進し ISV や Startup の支援を目的とした「Go_SaaS 三種の神器」というセミナーです。

このセミナーは ID 管理サービスの Auth0、決済サービスの Stripe、CI/CD サービスの CircleCI を、SaaS/サブスクリプション型のビジネス開発における三種の神器として、サービスの概要紹介とユーザー事例を紹介する半日のセミナーです。また SaaS 型サービス構築の考え方についてから始まるので、まさにサービス開発、新ビジネス開発に向けてパッケージングされたセミナーといえます。

主な内容

  • AWS ジャパンから見た SaaS 化における課題、及び、今後の展望 (岡崎 貴紀氏 - AWSジャパン ISV/SaaS パートナー部 部長)

  • 「Go_SaaS 三種の神器」が目指す新たな日本のSaaS促進支援の形 (小島 英揮氏 - Still Day One 合同会社 代表社員)

  • SaaS 三種の神器 - ID管理・CI/CD・決済

    • 藤田 純氏 - Auth0 株式会社 カントリーマネージャー
    • 森本 健介氏 - CircleCI カントリーマネージャー
    • ダニエル ヘフェルナン氏 - Stripe Japan 代表取締役
  • ユーザー事例紹介 - 三種の神器を活用したストレスフリーSaaS運用環境

    • Shifter 開発の舞台裏 (小賀 浩通氏 - Digital Cube 代表取締役社長)
    • SaaS化にあたり直面した課題 (Jeremy Hall, PhD氏 - AppSocially株式会社 VP of Engineering)

AWS ジャパンから見た Saa S化における課題、及び、今後の展望

まずは AWS の ISV/SaaS パートナー部長の岡崎さんから、ソフトウェア開発および SaaS の現状について。

国内の SaaS 市場の成長率は 15%、それに対してソフトウェア市場は 4.6%。また SaaS の利益率は 76% と、市場の拡大および利益への貢献度が高まっているとのこと。つまり SaaS 開発は収益性を向上させることができる。とはいえ最小限に稼働するレベルの SaaS を作るにしても3ヶ月~2年の開発期間が必要となる。よって既存の SaaS と組み合わせて構築していくことが必要となってくる。

AWS では、その SaaS 開発を支援するプログラムも用意しているので活用してほしいとのこと。

SaaS化が求められる市場の潮流と本取り組みへの期待

ソフトウェアを提供するには SaaS にするのが良いよというお話でした。現在はそういった流れなので新規で作るなら当然 SaaS 型になっていくだろうなというのは感じますし、AWS でそのための支援プログラムがあるというのがよいです。

「Go_SaaS 三種の神器」が目指す新たな日本の SaaS 促進支援の形

続いて Still Day One の小島さんより。小島さんは富士通から Adobe、AWS を経て現在は6社のサービスでアドバイザーをされているとのこと。まさに SaaS ビジネスのプロで、今回 SaaS をよく知っているほか、AWS と三種の神器(Auth0, CircleCI, Stripe) をつなぐことができる人物ということで本プログラムの進行を担当されているとのこと。

改めて SaaS/サブスクリプションビジネスの凄さについて説明。2019年時点で SaaS/サブスクリプションビジネスは3兆円規模で、年率40%以上で成長している。非常に魅力的なビジネスであるが、既存のパッケージ販売から転換するには大きな壁がある。たとえばファイナンスの壁では Adobe が SaaS 転換した際に、売り上げが落ちることを周到に説明する必要があったことなどがわかりやすい。実際に SaaS 転換後、大きく売り上げが落ち込んだ。現在は素晴らしい業績になっている。
組織文化としても大きく変わる。カスタマーサポートについては極端な例になるが売り切り製品の場合は小さくしたい、やめてしまいたい。販売後はコストになってしまうから。一方で SaaS は使い続けてもらう、解約されないようにするためフィードバックループを回す。顧客のビジネスにメリットをもたらす必要があるのでカスタマーサクセスが重要になってくる。営業よりもカスタマーサクセスの方が売り上げを叩きだすケース多い。
開発も大きく変わってくる。フィードバックループを回すために DevOps の体制が必要になってくるし、クラウドの活用が重要になってくる。SaaS の上に SaaS を作るようなイメージ、既存 SaaS と連携して開発する。

そうした壁もあるが、ビジネスとして美味しく魅力的である。サブスクリプションは売り切りでない。10件売って、次に10件売れば、20件の利益。売り切りは、10件は10件。
では、どのように転換していくかというと、まずは BYOL、ライセンス型のソフトウェアを EC2(AMI) に組み込んでライセンスだけをサブスクリプションとして売る。このサブスクリプションも月額固定でよいし、請求書ベースでも構わない。次にシングルテナントの SaaS にする。徐々に DevOps に向けて体制を変えデプロイを自動化できるようにしていく。ライセンスもライセンスコードの発行から利用ユーザーの ID ベースに移していく。そうなると課金モデルも変わってくる。月の途中で利用者数が変わってくる。
これらを新規で作ると大変であり、また問題を発生させかねない。ムリに作ろうとするとセキュリティ・インシデントとなる。ここは既存のサービスを使っていく。

構築したサービス利用の顧客決済についてはクレジットカードの導入は必須。B2B では請求書でないとダメや「できない」といわれることもあるが現実はできる。そうでなければ AWS がこれだけ使われるわけがない。
クレジットカード決済にすることでキャッシュフローが改善される。SaaS の利用料を月末で〆るとして、翌週には入金される。一方で AWS の利用料も月末で〆られるが引き落としは翌月。入金されてから出金の形なる。これが請求書だと逆になる。AWS の利用料が引き落とされ、それから請求書の支払いが1ヶ月、2ヶ月遅れで入金されてくる。売り上げが上がっているようで、キャッシュフローは赤字になっている。

「Go_SaaS 三種の神器」が目指す新たな日本の SaaS 促進支援の形

自社製品を SaaS 化するにあたってという観点から、とても勉強になりました。とくに売り上げが積み重ねとなるという考え方は、言われてみればその通りですが見落としてました。もちろん解約というリスクがありますが、前月の売り上げが次月にスライドして、次月の売り上げが重なるのは素晴らしいビジネスです。またキャッシュフローの改善は盲点でした。

ユーザー事例紹介: Shifter 開発の舞台裏

以前、JAMstack について発表させていただいた Shifter さん、偶然にも SaaS のユーザー事例として小賀さんが Shifter の開発についてお話されてました。

小島さんの既存パッケージソフトウェアを SaaS 化する話が、まさに Shifter がたどってきた道でした。
Shifter の元になる AMIMOTO という WordPress のパッケージがあり、当初は EC2(AMI) として提供していた。それをシングルテナントの SaaS として影響を開始。最終的にマルチテナントの SaaS、Shifter へと。商品から体験へ、ユーザーの価値観が変わってきている。

アーキテクチャはサーバーレスで作られていて、CircleCI と Stripe を使っている。ID 管理は Cognito を使っているが、ここは Auth0 に切り替えるとよいのかもしれない。検討していく。

CI/CD について、Jenkins が良いのではという話はよく聞く。カスタマイズなどができてよいのかもしれないが、いわゆる「Jenkins おじさん問題」がある。Jenkins を保守運用して管理する人が必要となってしまう。CircleCI を使うことで本業に集中できる。

また Stripe については、決済の仕組みを自前で開発したら恐ろしいことになるだろう。PCI DSS などの認証をとるのはとても大変。多通貨、多国籍、柔軟な定期決済と対応するものも多く、不正使用、不正請求などへの対処も必要となってくる。ここはサービスを利用することが重要。また小島さんが話していた通り、キャッシュフローの改善も重要。

その他、モニタリング、UI開発、サポートデスク、CRM とさまざまな SaaS を使っている。

Shifter 開発の舞台裏 三種の神器編

SaaS 開発の歴史をお話してくださり、開発のリアルをすごく感じました。「SaaS 提供者こそ SaaS を使い倒そう!」というメッセージがカッコよかったです!

AppSocially スタートアップの武器となるSaaS

発表が英語だったためレポートを書けず。。。すみません。

SaaS 三種の神器 - ID管理・CI/CD・決済

三種の神器の各サービス紹介の資料です。

Auth0がB2B SaaS企業に必要な理由

SaaSビジネスに必須のCI/CD by CircleCI

Stripe SaaSを支える決済機能のコツ


SaaS/サブスクリプション型のビジネスを始めるにあたって、最初に必要な知識や考え方をいっぺんに勉強できる素晴らしいセミナーでした。とくにユーザー事例として実際に SaaS を構築されている方々のお話もあり、そして SaaS を構築する上でも SaaS を組み合わせていくとよいというのが響きました。

スタートダッシュや知識のベースアップとして、こちらのセミナーを受け、そのうえで深堀したいサービスのセミナーやミートアップなどのイベントにつなげていくとよいのではないでしょうか。

「プレゼンドリル 伝えかた・話しかた」、勉強会、LT、イベント登壇のおともにしたいドリル

プレゼンテーション(プレゼン)というと大勢の人前で話をするイメージがありますが、プレゼンの本質は「人にわかりやすく伝えること」。そこには人の多さは関係ありません。人に何かを伝えアクションにつなげてもらう、そんなプレゼンの原点をシンプルに思い起こさせてくれる、そしてプレゼンの機会があるたびに毎回ふりかえりたくなる、そんなドリルを紹介します。

紹介する書籍はこちら、「プレゼンドリル 伝えかた・話しかた」

著者は日本マイクロソフトのエバンジェリスト、西脇 資哲(@waki) さん
マイクロソフトのイベントなどでプレゼン&デモをされているのをはじめ、多数のイベントで登壇されている IT 界のスーパーエバンジェリストのひとりです。

西脇さんは、多くのプレゼンやエバンジェリストに関する書籍を出していますが、今回は小学生向けに出版されました。もともと SSH(スーパーサイエンススクール) という取り組みをされており、筑波大学附属駒場中高や立命館小学校でプレゼンの授業をし、その中から本書ができたとのことです。

今回こちらの書籍を取り上げたのはプレゼン力を高めるためですが「小学生向け」というのが気に入り選びました。プレゼン(に限らないですが)は、話す内容をわかりやすく、極端に言えば小学生に伝わるように話せるとよいとも言われます。そのような中でスーパーエバンジェリストのひとり、西脇さんが本書を出されたということで即買いしました。

IT に携わる方が小学生に向けて作られたプレゼンのドリル。ページ構成こそ確かに小学生向けですが、その内容は大人にも満足できる書籍でした。勉強会での発表や、LT、イベント登壇とプレゼンに向けて、またはプレゼンの機会とまでいかなくとも日々の活動で説明を充実させるために、敢えて小学生向けのドリルでプレゼン力の強化を図るのもいかがでしょうか。

主な内容(目次より抜粋)

  • はじめに―プレゼンテーションとは「伝える」こと!
  • ドリルの使いかた
  • ドリルの注意点
  • 第1章 「伝える」方法を学ぼう
  • 第2章 シナリオを作る
  • 第3章 スライドを説明するトレーニング
  • 第4章 かっこよく話す基本テクニックと裏技
  • 第5章 実践!プレゼンテーションの手引き
  • 模範解答集
  • 保護者のみなさんへ

アイデアを「誰に」「何を」「どうやって」で整理し、自分の意見や考えを加えて広げよう

まずは、泣いている赤ちゃんや、天気予報などの絵をもとに「誰に」「何を」「どうやって」で説明できるように整理するトレーニングから始まります。プレゼンをはじめ、説明をするときに文章だけで考えていると、いつの間にか話が複雑になり最終的にわかりにくい話になってしまうことがあります。このトレーニングは何を話をしたいのか改めて整理するのによいです。

そこから伝えたいことを広げ、事実の説明だけでなく自分の意見や考えを入れるトレーニングに発展します。技術について話をする際に、意外とありがちなのが技術に関する事実や調査の結果にフォーカスしてしまい、最終的な考えや意見が入らなくなってしまうこと。もちろん客観的な事実がないと困りますが、調べればわかることだけで構成されていると少し物足りなくもあります。やはり、その技術に対する主張も聞きたいものです。

たとえば、こちらの写真を見て「お寿司です」以上、はさすがにないと思いますが、どういった説明に意見を加えますか?(実際にドリルにも寿司の問題は入っています)

子供向けとして使うのでしたら説明の仕方の基礎としてしっかりしていますし、プレゼンや登壇の準備として読み直してみるならアイデアの整理と拡大として活用できるのではないでしょうか。とくに2章は1回やったとしても、また新たな考えや意見が浮かぶでしょうし、敢えて違う意見を考えたり、アンチ側としてロールを変えてみるなど色々と使えます。

話のカッコよさ、それは修飾

名詞をただ置くだけではなく修飾をする。ちょっと付けるだけでイメージがだいぶ変わります。しかしながらボキャブラリが必要ですし、イメージを膨らまさないと文章を修飾するのも簡単ではありません。

それをトレーニングする「第4章 かっこよく話す基本テクニックと裏技」は、このドリルの中でとても好きな章です。「ライオン」や「子猫」などの絵から始まり、色のイメージ、比喩、事実に対する意見付け、スライドのつなぎ(ブリッジ)と、話をカッコよくする手法について次々とトレーニングします。ひとりでやるのもいいですが、みんなで意見交換しながらボキャブラリやアイデアを増やすのもよいでしょう。

またスライドのつなぎ(ブリッジ)についても、しっかりと学べる点がよいです。ここはついつい「えっと」や「それで」とかでつないでしまいがちなところを、きちんと考える練習となります。練習なきところに本番の成功はないので、キッチリと練習して身につけたいところです。

模範解答集を見て、思考をもっと柔らかく

「P.69 問題 39 - かっこいいかざりを考えてみよう」では子猫の絵をもとに、かっこいいかざり言葉を考えます。以下は問題をイメージするための写真で問題集の絵とは異なりますが、かっこいいかざり言葉いかがでしょうか?

こちらの模範解答は以下となっています。

ぬいぐるみのような
かわいい
モフモフした
思わず抱きしめたくなる
[問題 39 の解答例 - P.119 より抜粋]

いかがでしょうか。「かわいい」などは浮かびますが、ぬいぐるみや抱きしめたくなるなど、すぐには出てこないかもしれません。「モフモフ」はネットなどで使っているので浮かぶかもしれませんが、プレゼンを作るという思考回路の中で、このような柔軟な発想は出てきますでしょうか。

模範解答集をうまく活用することで、柔軟な思考を広げることにもなるでしょう。大人が読むからこそ、むしろ模範回答集が重要な章ともいえるのではないでしょうか。

まとめ

とても分かりやすく、それでいて実践的な書籍だと思います。

アイデアを広げるための1ページをドーンと使った演習をパラパラっと眺めながら、いろいろな想像の羽を広げることができます。IT 関連のプレゼン作りとなると、どうしても技術やロジックなど論理的になりがちです。そういった中で、ドリルに目を通すことで思考を柔らかくし表現力を高めることができるのではないでしょうか。

プレゼンのテクニックであったり、資料作りのための技術も大事ですが「人にわかりやすく伝えること」にフォーカスを戻すことも重要です。より多くの人に理解してもらう、そしてアクションにつなげてもらう、そんなプレゼンの原点に、いつでも立ち返ることができる素晴らしいドリルです。


前回の「ドリルの王様 1,2年のたのしいプログラミング」、自然とプログラミング的思考が身につく問題集に続き、またも小学生向けのドリルの紹介でした。

子供向けであることから逆にシンプルでわかりやすいというのがあるのではないでしょうか。(とはいえ、ひらがなの多さや文字の大きさには閉口するところもありますが)

このようなプレゼンの授業があるというのは、素晴らしいし、何よりうらやましいですね。プログラミングも見様見真似の写経で覚え、プレゼンはイベント登壇者さんを凝視し技を盗む。ちゃんと教えてもらうことができたら、もっと幅が広がったのかな。それとも逆にやらなくなったのか。いろいろと思うところはありますが、なによりも日々勉強にアウトプット。アウトプットを続け、改良していくことですね。

共有:

OSS-Friday 活動 - 2019年6月まとめ

普段お世話になっている OSS プロダクト、日常で OSS 活動をしていないと貢献する機会をつい逃しがち。なので毎週金曜日は少しでも OSS 活動へ意識を向ける習慣 OSS-Friday として位置付けるようにしています。2019年6月の OSS 活動についてサマリーします。

OSS-Friday 参考情報

サマリー

OSS-Friday のページで GitHub のアカウント連携すると自分のページが作られます。

このページの中に GitHub での「過去3ヶ月間&過去1,000イベント」から金曜日の活動をサマリーしたものがあります。以下、そちらから抜粋。

June 07, 2019

June 14, 2019

June 21, 2019

June 28, 2019

2019年6月の OSS-Friday 活動は12件でした!
以降、プルリクエストを出した背景など。

hexojs/hexo-theme-landscape #136, #137, #138

最初の2つ #136, #137 は、ブログメンターのカック@ブロガー / k9u (@kakakakakku)さんにメンタリングをしていただいている中から「Google+ は終了したのにテンプレートに残っているよね」との指摘からプルリクを出したものになります。

記事のシェアに Google+ があったほか、OGP にも Google+ がありました。Google+ という観点では1つですが、コードでは異なる範囲になるのでプルリクは2つに分けて出しました。

3つ目の #138 は、Customizable Banner Image · Issue #106 · hexojs/hexo-theme-landscapeを解決するためのプルリクです。デフォルトのブログトップ画像が CSS にハードコードされており、実際に自分のサイトを開くにあったり CSS を編集してパスを変えるか、画像を上書きする必要がありました。それを設定ファイルからパスを指定できるようにしました。

zefman/gridsome-source-instagram #1

こちらは、2019年6月1日の「初夏のJavaScript祭 in メンバーズキャリア」でGridsomeのデモアプリを作る際に、Instagram の写真を取得する Pluginzefman/gridsome-source-instagramを使わせてもらいました。設定する際に typo を見つけたので修正のプルリクを出したものになります。

関連コンテンツ

Readify/httpstatus #63, #64, #65, #66, #67

HTTP Status を返してくれるサービス httpstat.us を紹介する記事を書いた際に、いくつかの JSON レスポンスが期待値と異なったので修正するプルリクを出しました。

C# でできているとのことで、自分のスキルセットにないので若干ひるんだところもありましたが、コードがシンプルでわかりやすく作られていたのでプルリクを出すことができました。

合わせて、いくつかの HTTP Status に対応するプルリクも出しました。

関連コンテンツ

hexo-browsersync #34

これは切実に困っている問題に対するワークアラウンドになります。残念ながら根本解決することはできていないのですが、このプルリクによって暫定対処はできます。暫定対処のプルリクのためかマージいただけておらず、入ってくれると助かるのだけど。。。

この Plugin の機能は、Hexo でブログ記事の下書きをする際に、ブラウザを自動リロードしてくれるものです。しかしながら、コンテンツが長い場合にリロードできないという問題があります。トップページで5記事+サイドバーありは、ほぼエラーとなりリロードできず。単記事のページで文章が短いうちはリロードできるといったレベルです。おそらく、こちらProblem with long pages · Issue #15 · hexojs/hexo-browsersyncとも関連してると思われます。

問題の原因ですが、この Plugin は</body>タグの後にリロード用のスニペットを注入するのですが、コンテンツが長いと</body>へたどり着く前に切れてしまい、スニペットが注入できないことです。

解決に当たっては色々と試さないと分からないことが多いので、まずは</body>以外にスニペットを注入できるようにするオプションを導入し<body>と、開始タグへも注入させられるようにしました。これによりコンテンツが長くて切れてしまっても注入箇所は残るので Plugin は動作できるというものです。

Plugin が使っているBrowsersyncも、タグを変更できるオプションsnippetOptions - Browsersync optionsが用意されているので、そのような形として、こちらの Plugin にもあってもいいのかなと思います。

hexojs/hexo-generator-tag #22, hexojs/hexo-generator-category #23

それぞれ Issues へ上がっていたものに対応するプルリクです。

ブログのタグとカテゴリーの一覧表示のページでorder_byオプションを設定したいというものです。正直あまり用途が浮かばず、対応する必要があるのかなとは思ったのですが “like hexo-generator-archive and hexo-generator-index” とコメントされており、確かにアーカイブの一覧などではorder_byの設定ができます。デフォルトで導入されている Plugin 間で対応の差があるのもいかがと思いプルリクを作りました。


6月は Readify/httpstatus の新しい HTTP Status 対応があったので多くのプルリクが出せましたが、実際には1件出すのが精いっぱい、週によってはプルリクを出すことさえ難しいかなというのが正直な感想です。

それでも Issues を眺めたり、コメントを返したりと、まずは日頃お世話になっている OSS へ意識を向けることができればよいのではないでしょうか。

🚲 Let’s enjoyOSS-Friday!!

共有:

AWS で静的ウェブサイトをホスティングするための構成(S3 + CloudFront)

ここ最近、SPA(シングルページアプリケーション)や SSG(静的サイトジェネレーター)を利用してウェブサイトやアプリケーションを構築するケースが増えており、静的サイトを配信する仕組みについても興味を持つようになりました。便利なサービスとしては Netlify や Firebase Hosting, GitHub Pages など色々ありますが、ウェブサービスやシステム開発を行う上で、AWS を使っているならば AWS で完結したいということもあるかと思います。

この場合、Web サーバーを立てて実現することもできますが、AWS が提供するサービスをうまく活用することで、より簡単に実現でき、費用を抑え、運用の手間を減らすことができます。定番のやり方としては、例えば以下の AWS サービスが挙げられます。

  • AWS Amplify コンソール
  • S3 の静的ウェブサイトホスティング(Static website hosting)

この記事では、一見クラシックなやり方ではありますが、CloudFront を利用することで高速かつ柔軟性を持つ配信方法の一例を紹介します。AWS WAF や Lambda@Edge と組み合わせることで、単体のウェブアプリケーションだけでなく、社内利用を含め色んなシーンに対応できることが利点になります。

S3(ストレージ) や CloudFront(CDNサービス) といった AWS のサービスについての基本的な前提知識が必要となります。

この記事で紹介する構成

ポイントとしては、

  • Origin Access Identity を使用することで、外部から直接 S3 へアクセスすることはできない
  • CloudFront の各種機能をフル活用できる
  • アクセス制御や流量制限など、WAF や Lambda@Edge を利用して柔軟に対応できる
  • Origin を変更する場合でも、クライアントに提供されているエンドポイントを変更することなく対応できる
    ※ Origin の S3 をクロスアカウントにすることも可能

といった点です。

構築方法

上記の構成で静的サイトをホスティングするためには、大きく以下の2ステップに分けられます。

  • Origin となる S3 バケットを作成する
  • CloudFront ディストリビューションを作成する

Origin となる S3 バケットを作成する

どのリージョンでも問題ないので、普段良く使っているリージョンを指定してバケットを作成します。
バケット名をサイトのFQDNにする必要はありません。

設定はデフォルトで問題ないかと思います。
アクセス許可については、パブリックアクセスができないことを確認します。

CloudFront ディストリビューションを作成する

Web ディストリビューションを作成します。

Origin Settings


  • Origin Domain Name をクリックして、先程作成したS3バケットを選択
  • Restrict Bucket Access: Yes を選択
  • Origin Access Identity: Create a New Identity を選択
  • Grant Read Permissions on Bucket: Yes, Update Bucket Policy を選択

これで Origin Access Identity が作成され、この Identity からのアクセスのみ許可するように S3 のバケットポリシーが更新されます。構築後、CloudFront コンソール左側メニューの Security > Origin access identity を開くと名前と ID が確認できます。

Default Cache Behavior Settings


  • Viewer protocol policy: Redirect HTTP to HTTPS にするとリダイレクトしてくれます。
  • Object Caching については、とりあえず 全て 0 を設定します。
    • Minimum TTL: 0
    • Maximum TTL: 0
    • Default TTL: 0
  • Compress Objects Automatically: Yes を選択することで、リクエストヘッダーに Accept-Encoding: gzip が含まれている場合、圧縮してくれます。

Distribution Settings


  • AWS WAF Web ACL: WAFのACLをここで適用させることができます。
  • Default Root Object を設定しないと、ルートのURLパスで index.html を見てくれません。

ホスティングするサイトのトップページを表示するためには、Default Root Object に index.html を指定する必要があります。
ここは色々ハマりポイントがあるので、後日、別途紹介したいと思います。

ディストリビューションの作成

その他、独自ドメインや証明書、ログの設定などは一旦置いといて、
とりあえず Create Distribution ボタンを押します。そうすると、下記のようにディストリビューションが作成されます。
初期作成は 20 分 - 40 分ほどかかります。コーヒータイムですね。

サイトをリリース(更新)する

キャッシュを設定していなければ、Origin の S3 バケットのファイルを更新するだけですぐに反映されます。
例えば、AWS CLI を利用して CI やデプロイスクリプトに下記のようなコマンドを利用することで簡単にリリースできます。

1
aws s3 sync {リリース対象のディレクトリ} s3://{バケット名} --region {リージョン名}

特に問題なければ、下記のように表示されます。

また、S3 に入っていないパスやファイルを指定すると、下記のようなエラーページ(403) が表示されます。
カスタムエラーページを指定することで、この画面を見せないようにすることができます。

まとめ


  • 一見クラシックなやり方ですが、S3 + CloudFront の組み合わせは高速かつ柔軟性が高くおすすめです。
  • CI連携も兼ね揃えた AWS Amplify コンソールを使用するのも良い選択です。
  • AWSに限定しなくていい・もっと手間を省きたい場合、Netlify か Firebase か GitHub Pages 等、選択肢は多くあります。

いかがだったでしょうか。

引き続き、このパターンを用いた

といった方法や、AWS Amplify についても紹介していきたいと思います。

「ドリルの王様 1,2年のたのしいプログラミング」、自然とプログラミング的思考が身につく問題集

「鉛筆で学ぶ小学生用プログラミング教材」という、おもしろい見出しで紹介されているドリルがあります。「ドリルの王様 たのしいプログラミング」シリーズです。プログラミングを学ぶのにパソコンなしで鉛筆とはどういうことなのか、どうやって学習できるのか、本書を読んだ中から良かった点を紹介します。ドリルのターゲットである小学生はもとより、年齢に関係なくプログラミングへ興味ある方は一度手に取ってみるとよいでしょう。

紹介する書籍はこちら、「ドリルの王様 1,2年のたのしいプログラミング」

ドリルの王様は、新興出版社が出している小学生向けの教材シリーズです。
漢字や計算をはじめ、図形、時計、理科、社会、英語などと幅広く出版されている中、新学習指導要領対応でプログラミングが追加されました。2020年からはプログラミング教育が小学校でも必修化されるため同社ではいち早く対応し出版したとのことです。

こちらのドリルがネット記事で取り上げられはじめたときから気になっていました。思い返せばプログラミング自体ちゃんと習った覚えがなく(そもそもなかったと思いますが)。見よう見まね、いわゆる写経で覚えてきたのでプログラミングを教えるってどういったことなのか、さらにパソコンを使うことなく教えるとは!? 何気なく眺めたらおもしろく、せっかくなのでしっかり読みブログで取り上げることにしました。

主な内容(目次より抜粋)

  • じゅんじょ
  • くりかえし
  • ぶんき
  • イベントしょり
  • コンピュータの かんがえかた
  • へんすう
  • こたえ と おうちの方へ

コンピューターの動作は決められた手順と繰り返しが基本

まずは基本動作の手順(= じゅんじょ)と、反復(= くりかえし)について、積み木やシールの重ね張りとイメージしやすい問題から入ります。手順通りに作業をするというのを身の回りにあるものや、イメージしやすい形で表現しているのがわかりやすいです。これは本の中でわからなかったら、実際に積み木なりでやってみればよいので入門に良いのではないでしょうか。

また反復では交互の色塗りをしたり、いくつかの絵を1セットとしてセットを繰り返すとどのような順番になるかなど、こちらもイメージしやすくなっています。そのセットも、セットとして理解した後に1つ1つへ分解して繰り返しの一連の処理となるように発展するので、いつの間にかプログラミング的な処理の作り方を勉強していることになります。

繰り返しの概念を分かったうえで、その繰り返される部分へ最初に学んだ「じゅんじょ」を持ってくることで着実な理解が図られるようになっており、勉強の道筋ができていることに感心させられます。

最終的にはロボットを「1マス進む」「向きを変える」という手順と、繰り返しでどのように動いたかという応用問題になります。これまでの単純な手順が繰り返されるではなく「ロボットの向き」が入ってくるので手順がしっかり頭に入っていないとハマるのではないでしょうか。

条件分岐は複雑になりがち、ドリルで頭の整理にも

プログラミングしていると出てくる複雑な条件式。致し方ないケースもありますが、多くの場合は整理ができていないだけです。

簡単な分かれ道の右左分岐でイメージを増幅させてから「〇=〇」「△=△」「◇=◇」の形が同じ条件、またったく異なる形同士での条件マッチと、徐々に複雑化します。さらには算数を混ぜた計算のある条件式と、気づけば実際のプログラミングでも使うような形へ自然とつながっていきます。ここでもプログラミング的な思考力がいつの間にか勉強できています。

なによりも感心したのは状態が組み重なっていく問題。以下、問題文より抜粋 (実際には絵も入っててわかりやすいです)

あおいさんは 上がった はたを 見て、きまった ポーズを とります。

☆ の はたなら、かた手を 上げる。
□ の はたなら、かた足を 上げる。
☆ □ と ちがう はたなら、えがおになる

□、☆、△ の じゅんで はたが 上がりました。
あおいさんが さいごに とった ポーズは どれですか。

[#21 ぶんき ⑦ - P.43 より抜粋]

選択肢としてポーズの絵がありますが本ブログでは省略します。どのようなポーズになったかわかりますでしょうか。この問題は前回の状態を意識して次の条件の結果を加えていく状態変化でもあります。

このように「条件から導き出されること」「状態がどのように変わるのか」、ちょっと考えると簡単な問題ですが、実際のプログラミングとなると、いつの間にか複雑な条件に加えて難しい状態管理となってしまいます。本ドリルで今一度整理するのもよいでしょう。また問題をプログラムで表現するとどうなるのかを思い浮かべてみるのも楽しみ方のひとつと言えるでしょう。

プログラミングやコンピューターに詳しくなくても安心の解説

答えの章には「おうちの方へ」という解説もしっかり入っており、プログラミングやコンピューターに詳しくなくても解説から理解できるように作られています。

たとえば「変数」についての説明なども、下記抜粋のようにシンプルな説明と出題の意図が解説されています。

変数はプログラムで使用する値を一時的に保存することができます。必要な時に値を参照したり、値によって処理を変更したりするときなどに使われます。1つの変数に保存できるのは1つの値だけです。

今回の問題では、ロボットが最後に伝えられた言葉を覚えることを通して、「変数の値を1つしか覚えることができない」ことや、「値は上書きされることがある」などの変数のしくみについて考えることができます。

① ロボットは最初に「キャラメル」を覚え、次に「わたあめ」を、その次に「クレープ」を覚えます。ロボットは1つしか覚えることができないので、「キャラメル」と「わたあめ」は忘れてしまいます。

[こたえ #34 へんすう ① - P.94 より抜粋]

プログラミングに興味ある方にも手に取ってもらいたいと思ったのは、こちらの解説がシンプルで分かりやすいからです。もちろん小学生向けドリルの解説なので、この部分だけでプログラミングできるようになるわけではないですが、上記「変数」のように機能と使われ方がわかりやすく説明されており、ふりかえって問題を見てみるとさらに理解が深まるのではないでしょうか。

紙のドリルであることの良さ

最近ではScratch - Imagine, Program, Shareをはじめ、学習用のプログラミング環境やサービスがあります。それらに比べて「紙」であることは、どのようなメリットがあるでしょうか。

1つには、試行錯誤の過程を書き表せることではないでしょうか。
たとえば商品情報 - ドリルの王様楽しいプログラミングにて、以下の問題が公開されています。

ロボットの動きを考える問題ですが、鉛筆で書いて動きを考えることもできますし、説明する際にも必要な情報を書いてあげることもできます。もちろんパソコンなどを使う場合もディスプレイに加えてノートを使うことで同じようなこともできますが、やはり問題そのものに直接書けるのは紙のドリルならではでしょう。

もう1つには、Try & Error も同様に書いて試せることでしょう。
Scratch などでは実際に動かせるので、手軽に何度も Try & Error できますし実際に動くのでわかりやすいというメリットがありますが、パッと動いておしまいなので過程が飛ばされがちとも言えます。基礎段階としては、過程が残る形で繰り返し試すことは理解の助けになるといえるでしょう。

一方でデジタル・ネイティブ(インターネット・ネイティブ?)としてはどのように感じるのかは聞いてみたいです。生まれた時から YouTube などがあり、あらゆるものがデジタルでネットにつながっている。その様な環境で育ってくると、同じような問題をタブレットなどでやる方が分かりやすいのでしょうか。ぜひ聞いてみたいところです。

まとめ

1~2年生向けとのことでプログラミングの初歩かと思うと、意外と深くしっかりした考え方が身につく本だと思います。

とくに解説である「おうちの方へ」は、シンプルでわかりやすい表現で用語や使い方が解説されており必読です。プログラミングに興味ある方には、ぜひ解説を読んでいただきたいと思いますし、またプログラムを作る方にもこのぐらいシンプルに説明できるかを確認するという観点で見ていただくとよいのではないでしょうか。

今回は1~2年生向けのドリルを紹介しましたが、3~4年生向け、5~6年生向けと3冊でており、アルゴリズムやデータ活用などより発展的内容になっています。すべて解けるか、そして解説まで踏み込んで読み込むとおもしろいでしょう。

参考情報

紹介した書籍「ドリルの王様 1,2年のたのしいプログラミング」


デブサミ 2019 で開催されていた「こどもプログラミング本大賞」に足を運んだことがきっかけで、子供向けのプログラミング本というのに興味を持ちました。子供向けということですが、子供向けであるからこそ説明がシンプルで逆に本質がわかりやすいのだなと感心しながら手に取り、楽しませてもらいました。

今回取り上げたドリルはイベント後の発売なので会場にはありませんでしたが、書店で見かけた際にプログラムを書く身として興味を持ち手に取ったのがきっかけであり、またブログのメンターについていただいているカック@ブロガー / k9u(@kakakakakku)さんが書評を書いていたのが決め手となり本ブログで初書評として取り上げてみました。

本ブログ執筆時点では、またカックさんの書評を読んでおらず同じ本で挑戦してみて、どのような違いがあるかブログの勉強とともに、カックさんの記事を楽しみたいと思います。

カックさんの書評はこちら。

共有:

OS や IDE 固有ファイルの .gitignore はどこにする?

Git のソースコード管理の除外指定する .gitignore。ときどき気になるのが Thumbs.db や .DS_Store などの指定がプロダクトの .gitignore ファイルに含まれているケース。開発者固有の設定、どこにしたらよいでしょう?

開発者固有のファイルはプロダクトのソースコード管理からは除外したいです。とはいえ OS が自動で作ったThumbs.db.DS_Storeなどは、いつの間にかソースコード管理に紛れ込んでしまうことも。それを避けるために .gitignore があるのですが、Thumbs.dbなどの除外指定がプロダクトの.gitignoreファイルに書かれているといつもモヤっとします。

プロダクトとしてThumbs.db.DS_Storeが生成物であり、かつ管理不要だとしたらわかります。しかし、多くのケースはプロダクトの生成物ではありません。開発者固有といえるでしょう。このようなファイルの除外指定はどうするのが良いのか調べたのでまとめます。

gitignore.io での扱い

以前、本ブログで紹介した「.gitignore は、生成サービス gitignore.io を使って作ろう!」のgitignore.ioは、さまざまな環境の .gitignore に対応しています。

たとえばWindows の定義では[Dd]esktop.iniなどが設定されています。もちろんmacOS 版もありますし、Linux 版もあります。また Java のビルドツールMavenや、IDE のVisual Studioなどといったツールに関するものもあります。

ただし、これらをどのように使うのかにつて言及したドキュメントはありませんでした。

GitHub の gitignore リポジトリ

gitignore.io 発祥の元となる GitHub のgithub/gitignoreリポジトリを見てみます。このリポジトリは GitHub で新しいリポジトリを作成する際の [Add .gitignore] で使われるテンプレートです。

このリポジトリで気になるのがGlobalディレクトリです。OS や IDE/エディター の設定が、このGlobalディレクトリにあります。

そして、以下のドキュメントへのリンクがあります。色々説明がありますが OS 固有のファイルなどは global .gitignore を作り、そちらに設定するようにとのことです。

つまり、このGlobalディレクトリにあるような定義はプロダクトの.gitignoreではなく、グローバル側(ユーザーのホームディレクトリ以下) に設定するとしています。

Git のドキュメント

GitHub で答えが出たように思いますが、最後に Git 公式では、どのように考えられているのか確認します。
.gitignore に関するドキュメント「Git - gitignore Documentation」があります。

まず.gitignore自体について以下のように書かれています。
“Patterns which should be version-controlled and distributed to other repositories via clone (i.e., files that all developers will want to ignore) should go into a .gitignore file. -gitignore Documentation

そして、もうひとつ。
“Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a file specified by core.excludesFile in the user’s ~/.gitconfig. -gitignore Documentation

ざっくり意訳すると「すべての開発者が無視したいファイルをバージョン管理して、クローン先の他リポジトリへ配布するパターンとして.gitignoreファイルを使うべき」で「ユーザーのエディターが生成したバックアップや一時ファイルは、~/.gitconfigcore.excludesFileで指定したファイルに入れる」といった感じでしょうか。

全開発者で共有する内容に.gitignoreを使うべき(should be)で、ユーザー固有の設定はcore.excludesFileで指定したファイルにするのが一般的(generally)であると。

ここでも OS 固有の設定は.gitignoreではなく、グローバル側(ユーザーのホームディレクトリ以下) に作るとしています。

まとめ

Git 公式ドキュメントや、GitHub の説明から考えるとThumbs.db.DS_Storeなどの OS 固有の設定は、~/.gitconfigcore.excludesFile指定ファイルがよいといえるでしょう。

ただし使っている単語がshould be / generallyであり、mustではないので絶対ダメまではいかずとも、固有設定を.gitignoreに入れるのだとしたら、よく考えてからやりましょう、といったところでしょうか。(RFC ではないし、全大文字でもないですがRFC 2119 - IPAに倣って)

core.excludesFileのデフォルトは、以下の順で見つけたファイルを使います。そのためcore.excludesFileは明示的に設定せず、下記2番目の~/.config/git/ignoreファイルを作って使うのが簡単です。

  • $XDG_CONFIG_HOME/git/ignore
  • $HOME/.config/git/ignore(=~/.config/git/ignore)

これで、モヤっとしていたのがスッキリしました。
OS 固有の設定は~/.config/git/ignoreにしていきたいと思います。

では IDE/エディターの設定は?
“すべての開発者が無視したいファイル” か?、と考えると、やはり固有の設定といえるので~/.config/git/ignoreですね。OSS ではなく、クローズドなプロジェクトの場合は.gitignoreでよいかもしれませんが、いつ「すべての開発者」が変わるかもしれないと考えると~/.config/git/ignoreがよいと思います。

サーバレスな天気レポートの Slack ボット、「空鏡」

「空模様を図表に写して、天気をお伝えする「空鏡」」と題して、Slack で簡単に現在の天気情報を得られる Slack Slash Commands を作りました。そのサーバーレスなアーキテクチャを紹介します。

梅雨入りシーズン、天気予報を確認したり、お守り傘を持ったりしているかと思います。天気予報を確認するのは、いまの梅雨シーズンに限らず、次のゲリラ豪雨シーズンにも必要でしょう。普段はアプリやウェブサイトで確認しますが、Slack を使っている場合は Slack 上で確認できるとさら便利なのではないでしょうか。それを実現するのが「空鏡」です。

「空鏡(Sora-Kagami)」は Slack の Slash Commands として動作する天気レポートのサービスです。Slack で/sora 東京のような簡単な入力で天気情報が得られます。下図のような「現在の天気」「今後1時間の降水強度グラフ」「降水レーダー地図」で天気情報をお伝えします。(デモ環境については後述)

アーキテクチャ

「空鏡」は AWS 上に AWS Lambda と Amazon S3 を活用したサーバーレスなサービスとして構築されています。

以下、各パートについての概要です。別途詳細に解説する記事を書きたいと思います。今回はアーキテクチャとしての概要説明にとどめます。(いっぺんに書ききれない)

Slack Slash Commands のリクエスト受付

Slack Slash Commands は 3秒以内に応答する必要があります。最近でこそ Lambda の初期起動(コールドスタート)は速くなってきましたが、それでも外部 API 連携をしているサービスではかなり厳しい条件です。今回は遅延応答、Sending delayed responses - Slash Commandsを使ってレスポンスしています。これは Slack からのリクエストにいったん200 OKをレスポンスし、リクエストに含まれていたresponse_urlへ JSON を HTTP POST して返すというものです。この形式なら仕様上 30分まではレスポンスを遅らせることができます。(30分後にレスが突然来てもビックリかもしれませんが)

Serverless Framework による「Amazon API Gateway」と「非同期 AWS Lambda」の構成

Slack Slash Commands 遅延レスポンスを使うには、最初に200 OKを返すため、HTTP レスポンスとは別に非同期で本処理を行う必要があります。それを Lambda で行うには Amazon SNS や Amazon SQS へ処理を積むなどの工夫が必要だったのですが、Amazon API Gateway による非同期 Lambda の呼出しがサポートされました。X-Amz-Invocation-TypeEventの Lambda です。今回はこちらを使い200 OKの即時レスポンスと、非同期の本体処理を実現しています。

ただしX-Amz-Invocation-TypeEventの Lambda は、ちゃんと設定すると大変みたいです(途中で挫折した)。ここはServerlessを使うと簡単です。以下は Serverless での空鏡の定義抜粋ですがasync: trueと属性を設定するだけですべてを構成してくれます!

1
module.exports = {
2
  functions: {
3
    Command: {
4
      name: '${ self:custom.names.lambda.command }',
5
      handler: 'src/aws-lambda-handler/sora-kagami-command.handler',
6
      events: [{ http: { path: 'sora-kagami', method: 'post', cors: true, async: true }}]
7
    }
8
  }
9
}

非同期 AWS Lambda での処理

非同期な Lambda で構成されているとはいえ、基本的な Lambda の実装に変わりはありません。
以下は Lambda のメイン処理部分の TypeScript 実装です。

1
export const handler: Handler<APIGatewayProxyEvent, void> = async (event: APIGatewayProxyEvent): Promise<void> => {
2
  console.debug('Starting Lambda handler: event=%s', JSON.stringify(event));
3
4
  // tslint:disable-next-line: no-any - 'cus to parse non-JSON, JavaScript object literal like strings by Slack
5
  const command = event.body as any as SlashCommand;
6
  if (Env.SLACK_TOKENS.length !== 0 && !Env.SLACK_TOKENS.includes(command.token)) {
7
    return console.error('Forbidden: team=%s, command=%s', command.team_domain, JSON.stringify(command, undefined, 2));
8
  }
9
10
  try {
11
    const geo = await getGeometry(command.text);
12
    if (!geo) { return apis.slack.response(command, { text: `場所の検索に失敗しました。\`${command.command} [郵便番号 または 地名]\` を入力してください。` }); }
13
14
    const place = await getPlace(geo);
15
    const weathers = await getWeathers(geo);
16
17
    const filenames = Config.FILENAMES(geo, weathers.current);
18
    await Promise.all([
19
      apis.map.get(Config.REQUEST_MAP(geo)).then(async (value: Buffer) => {
20
        await apis.aws.s3PutObject(Env.S3_IMAGES_BUCKET, filenames.map, value, Config.CONTENT_TYPE_MAP);
21
      }),
22
      Config.CHART_CANVAS().renderToBuffer(createChartOps(weathers.data), Config.CONTENT_TYPE_CHART).then(async (value: Buffer) => {
23
        await apis.aws.s3PutObject(Env.S3_IMAGES_BUCKET, filenames.chart, value, Config.CONTENT_TYPE_CHART);
24
      })]
25
    );
26
27
    const message = createMessage(place, weathers, filenames, geo);
28
    await apis.slack.response(command, message);
29
  } catch (err) { await handleError(err as object, command); }
30
};

一番大きな違いは、1行目のメソッドの戻り値void(またはレスポンスを返すcontext/callbackを使わない点)です。API Gateway が200 OKをレスポンスしているため、Lambda からはレスポンスは返せません。そのためレスポンスにかかわる処理はありません。

変わってawait apis.slack.response(command, message);で Slack Slash Commands の遅延レスポンスresponse_urlへ HTTP POST して終了しています。また12行目のエラーレスポンスも同様に Slack へ返しています。

天気データは、Yahoo!デベロッパーネットワーク YOLP(地図)

天気や地点の検索は Yahoo! のYOLP(地図) APIを使っています。地図に関する API が豊富に用意されていて、利用方法も簡単です。
API の利用制限は 1日 50,000回までです。今回1リクエストで4回 API を使うので、デモ環境がもしかしたら辛そうです(このブログの PV から考えると十分耐えられると思いますが)。なお商用利用する場合は「お問い合わせください」とのことです。

今回は以下の API を使っています。

空鏡での機能YOLP API 名
郵便番号が入力された場合の地点検索郵便番号検索API
郵便番号でない場合の地点検索場所情報API
地点からのエリア名、周辺情報取得コンテンツジオコーダAPI
天気情報気象情報API
降水レーダー地図の生成スタティックマップAPI

グラフの描画は Chart.js

天気レポートの中段にある、今後1時間の降水強度予報グラフはChart.jsを使っています。

Chart.js は簡単なコードで綺麗なグラフを描画してくれます。以下はグラフ作成部分のコードです。(必要箇所のみ抜粋)

1
const createChartOps = (weathers: Weather[]): ChartConfiguration => {
2
  const data = weathers.map((value: Weather) => value.Rainfall);
3
  const borderColor = createChartColor(weathers, Config.ALPHA_BORDER);
4
  const backgroundColor = createChartColor(weathers, Config.ALPHA_BACKGROUND);
5
  return {
6
    type: 'bar',
7
    data: {
8
      labels: weathers.map((value: Weather) => dayjs(value.Date).format('H:mm')),
9
      datasets: [{ data, borderColor, backgroundColor }]
10
    },
11
    options: {
12
      legend: { display: false },
13
      scales: { yAxes: [{ ticks: { beginAtZero: true }}]}
14
    }
15
  };
16
};
17
const createChartColor = (weathers: Weather[], opacity: number): string[] =>
18
  weathers.map((value: Weather) => hexToRgba(WeatherForecastApi.getLevelColor(value.Rainfall), opacity));

dataに表示するグラフの配列を渡します。YOLP のレスポンスからRainfallの値を取り出して配列化しただけです。borderColorbackgroundColorは、雨雲レーダー - Yahoo!天気・災害の降水量の凡例からグラフの色を付けるための処理で、これも配列です。
基本的に配列を渡して、その配列群のインデックスが合うところを使う形です。

今回は1つしか描画しませんがdatasetsに複数の配列セットを渡すことで複数のグラフを描画できます。

Chart.js のグラフをサーバーサイドで画像化して Amazon S3 へ

Slack は、画像 URL を渡すと自動的に展開してくれます。逆に言うと URL がないと画像が表示できないということです。

画像をウェブサイトとしてホスティングするには S3 を使うのが AWS を使う上での常套手段でしょう。しかしながら、Chart.js が描画する Canvas を画像化するところがハマりました。

今回はSeanSobey/ChartjsNodeCanvasを使い、Node.js 上で Canvas を扱えるようにしています。
実態はAutomattic/node-canvasなのですが、こちらと Lambda の実行ランタイム環境との組み合わせの問題か、 Node.js 10.x では動作しませんでした。いったん Node.js 8.10 で動かしています。組合せとかもいろいろあるので、今後しっかりと調べたいと思います。

CircleCI

CI/CD にCircleCIを使っています。
基本的に Serverless がすべてをやってくれserverless deployだけなので難しいビルドプロセスはありません。

1つだけポイントがあります。デプロイ・ステージとブランチをマッピングしています。

今回、実行環境として Develop, QAS, Production の3つを用意しています。Develop は言わずもがなですが、デモ環境が必要なので分離して QAS を使っています。Production は使う予定ないですが、ソース公開にあたって設定しています。

それに応じてステージのキーワードを3文字でdevqasprdに。対応するブランチをmasterstableproductionとしています。

各ブランチにプッシュされると自動的にビルドが走り、ステージに応じた環境へデプロイされます。
継続的に開発を行うには CI/CD は必須であるとともに、今回のように複数環境へ対応できるようにすると便利です。

Slack へ、画像をポストする際のテクニック

Slack で、画像や URL をポストするときのテクニックを2つ。

画像 URL はランダムにする
URL の最後に?ランダムな値を付けます。パラメーター名が必要な場合は適当なものを付けて構いませんが、とにかくランダムな値(= URL) を作ってポストします。

これは Slack が同じ URL の文字列の場合、折り畳みで表示するためです。今回は日時と地点を使ってファイル名を作っていますが、YOLP が 10分おきのデータを作るため、たとえば同じ時間ゾーンだと画像 URL が同じなります。そうすると画像が展開されません。それを防止するためにランダムな値を付けます。

メッセージフォーマットを使う
これは公式ドキュメントにもあるのでテクニックまではいかないですが、使うと便利です。
画像などの URL をポストすると、生の URL が投稿されて、続いて画像が表示されます。ちょっと見た目が良くないので<URL|表示文字列><|>形式でポストします。

これにより、生 URL が表示されるのを避けられます。もっと言ってしまうと<URL| >と半角スペースにしてしまうと何も表示されません。(画像サイズの 129kB のような文字列はどうしても残ってしまいますが)

今後の展望

ゲリラ豪雨シーズンに向けて、着実にバージョンアップしていきたいと思います。

  • 指定地点で1時間以内の降水予報があったら自動通知
    現在は自分で Slash Commands をたたかないと表示されませんが、自動通知してくれるようにしたいです。
    ハードコードでよければ Amazon CloudWatch Events で cron 処理からの、Slack Incoming Webhooks で簡単ですが、地点は登録できるようにしたいですし、複数ユーザーに対応したい。そうなると結構複雑で今回は落としました。

  • Slack 以外のツールへ対応
    あまり需要がないかもしれませんが、何か他のツールにも対応してみたいです。
    ただアプリとウェブを使わないが、そのツールを使うというシーンが難しいです。ゆえに Slack として作りました。

  • ボット化
    今回「Slack ボット」と名乗っていますが、実態は Slash Commands です。ちゃんと会話の中から天気のキーワードを拾って返せるようにしたいです。これは WebSocketクライアントを作る必要があり、サーバーレスにしにくいというハードルがあります。サーバーレスの形態は崩したくないので、チャレンジですね。

その他、組み込んだらおもしろい機能などがあったら、ぜひ Issues や Pull Request をいただけたら幸いです。(もちろん Twitter DM@lulznekoでも)

デモ環境 & My 空鏡のセットアップについて

「空鏡」はデモ環境があります。空鏡デモを利用するには、お使いの Slack チームへSlash Commandsを導入します。

[コマンドを選択する] を/soraで、以下の Slack Slash Commands を設定します。

項目設定値
[URL]https://4tvr294f4h.execute-api.ap-northeast-1.amazonaws.com/qas/sora-kagami
[アイコンをカスタマイズ]任意の画像/絵文字 (※ もご利用いただけます)
[名前をカスタマイズ]任意の文字列 ( e.g.空鏡)
[説明]任意の文字列 ( e.g.現在の空模様をレポートします)
[使い方のヒント]任意の文字列 ( e.g.[郵便番号 or 地名])

以降、設定した Slack で /[コマンド名] [郵便番号 or 地名] を入力すると、空鏡デモから天気レポートが返信されます。

また「空鏡」は MIT ラインセスの元 OSS として公開しています。
利用している AWS の環境へデプロイすることもできます。

詳しくはリポジトリの README を、ご参照ください。

参考情報

Slack 関連

Yahoo! JAPAN 関連


非同期 AWS Lambda は Serverless から設定すると属性1つなので、とても簡単です。HTTP Request からの非同期処理はあまり作らないかもしれませんが、Serverless のこの機能は覚えておくとよいでしょう。

「空鏡」によって少しでも雨をよけられたら幸いです。

.gitignore は、生成サービス gitignore.io を使って作ろう!

Git のソースコード管理から特定のファイルやディレクトリを除外するのに .gitignore を使います。その .gitignore ファイル、手作りしていませんか?
gitignore.io のサービスを使うことでベストプラクティスを盛り込んだ .gitignore を手軽に作ることができます。素晴らしいサービスを活用して快適な .gitignore ライフを送りましょう!

gitignore.io とは

gitignore.ioは、”Create Useful .gitignore Files For Your Project” をタイトルに掲げている .gitignore 生成サービスです。

Java や Python, Node.js といった各種プログラミング言語や実行環境から、フレームワーク、開発環境、OS とさまざまな環境に応じた .gitignore を生成できます。先人たちの知恵が終結した、まさにベストプラクティスな .gitignore を簡単に手に入れることができるサービスです。

また生成元のテンプレートもGitHub で公開されているので、公式に追加してもらうこともできます。

ブラウザを使って生成

まずは使い方を確認するためにブラウザでアクセスして .gitignore を生成してみます。

ブラウザでhttps://www.gitignore.io/へアクセスします。
画面中央に入力フォームがあるので、生成したい環境を入力します。

インクリメンタルサーチが効いているので入力しながら確認ができます。またJavaScriptNodeなど、別名や集約されているケースがあるので、見つからない場合は、いくつか試してみてください。(どうしても見つからない場合や全候補が見たい場合はhttps://www.gitignore.io/api/listへ)

入力できると候補が確定します。欲しい組み合わせがある場合は検索ワードを追加し、完成したら [Create] ボタンをクリックします。

.gitignore が生成されます。
よくよく眺めてみると手入力では追加し忘れがちなyarn-error.logなども入っていて助かります。また逆に使っていないものも入っていますが、私は気にせずマルっと入れて使っています。

コマンドラインから生成

ブラウザからコピペもいいですが、コマンドラインからサクッと作ってしまいたいところです。
先ほどのブラウザで生成した .gitignore の URL を確認するとhttps://www.gitignore.io/api/node,nuxtのようになっています。https://www.gitignore.io/api/に続いて検索ワードをカンマ切りで追加しています。この URL を使うことで好みの .gitignore をcurlなどのコマンドから取得できます。

1
$ curl https://www.gitignore.io/api/node,nuxt
2
3
# Created by https://www.gitignore.io/api/node,nuxt
4
# Edit at https://www.gitignore.io/?templates=node,nuxt
5
6
### Node ###
7
# Logs
8
logs
9
*.log
10
npm-debug.log*
11
12
...(省略)

直接.gitignoreファイルへ書きだしてしまえば完成です。

1
$ curl -s https://www.gitignore.io/api/node,nuxt > .gitignore
2
$ ls -l .gitignore
3
-rw-rw-rw- 1 lulzneko lulzneko 1573  6月 18 11:14 .gitignore

コマンドラインからはインクリメンタルサーチの補完が効かず、また正確なキーワードが必要となります。キーワードがわからない場合はhttps://www.gitignore.io/api/listから全リストを取得して確認します。

1
$ curl https://www.gitignore.io/api/list
2
1c,1c-bitrix,a-frame,actionscript,ada
3
adobe,advancedinstaller,agda,al,alteraquartusii
4
altium,android,androidstudio,angular,anjuta
5
ansible,apachecordova,apachehadoop,appbuilder,appceleratortitanium
6
... (省略)

コマンドラインからも使えることで、プロジェクトの初期設定時に手軽に実行して .gitignore が作れるので助かります。


使っている環境に合わせて .gitignore を作れるのが嬉しいですね。新しいプロジェクトを作る時にサクッと生成して、すぐ次の作業や検討に入れるのがとてもよいです。

またプロジェクト固有の除外指定は、生成後に自分で追加できるので運用もあまり変わりなく、最初にプロジェクトメンバーの知見を集めるか、先人の知恵を借りるのかの違いといえるでしょう。むしろ率先してプルリクを出し先人の知恵に参加していきたいところです。

Shell の作業ディレクトリごとに自動で環境変数を設定する

さまざまなプロジェクトのソースコードを扱っていると、プロジェクトに応じて環境変数を切り替えたいことがあります。もし現在のディレクトリに応じて環境変数が自動的に切り替わったら?
それを実現してくれる direnv を紹介します。

The Twelve-Factor App (日本語訳)などでも取り上げられているように、アプリやシステムの設定に環境変数を使うことが多いです。

その環境変数を毎回設定するにしても手間ですし忘れがちです。また.bashrcなどに全部設定しロードしておくこともできますが、プロジェクトが増えてくると煩雑になり困ります。

そのような時に使えるのがdirenvです。対応しているのが “bash, zsh, tcsh, fish shell and elvish -direnv“ とのことなので、Linux/Mac そして WSL(Windows Subsystem for Linux) が中心となりますが、環境変数を自動的に切り替えてくれる素晴らしい機能を提供してくれます。

環境
本記事の開発環境は以下となります。

  • Windows 10 64bit + WSL Ubuntu 18.04.1 LTS
  • Bash 4.4.19 (WSL Ubuntu)
  • direnv/direnv 2.20.0

参考情報

direnv とは

Shell 用の環境スイッチャーで、現在のディレクトリに応じて環境変数をロードまたはアンロードしてくれます。

まさに “~/.profile ファイルを乱雑にすることなくプロジェクト固有の環境変数を使用できます -direnv“ とのこと。

もう、この一文で語りつくされているのではないでしょうか。(私の序文は長くて冗長だった。。。)

direnv の導入

WSL Ubuntu にはデフォルトで入っていないのでインストールします。
※ 各環境に合わせたインストールおよび設定はInstall - direnv/direnvをご確認ください

1
$ sudo apt install direnv

~/.bashrcに以下の設定をします。
※ ただし WSL Ubuntu の場合は~/.bashrcがデフォルトで読み込まれないので、今回は~/.bash_profileに設定

1
# direnv configuration
2
export EDITOR=vi
3
eval "$(direnv hook bash)"

設定ファイルを記述するためのエディターを環境変数EDITORに設定します。今回はviとしました。続いてeval "$(direnv hook bash)"で Bash のフックに direnv を登録します。

上記設定を読み込みます。

1
$ source ~/.bash_profile

利用するプロジェクトごとに環境変数を設定

環境変数を設定したいディレクトリで.envrcファイルを作り、exportで環境変数の定義を書きます。利用しているシェルの種類にかかわらず、このファイルは Bash の書式で記述します。

direnv edit [path]でエディターを起動し、設定を保存します。

1
$ cd ~/my-brilliant-project
2
$ direnv edit .
3
export MSG=Hello

エディターを保存して終了すると、そのディレクトリに.envrcファイルが作られます。また以下のように設定を読み込んだとのメッセージが出力されます。環境変数を確認すると、確かに読み込まれています。

1
direnv: loading .envrc
2
direnv: export +MSG
3
4
$ echo $MSG
5
Hello

ディレクトリを出ていくと、以下のようにアンロードしたとのメッセージが出力され、また入ると読み込まれます。ディレクトリに応じて自動的に環境変数が切り替わっているのがわかります。

1
$ cd ../
2
direnv: unloading
3
4
$ echo ${MSG-unloaded}
5
unloaded    # アンロードされている
6
7
$ cd ~/my-brilliant-project
8
direnv: loading .envrc
9
direnv: export +DEBUG +MSG
10
11
$ echo ${MSG-unloaded}
12
Hello       # .envrc が読み込まれている

あとは、必要なディレクトリごとに.envrcを用意します。

なおdirenv edit以外の方法で.envrcが作られたり変更されると、はじめて.envrcを読み込む際にエラーが表示されます。これはアーカイブやgit cloneなどで.envrcが作られた場合も同様ですし、他のユーザーが.envrcを編集した(そのユーザーがdirenv editを使ったとしても)もエラーが表示されます。

これは自分が明示的に編集した.envrcではない場合に、自動で読み込むと危険だからです。
エラーが表示された場合は.envrcに問題ないことを確認し、読み込む場合はdirenv allowを実行します。
※ 一度direnv allowしても、.envrcが自分のdirenv edit以外で書き変わると再エラー&確認が必要となります

1
$ cd ~/my-splendid-project
2
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
3
4
$ direnv allow
5
direnv: loading .envrc
6
direnv: export +MSG

注意
.envrcに秘匿情報がある場合は、Git などのソースコード管理の対象にしないよう注意が必要です。


Shell のディレクトリ移動に応じて環境変数の定義を切り替えてくれる direnv、一度設定すれば後は無意識に切り替えてくれるので助かります。