リリースを気軽に祝う文化を作るために 〜喋るSlack botを作った話〜

VPoEの小笠原(@yamitzky)です。今回は、僕が勝手にやっている「プログラミングで社内を活性化させる仕組み」について紹介します。

その取り組みの一つが、JX通信社の“しゃべる” Slackbot の「speakerbot」です。こちらは、エンジニア Hub の記事でも少し紹介いただいています。

employment.en-japan.com

speakerbot の機能は、Slack で送った文章を、社内のスピーカーで自動で読み上げるだけのものですが、NewsDigest が速報ニュースを検知したときに読み上げたり、アプリリリースなどの「良いこと」があったときに皆で祝ったりと、いろいろと活用されています。

お祝いのとき↓ f:id:yamitzky:20180927224133p:plain

速報ニュースを検知したとき↓ f:id:yamitzky:20180927224116p:plain

speakerbotの仕組み

speakerbotは、 Python 製の Slack bot で、スピーカーにつながった社内の Raspberry Pi 上で動かしています。Amazon Polly という音声読み上げサービスを使っています。

f:id:yamitzky:20180927221547p:plain

なぜspeakerbotを作ったのか

アプリの大型リリースなどを月例会や打ち上げで祝うこともあるのですが、もっと日常的な「良いこと」が、チームを横断して気軽に祝えれば良いなと思っていました。例えば、ちょっとした改善がうまくいったとか、新しく契約ができたとかです。

とはいえ、全員の前で言葉で発表するのはちょっと勇気がいる人もいるので、 Slack bot に代わりに発表させればうまくいくのではないか?と思って作りました。

speakerbotと報道テクノロジーの関係

speakerbotの「重大ニュースを読み上げる」という機能の源流は、報道機関の現場にあります。共同通信の加盟社の報道フロアでは、 速報ニュースがあると社内放送で読み上げられる仕組み になっており、通称「ピーコ」と呼ばれています(「ピーピポピポピポ」という音がなるため;参考)。

f:id:yamitzky:20180927223154p:plain

speakerbotの場合は機械音声による読み上げですが、まさに「報道×テクノロジー」が生んだbotなのです・・・!

speakerbotの工夫したポイント

speakerbot で気軽に祝うために、いくつか工夫していることを紹介します。

あえて #general で見えるように書き込む

speakerbot に読み上げさせる際には、#general上でメンションを飛ばす形の運用にしています。

ヘッドホンをつけている働いている人もいて、音声だけだと聞き逃してしまう可能性があるので、あえて文字として残るようにしています。

リアクションを自動で残す

一番最初(左)のリアクションは、ランダムに bot が勝手につけます。そうすることで、コメントを書かなくてもリアクションしやすい環境を作っています。

f:id:yamitzky:20180927223635p:plain

読み上げスピードを遅くする

Amazon Polly には、音声の読み上げスピードを調整する機能があります。

読み上げスピードが早いと、気づいたときには聞き逃してしまったりするので、かなりゆっくりめで喋らせるなどの細かい工夫もしています。

speakerbot が製品にも役立った

「自動音声で重大ニュースを読み上げる」という仕組みは、AI緊急情報サービス「FASTALERT」にも組み込みました。

プロジェクトには関係なく作ったものが、結果的に製品に組み込まれて、プレスリリースにつながり、サービス利用者からのフィードバックにも繋がったので、とても良い体験でした。

おわりに

まだ speakerbot を使ってないメンバーも居たりするので、積極的に利用を促していくのは今後の課題です。引き続き、プログラミングで社内を活性化していきたいと思います。

www.wantedly.com

Nginx と自前の認証システムを組み合わせてセキュアなリソースを制限する

こんにちは、Pythonエンジニアの @kimihiro_n です。
ブログを書くとハイボールが飲め… 会社のエンジニアブログをはてなに作ってもらったので初投稿してみます。


