2015年11月18日 (水)

AWS EC2 "悪い" EIPにご用心

エンジニアの佐藤です。こんにちは。
今回は「EIP(Elastic IP Address)は、払い出されたら外部接続を確認しよう」という注意喚起の話題を書かせていただきたいと思います。

EIPを設定したらGitHubに接続できない

ある日のこと、システムのリリースのためにEC2インスタンスを起動し、EIP(仮にxx.xx.xx.xx)を設定して、GitHubからcloneしようとすると、コネクションエラーになりました。おや?と思ってパケットキャプチャで調査すると、名前解決は成功するのですが、TCP SYNパケットに対する応答がありません。
EIPを外し、自動設定のグローバルIPアドレスが設定されると、接続できるようになりました。また、他のEIPを設定しても問題現象は再現しません。xx.xx.xx.xx固有の問題のようでした。
不思議なことに、問題のEIPを設定した場合でも「www.yahoo.com」には接続できます。しかし「msdn.microsoft.com」や「login.salesforce.com」には接続できません。接続先によって成功不成功があるようでした。

AWSのサポートに問い合わせる

AWSに質問したところ、初回の回答は順当なものでした。

  • AWS では特定のサイトやアドレスに関して制限をかけるといったことはしていない。
  • 接続先がアクセス制限を設定していた場合はAWSでは対応できない。

GitHubのブラックリスト

この段階で筆者が考えたのは、このxx.xx.xx.xxがブラックリストに掲載されており、GitHub(または中継ルーター)でブロックされている可能性でした。GitHubにはipset-blacklistというレポジトリがあり、有名ブラックリストを収集してくれます。早速実行してみました。
しかしながら、収集したブラックリストにxx.xx.xx.xxは入っていませんでした。

GitHubに問い合わせる

仕方がないのでGitHubに問い合わせてみることにしました。意外なことに1時間ほどで回答が来ました。「制限していない」と、明確な回答でした。

```

(筆者からGitHubへの質問) If I assign an IP address "xx.xx.xx.xx" to my computer, any request to GitHub is blocked. No connection can be established. That IP address isn't listed in "ipset-blacklist" blacklist. Does any additional filtering block that IP address?

(GitHubからの回答) There's no ban on that IP from our end. It could be an issue with your network environment of ISP. There's nothing we can do about it though.

```

再び、AWSのサポートに問い合わせる

いよいよ迷宮入りです。とりあえずこのGitHubからの回答をAWSサポートに追加情報として提供しましたが、解決に時間を要する可能性が高いと思いました。システムに設定しているEIPは変更し、AWSサポートの回答を待つことにしました。

同僚T氏から「IIJでこの種の問題が確認された場合は、中継ISPに順番に連絡してブラックリストを確認しているらしい。」という恐ろしい情報も伝えられました。ドツボにはまったのでしょうか。

原因はAWS内部のブラックリスト

そしてAWSサポートへの初回質問から約1ヶ月が経過したある日の晩、AWSサポートから以下のような回答が来ました。

  • EIP xx.xx.xx.xxは外部への接続を制限した状態だった。
  • 制限を解除したので、今後は通常通り使用できる。

急いで動作確認したところ、確かに問題現象は解消していました。

ふりかえると

インターネットは接続保証が無い世界ですから、今回のような問題現象は一般的には不自然な出来事ではありません。しかしパブリッククラウドサービスを提供する AWSの内部に原因が隠れており、アマゾンウェブサービス自身その存在を最初気付かず、AWSの利用者が原因を確認する手段もなかったというところに、今回の問題の恐ろしさがあります。問題に気付かないままIPアドレスを遠隔機器に設定したりしていたら、その修正は大変面倒なことになっていたでしょう。

もしかしたら、現在運用しているEIPも、接続制限されているかもしれません。接続先は無数にありますから完全な確認は不可能ですが、EIPが払い出されたら主要接続先のいくつかは試してみた方がいいかもしれません。
AWSサポートの皆さまのご尽力に感謝します。

2015年11月16日 (月)

AWS Lambdaを使ってRedshift料金を節約する

エンジニアの佐藤です。こんにちは。 前回AWS Lambdaを使ってEC2料金を節約するで、監視サーバを待機させずにEC2夜間自動停止を実装する手法をお話させていただきましたが、今回は同様の手法をRedshiftに適用してみましょう。
Redshiftは、カラム駆動型のデータ配置、圧縮、PostgreSQLに近いSQL言語などが特徴の高速分散DBMSと筆者は理解しているのですが、その課金体系はCPUとストレージのセット(ノード)の利用時間の従量課金です(長期事前予約による割引適用もありますが)。EC2と同様、利用が無い時間帯がある場合はリソースの自動解放・復旧を仕掛けることにより利用料金の節約が期待できます。

いくつかの問題と対処

ただしEC2のように単純にはいきません。以下の問題に対処する必要があります。

  • ノードを解放するとデータも消去されてしまうので、事前にスナップショットを作成する必要がある。復旧のときは、スナップショットからリソースを復元する。
  • 再起動した場合はエンドポイントが変更になる可能性がある。

幸い、いずれの場合についても少々の工夫で対処できました。前回同様にNodeJSとAWS SDK for Javascriptを使って実装してみましょう。今回もサンプルコード全体は以下の弊社公開リポジトリで公開しています。

https://github.com/FLECT-DEV-TEAM/cloudblog20151110

スナップショットの使用

稼働中のRedshiftをスナップショットにエクスポートして削除するには、以下のようにクラスターIDとスナップショットIDを指定してdeleteClusterを呼び出します。

var params = {
    ClusterIdentifier:              ctx.ClusterId,
    FinalClusterSnapshotIdentifier: ctx.SnapshotId
};

REDSHIFT.deleteCluster(
    params, 
    function(err, data) {
        if (err) {
            return cb(err);
        }
        cb(null, ctx);
    }
); // end of deleteCluster

このスナップショットから復元するには、クラスターIDとスナップショットのIDを指定してrestoreFromClusterSnapshotを呼び出します。(今回はVPC内部にRedshiftを設定しますので、設定先サブネットやセキュリティグループも設定する必要があります。)ノード数やマスターユーザ設定などは、特に指定しなければスナップショット作成時の設定が引き継がれます。

