ホーム ブログ ページ 45

IPA提供の、画像閲覧ソフトの脆弱性検出ツール「iFuzzMaker」の有効性とファジングについて

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、脆弱性検出ツール「iFuzzMaker」の有効性と想定外データの受け取りに伴う脆弱性診断について考えてみよう。

 iFuzzMakerについて

iFuzzMakerは、IPAがオープンソースで提供している、画像閲覧ソフトの脆弱性検出ツールだ。このツールを使うことにより、意図的に加工した画像を作成し、この画像を検査したいツールに入れることにより、システムクラッシュやバッファオーバーフローの脆弱性などを見つけることが出来る。この様な、様々な情報を相手に入れる(食わせる)ことにより、診断する手法をファジングと呼び、知識が無い状態でも脆弱性の有無を確認することが出来る。

 想定外のデータの受け入れについて

上記の場合は画像表示ソフトを対象としているが、これを他のシステムに流用することが出来る。たとえば、画像表示ソフトが厳密に画像であるか否かをチェックしていない場合、ワードファイルの拡張子を、.jpg や .jpeg に変更する事により、画像表示ソフトが厳密に画像処理を行っているかを確認することが出来る。

また、同様に他のサービスやシステムに於いても、通常受け入れるサイズ以上のデータを無理矢理入れることにより、バッファオーバーフローの脆弱性を発見することが出来る。

たとえば、データの受け入れサイズが、30バイトしかないところに、厳密にその受け取りサイズをチェックしていない場合、60バイトのデータを受け入れたとする。30バイトはそのままスタックされるが、残りの30バイトはプログラムの一部を書き換え、その先に意図的なプログラムコードを入れて権限昇格を狙う。これがバッファオーバーフローの脆弱性を利用する、主な考え方だ。

 サービス稼働しているシステムへの脆弱性検査

バッファオーバーフローの脆弱性が発生するのは、データの受け入れが明示的に示されている物だけでは無い。たとえば、80/tcp では、通常webサービスが稼働している。このポートに対して、通常はwebブラウザを使って接続しているが、明示的にtelnetを使って接続する方法もある。このほか、予め作成したデータを強制的に流し込む場合は、次のように入力する。

cat 送り込むデータ | nc 接続先IP ポート番号

この方法で、強制的に情報を流し込むことが出来る。通常のサービスでは、特定通信の内容と異なる場合は、その時点で接続を切って、受け入れを中止する。しかしながら、作りが甘いと、こうした情報を受け入れ続け、システムのメモリを食い尽くすまで受け入れが続く場合も有る。こうなると、復旧するにはシステムを再起動するしか方法はなくなる。

 スマートフォンアプリの場合

複数アプリを用いて、データの受け渡しを行う場合、送り出す側と受け取る側で、厳密にデータの内容をチェックする必要が有る。先ほどの例のように、データ送信側を偽装したデータ送信が行われた場合、最悪アプリがクラッシュしたり、OS毎巻き込んでスマートフォンが終了したり再起動したり、フリーズすることも十分に考えられる。受け取るデータが常に正しいと考えず、必ず受け取ったデータが正しい情報で有るかをチェックしてから、加工するようにしないと、大変なことになるかもしれない。

Rubyでuse_resultを使い、Mysqlから大量データをSELECTする

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Rubyでuse_resultを使い、Mysqlから大量データをSELECTする

 バックグラウンド処理でのMySQLの大量データの扱い

MySQLで大量データを扱うコツは、フロントエンドとバックグラウンドでは結構異なることがあります。

代表的なもので言えば、インデクスが挙げられます。

フロントエンド処理において大量データから必要なデータを抽出するためには、インデクスの作成がかかせません。

もしインデクスがなければ、テーブル内をフルスキャンを行わなければならず即時に応答を返すことができなくなります。

対してそのテーブルがバックグラウンド処理でしか使用されない場合、インデクスが必要不可欠かと言うとそうでもありません。

即時応答の必要がないからです。

インデクスがあることでテーブルの更新処理が遅くなり、足かせとなってしまう場合もあります。

今回はバックグラウンド処理でMySQLから大量データを取得する際のノウハウの一つが題材です。

 MySQLでの大量データSELECT

数千万レコードレベル以上のデータが保存されているテーブルから全レコードを取得しなければいけない場合、

通常軽量言語で使用するMySQLライブラリのqueryメソッドで全レコードを取得するような処理を実行すると

データがメモリに乗りきれなくなり、Out Of Memoryエラーとなります。

回避策としてLIMIT・OFFSETを使って、例えば数千件程度ずつに区切ってデータ取得するといった方法もあるでしょう。

しかし、SELECTの途中でテーブルの内容が更新されたりした場合、並び順が変わってしまって正しく全件を取得できない可能性があります。

 use_result

MySQLのC言語のライブラリにmysql_store_resultというメソッドが用意されています。

SELECTの結果すべてをメモリに乗せて取得するものです。フロントエンド処理で通常使用されているものはこの仕組みです。

対して、mysql_use_resultというメソッドがあります。

これはSELECTの結果を一度に取得せず、一行ずつ取得するものです。一度に使うメモリは一行分のみになるので省メモリとなります。

 use_resultをRubyから使用するには?

今回はMySQL/Ruby(version. 2.9.1)を使用します。

以下のように使います。

#-*- coding: utf-8 -*-
require "rubygems"
require "mysql"

dbh = Mysql.new("localhost", "user", "passord", "database")
dbh.query("set net_write_timeout=9999") #注意点 後述
dbh.query_with_result = false #query()実行と同時にresultオブジェクトを返さなくなります。
dbh.query("select * from big_table") #大量データテーブルからのSELECT
res = dbh.use_result # use_resultを実行してresultオブジェクトを取得
res.each do |row| 
 #処理
end
res.free
dbh.close

 注意点

use_resultの便利な面を説明しましたが、少しクセがあります。

そのうち代表的なものをあげます。

長時間になる場合、timeoutとなり途中でSELECTが中断されてしまう。

net_write_timeoutは通常デフォルトが60秒となっています。

use_resultは一度に結果取得をしない分、net writeの時間が長くなりこのtimeoutを超えてしまうケースがあります。

そのため上記コード例でもあげたとおり、

set net_write_timeout=9999

などとしてtimeout値を伸ばしておく必要があります。

SELECTは中断できない。

一度はじめたSELECTは全件を取得し終えるまでresultオブジェクトを開放できません。

つまり、use_resultをしているDBハンドラは全件を取得するまで別の行動ができません。

どうしてもSELECTの途中でMySQLの別の処理を行う必要がある場合は、

もうひとつDBコネクションを作成し、作成したハンドラで処理を行います。

SFTP専用アカウントの発行

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

他社様より scp / sftp を使用してファイルアップロード頂きたいとき、単にユーザアカウントを発行しポート制限を解除するのみの場合、 ssh ログインによるコマンド実行や上位階層への移動といった心配が発生します。そこでファイル転送専用にアカウント作成を行うこととなります。

 § 手順概要

  1. sftpしか行えないユーザを所属させる sftponly グループを作成します。
  2. sftponly グループに所属する sftpclient ユーザを作成します。
  3. sshサーバ側で sftponly グループは sftp しか行えないように設定します。
  4. sshサーバを再起動し完了。

※ グループ名 sftponly・ユーザ名 sftpclient は環境に合わせて作成してください。

 § 手順

※ root ユーザで実施します。

1. グループ作成

コマンドの実行を行えなくする為のグループを作成します。

# groupadd sftponly

2. ユーザ作成

上記グループに所属するユーザを作成します。

# useradd -s /bin/false -G sftponly sftpclient 
# mkdir /home/sftpclient/uploads
# chown root:root /home/sftpclient
# chmod 755 /home/sftpclient
# chown sftpclient:sftpclient /home/sftpclient/uploads

/etc/passwd ファイルに下記ユーザが登録されており、ログインシェルが /bin/false (ログインできない状態)となっていることを確認する。

sftpclient:x:505:505::/home/sftpclient:/bin/false

※ ユーザ作成後にグループに所属させる場合は vigr コマンドで 直接 /etc/group ファイルを編集します。

# vigr

sftponly:x:506:sftpclient

3. sshサーバ設定

/etc/ssh/sshd_config ファイルを編集します。

# 132行目あたり
#Subsystem     sftp     /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
# 最下行
Match group sftponly
   ChrootDirectory /home/%u
   X11Forwarding no
   AllowTcpForwarding no
   ForceCommand internal-sftp

4. sshd再起動

※ sshd_config を書き換えた後は設定を反映させる為に sshd を再起動する必要があります。

/etc/init.d/sshd restart

service sshd restart