Nginx で静的なファイルを配信する際に、認証をかませて配信対象を制限したいときってありますよね。 ページ自体のHTMLを表示する際にはログインが必須だけれども、そこで使っている画像やCSS, JSはそのまま見れてしまうという状況は場合によって好ましくありません。

静的ファイルに対する制限を手っ取り早く実現するには、 Basic 認証をかけてあげるのがシンプルです。ただ Basic 認証だとブラウザ側のダイアログが出てしまったりして、サービスとしてそのまま使いづらいです。DBとは別にユーザーの管理が必要になったりもしますし実用性に欠いてしまいます。

すでにログインのシステムが自前であるのであれば、システムと連携してよしなに出し分けできると嬉しいですね。Nginx には http_auth_request_module というモジュールが用意されており、これを用いることで任意の認証バックエンドと連携してリソースのアクセスを制限することが可能です。

http_auth_request_module とは

http://nginx.org/en/docs/http/ngx_http_auth_request_module.html

ngx_http_auth_request_module は Nginx 1.5.4 以降で導入されたカスタムモジュールです。リソースへアクセスする際に、プレリクエストとして認証サーバに問い合わせを行い、その結果に応じてアクセス制御を行います。 モジュールはオプションなので自分で Nginx をコンパイルする場合は、--with-http_auth_request_module というフラグを有効にしてコンパイルする必要があります。手元の Nginx に含まれているかどうかは以下のコマンドで確認が可能です。

nginx -V 2>&1 | grep -- 'http_auth_request_module'

Docker Hubにあがっている公式 Image の nginx:alpine にはすでに有効化された状態で入っていました。

$ docker run nginx:alpine nginx -V 2>&1 | grep -- http_auth_request_module
configure arguments: ...()... --with-http_auth_request_module ...()...

図: 連携イメージ f:id:nsmr_jx:20180822192711p:plain

ユーザーがプライベートなファイルにアクセスしようとすると、Nginx が 認証先として指定したサーバーへ確認のリクエストを飛ばしてくれます。認証側のサーバーは、リクエストを見て認証済かどうかを返します。この返り値に使われるのがステータスコードで、200番台のときは許可、401や403を返すと不許可となります。許可であれば Nginx はプライベートファイルをユーザーに返してくれます。 ステータスコードだけ通ればいいので、既存のログインシステムとかでも連携しやすそうですね。

実際に試してみる

https://github.com/pistatium/nginx_auth_sample

Docker-compose で簡単に試せる環境をつくってみました。

f:id:nsmr_jx:20180822191119p:plain:w200

Login ボタンを押すとログイン状態になり、/private/ 以下に置いた iframe 内のコンテンツを見ることができます。Logout ボタンを押せば再び見れなくなります。

server {
    server_name _;
    listen      80;
    access_log  /dev/stdout;
    error_log  /dev/stderr warn;
    root        /var/www/html;
    index  index.html;

    location /private/ {
        auth_request /auth/is_login;
    }
    
    location /auth {
        proxy_pass http://backend:8888;
        proxy_redirect off;
        proxy_set_header   Host $http_host;
    }
}

Nginx の設定はこんな感じです。 location /private/ のディレクティブで auth_request /auth/is_login; という指定をしています。これは /private/ 以下のファイルへアクセスする際に、/auth/is_login へ権限があるかを確認しにいくよう指定しています。/auth/is_login が 200 番台のステータスコードを返してくれればファイルを見ることができます。

設定の肝はこれだけなのですが、認証サーバーが別途ないことには試せないので、Python + Flask で擬似ログインシステムを作りました。/auth 以下のリクエストはすべてこのサーバーへ飛んでいきます。

@app.route('/auth/is_login')
def is_login():
    if not request.cookies.get(SESSION_KEY):
        abort(401)
    return ''  # 200 (204 を返してもいいかもしれない)

