ランキング1位の人気スマホアプリを
 カジュアル セキュアに運用する




             March. 16, 2013
                大井宏友
  株式会社リクルートホールディングス メディアテクノロジーラボ
自己紹介
       大井宏友 Hirotomo Oi
       Twitter: @hiroohi


       株式会社リクルートホールディングス
       メディアテクノロジーラボ

       チーフアーキテクト
       / Ambrotype Co-プロデューサー兼開発者
       / newsHUB 技術リーダー



       2007∼メディアテクノロジーラボにて、サービス企
       画開発運営(Recruit Web Services/演劇ライ
       フ)、クラウド環境構築に携わる。

       好きなAWSは、RDS。
Agenda
• メディアテクノロジーラボのご紹介
• AWS利用の際の全体ガイドライン
• アプリケーション事例紹介
リクルートグループ
リクルートGの実証実験機関

http://mtl.recruit.co.jp
事業化
      新規事業開発

R&D
MTL



                事業化
       新規事業開発

R&D
MTLのスマートフォンアプリ
(C)toC向けの、

  スマートフォン向け

  ソーシャルなんとか

    グローバルな

    サービスを

速く沢山生み出し改善しながら

   提供しています。
すべてAWS。
なぜ、AWS?
toCサービスの要件
toCサービスの要件
•規模が予測/コントロール不可能
•ユーザー数(多ければ多いほど嬉しい)
•データ量
•SNS上で突然の炎上バズ効果
•Yahoo!砲
toCサービスの要件
•規模が予測/コントロール不可能
•ユーザー数(多ければ多いほど嬉しい)
•データ量
•SNS上で突然の炎上バズ効果
•Yahoo!砲
•動いていて当たり前
•スマホアプリはサーバの状態が表に出ない
toCサービスの要件
•規模が予測/コントロール不可能
•ユーザー数(多ければ多いほど嬉しい)
•データ量
•SNS上で突然の炎上バズ効果
•Yahoo!砲
•動いていて当たり前
•スマホアプリはサーバの状態が表に出ない
•データをなくせない
toCサービスの要件
•規模が予測/コントロール不可能
•ユーザー数(多ければ多いほど嬉しい)
•データ量
•SNS上で突然の炎上バズ効果
•Yahoo!砲
•動いていて当たり前
•スマホアプリはサーバの状態が表に出ない
•データをなくせない
•低コスト
PDCAをぶんまわす
PDCAをぶんまわす
•予測不可能なので、PDCAを短期間のサイクル
で回し続ける。

•iOSアプリの場合、最短で2週間1サイクル。
•サーバ側で対応可能な場合1日単位での変更も。
AWSで解決
AWSで解決
•規模が予測/コントロール不可能
 ➡規模に応じて柔軟に増減できる。また様々なサ
 ービスを組み合わせられる。
AWSで解決
•規模が予測/コントロール不可能
 ➡規模に応じて柔軟に増減できる。また様々なサ
  ービスを組み合わせられる。


•動いていて当たり前
 ➡Multi-AZ, Regions, Route53, S3などなどを柔
  軟に組み合わせて
AWSで解決
•規模が予測/コントロール不可能
 ➡規模に応じて柔軟に増減できる。また様々なサ
  ービスを組み合わせられる。


•動いていて当たり前
 ➡Multi-AZ, Regions, Route53, S3などなどを柔
  軟に組み合わせて
AWSで解決
•規模が予測/コントロール不可能
 ➡規模に応じて柔軟に増減できる。また様々なサ
  ービスを組み合わせられる。


•動いていて当たり前
 ➡Multi-AZ, Regions, Route53, S3などなどを柔
  軟に組み合わせて


•データをなくせない
 ➡S3, RDSなどなどを柔軟に組み合わせて
カジュアルにセキュアに
 AWSをつかうために
カジュアルにセキュア
       =
アプリエンジニアでも安全に
×
全て一つのアカウントは厳しい
事業化
      新規事業開発

R&D
成功したら、MTLから卒業




 MTL



                事業化
       新規事業開発

R&D
成功したら、MTLから卒業

         事業会社で推進




 MTL



                      事業化
       新規事業開発
                   事業会社で推進


R&D
各サービス毎にAWSアカウント独自運用
約30人
   で