systemctl restart sshd.service など

再起動が完了したら WinSCP, FileZilla, Fugu などのクライアントで接続確認を行います。

 § Appendix

※ /etc/sshd_config では sshポートを分かりにくい数値に変更したり、管理ユーザのログインを禁止したり、鍵認証の強制(パスワードのみの認証は拒絶)合わせて行うとよりセキュリティーを高められます。

Port 58272
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no

※ sshdが停止していると新しくsshログインできません。既に接続中のsshセッションは維持されていますので sshd が起動失敗した場合でも気づきにくいので、sshd を再起動した際は別のプロンプトを開き接続できることを確認すると良いです。

※ 鍵の作成や ssh 関連記事

http://doruby.kbmj.com/sakuma85_on_rails/20080228/ssh_root_1

http://doruby.kbmj.com/nsho/20090426/ssh-agent1

http://doruby.kbmj.com/oneafter999_on_rails/20100224/_SCP_

Font Awesome 文字のアイコン

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rick No29です。
今回は、Font Awesomeという画像ではなく文字でアイコンが表示できるものをご紹介

環境

Rails 3

使用方法

ここよりDownload
とりあえずHomeディレクトリに解凍し、cssとfontだけを抜き出します。
$ cd Rails.root/public/stylesheets
$ mkdir font_awesome
$ cp -r ~/font-awesome/css Rails.root/public/stylesheets/font_awesome
$ cp -r ~/font-awesome/font Rails.root/public/stylesheets/font_awesome

viewにてcssを読み込み
$ vi app/view/hoge/index.html.erb
<%= stylesheet_link_tag ‘./font_awesome/css/font-awesome.css’ %>
<%= stylesheet_link_tag ‘./font_awesome/css/font-awesome-ie7.css’ %>
IE7でも正常に表示させたい場合は2段目のfont-awesome-ie7.cssが必要

viewにてタグの設置
$ vi app/view/hoge/index.html.erb

これだけでアイコンが表示されます。
他にどんなclassでどんなアイコンが表示されるかは、サイトを御覧ください。

サイズ変更

cssでfont-size:25px;とすると、アイコンのサイズが変更されます。(アイコンは画像でなく文字)

色変更

文字なのでcssのcolorで色も自由自在

マウスオーバー

a.zoom {
color: #222222;
text-decoration: none;
}
a.zoom :hover {
font-size: 25px;
color: #222222;
text-decoration: none;
}

たった1コマンドでネットショップ構築できちゃうelecoma-vagrant

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


よしだです。

今回はオープンソースのネットショップ構築アプリ「エレコマ」を、たった1コマンドで展開できるツール「elecoma-vagrant」を紹介します。

[2014/02/27] 「続・たった1コマンドでネットショップ構築できちゃうelecoma-vagrant」も合わせてご覧ください。

 必要な知識

  • ○ 端末へのコマンド入力

Windows の場合はコマンドプロンプト、

Mac/Unix の場合はターミナルを利用して作業を行います。

 用意するもの

  1. VirtualBox
  2. Ruby
  3. Git

それぞれのソフトウェアをインストールしておく必要があります。

既にインストールされている場合はとくに作業はありません。

 準備

GitHub から elecoma-vagrant をダウンロードします。

git clone git://github.com/hyoshida/elecoma-vagrant.git

Ruby に Bundler がインストールされていない場合は、

下記コマンドであらかじめインストールしておきます。

gem install bundler

 さっそく実行!

あとはダウンロードしたスクリプトのディレクトリに移動して、

セットアップ用のスクリプとファイルを実行するだけです。

cd elecoma-vagrant
./setup.sh

構築完了までに40分ほどかかるので、本でも読んでじっくり待ちます。

(※追記: 環境によってはライブラリ不足でインストールに失敗するケースがあるようです。原因については現在調査中です。 2013-06-28 17:30)

(※追記の追記: setup.sh 実行前に Nokogiri がインストールされている必要があります。「Installing Nokogiri」にしたがってインストールしてください。2013-06-28 18:30)

 構築完了

構築が完了すると画面に「Success!!」と出力されます。

この状態で、お使いのブラウザから「http://localhost:8080」にアクセスすると・・・

たったこれだけでネットショップが構築できちゃいました。

http://localhost:8080/admin にアクセスすると管理画面も見れます。

(id: admin, pw: pass)

 おわりに

今回は3つの技術を利用してエレコマ構築の簡易化を実現しました。

  1. vagrant
  2. chef
  3. serverspec

次回は、この3つの技術と elecoma-vagrant の解説をしたい思います。

vpsおよびクラウドシステムに於けるsshの安全性(仕様に於ける脆弱性)について

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今まで行ってきた個人的活動の中で、ssh接続の安全性について疑問が出てきたのでその内容をまとめてみる。

 問題の原点

まず、世に存在するvpsやクラウドシステムには、基本的には2種類の構成が存在している。このうちコンテナ型と呼ばれる構成では、予め必要とされてるsshやメールなどの基本的な内容が初期段階より構成されており、コンテナを選択するだけですぐにシステムの構築が出来る、手軽さが売りになっている。このコンテナには、予めsshが組み込まれていることが多く、そのため管理者のpasswordがデフォルトで決めうちになっている場合も多い。管理者のpasswordをデフォルトで放置していた場合、外部からの攻撃によって、あっさりと侵入を許してしまうことがある。

本題は、ここからだ。このsshが最初からインストールされている=ホストキーが最初から入っている=同じコンテナを使う限りホストキーは変わらない。ということになる。

また、vpsやクラウドシステムが大規模になればなるほど、この傾向は強まり、/16レベル(65535台)で同じホストキーで稼働しているケースもある。

ホストキーが同じと言うことは、sshを構成する際に用いられるseedキーも同一の物を使用していると考えて良いだろう。このseedキーは、乱数を用いており、このseedキーを変更する事で、ssh通信を行う際の暗号化通信に於いて、幅(バラエティさ)を持たせている。

この問題は、2008年に指摘された、下記内容に非常によく似た傾向をもつと考えられる。

DSA-1571-1 openssl — 予測可能な乱数の生成

http://www.debian.org/security/2008/dsa-1571

DSA-1576-1 openssh — 予測可能な乱数生成器

http://www.debian.org/security/2008/dsa-1576

 ssh 通信をあとからクラックしてみる

既に、幾つかの同一vpsを契約し、同一コンテナを展開することでホストキーが一致する or 一定の範囲内に収まることを確認している。

このホストキー情報を元に、予め生成してあるレインボウテーブルを用い、通信内容をあとから解析することで、その内容について平文に戻すことにも成功した。*1

また、多くのsshは、opensslを元に構成されており、デフォルトコンポーネントとして、opensslが含まれる場合はこの脆弱性が如実に表れる傾向がある。*2

 対策方法

このため、コンテナベースのsshを用いる場合は下記に注意し、速やかに対応することを強く推奨する。

  1. コンソールベースでログイン可能な場合は、sshのホストキーを再生成する
  2. 上記に加え、鍵交換を用いる

ベストな対応方法は、2であるが、どうしても都合により対応で気なのであれば、1を実行することで、ホストキーが事前生成された一定の範囲外になることにより、このリスクを低減させることが出来る。

*1: やり方については公開しない

*2: sshのクラックほどたやすくは無いが

JMeterでRailsのauthenticity_tokenを取得する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回はJMeterでauthenticity_tokenを取得する方法をご紹介します。

 概要

【環境】

Mac OS X 10.6.7

JMeter2.9

Rails2.0からCSRF対策として、Formに自動的にauthenticity_tokenが付加されるようになりました。

JMeterでPOSTする際などもこのauthenticity_tokenを正しくセットしないとアプリケーション外からのリクエストとして弾かれてしまいます。

 テスト計画構成と正規表現抽出

例えばテスト計画の下に「ログイン」というスレッドグループがあるとします。

さらに、その下に「ログイン画面」と「ログインアクション」という2つのサンプラー(HTTPリクエスト)がぶら下がるような設定です。

テスト計画

 ・ログイン

  ・ログイン画面

  ・ログインアクション

この場合、authenticity_tokenはログイン画面のFormに自動的に付加されていることと思います。

authenticity_tokenはログインアクションの際にパラメータとして必要なので、ログイン画面表示時にどうにかして、このauthenticity_tokenの値を取得しないといけないわけです。

そこで使用するのがJMeterの「正規表現抽出」という機能です。

正規表現抽出ではサンプラー(HTTPリクエスト)の後処理として設定することで、HTML BODY内の任意の値を正規表現で抽出し、次のサンプラーに渡すことができるのです。

 正規表現抽出追加