/auth/is_login のコード抜粋です。疑似ログインなので、特定の Cookie がセットされてればログインしたことにしています。実際は DB を見にいったりして正しいログイン状態であるかチェックする必要があります。 Nginxへ返すレスポンスは「ログインしていれば空のレスポンス(ステータスコード200)」 を、「ログインしていなければ401を返す」だけなので簡単ですね。 なお、プライベートなファイルにアクセスするたびに Nginx から認証のプレリクエストが飛ぶので、スループットを上げるには別途キャッシュなどの工夫が必要になりそうです。

これだけで Nginx のプロキシに対して独自の認証を組み込むことができました。静的なファイルの配信ではアクセス制御がおざなりになりがちですが、Nginx 上で弾けるのであれば積極的に使っていきたいですね。

参考

レッドアローで行く 秩父二泊三日の旅 「JX Summer Camp 2018」

f:id:numatch-jx:20180814180727j:plain

こんにちは、Androidエンジニアのぬまっちです。(@nuMatch)
5月に社内で技術書ビブリオバトルの記事を執筆して以来のブログになります。

www.wantedly.com

今年も7/25〜7/27の日程で合宿に行ってきました!
わたくし、ぬまっちが幹事を仰せつかりましたので、 ご紹介レポートをお届けしたいと思います。

レッドアロー号の指定席で秩父へ

今年の合宿の場所は秩父!池袋からレッドアローに乗って約1時間半、指定席に乗って快適な旅路です。

f:id:numatch-jx:20180811221402j:plainf:id:numatch-jx:20180811221340j:plain
車内にて

駅からはバスで迎えに来て頂き、今年の研修場所に到着です。
今年の宿は「梁山泊」さんに泊まらせていただきました。
ただし研修会場は宿とは別棟にありますので、まずはそちらに直行です!

f:id:numatch-jx:20180814180943j:plain

梁山泊ホール
ここが研修場所になります。
到着次第、息つく暇もなく研修が始まります。

f:id:numatch-jx:20180814181042j:plain

今年は開発合宿、ではない

去年までならば

「それじゃ、ここからは各自のテーマに沿って開発スタート!」  

とエンジニアがもくもくと開発に入っていくところでしたが今年は違います。

JX Summer Camp 2018

今年はエンジニアだけが参加する開発メインの合宿ではなく、
ビジネスチームも同時参加のSummer Campなのです!

普段の業務では中々取り組めない事をテーマにしてみようという初の取り組みになります。

f:id:numatch-jx:20180814181249j:plain f:id:numatch-jx:20180814181231j:plain

エンジニアとビジネスサイドが同じタイミングで一緒にブレストしたり、講習を受ける機会は中々作れないのでとても新鮮な体験になったと思います。
自分はエンジニアとしての合宿参加だったのですが、ビジネスサイドの業務を体験出来たのは新鮮でした!

f:id:numatch-jx:20180814181411j:plain f:id:numatch-jx:20180811230307j:plain

宿で思いっきりはしゃぐ

幹事として部屋割りに頭を悩ます必要はありませんでした。なぜなら全員一つの大部屋なのです。

f:id:numatch-jx:20180811230833j:plain

晩ごはんもみんなで仲良く一緒に。

f:id:numatch-jx:20180815012841j:plain

温泉に入ったり、お酒片手にボードゲームで懇親を深めたりで和気あいあい。チーム関係なく楽しい夜を過ごせました。

f:id:numatch-jx:20180814181858j:plain

畳の上でWelcome Contribution会

晩ごはんを食べてからも合宿は続きます!

エンジニアが普段できない開発をやってみるWelcome Contribution会が開催されました。畳の上で!

f:id:numatch-jx:20180811231717j:plain f:id:numatch-jx:20180815013013p:plain

まさに合宿感が出ている風景ですね。 チームの垣根を超えた開発体験が出来て良かったと思います。

ギャラリー

f:id:numatch-jx:20180815013043j:plain
夜はSwitchで盛り上がる一面も

f:id:numatch-jx:20180811231947j:plain
外でお弁当食べてリフレッシュ!