var params = {
    ClusterIdentifier:      ctx.ClusterId,
    SnapshotIdentifier:     ctx.SnapshotId,
    AvailabilityZone:       ctx.AvailabilityZone,
    ClusterSubnetGroupName: 'default',
    VpcSecurityGroupIds:    ctx.VpcSecurityGroupIds,
    PubliclyAccessible:     false,
    AutomatedSnapshotRetentionPeriod: 0
};

REDSHIFT.restoreFromClusterSnapshot(
    params, 
    function(err, data) {
        if (err) {
            return cb(err);
        }
        cb(null, ctx);
    }
); // end of restoreFromClusterSnapshot

エンドポイント(接続先)

Redshiftのクラスターを起動すると、以下のようなエンドポイントが払い出され、このエンドポイントにPosgreSQLプロトコルで接続することでクラスタを利用することができます。

<クラスターID>.<ランダム文字列>.<リージョン>.redshift.amazonaws.com:<ポート番号>

このエンドポイントは「クラスターIDやノード数を変更した場合に変更される」とSDKでは説明されていますが、「そうしない限り、保存される」とは書いてありません。つまりスナップショットの保存と復元の前後で同じエンドポイントが使える保証は無いようです。このままでは、エンドポイントの都度調査という面倒なことになります。
最も簡単な解決方法はElastic IP AddressでグローバルIPアドレスを設定してしまうことでしょう。しかし今回はVPC内での利用を想定しており、本来グローバルIPアドレスは不要です。
筆者が選択した方法は、「Route 53の内部DNSを設定する」というものです。Route 53ではVPCに接続された内部用のHosted Zoneを設定することができます。このHosted ZoneにCNAMEレコードをAPIで設定し、アプリケーションからはCNAME名でアクセスしてもらいます。具体的には、以下のようなレコードを設定します。

redshift.internal. 60 CNAME cluster-id01.aaaabbbbcccc.ap-northeast-1.redshift.amazonaws.com.

実装にあたっては、最初にクラスターのエンドポイントをクエリします。

var params = {
    ClusterIdentifier: ctx.ClusterId
};
REDSHIFT.describeClusters(
    params,
    function(err, data) {
        var clusters = data.Clusters;
        var c = clusters[0];
        ctx.Endpoint = c.Endpoint.Address;
        cb(null, ctx);
    }
); // end of describeClusters

次にこのエンドポイントを内部DNSのCNAMEレコードとして設定します。

var params = {
    HostedZoneId: ctx.HostedZoneId,
    ChangeBatch: {
        Changes: [{
            Action: 'UPSERT',
            ResourceRecordSet: {
                Name: 'redshift.internal',
                Type: 'CNAME',
                TTL: 60,
                ResourceRecords: [{Value: ctx.Endpoint}]
            }
        }] // end of Changes
    } // end of ChangeBatch
};
ROUTE53.changeResourceRecordSets(
    params,
    function(err, data) {
        if (err) {
            return cb(err);
        }
        cb(null, ctx);
    }
); // end of changeResourceRecordSets

Route 53 Hosted Zoneは以下のようになっています。

Screen_shot_20151116_at_155423


Screen_shot_20151116_at_155700


タイミングの問題

実は筆者はこの段階で一つの壁にぶつかってしまいました。 Redshiftクラスターをスナップショットへ保存する処理も、またスナップショットから復元する処理も、時に長い処理時間を要します。この処理時間は課金対象になりませんが(課金はクラスターが「available」になってから)、長いと復元処理を開始してからエンドポイントが参照可能になるまでの所要時間が、AWS Lambdaの実行時間上限(5分)を超えてしまうのです。また、Lambdaを5分も待機させるのは、そもそもナンセンスにも思えます。
筆者はこの内部DNS設定処理を、スナップショットからの復元処理が完了しそうな時間帯に10分おきに繰り返し実行することにしました。何回かは空打ちとなりますが、エンドポイントが利用可能になってから10分以内にはCNAMEレコードが設定されるはずです。1回の試行時間はわずかで待機中は課金されませんので、リーズナブルです。
最終的には以下のように3つのLambda Functionをスケジュールしました。

  • スナップショットからの復元:午前7時
  • DNS設定試行:午前7時から8時まで、10分おきに実行
  • スナップショット作成とクラスター削除:午前1時

Lambda Functionの設定方法については前回投稿をご参照ください。なお、Lambda Functionの設定にあたっては、前回同様Description項目に設定情報をJSON形式で記載することを前提にしています。以下はこのDescription文字列の例です。

{ "ClusterId": "xxxxxxxx", "SnapshotId": "xxxxxxxx", "AvailabilityZone": "ap-northeast-1c", "VpcSecurityGroupIds": ["sg-xxxxxxxx"], "HostedZoneId": "XXXXXXXXXXXXX" }

まとめ

実装が若干複雑ですが、Redshiftという重量級コンポーネントについても「夜間自動停止」が実装できました。今回ご紹介した手法は、RDSにも容易に転用可能でしょう。

2015年11月10日 (火)

AWS Lambdaを使ってEC2料金を節約する

エンジニアの佐藤です。こんにちは。
毎月のAWS(Amazon Web Service)の請求書を眺めていると、気が付くことがあります。請求金額のかなりの部分が「CPU料金」なのです。
EC2として直接買っているCPUだけでなく、Redshift、ElastiCache、RDSなどや、DynamoDBの帯域予約分もこれに該当するでしょう。何にせよ「CPUを構える」ことは、ストレージを構えるのに比べて高くつくのです。
一方で、こうして構えたCPUがどの程度仕事をしているのかというと、結構「暇」していることが多いのではないでしょうか。暇であろうとなかろうと、料金はかかります。
そんな折、AWS Lambda(以下Lambda)にスケジュール実行機能が追加されました。つまり「定時ジョブ」を、CPUを待機させることなく仕掛けることが可能になったのです。今回はこのLambdaを使って、EC2「夜間自動停止」機能を実装する手法をご紹介したいと思います。深夜早朝に全く利用がないと前提できるサーバは結構あるのではないでしょうか?今日からEC2料金を25%は節約できます。