ログイン画面のサンプラーを右クリック

 →追加

  →後処理

   →正規表現抽出

これでログイン画面の下に正規表現抽出という項目が追加されたはずです。

 正規表現抽出項目設定

では各項目を設定しましょう。

Apply to:

 調査中

 (例)Main sample only

Responce Field to check:

 チェックするフィールド

 (例)Body

参照名:

 後続するリスナーで指定する名前

 (例)hidden_TOKEN

正規表現:

 マッチする文字列の正規表現

 (例)<input name=”authenticity_token” type=”hidden” value=”(.*)” />

  ※都合上全角の括弧(<>)となっているのでご注意ください。実際は半角になります。

テンプレート:

 マッチした正規表現の何番目を取得するか。0だと全体

 (例)$1$

  ※上記正規表現例の括弧内を取得

一致番号(0から乱数)

 調査中

 (例)空白

初期値:

 初期の値

 (例)is_not_Exist

 値の取得(ログインアクション設定)

最後に設定した正規表現の値を取得する方法です。

後続のリスナー(ログインアクション)のHTTP リクエスト – Parametersの追加

 名前:authenticity_token

 値:${hidden_TOKEN}

 Encode?:チェックON

  ※このチェックをONにしないと、取得した値の間に半角スペースが入る場合がありました

 統合含む?:チェックON

※他のパラメータ(ログインID、パスワード)等は適宜設定してください

以上で設定は完了です。

この状態でテストを実行すれば、ログイン画面のauthenticity_tokenを自動で取得し、POSTのパラメータに含めることが可能となります。

Rails3における自動テスト推進とRSpecとGuard

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

よしだです。

Rails 3 アプリにGuard を導入して自動テストをより手軽にする方法を紹介したいと思います。

 はじまり

最近携わっている Rails 3 アプリの自動テスト(RSpec)が、すべて完了するのに1時間半かかるようになってしまいました。

5〜10分で終わっていた頃はファイルに変更を加えるたびにすべてのテストを確認できていましたが、それが難しくなってきたので Guard を導入することにしました。

Guard を利用すれば、変更のあったファイルに関連するのみを効率よくテストすることができます。

ローカルでは Gurad で自分が編集した部分のみテストして、リモートの jenkins などですべてのテストを確認、ということをできるようにするのが今回の目的です。

 Guard のインストール

というわけで、さっそく Rails 3 アプリに Guard を導入していきます。

bundlerを利用している場合は Gemfile ファイルに下記の行を追加します。

group :development do
  gem 'guard'
  gem 'guard-rspec'
  gem 'guard-spork'
end

追加後、gem をインストールします。

% bundle install

最後に、guard の設定ファイル Guardfile を生成します。

% guard init

(※bundler を利用している場合は「bundle exec guard init」とすれば実行できます)

 Guard の設定

インストール後は Guardfile を編集して動作設定を行います。

今回は Guardfile の rspec に関わる行を下記のように書き換えました。

guard 'rspec', :cli => "--color --fail-fast --drb", :all_after_pass => false, :all_on_start => false do
  # …
end

「:cli => “–color –fail-fast –drb”」 という部分は rspec のオプションを記述しています。

これらはそれぞれ次のような意味があります。

  • –color … 色をつけて表示する
  • –fail-fast … テストに失敗したら即座に中断
  • –drb … DRBサーバをサポートする

–drb オプションによって Spork が利用でき、テスト開始までの時間が短縮できます。

「:all_after_pass => false」という部分は、テストが通ったときにすべてのテストを実行するか否か、というオプションになります。

今回は、すべてのテストを実行していると時間がかかりすぎるので、 オフ にしています。

「:all_on_start => false」という部分は、Guard 起動時にすべてのテストを実行するか否か、というオプションになります。

これも上と同じ理由でオフにしています。

 Guard の実行

まず、テストの高速化を図るためにあらかじめ Spork を起動しておきます。

% spork

つぎに Guard を起動します。

% guard start

これで準備完了です。

 Guard を走らせる

適当なファイルを編集&保存するだけで、更新されたファイルに関連づいたファイルだけ自動的にテストが走ります。

ファイルの中身に更新があるかどうかは問わないようなので、下記のようにタイムスタンプを更新するだけでもテストの実行が可能です。

% touch app/models/hoge.rb

 おわりに

現在非常に多くのツールが Guard と連携できるようになっているようです。

例えば仮想端末ソフト tmux などと連携することで「テスト実行後に結果を通知」といったことまでできます。

今回紹介したのは使い方のほんの一部でしたが、また機会があればその他の使い方について紹介したいと思います。

Rails2.3アプリのRuby1.8⇒1.9移行に伴って得た知見

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

よしだです。

今回はRails2.3/Ruby1.8で動作する自社開発のオープンソースECパッケージ『エレコマ』を、Ruby1.9に移行するに伴って問題になった点と、その解決方法について紹介したいと思います。

 日本語メールが文字化けする

Ruby 1.9 になって、文字列オブジェクトが文字コードを持つようになりました。

このため Ruby 1.8 ⇒ 1.9 移行の際には、文字列が意図しない文字コードで解釈されてしまうのを防ぐ必要があります。

Rails 2 のメールシステムには TMail というライブラリが利用されています。

Ruby 1.9 でこの Tmail を利用すると、上記問題のため、メール処理部分で例外エラーが発生してしまいます。

これは config/initializers/tmail_19_patch.rb に下記のようなコードを設置することで解決できます。

# -*- coding: utf-8 -*-
# Ruby 1.9 + tmail-1.2.7 環境での
#「Encoding::CompatibilityError (incompatible encoding regexp match (ASCII-8BIT regexp with ISO-2022-JP string))」
# エラー対策。
# Rails の場合 config/initializers/tmail_19_patch.rb などに配置する。
#

module TMail19Jp
  def self.encoding_handler(text)
    raise unless block_given?
    enc = text.encoding
    text.force_encoding(Encoding::ASCII_8BIT)
    result = yield
    text.force_encoding(enc)
    result
  end
end

module TMail
  class Encoder
    alias :phrase_org :phrase

    # 本文用のパッチ
    def phrase(str)
      TMail19Jp::encoding_handler(str) do
        phrase_org(str)
      end
    end
  end

  # Subject欄用のパッチ
  class Unquoter
    class << self
      alias :unquote_and_convert_to_org :unquote_and_convert_to

      def unquote_and_convert_to(text, to_charset, from_charset = "iso-8859-1", preserve_underscores=false)
        TMail19Jp::encoding_handler(text) do
          unquote_and_convert_to_org(text, to_charset, from_charset, preserve_underscores)
        end
      end
    end
  end
end

# 本文用のパッチ
class StringOutput
  alias :push_org :<<

  def <<(str)
    TMail19Jp::encoding_handler(str) do
      push_org(str)
    end
  end
end


# From欄用のパッチ
module ActionMailer
  module Quoting
    alias :quote_address_if_necessary_org :quote_address_if_necessary

    def quote_address_if_necessary(address, charset)
      TMail19Jp::encoding_handler(address) do
        quote_address_if_necessary_org(address, charset)
      end
    end
  end
end

文字列を処理するまえに force_encoding(Encoding::ASCII_8BIT) で文字オブジェクトが持つ文字コードを変更しています。

こうすることで、意図しない文字コードで処理され、例外が発生するのを防いでいます。

参考: http://d.hatena.ne.jp/akishin999/20120220/1329731704

 半角カナ判別用の正規表現が動作しない

Ruby 1.9 で正規表現ライブラリが「鬼車」に変わったため、正規表現の一部表現がサポートされなくなっています。

エレコマでは、全角カナの判別にはもともと下記のような正規表現を利用していましたが、「鬼車」ではこのような文字コード単位での範囲指定を許可していないようです。

# 全角カナを判別するための正規表現 (for Ruby1.8)
KATAKANA_PATTERN = /^(?:\xE3\x82[\xA1-\xBF]|\xE3\x83[\x80-\xB6\xBC])*$/

これは moji という gem を利用すれば簡単に解決できます。

実際には下記のようなコードになります。

(※ここでは全角カナのほかに、マイナスなどの例外的な文字も含めるようにしています)