合宿参加者の声

  • 大部屋での作業はまったりしつつ聞くこともできて集中もできたので良かった
  • 別チームの課題を共有できた
  • 特急利用していけるのが快適だった
  • 他チームの具体的な仕事の話を一緒の空間で聞けたのは新鮮だった。
  • 大部屋だったので皆が集まるのに狭い思いをすることなく懇親できたのはよかった。
  • 24時間風呂使えるのよかった(前回は時間決まってたので)
  • このような機会がないと時間を作りにくいような講習を受けられたので凄く良かった。勉強になった。
  • 温泉でツルツルになれたのは良かった。

Next Camp is ... ?

いかがでしたでしょうか。年に一度の合宿はJX通信社の文化になりつつあります。

最後になりましたが、研修場所と宿への往復でバスを出して頂いたり、
細かいお願いにも快く対応して下さいました梁山泊さん、ありがとうございました!

秩父小鹿野温泉旅館 梁山泊

次はどんな合宿が開かれるのでしょうか?
今から次回が楽しみです。

f:id:numatch-jx:20180814182335j:plain

OSS 版 Redash を Docker と AWS でセキュアに運用する

VPoEの小笠原(@yamitzky)です。

JX通信社では、NewsDigestFASTALERT の KPI 管理や、データ分析の用途などで、 Redash を活用しています。

ただしセキュリティ上の観点から、Redash の OSS 版をプライベートなネットワーク内で運用しています。セキュリティ的には良いのですが、機能的な面ではマネージド版に劣る部分があります。例えば、Slack の bot や、Google Spreadsheet との連携などはできなくなってしまいます。そこで、新しくOSSを作ってこれらの課題を解決しています。その他にも、通常のマネージド版にはない機能を拡張したりもしています。

2年半 Redash を運用して溜まった知見を紹介します。

Docker クラスター上での Redash のホスト

f:id:yamitzky:20180704000651p:plain

JX通信社のインフラは、基本的には AWS 上にあります。

Redash の公式 Docker イメージを利用し、Amazon ECS を使った社内の Docker クラスター上にデプロイしてホストしています。後述する各種 OSS も、同様に Docker 化してデプロイしています。また、バージョンのアップデートは、Docker イメージのタグを切り替えることによって対応しています。

先述したように、セキュリティ的な観点から Redash はプライベート環境で運用されており、社外からは直接アクセスできないようになっています。

弊社の他サービスでも使ってる Docker クラスターにデプロイすることで、余剰リソースで Redash を使ってることになるので、かなり安価にホストできていることになります。また、WEB+DB PRESSに寄稿させていただいたようなサーバーレスログ基盤を運用しているため、ログデータの管理なども安価です。

OSS 版 Slackbot

Redash には Slack の bot がありますが、Redash がプライベートネットワーク内にあると公式 bot (外部ネットワーク)からアクセスできないために、動きません。

JX通信社では、hakobera さんが開発したものをフォークした、 yamitzky/redash を使っています。もちろん、Dockerイメージ もあります。

フォークした版は、元のものに比べて次のような追加機能があります。

  • グラフだけではなく、テーブルやダッシュボードの結果の投稿
  • 結果の投稿時に、クエリ名などを補完する (検索するとき便利です)
  • puppeteer への移行
  • オフィシャル Docker イメージの提供

f:id:yamitzky:20180705190958p:plain

Google Spreadsheet への連携

Google Spreadsheet は、IMPORTDATA 関数でインターネット上の CSV ファイルをインポートする機能があります。これを使うと、Redash の結果を Spreadsheet へインポートすることができます。

しかし、Redash がプライベート環境にある場合、外部ネットワークにある Spreadsheet のサーバーから Redash にアクセスできないので、動きません。

そこで yamitzky/redash-to-spreadsheet を開発し、一定の命名規則で作った Spreadsheet に、Redash のクエリ結果を自動でエクスポートするようにしています。こちらも Docker イメージがあります。