基本的なアイディアは以下のようなものです。

  • LambdaからAWS APIを実行してEC2インスタンスの起動・停止を実行する。Lambdaの実行権限には必要な権限を設定する。
  • 起動と停止それぞれLambda Functionを登録し、開始時刻と停止時刻にLambda Functionが実行されるように設定する。
  • 起動・停止するインスタンスのIDは、設定変更できるようにLambda Functionの設定情報としてDescriptionに記載する。

今回のソースコードですが、GitHubの以下の公開レポジトリに掲載しています。
https://github.com/FLECT-DEV-TEAM/cloudblog20151110

(以下はお使いの環境にgitとNodeJS、zipコマンドがインストールされているものとして説明します。)
最初にこのレポジトリをクローンしてください。

$ git clone https://github.com/FLECT-DEV-TEAM/cloudblog20151110

次に依存パッケージのインストールを行います。

$ npm install

次にLambda Functionとして設定するアーカイブを作成します。

$ source package.sh

scheduletask-yyyyMMddhhmmss.zipというファイルができます。

これで準備は完了です。AWSマネジメントコンソールにログインしてLambda Functionを設定しましょう。今回はEC2インスタンスの起動用に「testStart」、停止用に「testStop」という2つのLambda Functionを作成します。

Lambda Functionの作成では以下のように設定します。(赤文字で注記を入れています。)

Screen_shot_20151110_at_125307


「Role」は、Lambda Function実行された際、AWSのリソースに対してどれだけの実行権限を有しているかを設定するものです。ここでは簡単に、以下のポリシーを設定したroleを設定します。(実運用上は広すぎる権限ですので、適宜調整してください。)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*",
                "ec2:*",
                "lambda:*"
            ],
            "Resource": "*"
        }
    ]
}

以上でLambda Functionの設定は完了です。次にこのLambda Functionをスケジュール起動するイベントの設定を行います。

作成したLambda Functionを選択し、Event sourcesタブで「Add event source」を選択します。

Img01


Event source typeに「Scheduled Event」を選択します。

Img02


Schedule expressionに「cron(0 22 * * ? *)」などと入力します。

Img03


時刻はUTCタイムゾーンで指定するのでこの場合は「毎日午前7時」の意味になります。表記法はcrontabに沿っていますが、5つ目の曜日指定のワイルドカードが「?」であること、crontabには存在しない6つ目の年指定ができることなどが異なっています。なお、最短時間間隔は5分となっています。

これで仕掛けは完了です。あとは指定時間になったらインスタンスの起動停止を確認し、CloudWatchのログを確認します。インスタンスの起動に成功した場合は以下のようなログがLambda Functionのロググループに書き残されるはずです。

START RequestId: XXX Version: $LATEST
2015-11-09T22:00:23.210Z XXX ["i-xxxxxxxx"]STARTED
2015-11-09T22:00:23.211Z XXX FINISH
END RequestId: XXX
REPORT RequestId: XXX Duration: 1502.21 ms Billed Duration: 1600 ms Memory Size: 128 MB Max Memory Used: 36 MB

この実行でいくら課金されるのでしょうか?AWS Lambdaの課金は回数と実行メモリ容量×実行時間の2つあり、 回数については以下のようになっています。

  • First 1 million requests per month are free
  • $0.20 per 1 million requests thereafter ($0.0000002 per request)

使用メモリが128MBの場合の実行課金は以下のようになっています。

  • 3,200,000 Free tier seconds per month
  • $0.000000208 per 100ms

今回は1インスタンスあたり起動と停止が1日に1回ずつと考えて、1日2回実行で128MB、3200msだとすると、1か月での料金は、 3200 / 100 x 31 x 0.000000208 = $0.0002 たったの0.02セント(約0.024円)です。 EC2のt2.microインスタンスなら36秒間で使い切ってしまう金額です。

筆者には、このAWS Lambdaという名の「コードフラグメント・ホスティング」は、物理サーバ → 仮想サーバ → コンテナと続く一連の流れの最先端のように思えます。今後はVPC対応が実施される予定でVPC内のRDSやElastiCacheとも連携しやすくなります。実装やデプロイの難しさはありますが、急速に広まっていくのではないでしょうか。

2015年11月 6日 (金)

Webアプリケーションセキュリティについての社内勉強会を開いてみた(解答編)

今年も残り2ヶ月ですがこれから本気出します。エンジニアの小川(mitsuruog)です。
9/3にWebアプリケーションセキュリティというテーマで社内勉強会を開きましたが、解答編の記事を書いてませんでしたね。
すみません。

前回の記事はこちらです。
フレクトのクラウドblog(New): Webアプリケーションセキュリティについての社内勉強会を開いてみた

早速ですが、課題にどんな脆弱性が含まれていたのか?発表します。

回答編

架空のSNSサービスの設計に潜む脆弱性を探すというテーマでした。今回の脆弱性がある設計箇所を分類すると次のようになります。

  • システム全体設計に潜む脆弱性
  • 認証設計に潜む脆弱性
  • WebAPI設計に潜む脆弱性


システム全体設計に潜む脆弱性

システムの構成、サイト設計などSNSサービス全体に関わる設計に潜む問題です。

Img_20150908_002202

  • 通信経路がHTTP。
    • 新規Webサービスであれば、HTTPS前提にするべきです。
  • 管理者ページURLが推測しやすい。
    • 管理者ページが「/admin」となっていて非常に推測しやすいです。
    • 最近では、WordPressやWebアプリケーションジェネレータ(Yeoman)など、便利なツールが増えてきましたが、デフォルト設定を利用する場合も同様の注意が必要です。


認証設計に潜む脆弱性

システムのセキュリティの要、認証設計に潜む問題です。

Img_20150908_002221

Img_20150908_002232

  • HTTP...orz
    • 以下略
  • パスワード忘れ機能の設計ミス
    • 「ユーザーID」と「秘密の質問」を入力するとパスワードが変更できてしまう仕様です。最近であれば、登録済みのメールアドレスにメールを送信するなど、ワンクッション入れたいところです。
    • また、秘密の質問が「好きな色は?」となっており、万人が好きそうな色が予測できます。好きな色を固定して「リバースブルートフォースアタック」が成立しやすいです。
  • Cookieの設計について
  • セキュアな情報をクライアント側で保管している
    • 認証後の情報をlocalstorageにて保存しています。中に「管理者フラグ」が含まれていることもあり、容易に管理者へ昇格できます。


