devひよこのあしあと

いつでもひよっこな気持ちで学びと挑戦を

Rails5の新機能ActionCableを使ったスライド共有システムを作ってみた

社内LT大会で発表するネタとして、Rails5の新機能である ActionCable を使って某動画共有サイト風のスライド共有システム「nslides」を構築してみました。

まずは下記を参照ください。

ニコニコRails5 〜Rails5の新機能 ActionCable 使ってみたよ!〜 公開終了しました (2017/02/27)

f:id:devchick:20160313225406p:plain

ソースコードおよびシステム構築のためのプロビジョニング設定などはgithubにて公開しています。

https://github.com/devchick/nslides

ActionCableとは

ActionCableとはRailsアプリの中でWebSocketを簡単に利用できるようにするフレームワークです。 WebSocketを利用すると、クライアント側からサーバー側へいちいちHTTPリクエストでポーリングしたりすることなく、必要なタイミングでサーバー・クライアントが互いに通信することができます。これにより、サーバー側から通知情報をプッシュすることなどができるようになります。

ActionCableのサンプルとしてRails作者のDHHさんがシンプルなチャットシステムの作り方動画をこちらで公開しています。また、この動画の日本語解説が@jnchitoさんによってこちらで公開されています。

nslidesでは、コメントの配信と発表者のページ遷移に追従させるためにActionCableを利用しています。

ぶっちゃけてしまうと、「WebSocketって何? なんか便利らしいけどよーわからん。」程度にしかWebSocketを知りませんでしたがActionCableを使うことでそれなりに動作するモノが作れてしまったので、これからWebSocketの敷居が下がってくるのではないかと期待します。

Cable実装(サーバー側)

さて、ActionCableを使って実装している部分をピックアップして紹介します。詳細はリポジトリを参照ください。

Rails5においてActionCable関係のフォルダ構成は下記のようになっており、nslidesシステム用に作成したファイルはslide_channel.rbになります。

RAILS_ROOT
 └ app
   └ channels
     ├ application_cable
     │ ├ channel.rb
     │ └ connection.rb
     └ slide_channel.rb

SlideChannelはApplicationCable::Channelを継承したクラスで、クライアントからの接続要求の受け付けとアクションの受け付けを担わせました。ポイントは、ユーザーがいま閲覧しているスライドについての情報をやり取りしたいのでスライドIDごとにチャンネルを分けるようにしています。

なお、ApplicationCable::ChannelはActionCable::Channel::Baseを継承したクラスで、モデルでいうApplicationModelに相当する共通機能を定義しておく親クラスになります。

# RAILS_ROOT/app/channels/slide_channel.rb

class SlideChannel < ApplicationCable::Channel
  # 接続要求を受け付ける
  def subscribed
    # スライドIDごとにチャンネルを分ける
    stream_from "slide_channel_#{params[:slide_id]}"
  end

  # ユーザー定義のアクションメソッド
  def add_comment(data)
    data = data.with_indifferent_access
    comment = slide.comments.create(data[:comment])
    # 他の閲覧者への配信はバックグラウンドジョブに任せる
    CommentBroadcastJob.perform_later(comment, params)
  end

  private

  def slide
    @slide ||= Slide.find(params[:slide_id])
  end
end

上記で受信したコメント情報を接続されているソケット全部に対してメッセージ送信する処理は、下記のようにActiveJobを使って非同期に実施しています。

# RAILS_ROOT/app/jobs/comment_broadcast_job.rb

class CommentBroadcastJob < ApplicationJob
  queue_as :default

  def perform(comment, params)
    # スライドIDごとのチャンネルに対してメッセージ送信
    ActionCable.server.broadcast "slide_channel_#{params[:slide_id]}", comment: comment
  end
end

Cable実装(クライアント側)

クライアント側のActionCableに関する実装は下記のようにしました。フレームワークとして用いているReact.jsの方言がありますが、要はビューがレンダリングされたときにチャンネルにケーブル接続し、ケーブルを通してサーバー側からの通知を受ける仕組みとサーバー側に通知する仕組みを作っています。

// RAILS_ROOT/app/assets/javascript/components/views/slide_show.js.jsx