例えば、 Q135: ほげほげ というタイトルの Spreadsheet を作ると、クエリID「135」のクエリの結果が、定期的に保存されます。

追加のデータソース「iTunes Connect App Analytics」

ここからは、通常のRedash にはない機能です

Redash には、特定のフォーマットの URL(API) をデータソースとして扱う機能があります。

そこで、yamitzky/itunes-connect-analytics-api を作り、iTunes Connect の App Analytics の情報を Redash 向けに加工し、Redash 上からクラッシュ情報やストア情報をクエリできるようにしました。こちらも Docker イメージがあります。

ログ可視化ツール

こちらはまだ開発途中なのですが、 Redash で集計したユーザーログを、SPA 上でわかりやすく可視化する OSSyamitzky/redash-log-viewer」を作っています。ユーザーの行動をより定性的に追って、気づきを得たり、さらに使いやすいものにしていくのが目的です。

f:id:yamitzky:20180704000716p:plain

まとめ

最初に上げた構成図に紹介した OSS も含めて拡張した結果、こんな感じになっています。

f:id:yamitzky:20180704001116p:plain

Redash は OSS であり、API も完備されているということもあり、かなり拡張性があるものだと感じています。

引き続き、外部OSS という形で Redash のエコシステムをより便利なものにしていきたいです。

JX通信社では一緒にログ基盤を作るエンジニアを募集しています

WEB+DB PRESS vol.105の特集「実践サーバレス」を寄稿しました #wdpress

VPoEの小笠原(@yamitzky)です。技術評論社出版「WEB+DB PRESS」の今月号の特集「実践サーバレス」にJX通信社のエンジニア3名で寄稿しました。WEB+DB PRESSで初めてのサーバレス特集とのことです。発売日は6月23日(土)です。

表紙画像
WEB+DB PRESS Vol.105|技術評論社

きっかけ

今年の春頃、デブサミ2018でNewsDigestのサーバレスに関して発表させていただいたのですが、資料をご覧になった技術評論社の担当者の方にお声がけいただきました。

www.wantedly.com

特集の構成と見どころ

前半は導入、中盤は実践、後半は運用、といった構成になっています。

第1章:サーバレスとは何か・・・メリットと制限を正しく知る
第2章:サーバレス環境の作り方・・・AWS LambdaでHello World
第3章:サーバレスなAPIを作ろう・・・APIの設計,開発環境の構築,デプロイ
第4章:サーバレスなデータ分析環境を作ろう・・・Firehoseによる収集,Kinesis/S3による保存,Athenaによる集計
第5章:サーバレスを支える継続的デリバリ・・・Circle CI/Terraformによるテストとデプロイの自動化
第6章:サーバレスなシステムの監視・・・今日からできるログ/メトリクス監視

JX通信社では、2016年ごろからサーバレスなシステムを本番稼働しています。

それも一部の小さな機能だけではなく、4章のビッグデータ基盤や、3章の API のような、ある程度大きなシステムです。当然チームでシステムを作るので「サーバレスなシステムを、どうやってチームで開発・保守していくのか?」が課題となり、その解決策として、CI/CDの自動化やコード設計の工夫をしています。

今回のサーバレス特集は、初心者向けの入門だけではなく、そのような実運用を経た上でのプラクティスを紹介していますので、初心者から上級者までぜひご覧いただければと思います!

おわりに

人生で初めての「紙のデプロイ」で、いろいろと慣れないところも多かったのですが、編集の方にサポートいただきながらなんとかデプロイすることができました。とても貴重な経験でした。ありがとうございました!

まだ校了の打ち上げをしていないので、校正に協力してくれたJXのメンバーと焼き肉で打ち上げをしたいと思います。

↓ 校了の際のSlack (※社内スピーカーでも読み上げられる仕組みです) f:id:yamitzky:20180621184043p:plain

JX通信社ではエンジニアを募集しています