WebAPI設計に潜む脆弱性

WebAPIの設計も細かな注意点があります。

Img_20150908_002306

Img_20150908_002316

  • ユーザーIDの採番ルール
    • もし連番で発番した場合、容易に他人のユーザーIDが推測できると思われます。
  • リクエストパラメータの設計ミス
    • リクエストパラメータに「管理者フラグ」「ユーザーID」が含まれており、容易になりすましが可能でした。
    • メッセージ取得APIのレスポンスで投稿者のユーザーIDが取得できる仕様であるため、他人になりすまして投稿が容易に可能でした。


まとめ

もう、ダメダメですね。。。
設計のミスで重大なセキュリティ事故が発生した場合、システム開発会社の責任が問われることが多くなってきました。
そのため、特に認証周りの設計する際は次のようなことも留意するようにしています。

  • 独自認証設計をしない。OAuth2.0など標準的なものを利用する。
  • 秘密の質問自体をユーザーに選択させる。(秘密の質問の設計が甘いと設計責任が問われ兼ねない。)

実際に受けたメンバーからは「簡単すぎる」との意見が多かったのが反省点ではありますが、セキュリティについて再復習できたいい機会だったのではないかと考えています。

このような活動を地道に続けていく事で、少しずつ強いエンジニア組織にしていきたいですね。

ではではー

2015年11月 2日 (月)

express実践入門ついての社内勉強会を開いてみた

みかんが美味しい季節になりましたね。エンジニアの小川(mitsuruog)です。
10/29にexpress実践入門というテーマで社内勉強会を開きましたので、その話を紹介します。

発表した資料はこちらです。

express実践入門 · GitHubexpress実践入門 · GitHub

なぜ、やろうとしたのか?

Expressは、node.jsのWebアプリケーションフレームワークです。
事実上、node.jsでのデファクトスタンダートとなっており、既に利用している方や、これから始めようと興味を持っている方も多いのではないかと思います。

弊社でも、IoTでの導入が最近増えてきました。

巷には、express入門用の記事が多くあるのですが、なぜ「express実践入門」という形で再整理したかと言うと、
私が実務でexpressを利用してきた上で、「express入門用の記事の多くに」次のような不満があったからです。

express3系で作成されている古い記事が多い

expressの最新バージョンは4です。expressの3系と4系ではAPIに互換性がない変更があります。
現在、日本語で読める記事や書籍のほとんどがexpress3系より前の内容で書かれています。

expressの「Getting started」をやってみただけの内容が多く、深みに欠ける

「express入門用の記事の多く」はexpressの「Getting started」と同様の内容であることが多いです。 やはり、Webアプリケーションを作成するためには、もう少し踏み込んだ内容が必要です。

Webアプリケーションを作成するという内容に欠ける

Webアプリケーションを作成する上でexpressの全機能を利用することはまずありません。
また、expressだけではなく、様々なnpmモジュール(認証、DBなど)を組み合わせてWebアプリケーションは構成されています。

時にexpressの細部に踏み込んだ内容が必要なケースはありますが、ほとんどの場合、expressをある程度使いこなした後に出くわす場合が多いのではないでしょうか。
立ち上がりとしては、「expressでWebアプリケーションを構築する」という立ち位置での、まとまったインプットが欲しかったりします。

このような中、初学者がexpressを攻略する上でのつまづくポイントと、中規模開発をターゲットにWebアプリケーションを構築する上でのベストプラクティスを私の経験ベースでまとめました。

実施風景

昼食の時間帯に行いました。
会社支給の弁当を片手に真剣にexpressについて学びます。

456a2398


当日は業務が忙しい中、20名程度の参加がありました。

456a2402


「よく噛むと“記憶力”がアップする!?」という話を信じているのかは定かではないのですが、弊社では隔週ペースでランチ勉強会を開催して、社員やパートナーの皆さんの技術力向上に努めています。

まとめ

「私が考える最強のexpress実践入門」でした。
初めてexpressやる方で、この辺り悩んでいる方がいましたら、参考にしていただければ。。。

弊社でもIoT関連でどんどん実践投入していきます。

ではではー

2015年9月 8日 (火)

Webアプリケーションセキュリティについての社内勉強会を開いてみた

あっという間に秋になりましたね。エンジニアの小川(mitsuruog)です。
9/3にWebアプリケーションセキュリティというテーマで社内勉強会を開きましたので、その話を紹介します。
(特にディスカッションが面白かったのでその話を中心にします。)

Security00


Webアプリケーションセキュリティについては、新人時代などに一度は学習する方は多いと思いますが、それ以降は実践の中で学習していく人の割合が多いのではないかと思います。
とはいえ最近は「できてて当たり前」となっているWebアプリケーションのセキュリティ。

今回は普段やっていることの復習も兼ねて、社内で勉強会を開いてみました。

Security01


実施内容

内容は次の通りです。

  • Webアプリケーションセキュリティの概要とよくある脆弱性について
  • Force.comのセキュリティについて
  • Webアプリケーションセキュリティについてのディスカッション

特徴は、弊社の強みであるSalesforce.com上でのセキュリティ対策についてと、設計についてのディスカッションです。

Security02


Salesforce.com上でのセキュリティ対策については模様はこちらを参照してください。
 → セールスフォースの豆知識: セキュリティに気をつけてForce.comで開発しよう!

ディスカション資料はこちらです。

ディスカッションは、4人ずつ班に別れ架空のSNSサービスの設計に潜む脆弱性を探します。
ねらいは、異なる視点の意見を聞きながら、脆弱性につながりかねない設計上のポイントについて、新たな気づきを得ることです。

単に脆弱性がありそうというだけではなく、

  • どんな攻撃ができるか
  • どんなまずいことが起きる
  • どう防御すれば良いか

についてまで踏み込んで指摘できることが大事です!

これらのことを念頭にディスカッションしてもらいました。