var SlideShow = React.createClass({
    componentDidMount() {
        // ビューのレンダリングが終わったら呼び出されるコールバックでチャンネルにケーブルを接続する
        this.subscriptChannel();
    },

    // ActionCableチャンネルの購読
    subscriptChannel() {
        App.slide = App.cable.subscriptions.create(
            // チャンネルの種類とスライドのIDを指定。これがサーバー側にparamsとしてセットされる。
            { channel: "SlideChannel", slide_id: this.state.slide.id },
            {
                // ActionCableが受信したときのコールバック
                received(data) {
                    // 受信したデータを解析して状態を更新する
                    var next_state = this.mergeData(data);
                    this.setState(next_state);
                },

                addComment(comment) {
                    // ケーブルを通してコメントを通知。サーバー側のadd_commentメソッドが呼び出される
                    this.perform('add_comment', { comment: comment });
                }
            }
        );
        App.slide.received = App.slide.received.bind(this);
    }
}

あとは、スライド下部に配置しているボタンが押下されたときにApp.slide.addComment()をコールしてやることで、コメント文字列がサーバー側に通知され、その後前述のロジックによりサーバー側から全クライアントへコメント文字列が配信されてきます。

var ActionBox = React.createClass({
    render() {
        return (
            <div className="action_box">
              <form>
                <Input type="textarea" placeholder="コメント" rows={1} />
                <ButtonInput type="submit" onClick={ this.addComment } value="コメントする" bsStyle="warning" />
              </form>
            </div>
        );
    },

    addComment(event) {
        event.preventDefault();
        var comment = {
            page_id:       this.props.current_page.id,
            body:          event.target.form[0].value,
            recorded_time: this.props.getElapsedTime()
        };
        if (comment.body) App.slide.addComment(comment); // ← ケーブルを通してコメントを通知
        if (event.target.form) event.target.form[0].value = "";
    }
}

地雷踏み

今回はRails 5.0.0.beta2というRCにも満たないベータ版を利用しています。そのためなのか開発していて少しハマったことがありました。

rails sでpumaをdevelopment状態で起動した状態でJSなどのソースコードを修正したあとブラウザをリロードすると修正後のコードがキチンと適用されます。ところが、ActionCableを接続している状態で同じことをすると下記のようなエラーが発生し、pumaを再起動しないと動作しない状態となってしまいました。

ActionController::RoutingError - uninitialized constant CommentsController:
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:46:in `rescue in controller'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:44:in `controller'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:30:in `serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/journey/router.rb:42:in `block in serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/journey/router.rb:29:in `serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:724:in `call'
    ...

RC1もしくは正式リリースでは動作するようになってると嬉しいなー。

システム構成

LT大会の枠が余ってるので何か発表して〜って主催者に依頼されたとき、Rails5の最新版が5.0.0.beta2だったのでこれを利用しています。この記事執筆時は5.0.0.beta3がリリースされており、更に近々5.0.0 RC1がリリースされることが示唆されています (3/1って書いてあるけどまだ出てないよな…)。RC1へのバージョンアップについてなどは機会があればまた別の記事で。

バックエンドをRails5で構成し、フロント部分にはReact.jsを今回は用いました。私自身はビューやJS、CSSあたりがちょっと苦手なもので、流行りのJSフレームワークに乗っかって楽をしたかったためです。初めてReact.jsに触れてみましたがなかなかすっきりと構成できて良い感じの印象です。Flux?とかいうのはまだ勉強足りてなくて導入してません。

インフラ周りはAWSを利用しています。AWSアカウント開設から1年間はいろいろなサービスの無料枠がありますので、それらをフル活用して構成しました。なので、今回のサービス開設にあたって掛かった費用はいまのところ、ドメイン取得のための88円のみ (ありがとうムームードメインさん)。アクセス数が増えてきた時にAWS無料枠の中だけで収まるかな〜。

今後の展開

  • HTTP/2による高速化
  • AWS Lambdaを使ってPDFファイル分解
  • ユーザー認証機能
  • チーム内共有機能
  • かっこいいデザイン
  • 社員総会でこのシステムを使う!!
    • 社長による来期の方針発表中とかにコメント送ってみたいwww

参考

  • nslidesの元ネタ

死活監視ツールGodが暴走するときの対処方法

結論

DelayedJobのような長時間実行するプロセスに対するGod設定にはgraceを設定しましょう。

God.watch do |w|
  ...
  w.grace = 5.seconds
  ...
end

Godとは

Godとはプロセスの死活監視ツールの一つです。プロセスが死ねば再び命を与え、プロセスがコンピューティングリソースを浪費するような悪さをすれば罰を与えるという、まさに『神』の如きツールです。

Rubyで作られたツールであり、設定ファイルもRubyによるDSLを用いて柔軟に構成することができます。 下記は、いろいろなサイトで紹介されているよくある設定です。

RAILS_ROOT = "/path/to/rails_root"
RAILS_ENV  = "production"

3.times do |num|
  God.watch do |w|
    w.name = "DelayedJob-#{num}"
    w.pid_file = "#{RAILS_ROOT}/tmp/pids/delayed_job.#{num}.pid"
    w.start = "cd #{RAILS_ROOT} && script/delayed_job --environment=#{RAILS_ENV} --identifier=#{num} start"
    w.restart = "kill -TERM `cat #{RAILS_ROOT}/tmp/pids/delayed_job.#{num}.pid`"
    w.stop = "cd #{RAILS_ROOT} && script/delayed_job --environment=#{RAILS_ENV} --identifier=#{num} stop"
    w.log = File.join(RAILS_ROOT, "log/god_delayed_monitor.#{num}.log")
    w.behavior(:clean_pid_file)

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.interval = 5.seconds
        c.running = false
      end
    end

    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
        c.above = 500.megabytes
        c.interval = 10.seconds
      end
    end
  end
end

この設定によって以下のような挙動となります。

  • DelayedJobプロセスを3つ稼働させる
  • 5秒ごとにプロセスの存在をチェックし、存在していなければ起動させる
  • 10秒ごとにプロセスの物理メモリ使用量をチェックし500MBを超過したら再起動させる
    • 再起動にはkillを使いプロセスにTERMシグナルを送信する

こまりごと

前述の設定で死活監視としてはきちんと動作します。しかし、監視対象がDelayedJobの場合に困った事象が発生します。

DelayedJobはTERMシグナルを受け取ったときにジョブ実行中の場合、割り込み処理で内部のフラグを立てたのち元のジョブ処理に戻ります。そしてジョブ実行が完了した後にプロセスを終了するという、gracefulな終了をしてくれます。

一方Godは、監視対象プロセスがメモリ超過したことを検知し、TERMシグナルを送信しますが、DelayedJobプロセスはすぐには死なない。なので再びTERMシグナルを送信します。が、やっぱり死なない... このときのGodの挙動がヒドイ。鬼神の如くこれでもかってくらい殺しにかかる。

2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:15+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:16+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:16+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:16+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
2015-09-18T18:40:16+0900: [Worker(delayed_job.1 host:BG.EXAMPLE.COM pid:31039)] Exiting...
  ...

その数、1秒間に約12回。TERMシグナルを送るためにbashプロセスとkillプロセスがそれぞれ生成されるし、シグナル受け取った側はその度に割り込み処理と復帰処理が発生。ジョブが1時間くらいかかるものだった場合、その間ずっとこれらの処理が繰り返されます。おかげで、サーバーのCPU負荷が上がりまくり。

我々は神の怒りをかってしまった。この世に救いはないのか...

神の怒りを沈める方法

Godのソース(ver. 0.13.6)を眺めていたら下記の記述がありました。

def action(a, c = nil)
  ...
  case a
  when :start
    call_action(c, :start)
    sleep(self.start_grace + self.grace)       # ← ん?
  when :restart
    if self.restart
      call_action(c, :restart)
    else
      action(:stop, c)
      action(:start, c)
    end
    sleep(self.restart_grace + self.grace)     # ← んん!?
  when :stop
    call_action(c, :stop)
    sleep(self.stop_grace + self.grace)        # ← おおぉぉ!!!?
  end
  self
end

(ノ゚ρ゚)ノ ォォォ・・ォ・・ォ・・・・ 神は我らに慈悲を与え給うた...

Godのwatchブロックにはgraceおよびstart_grace, restart_grace, stop_graceが用意されていました。これを設定すると再起動等のアクションが実行された後、通常の監視状態に戻る前に指定時間だけsleepしてくれます。

God.watch do |w|
  ...
  w.grace = 5.seconds
  ...
end

この設定をいれることによって、穏やかに再起動が実行されるようになりました。めでたし。

まとめ

GodでDelayedJobを監視したときに再起動処理が短時間に何度も繰り返される挙動を緩和する方法を紹介しました。

余談ですが、死活監視にGodというメタファーを用い、ウェイト時間にgrace(慈悲、寵愛)という名前を付けるセンスが羨ましい...

UMLでRailsモデリング

Railsエンジニアな皆さん、モデリングしてますか?

ひとりでシステム構築しているなら不要かもしれませんが、チームで活動し、ある程度の規模のシステムを構築/改修する場合は、いきなり実装するのではなくモデリングをしましょう!

モデリングの手段はたくさんありますが、統一記法であるUMLに従うのがいろいろメリットを享受できてよいかと思います。特に下記のメリットが重要です。

  • 視覚的な表現によって構造・振る舞いを直感的に把握できる
  • 開発に関わるメンバ全員が共通の言語でコミュニケーションできる

本記事ではRailsシステムをUMLモデリングする際の表現方法を紹介します。想定する読者は、上位者の指示の下Railsシステムの構築/改修をすることができ、今後ステップアップとして実装設計とか構造設計と呼ばれるフェーズを独力で実施できることを望むような人(およびその上位者)です。これによって少しでも多くの人が実装設計できるようになることを願います。

なお、モデリングツールとしては「astah* community」がオススメです。無償で使えて基本的なモデリング作業はほとんどできてしまう。しかも商用利用OK! (ただし、ver. 7.0からは商用利用できなくなってしまいました...) モデリングツールをまだインストールしていない人はぜひ入れておきましょう。

astah* community - 無償UMLモデリングツール | Astah

サンプルシステム

本記事で例示するシステムは下記のユースケースを想定したものとします。

f:id:devchick:20160312100400p:plain

構造設計

モデルの表現

RailsのモデルはO/Rマッピングなので、クラス図と特に相性がよいです。 コードと1対1で完全に一致するような正確性よりも、関係者間で共通の認識を持てることが重要です。そのため部分的に表現を省略することで、読み手に注目してもらいたい箇所が際立つようにします。機能改修テーマであれば、変更のある属性やメソッドだけを記載するといった工夫をすると良いと思います。

属性の表現

クラス図ではクラスの属性とメソッドを表現できます。これを使ってモデルを表現します。

f:id:devchick:20160312100418p:plain

idcreated_atupdated_atといった属性は大抵のモデルには存在しますが、煩雑になりますのでいちいち記述しないようにします。また、ActiveRecordの機能で属性に対するセッター/ゲッターは自動的に作成されますが、これも煩雑になりますので記述しないようにします。(属性をpublicにすることで表現してもいいのですが、毎度可視性を変更するのは面倒臭いのでやらないほうがいいでしょう。)

マイグレーションファイルにすると以下のようになります。

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string   :login
      t.string   :email
      t.string   :hashed_password
      t.string   :password_salt
      t.datetime :activated_at
      t.boolean  :enabled, null: false, default: true
      t.timestamps
    end
  end
end

なお、Datetime型やText型などRubyRailsでは標準で存在するけどモデリングツールにはデフォルトで存在しないようなクラスは、rubyパッケージを作成してそこに突っ込んでおくとよいです。

f:id:devchick:20160312100434p:plain

スコープの表現

モデルのスコープは静的メソッドにステレオタイプを付けて表現します。

f:id:devchick:20160312100451p:plain

上図のようにクラス図では、静的メソッドは下線付き、ステレオタイプは<< >>で表現します。

STIの表現

STI(Single Table Inheritance: 単一テーブル継承)はクラスの継承線にステレオタイプを付けて表現します。

f:id:devchick:20160312100506p:plain

typeカラムに具象クラス名を入れておくことで、インスタンスを取り出した時にActiveRecordが自動的にそのクラスのインスタンスに変換してくれます。

もうちょっと細かいSTIの話は下記のサイトを参照ください。 【Rails】ActiveRecord:単一テーブル継承(sti)とポリモーフィック関連を未だにぱっと思い出せないのでまとめ。 - 記すに足らず。

継承線に<<STI>>というステレオタイプを付けることで表していますので、typeカラムはクラス中に記載しなくてもよいのですが、「typeカラムに具象クラス名が入っているのでここはこのインスタンスになるんです〜」というSTIの説明を何度もすることがあるため、私はいつも記載するようにしています。関係者がSTIをしっかり理解してくれているならtypeカラムは省略してもよいのではないでしょうか。

class CreateImages < ActiveRecord::Migration
  def change
    create_table :images do |t|
      t.string   :type
      t.integer  :width
      t.integer  :height
      t.binary   :data
      t.timestamps
    end
  end
end

class Image < ActiveRecord::Base
end

class Avator < Image
end

class Photo < Image
end

has_one関連の表現

has_one関連はクラス間の集約を用いて表現します。白抜きひし形が付いている方が所有する側、線の繋がる先が所有される側になります。

f:id:devchick:20160312100529p:plain

上記の例の場合、所有される側のUserAttributeuser_idカラムが必要ですが、関連線があることで自ずと必要なことがわかりますので記載を省略します。

class CreateUserAttributes < ActiveRecord::Migration
  def change
    create_table :user_attributes do |t|
      t.integer  :user_id
      t.string   :title
      t.string   :zip_code
      t.string   :address
      t.string   :phone_number
      t.string   :url
      t.timestamps
    end
  end
end

class User < ActiveRecord::Base
  has_one :user_attribute
end

class UserAttribute < ActiveRecord::Base
  belongs_to :user
end

has_many関連の表現

has_many関連はクラス間の集約に多重度を付けて表現します。

f:id:devchick:20160312100547p:plain

has_one関連のときと同様にArticle側のuser_idカラムは省略します。

class CreateArticles < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      t.integer  :user_id
      t.string   :title
      t.text     :content
      t.timestamps
    end
  end
end

class User < ActiveRecord::Base
  has_many :articles
end

class Article < ActiveRecord::Base
  belongs_to :user
end

polymorphic関連の表現

polymorphic関連は、集約線にロール名をつけることで表現します。

f:id:devchick:20160312100603p:plain

上記の例ではSTIと組み合わせてあるのでちょっと複雑になっていますが、Imageモデルの所有者にownerというロール名を付けています。Imageモデルにはowner_typeowner_idカラムを記載していますが、polymorphic関連であることを関係者が認識してくれるなら記載を省略してもよいでしょう。

polymorphic関連についてもうちょっと細かい話は下記のサイトを参照ください。 【Rails】ActiveRecord:単一テーブル継承(sti)とポリモーフィック関連を未だにぱっと思い出せないのでまとめ。 - 記すに足らず。

class AddOwnerToImages < ActiveRecord::Migration
  def change
    add_column :images, :owner_type, :string
    add_column :images, :owner_id,   :integer
  end
end

class User < ActiveRecord::Base
  has_one :avator, as: :owner
end

class Article < ActiveRecord::Base
  has_many :photos, as: :owner
end

class Image < ActiveRecord::Base
  belongs_to :owner, polymorphic: true
end

ネームスペースの表現

ネームスペースはパッケージを使用して表現します。

f:id:devchick:20160312100619p:plain

class Image::Avator < Image
end

class Image::Photo < Image
end

Mix-inの表現

モジュールのMix-inは依存関係を用いて表現します。

f:id:devchick:20160312100630p:plain

Mix-inされるモジュールにはモジュールであることを示すためにステレオタイプで<<module>>を記載します。そしてMix-inする側からされる側へ、<<include>>ステレオタイプ付きの依存関係を引いて表現します。

class User < ActiveRecord::Base
  include User::Exportable
end

module User::Exportable
  extend ActiveSupport::Concern
  
  module ClassMethods
    def export
      ...
    end
  end
  
  def to_csv
      ...
  end
end

コントローラの表現

コントローラの構造をクラス図で表現することはできますが、コントローラに複雑な構造を持たせることもあまりないでしょうから、わざわざ図に起こすまでもないかも。ここでは、もし可視化したい要求があった場合の書き方を示します。

アクションの表現

アクションはシンプルにクラスのpubicメソッドとして表現します。

f:id:devchick:20160312100645p:plain

strong parameter用のメソッドなどのアクションから呼ばれるメソッドたちは可視性をprivate(もしくはprotected)にしたメソッドで表現します。

フィルターの表現

コントローラのフィルター機能はステレオタイプ付きprivateメソッドで表現します。

f:id:devchick:20160312100657p:plain

完成図

以上を踏まえて作成したクラス図が下記になります。

f:id:devchick:20160312100710p:plain

(...うーん、配置にセンスがないなぁ。)

振る舞い設計

システムの振る舞いはシーケンス図などを利用して表現します。

アクションの表現

f:id:devchick:20160312100730p:plain

DelayedJobやsidekiqなどを用いた非同期処理を含む場合も上図のようにシーケンス図内に記載することができます。

まとめ

本記事ではRailsシステムをUMLモデリングする際の表現方法を紹介しました。特に(Rails的な意味の)モデルの構造やモデル間の関係を表現する際に役立つのではないでしょうか。

ソースコードで語り合う前に(UML的な意味の)モデルを使ってチームメンバ間で会話してみましょう。より早く問題点を見つけられるかもしれませんし、その後のコーディングがより速くなると思います。 お試しあれ。

GitHubから人間失格の烙印をもらってしまった

事件発生

別記事を書くために初めてGistを使ってみたのですが、それの影響でGitHub上に下記のような警告が表示されるようになってしまいました。

f:id:devchick:20160311185531p:plain

One of our mostly harmless robots seems to think you are not a human.

オメーは人間じゃねーな!!? (意訳)

いやいやいやいや、めっちゃ人間ですって。あいむ あ ひゅーまんびーいんぐ。

おかげで先の記事に貼り付けたGistが自分では見れているけど、別ユーザーからは404 not found状態で表示されないという状態になってしまいました。

対処

please contact support

とあったのでサポートページからメールを送信しました。

Subject: I'm a human!!!

I got a message as : "One of our mostly harmless robots seems to think you are not a human."

No! I'm a human.

What should I do next?

ちょー簡単な内容ですが、人間っぽさが感じられる内容ならなんでもいいらしいです。

復活

サポートに連絡を入れてから待つこと約5時間。GitHubから返信がありました。

Hello there,

I'm sorry about our misbehaving robots - they do a good job but can be a bit overzealous at times. I've just unflagged your account and made your profile public again, you are all set!

うちのボットが迷惑かけたね、ごめんごめん。彼らはいい仕事するんだけどたまにやり過ぎちゃうんよ。とりま、フラグ外しといたんでこれで勘弁して。 (意訳)

メール受信後にGitHubを確認したら無事に警告が削除されており、Gistも表示されるようになりました。

めでたし。

MySQLのダンプファイルをテーブル毎に分割する

サービスが大きくなってくるとMySQLのダンプデータって巨大になってしまって、一部のデータだけリストアしたくってもダンプファイルを転送するだけでも時間かかるし、全データリストアしようものなら半日待ちぼうけとかになりかねません。

そんなときは、下記のスクリプトをご利用あれ。

MySQLのダンプファイルをテーブル毎に分割するスクリプト

MySQL 5.5で動作確認してます。

1から学ぶクラウドのセキュリティ勉強会

  • 日時: 2014/08/23 13:00〜18:00
  • 場所: fabbit (北九州市小倉)
  • 参加者: 20名程度

所感

JAWS-UGの勉強会への初めての参加であり、どんな情報が得られるのか全くわからず参加しましたが、行ってみてよかったと思います。 サーバー証明書には3種類あるんですとか、MicrosoftSHA1排除ポリシーとか、AWSの共有責任モデルという考え方とか、このWebシステム業界としては(特にインフラエンジニアとしては)知っていないといけないことを、今まで知らなかったことに気付かされました。

今回のはちょうど私の関心事に合致したテーマではありましたが、今後も同様の勉強会があれば参加したいと思います。

高まる「認証」の必要性~SSLサーバー証明書の基礎、最近の話題~

講師: サイバートラスト 坂本氏

サーバー証明書の用途:

  • 昔は暗号化
  • 最近はサイト証明

なぜ? → フィッシング詐欺などが多発

  • 2013年上期: 4,500件
  • 2013年下期: x,xxx件
  • 2014年上期: 18,000件

コンシューマーが危惧すること

  • 1位: フィッシング詐欺
    • フィッシャーの技術が上がっており、一見しては真偽を見極められない。
      • 昔はウチのサイトを真似ることはできないから大丈夫.. という意見もあった。
    • 玄人ならカギマークをクリックして証明書を確認するかもしれんけど、エンドユーザーは..?

求められるのはEVサーバー証明書

  • EVだけがわかりやすく「安全」をアピール
    • EVは規格の名称
    • DV: 安い。フィッシャーも簡単に取得できてしまう。
  • 「『緑』でなければ警戒して」という活用例は既にはじまっている。
    • 各ブラウザがURL入力欄を緑色で表示するように対応し始めている。

証明書3種類

  • DV: Domain Validation
    • 暗号化: OK, 企業認証: NG
  • OV: Organization Validarion
  • EV: Extended Validation
    • 暗号化: OK, 企業認証: OK(厳格な証明)

サイバートラストのメリット

  • モバイルの対応が強い
  • 発行スピードが速い
    • メール、電話、チャット、リモートデスクトップでのサポート完備
    • OVなら30分で発行。他社なら3時間とか1日。
    • EVなら1日

Microsoft SHA1 Deprecation Policy

  • https://www.cybertrust.ne.jp/ssl/sureserver/sha1ms.html
  • 「売るな」「使うな」に関する規制
  • MS製品上のみで実行される規制
  • SSLとコード署名証明書に対してのみ適用
  • 2010年問題
    • 業界ルールとして1024bitの暗号化はNGに。
    • 同じことがハッシュアルゴリズムにもこれから発生する。
  • Microsoftの指針
    • SHA-1証明書の発行: 2016/1/1に発行停止。以降発行禁止
    • SHA-1証明書によるWindowsSSL通信: 2017/1/1にSSL通信拒否。以降SSL通信不可。
      • MSがパッチを配布。パッチ適用後は通信不可。
  • サイバートラストでは
    • SHA1からSHA2へのアップグレードは無償
    • 2017/1/1以降も有効な証明書も提供可能。
      • 他社ではできないといわれることも。
      • MSと関係ないサービスを提供している顧客のために。
      • 予算組んでないよという顧客のために。
  • ガラケーの多くがSHA-2証明書に非対応
    • docomo 2009年冬春モデルより順次対応
    • au 2008年発売機種より順次対応
    • Softbank 2012年発売機種より順次対応
    • ガラケー用Gateを廃止するきっかけになるかも!!

利用者責任範囲におけるセキュリティ実装の方法について~ユースケースから考えてみる~

講師: トレンドマイクロ 南原氏

トレンドマイクロ

  • 創業者は外国人だけど、日本で起業した国内のベンダー

クラウドのセキュリティ

  • 情報漏洩などのセキュリティが心配...
    • オンプレミスのセキュリティって?
      • ネットワーク、ストレージ、サーバー、仮想化、OS、ミドルウェア、ランタイム、データ、アプリ ←全部ユーザー管理
    • クラウドサービス IaaS
      • ネットワーク、ストレージ、サーバー、仮想化 ←クラウドベンダーが管理
    • クラウドサービス SaaS
  • AWSのセキュリティの考え方 - 共有責任モデル

どうやって利用者責任範囲を守るか

  • piyolog
  • 攻撃タイプ
    • 正面から突破系(外部公開Webへのアタック)
      • 脆弱性の悪用
      • 不正な権限の取得
      • 基本的に改ざんされても気づけない。
        • iframeでwidth=0 height=0にして気づけないようにしてウィルスを入れるとか。
      • アカウントリスト攻撃が増えている
        • どっかから漏れたアカウントとパスワードを入手して、別のサイトにトライする
          • ヒット率: 0.3%
          • iTunes Cardが一番換金率がいいので、大抵それを購入される。
    • 中から攻め上がってくるタイプ(メールなどでクライアント感染。そこから...)
      • なりすまし&脆弱性の悪用
      • 不正な権限の取得
      • Code Spaces
        • いついつまでにこれをしろ。やらないと全部削除してやる。という脅迫を受けた。
        • ほかっといたら本当に消された。
        • 実はAWSのマネージメントコンソールのアカウントが抜かれていた。。。

必要な対策は

  • 防ぐというよりは、いかに早く気づくか
  • 総合対策を。
    • 従来型は予防的な対策が中心
    • 今後は発見的な対策も強化
      • 不正侵入、改ざんの検知。大量認証試行の検知など
    • 予防と発見で多層的な防御の仕組みを構築しよう。
      • Firewall
      • WAF IPS/IDS
      • ウィルス対策
      • セキュリティログ監視
      • 変更監視
    • ウィルスを出す方も、Mcafeeトレンドマイクロなどのセキュリティソフトで見つからないことを確認してから出してきている。

トレンドマイクロの商品

  • Trend Micro Deep Security
    • http://www.trendmicro.co.jp/jp/business/products/tmds/
    • インスタンスごとに対応が可能な「ホスト型」
    • httpリクエストを監視
    • ...
    • 5%程度のスループット低下
    • クックパッドさんで、500msecのリクエスト応答要求にも、調整次第で対応できた
    • エージェント型のシステム要件は512MB以上。
    • エージェント型の使用メモリはだいたい200MB。リクエスト数などには変動せずだいたい200MB前後で推移。
    • AutoScaling対応。契約台数の2倍までは利用OKなライセンス/料金体系。
    • 年間契約タイプ

クラウド環境で利用されるWebアプリケーションファイアウォール

講師: セキュアスカイ・テクノロジー 前平氏

なにを守るか?

  • 個人情報。重要情報
  • サイトの信頼性
  • ユーザーが攻撃者になるかも
  • サーバーが攻撃に利用されるかも
    • → 情報も持っていなくても、リスクがある。

攻防

  • [攻撃者] アカウントリストを元にIDアタック開始
  • [管理者] 同一IPからの認証NGが多いため、そのIPを遮断
  • [攻撃者] IP遮断されたことを関知して、プロキシを変えて攻撃続行
  • [管理者] 認証NGが閾値(30件)を超えたら遮断
  • [攻撃者] 閾値を超えないように調整(29件まで)して攻撃を続行

AWSが取得している第三社認証について

講師: サーバーワークス 小室氏

  • HIPAA
    • USの医療関係情報を扱ってもいいよという規定
  • SOC 1/SSAE 16/ISAE 3402
    • 委託会社の財務諸表に関するリスクに対して財務諸表監査
  • SOC 2
    • (委託会社の)可用性、気密性、セキュリティ、プライバシー、完全性をリスクとし、コンプライアンスまたはオペレーションに関する内部統制の報告
  • SOC 3
    • SOC2をより簡単に一般化・要約したもの
  • PCI DSS レベル1
    • クレジットカード情報を保管、処理、送信を行える認証
      • レベル1: 30万件以上/年
      • レベル2: 30万件未満/年
  • ISO 270001
    • 情報セキュリティに関する標準規格
    • 情報の気密性、完全性、可用性の3つを管理、運用する
  • FedRAMP (SM)
    • 日本にはあんまり関係ない
    • US政府がクラウドを使ってもOKと太鼓判おしたもの
  • DIACAPおよびFISMA
    • 連邦政府が外部委託先に対して決めた、セキュリティ規定
  • ITAR
    • 日本にはあんまり関係ない
    • 武器国際取引に関する規則
    • 武器や暗号化方式、飛行機の設計図などを輸出入してもOK
  • FIPS 140-2
    • 暗号化をどうやって保つか、セキュリティ要件の私用を規定するUSれんぽう標準規定
  • CSA
    • Cloud Security Alliance
    • クラウドプロバイダ内でのセキュリティ業務の透明性を推進し、セキュリティ管理作業を文書化する
  • MAPP
    • US映画協会
    • メティアやコンテンツを安全に保存、処理、配信するための一連のベストプラクティスに準拠しているよ。というもの

AWSに組み込まれてるセキュリティ機能の紹介

講師: ハウインターナショナル 安土氏

セキュリティグループ

VPC

  • 論理的に分離した仮想ネットワークを構築
  • よくある構成
    • Publicサブネット
      • 外部からのアクセスを許可するサブネット
    • Privateサブネット
      • 内部ホストやVPN接続された自社からのアクセスを許可するサブネット
      • 専用線接続
        • データセンターやオフィスとAWS間をインターネットを介さずに専用線でアクセス
      • ハードウェアVPN
      • ソフトウェアVPN

VPCネットワークACL

IAM

  • AWSサービスにアクセス可能なここのユーザーを作成
  • ユーザー個別にセキュリティ認証情報(パスワード、アクセスキー、MFA)を設定
  • AWSサービスへの権限設定
  • ユーザーの集合に対して権限設定できるグループ
  • IAM Role for EC2 Instance
    • EC2起動時にインスタンスに適用するRoleを指定すれば、Roleの権限によってそのインスタンスから他のAWSサービスへアクセス可能に。
    • 定期的にキーが更新されるため、キーが漏れても被害が一時的になる。
  • MFAデバイス

S3ストレージの暗号化

  • サーバーサイド暗号化
    • AWS側で生成したキーで暗号化
    • 自前で用意したキーを使用することもできる
  • クライアントサイド暗号化

Trusted Advisor

  • 最近無料化された!
  • 特定のポートに対して無制限アクセスを許可していないか?
  • ルートアカウントでMFAが無効でないか?
  • EC2のEBSが80%を超えていないか?
  • ...