約30サービス
各サービス毎にそれぞれ数名のチーム
各サービス毎にそれぞれ数名のチーム
典型的なチーム体制
典型的なチーム体制




  主に企画
典型的なチーム体制




  主に企画   主にアプリ開発
典型的なチーム体制




  主に企画   主にアプリ開発
典型的なチーム体制




  主に企画         主にアプリ開発



   no infra specialist
各サービス毎にそれぞれ数名のチーム
各サービス毎にそれぞれ数名のチーム
社内外のアプリエンジニアと協力
3つの指針
3つの指針



•ACLサーバによるssh制限
3つの指針



•ACLサーバによるssh制限

• 必ずELB
3つの指針



•ACLサーバによるssh制限

• 必ずELB

• Auto Scaling
アプリエンジニアはNW/セキュリティ苦手
社外のアプリエンジニアさん
社外のアプリエンジニアさん
•固定IPではないネット環境
社外のアプリエンジニアさん
•固定IPではないネット環境
•コワーキングスペース
社外のアプリエンジニアさん
•固定IPではないネット環境
•コワーキングスペース
•ノマドワーク
社外のアプリエンジニアさん
•固定IPではないネット環境
•コワーキングスペース
•ノマドワーク
•モバイル回線
社外のアプリエンジニアさん
•固定IPではないネット環境
•コワーキングスペース
•ノマドワーク
•モバイル回線
➡IPよく分からない
「SSH 0.0.0.0/0」orz...
ACLサーバで制限
•自分の接続元IPを簡単にSecurityGroupに登録
する画面を設置

•この画面はSSLクライアント証明書でアクセス制限

•一日一回、SecurityGroupのsshを消去するス
クリプトを実行
IP登録画面
IP登録画面
スマホでカジュアルにssh
Remove from Security Group
$ec2 = new AmazonEC2();
$ec2->set_region($AWS_REGION);
$response = $ec2->describe_security_groups(array('GroupName' => $groupName));
$ip_rows = $response->body->securityGroupInfo->item->ipPermissions->to_array();
$ipranges = array();
foreach($ip_rows as $ip_row){
  foreach($ip_row as $row){
    if(!($row["ipProtocol"] == "tcp" && $row["fromPort"] == "22")){continue;}
    foreach($row["ipRanges"] as $iprange){
      foreach($iprange as $range){
        if(is_array($range)){
          $ipvalue = $range['cidrIp'];
        }else{
          $ipvalue = $range;
        }
        $response = $ec2->revoke_security_group_ingress(array(
          'GroupName' => $groupName,
          'IpPermissions' => array(
            array(
               'IpProtocol' => 'tcp',
               'FromPort' => '22',
               'ToPort' => '22',
               'IpRanges' => array(
                 array('CidrIp' => $ipvalue),
               )
            )
          )
        ));
      }
    }
  }
}
Remove from Security Group
$ec2 = new AmazonEC2();
$ec2->set_region($AWS_REGION);
                                         describe_security_group
$response = $ec2->describe_security_groups(array('GroupName' => $groupName));
$ip_rows = $response->body->securityGroupInfo->item->ipPermissions->to_array();
$ipranges = array();
foreach($ip_rows as $ip_row){
                                         s()でsg取得
  foreach($ip_row as $row){
    if(!($row["ipProtocol"] == "tcp" && $row["fromPort"] == "22")){continue;}
    foreach($row["ipRanges"] as $iprange){
      foreach($iprange as $range){
        if(is_array($range)){
          $ipvalue = $range['cidrIp'];
        }else{
          $ipvalue = $range;
        }
        $response = $ec2->revoke_security_group_ingress(array(
          'GroupName' => $groupName,
          'IpPermissions' => array(
            array(
               'IpProtocol' => 'tcp',
               'FromPort' => '22',
               'ToPort' => '22',
               'IpRanges' => array(
                 array('CidrIp' => $ipvalue),
               )
            )
          )
        ));
      }
    }
  }
}
Remove from Security Group
$ec2 = new AmazonEC2();
$ec2->set_region($AWS_REGION);
                                         describe_security_group