実施風景

(真剣なディスカッション)

Security04


(脆弱性がある箇所に付箋を貼っていきます)

Security05_2


(ディスカッションにタイムキーパーは必須です)

Security03


ディスカッション終了後は、全員で発見した脆弱性の報告会。
その後、ビールを片手にさらなるディスカッションが展開されました。

Security07


まとめ

脆弱性を見つけてくれるか少し心配したのですが、ほとんど見つけられてしまいました。
さすがです!!
(とはいえ、少し簡単すぎたかな。。。)

実際にディスカッションをやってみて、次の学びがあったと思います。

  • やっぱり集合知はすごい
    • 複数人でチェックすることで、全ての班でほとんどもれなく抽出できた。
    • ベテランと若手で班になると、教育効果としても良さそう。
  • 短時間で共通認識を得ることができた
    • 発見した脆弱性を全員で共有することで、設計の危ないポイントについて全員で共通認識を得ることができた。
  • 設計を題材とすることで、エンジニア以外も参加できた
    • 実装より設計の方が対策コストが低い、もちろん要件の方がもっと低い。
    • 次回は要件編をやっても面白そう。

(各班同じような箇所を指摘しています)

Security08_2


このような「できて当たり前」の共通認識の浸透は、ついついおそろかになってしまいがちですですね。
地道に続けていく事で少しずつ強いエンジニア組織になっていくのではないかと思ました。

少し長くなりましたので、発見した脆弱性のレポートについては次回にします。

解答編はこちらです。
フレクトのクラウドblog(New): Webアプリケーションセキュリティについての社内勉強会を開いてみた(解答編)

Security06


ではではー。

続きを読む "Webアプリケーションセキュリティについての社内勉強会を開いてみた" »

2015年5月28日 (木)

MESHとIFTTTを組み合わせて30分お手軽IoTクッキング

こんにちは。IoTチームエンジニアの小川(mitsuruog)です。フレクトには5月からお世話になってます。

先日、出社するとこんなものが・・・

Img_20150520_123417

そう、SONYが開発した電子ブロック「MESH」です。

MESHには加速度、スイッチ、LED、GPIOの4種のセンサーモジュールと、iPad上でこれらのモジュールを簡単に接続できるアプリのがセットになっています。
MESHのモジュールとアプリはBluetoothで相互接続されます。

今まで、IoTのプロトタイプを作成する際は、いちいちデバイスを準備したり、回路を設計したりする手間がありましたが、MESHをレゴブロックのように組み合わせることで、簡単なIoTのプロトタイプを作成することができます。

こ、これは!素晴らしい未来が待っているかもしれません!!

動かしてみる

早速ですが、MESHの加速度センサーモジュールを入り口のドアノブに取り付けて、ドアが開いた瞬間に少し離れたところにあるiPadにて入ってきた人を撮影できるか試してみした。

Img_20150520_122516

MESHセンサーはドアノブに対して少し斜めに取り付けるのがミソです。

Img_20150520_123030

撮影はドアから2mほど離れた場所で行いました。

MESHのアプリキャンバスはこちらです。

May_20_2015_at_0131pm


非常にシンプルですね。

では、実験開始。

ガチャ(ドアが開く音)



(しばしの沈黙)



カシャ(シャッター音)

現状、MESHからデバイスのカメラを起動させて、写真を撮るまでは少しタイムラグがあるようです。
(ということで・・・社員の方には、ドアの前で少し待機するように指示)

May_20_2015_at_1225pm

タイミング調整はこれでばっちりです。

繋げてみる

MESHにて来訪者を撮影することができましたので、これをクラウドサービスに連携してみましょう。
ここはIFTTTを利用します。IFTTTはデバイスやクラウドサービス同士を簡単に連携することができるWebサービスです。

ここでは、シンプルにiPad上に新しい写真が撮られたら、SalesforceのChatter上にある、特定のグループに誰かが入ってきたことをFeed投稿します。

全体的なシステム構成は次の通りです。

System001

完成!!

では、実際にChatterのFeed投稿されるか試してみます。

Mesh


無事、ChatterにFeed投稿されました!
(実際には、IFTTTの連携にタイムラグがあるので、リアルタイムではないです。)

まとめ

最近、MESHなど簡単にプロトタイプできるデバイスが登場してきたことで、フィジカル(物理)とデジタルを繋ぐ敷居が下がってきたように感じます。

アイデア出しからプロトタイプ作成まで、正味30分。
昼休みの時間にこれだけの遊べるものができるのは嬉しいです。

MESHはまだまだできることが少ないのが現状ですが、将来のロードマップを見ると、WebAPIや他のデバイスとの連携についも視野に入れているようです。
WebAPIと連携するようになると、かなりできることが増えそうで楽しみです。

フレクトではIoTのプロトタイプやなどやってますのでお気軽にお問い合わせください。
ではではー。

続きを読む "MESHとIFTTTを組み合わせて30分お手軽IoTクッキング" »

2015年4月14日 (火)

Microsoft Surface 2でクラウド開発

こんにちは。エンジニアの佐藤です。 新しいオフィスになって気を良くしているのですが、ところで筆者はMS Surface 2 を使っています。Surface Proではありません。少し趣味的ではありますが、今回はこの話題をお届けしたいと思います。

Surface 2、この恐ろしく制約に満ちた環境

ご存知のとおり、このモデルは、既に製造中止になった「終わった」商品です。Surface 2のOSはWindows RTですから、Windows 8.1の標準機能とOffice 2013、それにわずかな「Windowsストアアプリ」しか使えません。EclipseやIntellij IDEAのようなIDEはおろか、GitもSubversionもNodeもPHPもありません。

突破口は1時間約1円のクラウドインスタンス

ですが、私は移動時間中にはSurface 2でソフト開発をやっていますし、一日これしか使わない日もあります。 突破口は、クラウドインスタンスです。筆者が使っているのはGoogle Compute Engine (GCE)の「f1-micro」Ubuntuインスタンスで、利用料金は1時間あたり0.009USドルから0.012USドル(使用量によって変わります)。1か月上げっ放しでも千円ぐらいです。このインスタンスを、「SSH+SFTP+WebDAV+Web」サーバーとして設定します。 (後述の「WindowsエクスプローラをWebDAVにつなぐ」参照) GitやSubversionなどが必要な場合は、これらもインストールします。(こちらについてはネット上に手順が豊富に紹介されていますので、割愛します。) こうすることで、ファイル管理ツール(Windowsエクスプローラ)とバージョン管理ツール(Git/Subversion)、ブラウザ(IE11)とMS Officeが使えるようになりました。あと少しです。

