ホーム ブログ ページ 46

yum updateしたらcrmコマンドが無くなった!(pcsコマンド対照表)

0

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

CentOSでyum updateしたらcrmコマンドが無くなりました。
理由は解らないけど、crmを捨てて、新しい(?)pcsコマンドに移行する感じなのかと。
crm使って、今までやっていた事がpcsだとどうやるか、よく解らなかったので、updateを暫く凍結してました。
が、それじゃいけないと思い、ググったり、ヘルプ見たり、試したりして、やっと同じ事が出来るようになったので、対照表と言いつつ、表じゃないけど、纏めました。

●pcsインストール

これをやらないと始まらない。

# yum -y install pcs

●crmと同じ事が出来るpcsコマンド

それぞれが何をするコマンドかは別の所で調べてください。

# crm configure property stonith-enabled=”false” no-quorum-policy=”ignore” default-action-timeout=”240″ default-resource-stickiness=”200″
 ↓
# pcs property set stonith-enabled=”false” no-quorum-policy=”ignore” default-action-timeout=”240″ default-resource-stickiness=”200″
# crm configure rsc_defaults resource-stickiness=”INFINITY” migration-threshold=”1″
 ↓
# pcs resource rsc defaults resource-stickiness=”INFINITY” migration-threshold=”1″
↑コマンドが変わったみたいで使えなくなった(2013/11/16)
# pcs resource defaults resource-stickiness=”INFINITY” migration-threshold=”1″
# crm configure primitive mailto ocf:heartbeat:MailTo params email=”warning-root@localhost” subject=”[Pacemaker]”
 ↓
# pcs resource create mailto ocf:heartbeat:MailTo params email=”warning-root@localhost” subject=”[Pacemaker]”
※更新はcreateの代わりにupdate
# crm configure primitive vip ocf:heartbeat:IPaddr2 params nic=”eth0″ ip=”192.168.11.210″ cidr_netmask=”24″ op monitor interval=”20s”
 ↓
# pcs resource create vip ocf:heartbeat:IPaddr2 params nic=”eth0″ ip=”192.168.11.210″ cidr_netmask=”24″ op monitor interval=”20s”
# crm configure primitive drbd ocf:linbit:drbd params drbd_resource=”r0″ drbdconf=”/etc/drbd.conf” op monitor interval=”20s”
 ↓
# pcs resource create drbd ocf:linbit:drbd params drbd_resource=”r0″ drbdconf=”/etc/drbd.conf” op monitor interval=”20s”
# crm configure ms drbd-clone drbd meta master-max=”1″ master-node-max=”1″ clone-max=”2″ clone-node-max=”1″ notify=”true”
 ↓
# pcs resource master drbd-clone drbd master-max=”1″ master-node-max=”1″ clone-max=”2″ clone-node-max=”1″ notify=”true”
# crm configure primitive cluster ocf:heartbeat:Filesystem params device=”/dev/drbd0″ fstype=”ext3″ directory=”/cluster” op monitor interval=”20s”
 ↓
# pcs resource create cluster ocf:heartbeat:Filesystem params device=”/dev/drbd0″ fstype=”ext3″ directory=”/cluster” op monitor interval=”20s”
# crm configure primitive mysql ocf:heartbeat:mysql params binary=”/usr/bin/mysqld_safe” op monitor interval=”10s”
 ↓
# pcs resource create mysql ocf:heartbeat:mysql params binary=”/usr/bin/mysqld_safe” op monitor interval=”10s”
# crm configure primitive apache ocf:heartbeat:apache params configfile=”/etc/httpd/conf/httpd.conf” port=”80″ op monitor interval=”20s”
 ↓
# pcs resource create apache ocf:heartbeat:apache params configfile=”/etc/httpd/conf/httpd.conf” port=”80″ op monitor interval=”20s”
# crm configure group nfs-group mailto vip cluster mysql apache
 ↓
# pcs resource group add nfs-group mailto vip cluster mysql apache
※リソース削除はaddの代わりにremove_resource
# crm configure colocation nfs-group_on_drbd inf: nfs-group drbd-clone:Master
 ↓