$response = $ec2->describe_security_groups(array('GroupName' => $groupName));
$ip_rows = $response->body->securityGroupInfo->item->ipPermissions->to_array();
$ipranges = array();
foreach($ip_rows as $ip_row){
                                         s()でsg取得
  foreach($ip_row as $row){
    if(!($row["ipProtocol"] == "tcp" && $row["fromPort"] == "22")){continue;}
    foreach($row["ipRanges"] as $iprange){
      foreach($iprange as $range){
        if(is_array($range)){
          $ipvalue = $range['cidrIp'];
        }else{
          $ipvalue = $range;
        }
                                              revoke_security_group_i
        $response = $ec2->revoke_security_group_ingress(array(
          'GroupName' => $groupName,
          'IpPermissions' => array(
            array(
                                              ngress()でレコード削除
               'IpProtocol' => 'tcp',
               'FromPort' => '22',
               'ToPort' => '22',
               'IpRanges' => array(
                 array('CidrIp' => $ipvalue),
               )
            )
          )
        ));
      }
    }
  }
}
WEB用AMIの制限
•iptablesやhosts.allow/denyでインターネットから
 のsshを拒否。

 •Security Groupを設定されちゃっても大丈夫
•sshはACLサーバからのみ許可
×
WEB用AMIの制限
•iptablesやhosts.allow/denyでインターネットから
 のsshを拒否。

 •Security Groupを設定されちゃっても大丈夫
•sshはACLサーバからのみ許可
操作ログの取得
•sshの操作ログはACLサーバ上でscriptコマン
ドで全取得

•操作ログを含むシステムログはS3→Glacierで1
年間保存
必ずELB
•攻撃者に攻撃の手がかりを与えない
•手がかり:使用ミドルウェアやバージョン情報

•ELBを通すと、手がかりが隠 される。
•勿論、必要なポートだけあけるので安全。
Auto Scaling
•サービスが常に動いている状態をカジュアルに
 構築するため。



•1台の場合でも設定=サーバがこけた時もサー
 ビス継続

•突発的な炎上バズ対策としても有効
共通AMIを各アカウントに配布
共通AMIを各アカウントに配布
basic archtecture
                                 EC2(web) 1
         ELB
                               sshはACLからのみ
    http/httpsのみ
                                  AutoScale
     1台でも設置




http/https
                             Availability Zone




   ssh                       Availability Zone




                        EC2(ACL)
                       sshの踏み台
                       操作ログ取得
各サービス毎に自由に構成
事例をご紹介


 Ambrotype



             Cameran



        newsHUB
事例をご紹介

                        DevOpsっぽい例として
      Ambrotype



                  Cameran

 サービスに特化した
アーキテクチャ採用例と
     して       newsHUB
http://ambrotype.com
1827年
約200年後
「写真撮影」は
 より⾝身近に
10%
20%
思い出
 の
所在...
Ambrotype
     =
「思い出アルバム」
DEMO
Re-fetching
your photos
 from these
  serivices
Sort by
     date
“Automatically”
Notify a photo
   of your
 memories
     daily
= Serendipity
Communication
Make album
  by Face
recognition
Make
album
by Geo
Make a
Greeting Card
Make a
Greeting Card
写真を集める
思い出を整理理する
思い出に出会う
思い出コミュニケーション
Ambrotype の AWS
Ambrotypeの技術トピックス
• 各SNS/クラウドサービスのAPIを叩きまくる
 • 対応サービス毎にAPI仕様が全く異なる。

• はじめから大量の写真情報が存在
 • 各社のAPIのリクエスト上限との戦い。
 • データ量、規模が予測できない。
コンテンツの増え方の違い

         一般的UGC          Ambrotype




  ↑
photos




                  days
Ambrotypeのサーバ側機能
• アプリケーションとのAPI
• クローラー
• 顔認識エンジン
• ソーシャル投稿
• プッシュ通知
構成(2012.6)
                                            iPhone
                                              App


                                             Route 53


                                                            ap-northeast-1
                                                    ELB



                         Web/App/             Web/App/
         Crawler
                          Crawler              Crawler
         EC2             EC2                   EC2
                               Auto scaling Group




                         RDS               RDS
                   AZ1                    Standby         AZ2