貴重な2つのWindowsストア無料アプリ

次はWindowsストアで以下のアプリをインストールします。いずれも無料です。
ソースコードエディタ:Actipro Software社 「Code Writer」
SSHクライアント:Stefan Podskubka氏「Remote Terminal」
Windowsストアアプリは残念ながら未だに充実とは言いがたい状態ですが、この2つは実用的だと思いました。欲を言えば、日本語入力に対応してほしいですが、現バージョンでも日本語の表示・貼り付けはできます。

Pic01

<図1:Code WriteとRemote Terminalの画面例>

ついに本格的作業環境へ

これで、一通りの作業ができるようになりました。SSHクライアントでUbuntuインスタンスにログインし、PHPとMySQLをインストールしてLAMP開発を開始できます。 よくあるパターンでは、PowerPointの提案書を見て実装要件を確認し、エディタでコード記述。ブラウザで動作確認してOKだったらGitレポジトリにコミット、といった手順です。 ポイントは、画面を縦にすることです。縦にすると、スクリーンキーボードを表示してもアプリケーションの表示スペースが十分に取れます。ソースコードの見通しも良くなりますし、スクリーンキーボードが片手で打ちやすいサイズになります。

Salesforce開発は「Force.com CLI」を使用

通常のWeb開発はこれでなんとかなりますが、Salesforce開発を行う場合は、Ubuntuインスタンス側に追加でForce.com CLIをインストールします。 Force.com CLI はGitHubで「heroku/force」として公開されています。こちらは日本語情報が不足しているので少し解説したいと思います。 最初はUbuntuインスタンスにSSHでログインします。次にSalesforce環境にログインしますが、このときコマンドラインオプションでユーザー名とパスワードを指定します。
$ force login -u username@organization.com -p pa_ssword
ログインしたら、以下のコマンドでメタデータ(ApexクラスやVisualforceページなど)一式をダウンロードします。
$ force export
あとはテキストエディタでコード記述などを行い、以下のコマンドでSalesforceにアップロードします。
Apexクラスをアップロードする場合:
$ force push -n SomeClassName -t ApexClass
Visualforceページをアップロードする場合:
$ force push -n SomeVisualforcePage -t ApexPage
テスト実行は以下のコマンドです。
$ force test SomeTestClass
Salesforceには標準機能としてApexやVisualforceコードの記述をWebブラウザ上で行う機能があります。しかしソースコードをGitやSubversionのレポジトリなどで管理したい場合が多いですし、ソースコードエディタの操作性は、やはりネイティブアプリの方が優れています。

キーボード・マウスが使える場合は「CodeAnywhere」を利用

とは言っても、机がある環境ではキーボードとマウスを使った方が効率が高いのも事実です。前述「Code Writer」はタブレット向けUIのため、よくやる「広いディスプレイの左右のウィンドウに2ファイル同時表示」ができません。かと言って、Surface 2に「デスクトップ版」エディタの類はありません。 この問題を解決するのが、ブラウザ版IDEの「CodeAnywhere」です。(他にもいろいろありますが、筆者はこれが気に入っています。) サインインして、先ほどのUbuntuインスタンスにSFTPで接続するように設定します。

Codeanywheresettings

<図2:CodeAnywhere接続例>
IDEの操作性は十分実用に耐えるもので、先ほどの「広いディスプレイの左右のウィンドウに2ファイル同時表示」も、もちろん可能です。日本語入力もできます。SFTPで1サーバー接続するだけなら、無料です。 CodeAnywhereは米国にホストがありますので、Ubuntuインスタンスも米国リージョンのものを選んだ方が操作は快適です。

Codeanywhere

<図3:CodeAnywhere縦スプリット画面例>

WindowsエクスプローラをApache WebDAVにつなぐ場合の特別設定

ApacheをWebDAVとして設定する方法はネット上に豊富に紹介されていますので割愛したいと思いますが、筆者が引っかかったのは以下の設定です。
BrowserMatch "^Microsoft-WebDAV-MiniRedir/" redirect-carefully
この設定はWindowsエクスプローラをApacheのWebDAVに接続するための特別設定です。 Apacheの設定ファイル(部分)は以下のようになりました。

ServerName server03
ServerAdmin webmaster@localhost
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

<IfModule mod_ssl.c>
    <VirtualHost _default_:4443>
        DocumentRoot /webdav

        SSLEngine on
        SSLCertificateFile  /home/sato/CA/server03_crt.pem
        SSLCertificateKeyFile   /home/sato/CA/server03_key.pem

        AddDefaultCharset utf-8

        BrowserMatch "MSIE [2-6]" \
                nokeepalive ssl-unclean-shutdown \
                downgrade-1.0 force-response-1.0
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
        BrowserMatch "^Microsoft-WebDAV-MiniRedir/" redirect-carefully
        DAVLockDB      /home/sato/DAVLock

        <Location />
            SSLRequireSSL
            Options Indexes MultiViews FollowSymLinks
            AllowOverride None
            DAV On
            AuthType Basic
            AuthName "sato's WebDAV"
            AuthUserFile /home/sato/passwd.dav
            Require valid-user
        </Location>
    </VirtualHost>
</IfModule>

後はこのWebDAVにネットワークドライブとして接続します。

Explorerdav01

Explorerdav02

筆者が低スペックタブレットにこだわる理由