# pcs constraint colocation add nfs-group drbd-clone INFINITY with-rsc-role=Master
# crm configure order nfs-group_after_drbd inf: drbd-clone:promote nfs-group:start
 ↓
# pcs constraint order promote drbd-clone then start cluster
# crm
# cib new ~/pcs_cfg
# configure ・・・
# cib commit ~/pcs_cfg
# quit

# pcs cluster cib ~/pcs_cfg
# pcs -f ~/pcs_cfg ・・・
# pcs cluster push cib ~/pcs_cfg
↑コマンドが変わったみたいで使えなくなった(2013/11/16)
# pcs cluster cib-push ~/pcs_cfg
# crm configure show
 ↓
# pcs cluster cib
# crm_mon -1
 ↓
# pcs status
※crm_monも使えます。
# crm resource move nfs-group host1 force
 ↓
# pcs resource move nfs-group host1 force
↑ホスト名とforceは指定出来ませんでした。(2013/11/25)
# pcs resource move nfs-group
※host1は実際のホスト名
# crm configure edit -> 「node host1」の行を削除
 ↓
# cibadmin –delete –obj_type nodes –crm_xml ”
# cibadmin –delete –obj_type status –crm_xml ”
※host1は実際のホスト名

anythingを使ってMongoDBやNagiosをPacemakerで起動制御する方法

0

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

MongoDBとNagiosをPacemakerで起動制御出来るようにした時のメモです。
ApacheやMySQL等は専用のスクリプトが用意されていますが、MongoDBとNagiosのは無くて、作るのも労力なので、汎用的に使えそうなanythingで代用しました。

●Pacemakerリソース追加

既にyum updateしてcrmコマンドが無くなっているので、pcsを使います。
crmの方は、yum updateしたらcrmコマンドが無くなった!(pcsコマンド対照表)も参考にしてください。

・MongoDBの場合

Nagios Pluginのcheck_tcpを使って、死活監視をしています。

# pcs resource create mongodb ocf:heartbeat:anything params \
	user="mongodb" \
	binfile="/usr/bin/mongod" \
	cmdline_options="-f /etc/mongodb.conf > /dev/null 2>&1" \
	pidfile="/var/run/mongodb/mongodb.pid" \
	monitor_hook="/usr/lib64/nagios/plugins/check_tcp -H localhost -p 27017" \
	op monitor interval="20s"
# pcs resource group add nfs-group mongodb

・Nagiosの場合

Nagiosはサービスに影響がないので、落ちてもフェールオーバしないように死活監視はしてません。
Nagios自体は外部監視するのが良いと思います。

# pcs resource create nagios ocf:heartbeat:anything params \
	user="nagios" \
	binfile="/usr/bin/nagios" \
	cmdline_options="-d /etc/nagios/nagios.cfg" \
	pidfile="/var/nagios/nagios.pid"
# pcs resource group add nfs-group nagios

●anythingカスタマイズ

上記で終わりと思いきや、実際には動きません。
理由はanythingで作ったPIDファイルをMongoDBやNagios側でも作成して上書きしてしまう為です。
anythingが使いたいPIDではなくなってしまう。。。
別のファイルを指定したりもしましたが、上手く動かず断念!
なので、少し細工します。但し、元々の挙動でも動くように。

# cd /usr/lib/ocf/resource.d/heartbeat
# cp -a anything anything,201309
# vi anything
### START 2013/09 taka ###
#		eval $cmd > $pidfile
		eval $cmd > $pidfile.tmp
		sleep 1
		if [ -e $pidfile ]; then
			rm -f $pidfile.tmp
		else
			mv -f $pidfile.tmp $pidfile
		fi
### END ###

●まとめ

これで無事、意図通り動くようになりました。
見ての通り、起動ユーザやコマンド(起動スクリプトを見れば解ります)と監視コマンドを用意すれば、MongoDBやNagios以外にも利用出来ます。

●追記(2013/11/04)

yum updateしたらanythingが無くなり、Corosyncが停止出来なくなりました。(crmに続き、またか〜)
幸いバックファイル(anything,201309)が残っていたので、そいつをベースに再度カスタマイズを施し修復!

新規構築等で最初からない場合は、下記等から入手してください。
https://github.com/ClusterLabs/resource-agents/blob/master/heartbeat/anything