構成(2012.6)
                                            iPhone
                                              App


                                             Route 53


                                                            ap-northeast-1
                                                    ELB



                         Web/App/             Web/App/                 Auto Scaling
         Crawler
                          Crawler              Crawler                     >=1
         EC2             EC2                   EC2
                               Auto scaling Group




                         RDS               RDS
                   AZ1                    Standby         AZ2
構成(2012.6)
                                            iPhone
                                              App


                                             Route 53


                                                            ap-northeast-1
                                                    ELB



                         Web/App/             Web/App/                 Auto Scaling
         Crawler
                          Crawler              Crawler                     >=1
         EC2             EC2                   EC2
                               Auto scaling Group




                                                                             Multi-AZ
                         RDS               RDS
                   AZ1                    Standby         AZ2
リリース後に判明した課題
• 表示パフォーマンス
  • 適切な寸法の画像がない
  • 元画像のCDN利用の有無
CDNの有無

             Country       CDN

 Facebook     US            ⃝

   Flickr     US            ×

  Picasa      US            ⃝

   mixi        JP           ×

 Instagram    US       ⃝(CloudFront)
Twitter外部サービス




サムネイルがないなど寸法、CDN有無などバラバラ
リリース後に判明した課題
• 表示パフォーマンス
  • 適切な寸法の画像がない
  • 元画像のCDN利用の有無



• 自分たちでキャッシュする
構成(2012.6)
                                               App



                                             Route 53


                                                            ap-northeast-1
                                                    ELB



                         Web/App/             Web/App/
         Crawler
                          Crawler              Crawler
         EC2             EC2                   EC2
                               Auto scaling Group




                         RDS               RDS
                   AZ1                    Standby         AZ2
構成(2012.11)
                                                App



                                              Route 53
            CloudFront

                                                             ap-northeast-1
                   S3                                ELB



                          Web/App/             Web/App/
         Crawler
                           Crawler              Crawler
         EC2              EC2                   EC2
                                Auto scaling Group




         Face

         EC2              RDS               RDS
                    AZ1                    Standby         AZ2
newsHUB(ニュースハブ)
3/11リリース
ニュースカテゴリで1位
DEMO
ニュースを素早く
把握
ニュースのさわり
もサクサクと
週末版には漫画で
わかるニュースを
配信
newsHUB の AWS
newsHUBの技術トピックス
•認証がない
 •プッシュ通知用のIDをサーバに送る
 •記事の共有はアプリが行う

•設定がない

•1時間毎に同一のニュース記事を更新
 •新聞と同じモデル
newsHUBのサーバ側機能
•アプリケーションとのAPI
•プッシュ通知の為の登録
•クローラー
•プッシュ通知
構成
                                               App



                   JSON                      Route 53


                                                            ap-northeast-1
メディア各社             S3                               ELB



         Crawler          Web/App             Web/App
          Push
         EC2              EC2                  EC2
                               Auto scaling Group




                          RDS              RDS
                    AZ1                   Standby         AZ2
構成
         ほぼ
                                                    App
         これ


                        JSON                      Route 53


                                                                 ap-northeast-1
メディア各社                  S3                               ELB



              Crawler          Web/App             Web/App
               Push
              EC2              EC2                  EC2
                                    Auto scaling Group




                               RDS              RDS
                         AZ1                   Standby         AZ2
蜷川実花監修 cameran
日本を始め、台湾、香港等ア
ジア各国でNo.1

リリース10日間で100万DL
リリース5ヶ月で280万DL
DEMO
cameran の AWS
cameranの技術トピックス
•認証がない
 •プッシュ通知用のIDをサーバに送る
•ソーシャル拡散ページの生成
newsHUBのサーバ側機能
•アプリケーションとのAPI
•プッシュ通知の為の登録
•プッシュ通知
•SNS投稿したWEBページ
構成
                                         App



     Images                            Route 53


                                                      ap-northeast-1
          S3                                  ELB



                    Web/App             Web/App

                    EC2                  EC2
                         Auto scaling Group

              AZ1                                   AZ2




                       DynamoDB
DynamoDBを使ったわけ
•扱う情報が
 •Push通知用トークン
 •投稿ページURL

➡key-valueでいい。
サービス単位で最適な構成を追求
現在60アカウント位
カジュアルに稼働中
Thank you
 question?

Jaws days ランキング1位の人気スマホアプリを カジュアル×セキュアに運用する