筆者がここまでタブレットにこだわるのは、第一に通勤時間を有効活用したいからです。 首都圏で勤務する筆者にとって、往復2時間を超える通勤時間の過ごし方は重要な問題です。この間はまず座れないのでノートパソコンは使えませんし、スマホの画面サイズでは辛いものがあります。 もう一つは、経済的合理性です。 クラウドコンピューティングの発達により、手元にハイスペックの環境を用意する必要性は減少しています。リソースはなるべくクラウドで利用し、手元のコンピュータは軽く薄くした方が、荷物も軽くなりますし、出費や生活空間の圧迫が小さく済みます。 今回ご紹介した手法はOSを問わず適用できます。テキストエディタとWebDAVクライアント、ファイルマネージャ、SSHクライアントがあれば、AndroidでもiOSでも容易に適用可能でしょう。

続きを読む "Microsoft Surface 2でクラウド開発" »

2014年12月30日 (火)

DockerでLinux仮想デスクトップサーバをつくる話

こんにちは。エンジニアの佐藤です。2014年も残すところわずかとなりましたが、今回は再びDockerの話題を取り上げさせていただきたいと思います。(前回のDockerでLAMPサーバをつくる話も合わせてご覧ください。)今回ご紹介したいのは、DockerでLinux仮想デスクトップサーバーを作成する方法です。

仮想デスクトップとは

ものすごく簡単に言うと、ネットワーク経由でデスクトップ画面を配信する機能です。Windowsでは「ターミナルサービス」や「リモートデスクトップサービス」などと呼ばれています。サーバ上で仮想デスクトップサーバなるサービスを実行して接続を待ちます。クライアントはビューワーアプリで接続してデスクトップを表示し、リモートコンピュータを操作します。

何の役に立つの?

仮想デスクトップの主な用途は 1)データセンターに格納されたサーバマシンを遠隔で管理する。2)一台のアプリケーションサーバを安価なシンクライアント経由で共有する。の2つです。

なぜDockerで仮想デスクトップ?

他の環境への引っ越しが非常に楽になります。つまり手元のパソコンで調整した開発環境をわずかなコマンド実行で隣のコンピュータに移すことができます。仮想デスクトップですので、物理的な画面を持たないクラウドインスタンスなどへも全く同じ手順で引っ越すことが可能です。例えばAWS EC2の開発環境をGoogle Compute Engineへ乗せ換える、というようなことが可能になります。Dockerなしでは、こういうことは難しいと思います。

仮想デスクトップサーバ「コンテナ」の作成

それでは実際の手順ですが、以下のような手順で実行可能です。

  1. Dockerのインストール
  2. Dockerのストレージを「devicemapper」に設定
  3. Ubuntuの最新イメージをDocker hubからpull
  4. /bin/bashでスタート
  5. Linuxデスクトップのセットアップ
  6. 仮想デスクトップのセットアップ
  7. 起動スクリプトを書く
  8. イメージを保存して、docker run
  9. クライアントからの接続

前回のDockerでLAMPサーバをつくる話と基本的には同様です。ただしいくつか注意する点があります。

1. Dockerのインストール

今どきのLinuxディストリビューションでは、コマンド一発です。

# apt-get install docker.io

2. Dockerのストレージを「devicemapper」に設定

いきなり「?」な内容ですが、この手順を実行しないまま既定のAUFSでDockerを実行すると一部のコマンド実行が失敗してしまいます。(この点については後述します。)

# vi /etc/default/docker
(以下の行を設定)
DOCKER_OPTS="-s=\"devicemapper\""
# service docker restart

3. Ubuntuの最新イメージをDocker hubからpull

これはコマンド一発です。

# docker pull ubuntu:latest

4. /bin/bashでスタート

次に「bash」コマンドを指定してコンテナをスタートします。この時「-i -t」オプションを指定し、コンテナ内で起動したbashの標準入力と標準出力を、今まさにdockerコマンドを打っているターミナルに接続します。

# docker images | grep ubuntu  <-- UbuntuのイメージIDを確認
ubuntu              latest              5506de2b643b        9 weeks ago         197.8 MB
# docker run -i -t 5506 /bin/bash <-- bashを指定してコンテナを起動。イメージIDは前方一致で指定できる。
bash-4.1# whoami <-- コンテナ内のbashのプロンプト
root

5. Linuxデスクトップのセットアップ

ここが結構難所でした。今どきのデスクトップ(Gnomeなど)はUX改善のためGPUを活用していることが多く、これがDockerとぶつかります。また、仮想デスクトップはネットワーク経由でデスクトップ画像を送信するので、派手なUXでは転送容量が膨張して足かせです。そこで数あるLinuxデスクトップの中から、LXDEを選びます。日本語入力にはGoogle日本語入力のLinux版であるMozcを選びました。

# apt-get install openssh-server lxde mozc-server uim uim-mozc fonts-takao
# locale-gen en_US.UTF.8

このインストールは800MBほどのダウンロードになるので結構時間がかかります。 注意する必要があるのが、2行目のコマンドでロケールを作成するところです。このコマンドを実行しないと、ターミナル上で日本語表示ができなくなります。

6. 仮想デスクトップのセットアップ

Linuxの仮想デスクトップソフトはいろいろありますが、筆者がおすすめなのはTigerVNCです。Fedoraにも収録されており、MacOS X、Windows、Linuxに対応しています。ここでは現時点の最新版1.4.0のLinux版をダウンロードします。ダウンロードしたらアーカイブを展開し、ファイルをコピーしてインストールします。

# tar xzf tigervnc-Linux-x86_64-1.4.0.tar.gz
# cp -rf usr/bin /usr
# cp -rf usr/lib64 /usr
# cp -rf usr/share /share

次に仮想デスクトップをスタートするときのスクリプトを作成し、これにLXDEデスクトップを起動するコマンドを追加します。

# adduser hoge <= 実際にデスクトップにログインするユーザを作成
(中略)
# su hoge
$ vncserver <= 既定の起動スクリプト作成のため一回起動
(パスワードを求められるので適当に設定)
$ vncserver -kill :1 <= 起動スクリプトが生成するので、一旦終了
$ vi ~/.vnc/xstartup
(以下のようにxstartupファイルを修正)
# xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" & <= コメントアウト
# twm & <= コメントアウト
startlxde & <= 追加

7. 起動スクリプトを書く

コンテナが起動した時に仮想デスクトップサーバが起動するように、以下のように作成します。(起動スクリプトについては前回のDockerでLAMPサーバをつくる話5. 最後に起動スクリプトを書く も合わせてご覧ください。)