そもそもyum updateする時はCorosync止めてからじゃないと危険だね。
再起動したまま帰ってこないくて、最悪、オンコールリブートになりそうな。

Railsからデータをエディタで作成したPDFに出力する方法

0

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

「ThinReports Editor」と「ThinReports Generator」 があればエディタで作成した形に

データを出力できるようになり、納品書等の帳票が簡単に作れます。

 動作環境

Ruby 1.8.7,1.9.3

 1、「ThinReports Generator」をインストール

まずはRailsから出力するための必要な「ThinReports Generator」をインストールします。

$ gem install thinreports

※Ruby1.8.7の場合は、別途 json のインストールが必要

$ gem install json

 2、「ThinReports Editor」 のインストール

次にPDFのデザイン作成に必要な「ThinReports Editor」 をインストールします。

下記のURLにアクセスして自分のOSにあったものをインストールしてください。

http://www.thinreports.org/download/

インストールするものは以上です。

参考:http://osc.matsukei.net/projects/thinreports/wiki/Installation_Guide

 3、PDFのレイアウトを作成する

先ほどインストールした「ThinReports Editor」をつかい.tlfファイルを作成します

下記のURL先で使い方がわかると思います。

http://osc.matsukei.net/projects/thinreports/wiki/Getting_Started

.tlfファイルを作成し終わったらRailsの/public/の下にでも置いてください。

 4、PDFにデータを出力してダウンロードする

このアクションが呼ばれればPDFをダウンロードできます。

require ‘thinreports’

~~~~~~~~~~

~~~~~~~~~~