# 半角カナを判別するための正規表現 (for Ruby1.8)
KATAKANA_PATTERN = /^(#{Moji.zen_kata}|ー|-)*$/

また「鬼車」では /[\p{katakana}+/ のように書くことでカタカナの判別が可能です。

ただし、こちらは半角カナも含んでしまうため、今回の例では使用できませんでした。

 PostgreSQL とうまく連携できない

エレコマでは DB として利用する PostgreSQL の gem に「postgres」を利用しています。

しかし、これは Ruby 1.9 では動作しないので、代替として「pg」をインストールします。

# gem uninstall postgres -v 0.7.9.2008.01.28
(古い gem をアンインストール)
# gem install pg --no-ri --no-rdoc
(Ruby 1.9 向けの新しい gem をインストール)

 PostgreSQL が古くて pg がインストールできない

「pg」は PostgreSQL 8.3 以上が必要になります。

このためインストール済みの PostgreSQL のバージョンが低い場合はアップデートが必要になります。

【CentOSの場合】

すでに PostgreSQL が入ってしまっているなら、下記コマンドで古いパッケージをアンインストールします。

# yum uninstall postgresql-devel postgresql-server

その後 PostgreSQL を 8.4 (8.3以上であれば良い) にします。

# yum install postgresql84-devel postgresql84-server

 さいごに

エレコマは現在 Ruby 1.9 に移行中です。

その中でまた問題と解決方法が見つかり次第、本記事に追記していこうと思います。

FreeBDにmuninを入れて負荷監視

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

よしだです。

今回はサーバ監視ツール munin を FreeBSD に入れる手順を紹介します。

 やりたいこと

ここでは nginx や MySQL が実行されているウェブサーバを監視することを目的とします。

そのために、これとは別に監視用のマシンを用意して、そこに munin を入れていきます。

 想定環境

  • ◇ munin を入れるサーバマシン
  • ◇ 監視対象となるnginx+MySQLサーバ

(どちらも FreeBSD)

 サーバ側セットアップ

サーバ側には port から sysutils/munin-master をインストールします。

cd /usr/ports/sysutils/munin-master
make install clean

インストールが正常に終了した後、監視対象となるサーバのIPアドレスを設定します。

# vim /usr/local/etc/munin/munin.conf
(※下記のような差分が出るように編集)
# diff /usr/local/etc/munin/munin.conf /usr/local/etc/munin/munin.conf.sample
< [domain.name]
<     address x.x.x.x
<     use_node_name yes

 クライアント側セットアップ

サーバ側には port から sysutils/munin-node をインストールします。

(※sysutils/munin-common というスケルトンもありますが、どうやらこれは munin-master もしくは munin-node のいずれかを入れるときに自動的にインストールされる共通ライブラリらしいです)

cd /usr/ports/sysutils/munin-node
make install clean

監視対象マシンにクライアントマシン自身をエントリします。

# cp /usr/local/etc/munin/munin-node.conf /usr/local/etc/munin/munin-node.conf.org
(※念のため初期設定をバックアップ)
# vim /usr/local/etc/munin/munin-node.conf
(※下記のような差分が出るように編集)
# diff /usr/local//etc/munin/munin-node.conf /usr/local//etc/munin/munin-node.conf.org
51,52c51,52
< #host *
< host 127.0.0.1
---
> host *
> # host 127.0.0.1

次に munin-cron を実行してクライアントの情報を定期的にサーバに送信するようにします。

# sudo -u munin /usr/local/bin/munin-cron

最後に munin のログローテート用に、syslog の設定に追加の記述を行います。

ここで munin-node.log の所有者が munin になるようにしておかないと、深夜 0 時とともに munin-node が落ちることになります。

# vim  /etc/newsyslog.conf
(※下記のような差分が出るように編集)
# diff /etc/newsyslog.conf
- /var/log/munin/munin-node.log                644  7     *    @T00  Z /var/run/munin/munin-node.pid
+ /var/log/munin/munin-node.log   munin:munin             644  7     *    @T00  Z /var/run/munin/munin-node.pid

 プラグインの追加

nginx の監視

手始めに nginx を監視するためのプラグインをクライアント側に導入します。

ln -s /usr/local/share/munin/plugins/nginx_status /usr/local/etc/munin/plugins/
ln -s /usr/local/share/munin/plugins/nginx_request /usr/local/etc/munin/plugins/

作業はこれだけで終わりです。

あとは munin-node を再起動すればプラグインが有効になります。

/usr/local/etc/rc.d/munin-node restart

MySQL の監視

次に MySQL の監視設定を追加します。

perl /usr/local/share/munin/plugins/mysql_ suggest

で、出現したコマンドの中から監視したいものを選択します。

perl /usr/local/share/munin/plugins/mysql_ suggest
bin_relay_log
commands
connections
files_tables
innodb_bpool
innodb_bpool_act
innodb_insert_buf
innodb_io
innodb_io_pend
innodb_log
innodb_rows
innodb_semaphores
innodb_tnx
myisam_indexes
network_traffic
qcache
qcache_mem
replication
select_types
slow
sorts
table_locks
tmp_tables

たとえば network_traffic を有効にしたい場合は下記のようにします。

ln -s /usr/local/share/munin/plugins/mysql_ /usr/local/etc/munin/plugins/mysql_network_traffic

最後に munin-node を再起動してプラグインを有効にします。

/usr/local/etc/rc.d/munin-node restart

 おまけ

おまけ1: MySQL監視がうまくいかない場合

Can't locate DBI.pm in @INC 

というメッセージ我出る場合、

cd /usr/ports/databases/p5-DBI
make install clean

で DBIライブラリ(DB接続用)をインストールします。

その後、下記のようにファイルを編集します。

# vim /usr/local/etc/munin/plugin-conf.d/plugins.conf
(※下記のような差分が出るように編集)
# diff /usr/local/etc/munin/plugin-conf.d/plugins.conf /usr/local/etc/munin/plugin-conf.d/plugins.conf.org

[mysql*]

env.mysqladmin /usr/local/bin/mysqladmin env.mysqlshow /usr/local/bin/mysqlshow +env.mysqlconnection DBI:mysql:mysql +env.mysqluser root

設定変更後は munin-node を再起動します。

/usr/local/etc/rc.d/munin-node restart

おまけ2: BASIC 認証を行う

htpasswd でパスワードファイルを作成後、ウェブサーバに設定を追加します。

(下記は nginx の場合を例にしています)

# htpasswd -c /usr/local/etc/munin/munin-htpasswd ユーザ名
# vim /usr/local/etc/nginx/nginx.conf
(※下記のような記述を追加)
        location /munin {
            root /usr/local/www;
            access_log /var/log/nginx-munin-access.log;
            error_log /var/log/nginx-munin-error.log;
            auth_basic "realm";
            auth_basic_user_file /var/www/munin/.htpasswd;
        }
# /usr/local/etc/rc.d/nginx reload

Webアプリケーション提供に於ける、passwordのあり方

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

お久しぶりです。ととろです。半年ほど、留守にしておりました。その間、様々なところで、インシデントが発生し、どこかで私の書いた記事を読まれた方も多いかと思いますが、今後は引き続きこちらで掲載していきますので、今後とも宜しくお願いします。

 不正ログインの大量発生

さて、いずこかの場所で、約12億ユーザーにものぼる数のpasswordが漏えいしました。これを期したかの様に、日本国内の数々の大手サービス会社が狙われ、根こそぎログイン可能なIDとpasswordが盗まれる事態になりました。一部の新聞記事で私がコメントした内容ですが、「今回の事件は、確実にログインできるIDとpasswordリストを売買する闇市場が有る」と考えています。つまり、ユーザーが同じIDとpasswordの組み合わせを、他のサービスで利用している以上、マスターキーとなるべく、確実にログインできる辞書ファイルが作成されつつ有り、それが高値で取引されるブラックマーケットが存在している。その様に考えています。

ユーザーに、どんなにサイト毎にpasswordを変えて下さいとお願いしても、ユーザーは「まさかそんなこと」と、相手にもせずにそのまま同じIDとpasswordの組み合わせを使い続けることでしょう。

 サービス提供会社としては?

先ほど、ユーザーは対岸の火事と考え、同じIDとpasswordの組み合わせを使い続けると書きました。では、サービスを提供する側に立って考えてみましょう。サービスを提供するが解らしてみれば、ユーザーが勝手に他のサービスと同じIDとpasswordを使い回した結果、不正ログインされるわけです。それが、数件ならまだしも、数百件、数千件にも上れば、新聞沙汰になりかねませんし、提供しているサービスが有名であれば、有名であるほど、ユーザーのサービス離れ(サービス解約)に拍車がかかります。サービス提供会社に、落ち度が無いにもかかわらず、ユーザーの勝手な思い込みにより、サービス提供が出来なくなる。こんな理不尽なことはありません。

今まで、どのサービスに於いても、password設定に関する主導権は、ユーザー側にありました。ポリシーとして、記号を入れるや、大文字を含める、数字を含めるなどいくつかの制限を盛り込んだとしても、それはあくまでもpassword設定に対して求める内容であって、passwordそのものを決定づけるのは、ユーザー自身です。これは、不文律で有り、世界の常識でした。しかしながら、昨今の様に立て続けに不正アクセスが続き、そして、不条理にもユーザーの勝手なpassword設定によって、不正アクセスが表沙汰になり、大騒ぎとなってサービス停止や、ユーザー離れにつながる。これでは、サービス提供会社はたまったものではありません。そこで、敢えてこの「passwordはユーザーが設定する物」という不文律を変えてみたいと考えています。

 では、どのようにすればいいのか?

サービス提供者から、passwordをいくつか提示し、そのpasswordの中から、ユーザーに利用するパスワードを決めて貰えば良いのです。このとき、パスワードのみを提供し、ユーザーID(ログインID)は、ユーザーに提供して貰います。データベース的には、ユーザーIDのみを記録し、passwordは記録しません。ユーザーには、先ほど書いた様に、ユーザーIDを提供して頂きますが、そのときの打鍵の情報をsaltとして持ちます。つまり、打鍵の早さによってバイオメトリックス認証もどきを行います。バイオメトリックス認証そのものを行うわけでは無く、あくまでも、saltとして用いるだけであり、他の用途には用いません。そして、ユーザー登録した日時を、秒まで含めて記録します。頭のキレる方はお気づきのことと思いますが、ユーザー認証に用いるIDとそれを入力した時間、それに加え、saltキーを元に幾何学演算を用い、いくつかの候補を画面に表示し、どれを選んだかを、DBに記録します。

これを行う事により、認証に用いられるpasswordは、ユーザーのみが記録しておき、システム側はそのpasswordを記録すらしません。存在するのは、生成アルゴリズムとユーザーが入力したID、それに暗号化したsaltのみである。これなら、アプリケーションに穴があったとしても、passwordは漏えいしませんし、当然、ユーザーからpasswordが漏えいしたとしても、他のユーザーへの影響はもちろんのこと、他のサービスに於いても、影響を受けることがありません。

 まとめ

今回は、ユーザーにも優しく、システム側にも優しい、passwordのあり方について考えてみました。

JavaScriptにて非同期通信を同期通信のように動作させる方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rick No28です。
今回は、JSの外部通信にてJSONPを使用し、画面遷移直前に使用する場合、非同期通信通信が途切れてしまう時があるのでその対策となります。

設定

・Webサイト
・外部サーバ
・画面A
・画面B
・jQuery

状況

JavaScript(jQuery)にて外部サイトに通信を行う場合、
クロスサイトスクリプティング対策としてJSONPとしますが、
同期通信は対応しておらず非同期通信しか使用できません。

この場合、Webサイト画面Aより画面Bへ遷移する直前(クリック時)に
非同期通信のJSONPを使用すると、
画面Bへの遷移が早すぎるためか外部サイトへの通信が行われない場合があります。
(遷移する前をブレイクポイントなどで止めると通信が行われます)
そのため、同期通信のような動作をさせる必要があります。

対策

遷移リンクを押した時に発動するため、

まずリンク等をやめるか、遷移イベントをキャンセルします。
例えばの代わりにでname=URLを記載し、
クリックイベントを貼り付けます。
その後の通信にて下記のようajaxを行います。
$.ajax({
url: URL,
dataType: “jsonp”,
data: data,
jsonpCallback: “callback”,
async : true,
complete: function(u) {
return function() {
location.href = u;
};
}(url)
});
工夫した点は1箇所completeの点です。
外部通信が完了した後の処理completeにて遷移処理をJS側で行うことで
同期通信のような動作となります。
これにより、クリック時通信を完了した後に遷移を行うことができ、
クリック時の外部通信処理が途切れなくなりました。

TeedaでAjax

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

WEBフレームワークのTeedaで簡単にAjaxを実装する方法を実例とともにご紹介します。

【環境】

Teeda 1.0.13

Seasar 2.4

TeedaにはAjaxを実装するためのプラグイン「Kumu.Ajax」が用意されています。

使用するには以下のライブラリを設定おきます。

・teeda-ajax-1.0.13-xx.jar

・ajax.js

 teeda-ajax-1.0.13-xx.jar 設定

WEB-INF/lib配下にteeda-ajax-1.0.13-xx.jarを含めます。

web.xmlも以下のように設定しておきます。

<servlet>
	<servlet-name>ajaxServlet</servlet-name>
	<servlet-class>org.seasar.teeda.ajax.AjaxServlet</servlet-class>
 	<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>ajaxServlet</servlet-name>
	<url-pattern>*.ajax</url-pattern>
</servlet-mapping>

 ajax.js 設定

ajax.jsを任意のディレクトリに配置します(src/main/webapp/js等)

もしajax.jsが無い場合はTeeda本体をダウンロードして取り出して下さい。

http://teeda.seasar.org/ja/

→「ダウンロード」より最新の「Teeda core(JSF実装)/extension(Htmlテンプレート等を含む拡張機能)/ajax(Ajax実現機能)を含む本体」をDL

※解凍後、src/main/resources/org/seaser/teeda/ajax/js内にあります。

HTML側でajax.jsを読み込みます。

<head>
	<script type="text/javaScript" src="../../js/ajax.js" />
</head>

 HTML側(リクエスト処理)

これで準備は完了です。

では、選択した都道府県セレクトボックスに連動して、市区町村セレクトボックスを切り替える処理を実装してみたいと思います。

都道府県のセレクトボックスにonchangeを設定し、javascriptで定義したgetCityメソッドを呼び出します。

< select id="pref" onchange="getCity(this.value);">
	< option value="0">dummy
< /select>

getCityではKumu.Ajax.executeTeedaAjaxを呼び出します。

第1引数:呼び出したいパッケージ + メソッド名を設定

第2引数:アプリ側に渡すパラメータ

第3引数:戻り値の型 ※TEXT以外にもJSONなども使えます

function getCity(prefId){
	Kumu.Ajax.executeTeedaAjax(mypage_updateAccountAction_ajaxCity, [prefId], Kumu.Ajax.RESPONSE_TYPE_TEXT);
}

 アプリ側

アプリ側では以下のように受けるメソッドを定義しておきます。

prefIdがパラメータとして渡ってくるので、その引数を元に市区町村を取得し、TEXT型で返します。

(mypage/updateAccountAction)

public String ajaxCity(String prefId){
	Map<string , string> items = getCityItems(Long.valueOf(prefId));
	String str = items.toString();
	return StringUtils.strip(str, "{}");
}

 HTML側(レスポンス処理)

コールバック関数にはリクエスト時の第1引数と同じ名前を付けておきます。

function mypage_updateAccountAction_ajaxCity(res){
	createCityOptions(res);
}

あとはこれを展開して市区町村セレクトボックスのリストの内容を書き換えればOKです。

function createCityOptions(res){
	var city = document.getElementById("city");
	
	// セレクトボックスを初期化
	removeChildren(city);
	city.options[0] = new Option("選択してください", null);
	
	if (res != "") {
		// カンマで分割し配列に格納
		var resArray = res.split(", ");
		
		for (var i = 0; i < resArray.length; i++) {
			var detailArray = resArray[i].split("=");
			var name = detailArray[0];
			var id = detailArray[1];
			city.options[i+1] = new Option(name, id);
		}
	}
}

function removeChildren(x) {
	if (x.hasChildNodes()) {
		while (x.childNodes.length > 0) {
			x.removeChild(x.firstChild)
		}
	}
}

以上です。わりと簡単にAjaxを実装できるKumu.Ajaxおすすめです!

Googleリーダー→netvibesに乗り換えてみた

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


Googleリーダー→netvibesに乗り換えてみた

 Googleリーダー終了

Googleリーダーが7月にサービス提供終了するとの一報が飛び込んできました。

私としては粛々と代替サービスに乗り換えることにいたしました。

 乗換先

netvibesがなんだかよさげという言葉を鵜呑みにしてみました。

 移行手順

エクスポート&インポートのわずかな作業で移行できました。

前準備

netvibesにアカウント登録をしておきます。

facebookアカウントが利用できるほか、

netvibes上でサインアップも可能のようです。

Googleリーダーからフィード情報をエクスポート

Googleリーダーをブラウザで開き歯車マーク→リーダーの設定をクリック

エクスポート/インポート→Download・・・をクリック

別ページに遷移するのでダウンロードをクリック

ダウンロードをクリック

フィード情報のアーカイブファイルのダウンロードがはじまります。

アーカイブファイルを展開すると中にsubscriptions.xmlというファイルがあります。

こちらを使用します。

netvibesにフィード情報をインポート

netvibesにログインし、

上部にある

コンテンツを追加する→フィードを追加する→インポート

でにsubscriptions.xmlをインポートします。

上記のメッセージが出たら成功です。OKをクリック

Googleリーダーで購読していたフィードが登録されました。

リーダーをクリックすると見た目がGoogleリーダーに近づく感じです。

 雑感

まだ使用して1日なので操作感などはコメントできませんが、

たとえばflickrなど画像投稿系の記事チェックは非常にやりやすくなりました。

表示をモザイクに変更します。

こんな感じです。

————–

確認環境

Windows7

Firefox14

【負荷対策】rubyの思わぬ落とし穴、putsについて

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。アピリッツの本多です。

久しぶりにruby関連の記事を書きたいと思います。

putsという、rubyの中ではメジャーな部類の関数がありますが、今日はこれに関する話題です。

ruby on rails案件にて、ループ処理系のバッチを実行する際に、進捗状況を確認するためにこんな書き方をしているケースがあると思います。

items.each_with_index do |item, i|
  (何かの処理)
  puts "#{i + 1} / #{items.size}"
end

この場合、展開するデータの件数が多くない場合は良いですが、例えば数十万件のデータを処理する場合などは

putsの処理時間が無視できないレベルになってきます。

例えば、弊社で公開しているエレコマというパッケージでは、住所マスタの取込バッチが実装されています。

ECサイト構築パッケージ「エレコマ」

elecoma/README at master ・ elecoma/elecoma ・ GitHub

================================================================================
* エレコマの住所マスタ更新
================================================================================
エレコマの住所マスタは郵便事業株式会社の郵便番号マスタを利用しています。
登録はコンソールから以下のように行ないます。

$ ruby script/runner -e production Zip.import

郵便番号マスタは以下のサイトにて配布されているものを自動的に取り込みます。
http://www.post.japanpost.jp/zipcode/download.html

住所マスタ更新機能はLhaLibに依存しています。
LhaLibの詳細については以下のサイトをご確認ください。
http://www.artonx.org/collabo/backyard/?LhaLibEn

このバッチですが、上記例と同様ループ処理中にputsで進捗状況を出力しているのですが、

いかんせんデータ数が2013年1月31日時点で123,385+22,087=145,472件と非常に多いです。

そしてデータ量が多いということは、イコールループ処理中のputsの影響も大きいという事ですね。

実際に動かして検証

私の環境(スペックは公開出来かねます。すみません)で実行してみます。

3回実行してみて、時間は

379.116285

389.899668

384.368132

⇒平均384.46秒(6分24.46秒)

でした。

結構長いですね。

ではputsをコメントアウトしてみましょう。

エレコマの郵便番号マスタのputsは2箇所あるので、両方をコメントアウトします。

コメントアウトしたら、再度同じバッチを実行します。

先ほどと同様に3回実行し、時間は

320.188456

315.7741

320.52054

⇒平均318.83秒(5分18.83秒)

でした。

1分以上の短縮です。かなり効果が出ましたね。

しかし、進捗状況が分からないと正常に動いているか不安ですね。

では間を取って、「1000処理毎にputsする」ようにしてみましょう。

実行時間は

298.578724

314.859872

323.760253

⇒平均312.40秒(5分12.40秒)

でした。

逆に若干puts無しより速い結果が出ましたが、まぁ…誤差の範囲という事で。

まとめ

ループ処理中の画面出力はほどほどに控えましょう。

実はこれらはrubyに限った話では無いですが、画面出力系の処理は意外に「重い」です。

そのため、今回のようなループ処理等、必ずしもputsが無いと困るわけではない場合に、思い切って処理を削る事で

パフォーマンスが改善する場合があります。

ちなみに後日談ですが、上記内容を社内のエレコマチームに報告し、2013/2/22現在は負荷改善対応がなされています。

JMeter で EC サイトを負荷テストする方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


よしだです。

今回は JMeter を使った負荷テストの方法について、EC(通販)サイトを例に紹介していきたいと思います。

 概要

負荷テストとは何でしょうか?

単純にアクセス数を増やすだけではアタックにしかならないし、結果的にサーバの性能を計測しているに過ぎない結果となりかねません。ここでいう負荷テストは、実際の運用時のアクセス状況を想定し、これをシュミレートした適切な負荷をかけることをさします。

EC サイトの場合、ひとつの商品ページにアクセスが集中することはあまりありません。多くのユーザは、1. サイトのどこか(大半はトップページ)から入場し、2. 商品を検索し、3. 目的の商品ページにたどりつき、4. カートに入れて、5. 購入処理を行います(6. 必要であれば会員登録も行うでしょう)。それぞれのアクションの間隔は 3~10 秒くらいで、同じようなアクティブユーザが他に何人もいるのが一般的です。

正確な負荷テストを行いたいなら、このような状況を再現する必要があります。ここまで複雑な処理を手動テストするなんて考えたくありません。

そこで、これを自動化してくれるツール JMeter の登場というわけです。

 想定するシナリオ

アクセスされうるページ

先ほどあげた通り、EC サイトであればユーザは下記のページにそれぞれアクセスする可能性があります。

  1. トップページ
  2. 商品検索
  3. 商品詳細
  4. カート
  5. 購入ページ
  6. 新規会員登録

想定するデータ

負荷状況は、アクセス状況のほかに、サービスが持つ情報量にも左右することがあります。

ここでは下記のデータをサービスが所有するものとして話を進めていきます。

(この値は、およそ中規模程度の EC サイトが所有するデータ量になります)

  • 商品数: 5,000
  • 会員数: 5,000
  • 受注数: 5,000

一般的に、

  • 商品数が多ければ商品検索・商品ページの読み込みに
  • 会員数が多ければログイン処理・会員登録処理に、
  • 受注数が多ければカートに入れる処理、受注処理に

それぞれ時間がかかりがちになります。

EC サイトではアクティブユーザの大半が商品検索を行うことになるので、実際には商品まわりを重点的にテストすべきです。また、ここではわかりやすくするために数値を固定していますが、本来は商品数・会員数・受注数・アクティブユーザ数の値をそれぞれ変更した場合のテストも行い比較すべきです。

それではこのシナリオを JMeter に設定していきましょう!

 JMeter 導入手順

改めて説明するものでもないので割愛します。

こちらでダオカさんが紹介しているので、ぜひ参考にしてみてください。

http://doruby.kbmj.com/daoka_tips/20090328/JMeter___

 用語解説

JMeter の用語を、今回のシナリオで必要になる要素に当てはめると下記のようになります。

  • ○ スレッドグループ … 1ユーザの行動シナリオおよび設定
    • ◇ スレッド数 … アクティブユーザ数
    • ◇ Ramp-Up期間 … スレッドが開始する間隔(ユーザ数の立ち上がり緩急度)
    • ◇ ループ回数 … シナリオを繰り返す回数
  • ○ ガウス乱数タイマ … 1ユーザのアクセス間隔(平均 n 秒でページ遷移)
    • ex.) 100アクティブユーザ * (1アクセス/5秒) = 20アクセス/秒
  • ○ リクエスト … 各ページへのアクセス
  • ○ コントローラ … 各ページへの遷移条件や順序を管理

 シナリオ作成

スレッドグループ

今回の負荷テストでは用意したシナリオに、さらに次の条件をつけて設定しました。

  • アクティブユーザ数: 会員数の 1%
  • アクティブユーザのページ遷移間隔: 平均 5 秒

これに基づき下記のような設定を行って行きます

スレッド数: 50 (アクティブユーザ 50 人の想定)
Ramp-up期間(秒): 10 (ページアクセスを開始をばらけさせるため)
ループ回数: 5 (適度に繰り返して、より正確なデータを入手するため)

HTTP リクエスト初期値設定

「サーバ名または IP」にはテストしたいウェブページのアドレスを入力します。

これで以降登場する「HTTP リクエスト」のデフォルト値をいちいち変更する必要がなくなります。

HTTP クッキーマネージャ

クッキーを有効にするために、「HTTP クッキーマネージャ」をスレッドグループに追加します。

ガウス乱数タイマ

「アクティブユーザのページ遷移間隔: 平均 5 秒」を実現するためにタイマを設定します。

偏差: 2000
遅延時間オフセット定義: 5000

コントローラ&HTTP リクエスト

先に作成したシナリオに従って、下記のような構成・設定を行いました。

  1. ログインが必要でかつ未ログインである場合
    1. ログイン画面に遷移
    2. ログイン処理
  2. 次のうちどれかのページにランダムアクセス
    1. トップページ
    2. 商品検索
    3. 商品詳細
  3. 4/5の確立で商品詳細へのアクセスを続ける
  4. 直前に商品詳細にアクセスしていた場合
    1. カートに入れる
    2. 1/10の確立で注文処理

実際の画面では以下のような構成になっています。

 シナリオを実行する

シナリオを設定し終えたら、あとは実行するだけです!

ここでスレッドグループに「結果を表で表示」をコントローラに加えておくと、アクセスログがばんばん表示されるようになります。この結果を Excel に貼り付けて保存するもよし、グラフとして保存するもよしで、割といろいろなことができます。

 終わりに

触り始めは覚えるのが大変な JMeter ですが、一度慣れてしまえばいろいろなことができるので楽しめると思います。ここではそのごく一部しか紹介できませんでしたが、ぜひ試してみていただければと思います。

 参考文献

解答例 - 実習課題1 - 8.負荷テスト計画の立て方 | TECHSCORE(テックスコア)
http://www.techscore.com/tech/Java/ApacheJakarta/JMeter/answer/8-1/

JMeter の実践的な使用例として参考になります。

負荷テストあれこれ-JMeterの使い方-|A Day In The Boy's Life
http://ameblo.jp/itboy/entry-10039380165.html

コントローラの説明がていねいでわかりやすいです。

コントローラ(IFコントローラ) - JMeterガイド - livedoor Wiki(ウィキ)
http://wiki.livedoor.jp/susatadahiro/d/%A5%B3%A5%F3%A5%C8%A5%ED%A1%BC%A5%E9%A1%CAIF%A5%B3%A5%F3%A5%C8%A5%ED%A1%BC%A5%E9%A1%CB

わかりやすい IF コントローラの説明があります。

ガルーンの負荷テストをjmeterでやってみる|千代田区で働いていた元課長の退職日記
http://ameblo.jp/ys6872/entry-10355379947.html

よくわかるスレッドの解説が掲載されています。

TestLinkのインストールとお奨めチューニング

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

TestLinkはテスト管理システムの1つです。
以前から気になっていたけど、やっと導入したので、その時のインストール手順とお奨めチューニングを記載します。
Excel管理の課題からは解放されたけど、TestLinkもかゆい所に手が届かないので、上手く付き合っていく必要はあります。
その辺は別の機会に記載します。

●TestLinkダウンロード

$ cd /usr/local/src
$ sudo wget http://sourceforge.net/projects/testlink/files/TestLink%201.9/TestLink%201.9.4/testlink-1.9.4.tar.gz/download
$ sudo wget http://mattari.sumomo.ne.jp/wp/wp-content/uploads/2011/08/TestLink1-9-3-ja_JP.zip

●TestLinkインストール

$ cd /usr/local/src
$ sudo tar zxvf testlink-1.9.4.tar.gz
$ sudo mv testlink-ga-testlink-code testlink-1.9.4

$ sudo unzip TestLink1-9-3-ja_JP.zip
$ sudo mv testlink-1.9.4/locale/ja_JP testlink-1.9.4/locale/ja_JP,201211
$ sudo mv ja_JP testlink-1.9.4/locale/

$ sudo chown -R apache:wheel testlink-1.9.4
$ sudo mv testlink-1.9.4 /var/www/html/
$ ln -s /var/www/html/testlink-1.9.4 /var/www/html/testlink

●DBとユーザ追加

$ mysql -u root -p mysql
—- ここから —-
CREATE DATABASE testlink DEFAULT CHARACTER SET utf8;
GRANT ALL PRIVILEGES ON testlink.* TO testlink@localhost IDENTIFIED BY ‘********’;
FLUSH PRIVILEGES;
\q
—- ここまで —-
※「Query OK」と表示されればOK

●TestLink設定変更(お奨めチューニング)

$ cd /var/www/html/testlink
$ cp -a custom_config.inc.php.example custom_config.inc.php
$ vi custom_config.inc.php
—- ここから —-
//### START 2012/11 ###
$tlCfg->default_language = ‘ja_JP’;
$tlCfg->log_path = TL_ABS_PATH . ‘logs/’;
$g_repositoryPath = TL_ABS_PATH . ‘upload_area/’;
$g_smtp_host = ‘localhost’;
$g_tl_admin_email = ‘admin@mydomain.com’;
$g_from_email = ‘testlink@mydomain.com’;
$g_return_path_email = ‘admin@mydomain.com’;
$g_tree_type=’JTREE’;
$tlCfg->treemenu_type = ‘EXTJS’;
$tlCfg->sessionInactivityTimeout = 86400;
$tlCfg->user_self_signup = FALSE;
$tlCfg->charts_font_path = “/usr/share/fonts/ipa-pgothic/ipagp.ttf”;
$tlCfg->document_generator->company_name = ‘株式会社**** 御中’;
$tlCfg->document_generator->company_copyright = ‘Copyright© ‘ . date(‘Y’) . ‘ 株式会社****’;
$tlCfg->document_generator->confidential_msg = ‘****事業部’;
$tlCfg->document_generator->company_logo = ‘company_logo.gif’;
$tlCfg->document_generator->company_logo_height = ’43’;
//### END ###
—- ここまで —-

$ cd /var/www/html/testlink/gui/themes/default/images
$ wget -c http://mydomain.com/images/logo.gif -O company_logo.gif
$ chmod 664 company_logo.gif

$ cd /var/www/html/testlink/locale/ja_JP
$ sudo cp -a strings.txt strings.txt,201211
$ sudo vi strings.txt
—- ここから —-
//### START 2012/11 ###
//$TLS_scope = “適用範囲”;
$TLS_scope = “概要”;
//### END ###
—- ここまで —-

●TestLink設定

http://mydomain.com/testlink/
[New installation]
Acceptance of License
■I agree to the terms set out in this license.
[Continue]
Verification of System and configuration requirements
[Continue]
Definition of DB access
Database name:testlink
Database admin login:testlink
Database admin password:********
TestLink DB login:testlink
TestLink DB password:********
[Process TestLink Setup!]
Installation was successful!
※「Failed! – Could not create user: ********!」と表示されるけどOK
[Testlink]
ログインしてください …
ログイン名:admin
パスワード:admin
[ログイン]
[My Settings]
Email:admin@mydomain.com
Locale:English(wide/UK) ->Japanese
[Save]
旧パスワード:admin
新パスワード:********
新パスワード(確認):********
[パスワード変更]

$ rm -fr /var/www/html/testlink/install

Teedaのsessionscopeについて

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最新、Seasar2 + Teedaのプロジェクトを作成しているので、
Teedaのsessionscopeについてメモします。

Teedaには、スコープにはいくつかありまして、
そのうち、サブアプリケーションスコープ(@SubapplicationScope)がドキュメントの書いた通り、
同じ サブアプリケーション のページを表示している間維持されるスコープです。
サブアプリケーションスコープは, 初期表示 や リダイレクト表示 で 他の サブアプリケーション から遷移した際に開始されます。
初期表示 や リダイレクト表示 で他のサブアプリケーションのページが要求されると破棄されて, 新しいサブアプリケーションスコープが開始されます.

サブアプリケーションの入力画面が非常に多い時、とても便利なものです。
ただし、
——-
初期表示 や リダイレクト表示 で他のサブアプリケーションのページが要求されると破棄されて, 新しいサブアプリケーションスコープが開始されます.
——-
ということで、一連の操作の途中に万が一、同じブラウザで、別サブアプリケーションへアクセスすると、
一連の操作は続けられなくなってしまう可能性が十分ありますので、ご注意ください。

例えば、
Aというサブアプリケーションには
入力画面1~5、確認画面、完了画面からなります。
入力画面が多いので、全ての項目をhiddenで渡すと、しんどいので、
———–
@SubapplicationScope
public TestDto test;
———–
を定義して、入力画面の入力項目を格納しました。

偶然、入力画面2が開いている中、別のサブアプリケーションBの画面を見たくて、
同じブラウザで、Bの画面へアクセスしました。
そうすると、また、Aの入力画面2に戻って、次へボタンを押すと、testがNULLになって、
NullPoint例外が投げられました。
なぜでしょうかと考えると、@SubapplicationScopeの仕様にぴったりでした。

ある機能操作中、別機能の画面を見るのは少ないケースですが、ないわけではない。
@SubapplicationScopeを使用するとき、ご注意ください。

↑のケースにはどうしても操作を続けたいという希望があるので、
セッションを使うようにしました。

TestDtoを「@Component(instance = InstanceType.SESSION)」で定義して、
Page側で、セッションとして使うとき、
———-
    @Binding(bindingType = BindingType.MUST)
    protected TestDto testDto;
———-
のように定義すれば、testDtoはセッション級のものとして、使えます。
(※自動バインディングのルールとしてクラス名がTestDtoである場合、変数名はtestDtoにしないと、自動バインディングしてくれないのでご注意)

セッションから、removeは

最後の完了ページが表示されるとき、

    @RemoveSession(name={“testDto”})
    public Class prerender() {
        return null;
    }

すれば良いです。

Kindle Fire HD を Android 端末に変身させるハック!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

よしだです。

最近になって Kindle Fire HD を手に入れたので、これをさらに便利に使う為の手順をまとめたいと思います。

 概要

Kindle Fire HD は Amazon 初の電子書籍向けタブレット端末です。

ベースは Android なのですが、アプリは Amazon が提供するストアで公開されているものしか利用することができません。

つまり、通常の Android 端末なら利用できる Dropbox や Dolphin ブラウザなどの便利なアプリが、使えない状態となっています(2012/1/9現在)。

そこで Kindle Fire HD に Android アプリを入れられるようにハックしていきます。

いわゆる root 奪取などの複雑な手順はいっさい必要ありません。

 準備

  • Kindle Fire HD のみ

(Kindle Fire でもいけると思いますが未確認です)

 手順

では、早速ハックしていきます。

1. アプリケーションのインストールを許可

まず野良の Android アプリをインストールできるように、設定を変更します。

Kindle Fire HD の画面上部から下に向かってスワイプするとメニューが降りてくるので、ここから「設定」> 「端末」>「アプリケーションのインストールを許可」を「オン」にします(画像1, 2)。

  • 画像1
  • 画像2

2. Android アプリをインストールするためのアプリ導入

apk ファイルから Android アプリをインストールできるアプリであればなんでも良いですが、ここでは利便性の高い ES File Manager を選択します。

「ホーム画面」>「アプリ」>「検索」から「ES File Manager」と検索して、トップに表示されたアプリをインストールします(画像3, 4)。

  • 画像3
  • 画像4

3. Android アプリが一覧できるストアアプリをダウンロード

「ホーム画面」>「ウェブ」から URL 直接入力で「http://www.1mobile.com/app/market」にアクセスします(画像5)。

開いたページの「Download」ボタンを押して、ストアアプリの apk ファイルをダウンロードします(画像6)。

  • 画像5
  • 画像6

4. ダウンロードしたストアアプリ導入

「ホーム画面」>「アプリ」>「端末」から、2. でインストールした「ES File Manager」を起動します。

「/mnt/sdcard/Downalod」に 3. でダウンロードした apk ファイルがあるので、これを選択してインストールします(画像7, 8)。

  • 画像7
  • 画像8

5. ストアアプリ起動

「ホーム画面」>「アプリ」>「端末」から、4. でインストールした「1mobile market」を起動します。

すると通常の Android 端末でみるようなストア画面が表示されます(画像9)。

  • 画像9

6. 好きなアプリをインストール!

あとはもう自由です。

欲しいアプリを検索してインストールしていく流れになります。

 おわりに

Kindle Fire HD は値段がお手頃なので、この手法と合わせることで安価な Android タブレットを入手できることになります。

ただし、公式にサポートされた方法ではないので、あくまで自己責任になります。

また「アプリケーションのインストールを許可」オプションは、セキュリティ面で危険が伴いますので注意してください。

Rails3 メールテンプレートにURL作成の注意点

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

メール本文中のURLはエスケープされて、「&」は「& amp;」になってしまう注意点

 URLを作成

メール中でURLを作成するため、url_forを使用します。

 URLにパラメータを追加

url_for(:action => ‘some_action’, :custom1 => ‘some_value’, :custom2 => ‘some_value’, :escape => false)

:escape => falseを指定しないと、urlがエスケープされます。

「&」は「& amp;」になってしまいます。

●注意点:

Rails3から、<%= … %>で出力される値が暗黙的にエスケープ処理されるように変更になりました。

ですので、メールテンプレートの中で、下記のように書いても、メールを表示するとき、エスケープされて、「&」は「& amp;」になってしまいます。

<%= url_for(:action => ‘/some_action’/, :custom1 => ‘/some_value’/, :custom2 => ‘/some_value’/, :escape => false) %>

●対策:

html_safeを使用

<%= url_for(:action => ‘/some_action’/, :custom1 => ‘/some_value’/, :custom2 => ‘/some_value’/, :escape => false).html_safe %>

or

rawを使用

<%= raw(url_for(:action => ‘/some_action’/, :custom1 => ‘/some_value’/, :custom2 => ‘/some_value’/, :escape => false)) %>

 :formatを指定する場合

url_for :controller=>’posts’, :action=>’index’, :format=>:xml

結果:

http://www.example.com/posts.xml

url_forの詳しい使用について、下記を参照のこと

ドキュメント:

http://apidock.com/rails/ActionMailer/Base

http://apidock.com/rails/ActionController/Base/url_for

【GoogleAnalytics】eコマース機能「収益」と「商品の収益」

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

GoogleAnalyticsのeコマース機能にある
『収益』 と 『商品の収益』 の定義、知っていますか?今回は、書いてあるようで書いてない、細かい定義を説明します。

※2012.12 撮影

■ Google Analytics の『収益』とは

上図の『収益』の説明を見てください。下記のように表記されています。

————————————————–
e コマース トランザクションの合計収益(税金と配送料を含む)です。
————————————————–

この表記のままで考えると
————————————————–
『収益』 = 「total(合計金額)」 + 「shipping(送料)」 + 「tax(税)」
————————————————–

だと思いますよね?

だが、しかし….
実際は異なるという情報をGoogleさんから回答頂きました。
正しくはこうです。
————————————————–
『収益』 = 「total(合計金額)」
※ _addTrans 内に存在する total の数値が採用される
————————————————–
みなさん、ご注意ください。

■Google Analytics の『商品の収益』とは

こちらはご想像通りかと思います。
————————————————–
『商品の収益』 = 「unit price(商品単価)」 × 「quantity(購入数量)」
※ _addItem 内に存在する unit price, quantity を掛けあわせた数値の合計
————————————————–

■「unit price(商品単価)」 × 「quantity(購入数量)」 = 「total(合計金額)」?

当然、Googleに渡す値によって異なるとは思いますが
————————————————–
「unit price(商品単価)」 × 「quantity(購入数量)」 = 「total(合計金額)」
————————————————–
になる会社さんが多いかもしれません。

ただし、以下のような場合は 
————————————————–
「unit price(商品単価)」 × 「quantity(購入数量)」 > 「total(合計金額)」 
————————————————–
という状況が成り立ちます。
————————————————–
例: 1,000円のT-Shirtを3枚購入。
  しかし500円の割引が適用され会計金額(total)は2,500円だった。
————————————————–
この場合の計測結果は以下の通り。

『商品の収益』 ¥3,000
『収益』¥2,500
※考え方
————————————————–
『商品の収益』 ¥3,000 = 「unit price(商品単価)」¥1,000 × 「quantity(購入数量)」3
『収益』¥2,500 =「total(合計金額)」¥2,500
————————————————–

※上記例のeコマーストラッキングデータ
————————————————–
_gaq.push([‘_addTrans’,
‘5555’, // order ID – required(注文ID)
‘Womens Apparel’, // affiliation or store name(ショップ名)
‘2500’, // total – required(合計金額)
‘125’, // tax(税)
‘315’, // shipping(送料)
‘渋谷区’, // city(市名)
‘東京都’, // state or province(都道府県)
‘日本’ // country(国名)
]);
_gaq.push([‘_addItem’,
‘5555’, // order ID – required(注文ID)
‘DD33’, // SKU/code – required(商品ID)
‘T-Shirt’, // product name(商品名)
‘Olive Medium’, // category or variation(カテゴリー)
‘1000’, // unit price – required(商品単価)
‘3’ // quantity – required(購入数量)
]);
_gaq.push([‘_trackTrans’]);
————————————————–

以上、何かのお役に立てれば幸いです。

[PR]アピリッツのGoogleアナリティクスサポートサービス

■Google アナリティクス セミナー・トレーニング

アピリッツでは、 Googleアナリティクスセミナー(無料・有料含む)を過去200回以上の開催をしております。ツールのことは勿論、事業内容であるシステム開発、デザイン制作、各ASPツールのサービス展開より得られた「売上向上・受注獲得のための現場のノウハウ」を重視し、皆様のビジネス上での成功をお手伝いできるようセミナーを展開しております。
– 入門編
– 分析手法編
– 設定編

■Google アナリティクス コンサルティング

Googleアナリティクスの導入・解析・運用・ナレッジ化をサポートします。
– コンサルティング
– レポーティング
– 導入・カスタマイズ

■リスティング広告出稿代行

[Google Partner] 当社は AdWords 認定資格に合格しています。

最近人気な記事