# vi /root/start.sh
#! /bin/bash
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

service rsyslog start
service ssh     start
sudo -u hoge -H vncserver

term() {
    sudo -u hoge -H vncserver -kill :1
    service ssh     stop
    service rsyslog stop
}

trap "term; exit" SIGHUP SIGINT SIGTERM

while true; do
    sleep 1
done

8. イメージを保存して、docker run

セットアップ作業が終わったコンテナを終了し、イメージを作成します。

# exit  <-- コンテナを終了
exit
# docker ps -l <-- コンテナのIDを確認
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES 
ad8596fad31e        ubuntu:latest      "/bin/bash"         51 minutes ago      Exited (1) 3 seconds ago
# docker commit ad85 vncserver01 <-- イメージを作成

いよいよ起動ですが、ここで2点注意することがあります。

  1. 「--privilege=true」オプションを指定する。(このオプションを設定しないと、日本語入力のMozcが動きません。) ※1
  2. 仮想デスクトップ接続用ポート5901番をホストに接続する。

実際のコマンドは以下のようになります。

# docker run --privileged=true -p 5901:5901 vncserver01 /root/start.sh

すべてがうまく行けば、これでサーバは仮想デスクトップの接続待機となったはずです。

9. クライアントからの接続

ここでではWindows 8.1マシンから接続してみます。 先ほどのTigerVNCのダウンロードサイトから、今度はWindows版をダウンロードします。ダウンロードした実行ファイルを実行するとインストーラが開始されます(ここではTigerVNCをサービスとして登録するオプションは設定しません。) インストーラが終了したら、「TigerVNC Viewer」を起動します。 接続先を問われるので、ホスト名:ポート番号形式で指定し、Connectをクリックします。パスワードを聞かれますので入力すると、LXDEデスクトップが表示されるはずです。 ここまで来れば、あとはほとんど通常のLinuxデスクトップと同様に使えます。

未解決の問題

「ほとんど通常のLinuxデスクトップと同様に使えます」とは言ったものの、実は問題点もあります。筆者が直面した問題をいくつか上げておきたいと思います。

Google Chromeが起動後しばらくするとクラッシュ(回避方法あり ※2)

これが一番困っている問題です。巷のサイトにはChromeの起動オプション「--no-sandbox」を設定する方法が紹介されていますが、このオプションを設定しても回避できません。 (なお、Firefoxは問題なく実行できます。)

tcpdumpが実行できない(回避方法あり)

tcpdumpとは、コマンドで実行できるパケットキャプチャツールです。便利なのですが、Dockerのストレージが既定の「aufs」のままだと起動できません。ストレージに「devicemapper」を指定することで回避できます。

コンテナ内の/etc/hostsが変更できない(回避方法あり)

これはDockerの制約です。(最新のDockerでは回避されているかもしれません。)回避方法は少々複雑です。

  1. Dockerを実行するLinux(Dockerホスト)にdnsmasqをインストールして起動
  2. docker runで仮想デスクトップサーバのコンテナを実行するとき、オプション「--dns="172.17.42.1"」を追加する。
  3. コンテナ内の/etc/hostsに名前を追加する代わりに、Dockerホストの/etc/hostsを修正してdnsmasqを再起動

まとめ

一般的にDockerは、サービスの実装インフラ技術として取り上げられることがほとんどだと思いますが、今回ご紹介したようにデスクトップ環境を実装することも可能です。 こんなことをして何の役に立つのか?と思われる方も多いと思いますが、この技術を使うと、ソフト開発作業などのいわゆる「パソコン仕事」をほとんどすべてクラウドに収容することができます。Dockerですので、手元のパソコンからクラウドインスタンスへの移行は相当に省力化されます。 筆者の勝手な見解かもしれませんが、もはや手元にハイパフォーマンスのコンピュータを用意する時代は、終わったような気がします。

2016-06追記

※1: 2016-06現在は、Mozcの実行に--privilege=trueは不要になっています。 ※2: docker runの時にオプション「-v /dev/shm:/dev/shm」を付けると回避できます。元ネタはこちら

2014年10月28日 (火)

AmazonWebServicesアカウントの強制停止から復活

こころです。 
ある日AWSマネジメントコンソールにログインすると


■アカウントが強制停止に

20141027_150537_2

”ご使用のアカウントは停止されているため、認証は失敗しました。AWSカスタマーサポートにお問い合わせください。”

の文字が。

実は支払い先のクレジットカード情報を更新していなかったためbilling statusが更新されずに強制停止されたのでした。
あわててクレジットカード情報を更新し、未払い請求を無しにしてもらったのですが、

20141027_150537_3

マネジメントコンソールは相変わらず停止されています。
ので、サポートにケースをあげてみました。
https://aws.amazon.com/support/

返信がきました。

20141028_110122

一度アカウントがロックされてしまいますと、未払い分をお支払いいただいても アカウントのロックは自動的には解除されません。 お手数ですが、お支払完了後に本窓口にアカウント再開ご希望の旨をご連絡いただく形となっております。

のお返事。
その後すぐにマネジメントコンソールにアクセスできるようになりました!


■アカウント復活方法

AWSアカウントが強制停止された場合、強制停止理由(この場合不払い)を解決しても自動的にはアカウント再開はせず、サポートに連絡して復活して欲しい旨明示すると復活してもらえます。


■まとめ

  • AWSマネジメントコンソールにアクセスできなくなる(当然)
  • サービスにも一切アクセスできなくなる(サイトやメールを運用してる場合は当然停止。)
  • アカウントを再開した場合、停止直前の状態で起動される(停止していたインスタンスは停止状態、起動していたEC2インスタンスはStart状態でした。)

こうならないように請求情報には目を通し、複数アカウントを管理している場合は一括請求(consolidated billing)を設定し請求を集約すると良いと思います。

気づいたのが停止してから2,3日だったのですが、長期放置してしまうとTerminateされていても文句は言えなかっただけによかったです。まあその場合もsnapshotとか何らかバックアップは取っておいてくれるのでしょう、AWSなら、きっと。

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上での
Webアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、セールスフォースパートナーです。
また、heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。

2024年4月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
ブログ powered by TypePad