def pdf_download

 #Reportオブジェクトの生成、先ほど作ったレイアウトの読み込み

 report = ThinReports::Report.new :layout => ”/public/pdf_layout”

 #新しいページを作る際にここが呼ばれます

 report.events.on :page_create do |e|

  e.page.item(:page_num).value(e.page.no) #現在のページ数入力

 end

 #PDFを生成するときにここが呼ばれます

 report.events.on :generate do |e|

  e.pages.each do |page|

   page.item(:page_total).value(e.report.page_count) #総ページ数入力

  end

 end

 #ページを作成し、データを入力していきます。

 report.start_new_page do |page|

  page.item(:name).value(‘名前’)

  #リストを作っていた場合はリストに入力していきます。

  for i in 0..10 #10行分

   page.list(:list_test).add_row do |row|

    row.item(:quantity).value(“数量#{i}”)

    row.item(:price).value(“値段#{i}”)

   end

  end

 end

 #PDF生成

 send_data report.generate, :filename => ”ファイル名.pdf”,

 :type => ’application/pdf’,

 :disposition => ’attachment’

end

ペンテスターを取り巻く環境

0

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

先日、某所で行われたペンテスター(脆弱性診断を行っているひと)たちにの寄り合いに出かけ、そのときに議題として上った話を、いくつかかいつまんで解説してみよう。

 いま、脆弱性診断業界で何が起きているのか?

ペンテスター業界全般で、システム上の後継者問題が浮上している。後継者問題といっても、人としての後継者ではなく、システム的な後継者の話だ

  1. IE 8
  2. Chrome 最新版
  3. Firefox 最新版

この3つで共通している問題がある。それは、webアプリケーションを診断する上で、比較的見つけやすい脆弱性である、XSSを検知することが出来ないブラウザだ。

ユーザーにとって、XSSは時にはセッションハイジャックをもたらすやっかいな存在だが、各ブラウザーベンダーが、ブラウザそのものでXSSが出来ない対策を施し始めた。

この事は、ユーザーそのものとして見た場合、非常にウェルカムな考え方だが、脆弱性診断を行っている場合、診断に用いているブラウザによっては、XSSが存在しているにもかかわらずあたかもそれが存在していないかのように誤検知してしまう恐れがある。

 では、どうするのが良いのか?

代替案として、ブラウザに搭載された互換モードを利用するという考え方もある。しかしながら、互換モードはあくまでも表示上の互換性を維持するための物であり、XSSをはじめとするいくつかの再現しない脆弱性について、互換表示する物ではない。そのため、

まもなくサポートが終了する、Windows XP を利用し、IE6とIE7を確保する

といった解決策が必要となってくる。当然、これらのOSを使用することはウイルスに感染したり、外部からの攻撃を受けやすくなる等の問題があるため、現時点に於いて、一般利用者に通常はWindows XPの採用は推奨することはない。しかしながら、今回の様に誤検知の恐れがある以上ペンテスターにとっては、完全な再現性を担保するため、仮想環境の中でWindowsを稼働させ、診断が終わるたびに、元の安全な状態に戻すといった方法や、復元ポイントを用いた、環境の確保が必要不可欠となる。

 Windows XP で安全にwebアプリケーション診断に使うには?

先ほど述べたとおり、Windows XPは来年春にマイクロソフトによる正式サポートが終了する。このため、現状できうる限りのセキュリティパッチやサービスパックなどは適用しておき、その状態をマスターとして保存し、必要に応じて呼び出すのが良いだろう。当然として、アンチウイルスは導入し、EMETと呼ばれる、脆弱性を緩和させるフレームワークを導入することも慣用だろう。

今後、ブラウザが進化するに従って、従来は検知出来た脆弱性が益々検知することが難しくなることが十分予測される。もしかしたら、IE7やIE8といった、比較的最近のバージョンも保持対象となる日が訪れる事になるかもしれない。一般利用者にとっては、セキュアな方向にすすむため、非常にうれしい状況に有るだろうが、ペンテスターとしてみると、非常に悩ましい問題の1つと言えよう。

Unicode正規化 norm_KCとnorm_KDの注意点

0

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

Unicode正規化 norm_KCとnorm_KDの注意点特殊な文字に対して、別文字になってしまいます。
例:
irb(main):004:0> query=”250℃”
=> “250℃
irb(main):005:0> q = query.downcase.to_u.norm_KC.to_s
=> “250\xC2\xB0C”
irb(main):006:0> q.force_encoding(“UTF-8”) if q.respond_to?(:force_encoding) => “250°C”

一文字「℃」は2文字「°C」になってしまう。

inputNFD,NFCNFKD,NFKC
IDSPU+3000和字間隔IDSPU+3000和字間隔SPU+0020スペース
U+2025二点リーダU+2025二点リーダ..U+002E U+002Eピリオド+ピリオド
U+2026三点リーダU+2026三点リーダU+002E U+002E U+002Eピリオド+ピリオド+ピリオド
U+2033U+2033′′U+2032 U+2032分+分
U+2103摂氏度記号U+2103摂氏度記号°CU+00B0 U+0043度+ラテン大文字C
U+222C二重積分記号U+222C二重積分記号∫∫U+222B U+222B積分記号+積分記号

Unicode正規化を参照

blank?は意外なサプライズ

0

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

文字列のblank?メソッドは正規表現を使っていますので、UTF-8的に正しいバイト列ですかチェックしています。

型によって、blank?の処理が違います。

文字列の場合、正規表現で判断しています。

配列の場合、Arrayのempty?と同じです。

ハッシュの場合、Hashのempty?と同じです。

blank.rbの一部ソースコード:

class String

def blank?

self !~ /[^[:space:]]/

end

end

class Array

alias_method :blank?, :empty?

end

class Hash

alias_method :blank?, :empty?

end

Ruby 1.9 でUTF-8的に正しくないバイト列がある文字列を扱っていると、

正規表現マッチや gsub といったメソッドを使っているところで ArgumentError: invalid byte sequence in UTF-8 例外が発生します。

文字列を生成したときではなくて正規表現マッチなんかをしたときに始めてエラーが出るのです。

例:

str = “\xC1\xB9\xA4\xB1\xA4\xF3\xA4\xC1\xA4\xF3\xBD\xC1”

begin

str.blank?

rescue => e

p e # ArgumentError: invalid byte sequence in UTF-8

end

文字列のblank?メソッドは正規表現を使っていますので、UTF-8的に正しいバイト列ですかチェックしています。

配列の要素に対して、正しいUTF8バイト列をチェックするため、要素に対して、blank?を使用します。

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現在は負荷改善対応がなされています。

最近人気な記事