先週月曜日の日付を取得するアルゴリズム

先週の月曜日を求めるアルゴリズム

  • 先週(7日前)が月曜日である場合はその日付を返す
  • 月曜日でない場合
    • 月曜日より前であれば日付を1日たす
    • 月曜日より後であれば日付を1日ひく

Rubyで実装

1
2
3
4
5
6
7
8
9
def last_monday(date = Date.today - 7)
return date if date.monday?
if date.wday < 1
date += 1
else
date -= 1
end
last_monday(date)
end

先週の金曜日を求める場合

1
2
3
4
5
6
7
8
9
def last_friday(date = Date.today - 7)
return date if date.friday?
if date.wday < 5
date += 1
else
date -= 1
end
last_friday(date)
end

次の月曜日の日付を求めるアルゴリズム

  • 明日が月曜日かどうか
    • 月曜日であればその日を返す
    • 月曜日でなければ1日たす

Rubyで実装

1
2
3
4
def next_monday(date = Date.today + 1)
return date if date.monday?
next_monday(date + 1)
end

前回の月曜日の日付を求めるアルゴリズム

  • 昨日が月曜日かどうか
    • 月曜日であればその日を返す
    • 月曜日でなければ1日ひく

Rubyで実装

1
2
3
4
def prev_monday(date = Date.today - 1)
return date if date.monday?
prev_monday(date - 1)
end

実行結果

1
2
3
4
5
6
7
8
9
10
puts Date.today.strftime("%Y-%m-%d (%a)")
=> 2016-06-09 (Thu)
puts prev_monday.strftime("%Y-%m-%d (%a)")
=> 2016-06-06 (Mon)
puts next_monday.strftime("%Y-%m-%d (%a)")
=> 2016-06-13 (Mon)
puts last_monday.strftime("%Y-%m-%d (%a)")
=> 2016-05-30 (Mon)
puts last_friday.strftime("%Y-%m-%d (%a)")
=> 2016-06-03 (Fri)

ActionMailerの添付ファイルをRspecでテストする

ActionMailerで添付ファイルを送るようにしたのですが、そのテストをするときの情報があまりなかったのでまとめました。

以下のようにテストしました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
RSpec.describe AppMailer, type: :mailer do

before(:all) do
Archive::Zip.archive(
"tmp/app.zip",
"README.md")
end

after(:all) do
FileUtils.rm "tmp/app.zip"
end

let(:mail) do
AppMailer.send_email(zip_path)
end

it 'assings the attachment file' do
attachment = mail.attachments[0]
expect(attachment).to be_a_kind_of(Mail::Part)
expect(attachment.content_type).to be_start_with('application/zip')
expect(attachment.filename).to eq "app.zip"
end
end

まず、before(:all)でテストに使うzipファイルを作成します。
zipファイルはarchive-zipを使って作成しています。
アーカイブするファイルは何でもよいですが、この記事ではREADME.mdとしています。
テストで作成したzipファイルはafter(:all)で消しています。
mail.attachments[0]に添付ファイルが入っているので、その種類やファイル名を確認しています。

参考リンク

TCPWrappersとは何なのかを調べてみた

sshのハンドシェイクでこけてしまい、その原因がわからずハマりました。
原因としては、TCPWrappersで拒否されていました。
TCPWrappersとはなんだろうということで調べてみました。

TCPWrappersとは

TCPWrapperとは、ネットワークのアクセス制御をする機能です。
デフォルトでインストールされています。

Linuxの基本的なアクセス制御の仕組み

Access Control to Network Services

アクセス制御の仕組みとして、FirewallとTCP Wrappersがあります。
Firewallはiptablesで制御します。
なぜ2つの仕組みが存在するのかはわかりません(誰か教えてください)。

クライアント→Firewall→TCPWrappers→サービスという流れで処理を行います。
TCPWrappersは接続を許可するかどうかのファイルを参照し、許可リストにあればサービスに処理を受け渡します。

処理のログはsyslog daemon (syslogd)によってクライアントと接続先サービスの情報を /var/log/secure または /var/log/messages に書き込まれます。

TCPWrappersのアドバンテージ

TCPWrappersを使うことで、以下のメリットがあるとのこと。

  • 接続したクライアントとそのサービスがログに残る
  • 様々なプロトコルを集約して管理できる

##TCPWrappersの設定ファイル

以下の2つのファイルがあります。

  • /etc/hosts.allow
  • /etc/hosts.deny

TCPWrappersはクライアントからのリクエストを受けると、以下の処理を行います。

  • /etc/hosts.allow を参照します。クライアントがリストに存在した場合、接続を許可します。リストに存在しない場合は次のステップに進みます。
  • /etc/hosts.denyを参照します。クライアントがリストに存在した場合、接続を拒否します。リストにない場合は接続を許可します。

注意点

  • /etc/hosts.allowから先に評価され、そこでリストに一致した場合/etc/hosts.denyは評価されません。/etc/hosts.allow/etc/hosts.denyに同じクライアントを指定した場合は/etc/hosts.allowが優先されます。
  • ファイルの上から評価されていき、一致した時点で評価を打ち切ります。順番が重要です。
  • TCPWrappersはキャッシュを持ちません。ですので、設定ファイルを書き換えたら即反映されます。デーモンをリスタートする必要はありません。
  • 最後に改行を含めるとエラーメッセージが出るとのことなので、含めないほうがよさそうです。warning: /etc/hosts.allow, line 20: missing newline or line too longというメッセージが /var/log/messages または /var/log/secureに出力されるとのことです。

参考リンク

クロスサイトスクリプティングの脆弱性とその対策

クロスサイトスクリプティングはユーザーの入力を受け付ける動的なアプリケーションに含まれる脆弱性を利用した攻撃です。
英語ではCross Site Scriptingと呼ばれその頭文字をとるとCSSとなりますが、「Cascading Style Sheets」との区別が紛らわしいため一般的にXSSの表記が使われています。

クロスサイトスクリプティングとはどのような脆弱性であるのか

XSSとは動的なWebサイトのプログラムの脆弱性を利用した攻撃です。
この脆弱性を利用することで、攻撃者は悪意のあるJavaScriptコードをサイトに埋め込み、そのコードを実行することができるようになります。

例えば、XSSの脆弱性がある掲示板があったとします。
攻撃者はフィッシングサイトにページを遷移させるJavaScriptコードを投稿しました。
すると、他の利用者がこの掲示板を閲覧したときにそのJavaScriptコードが実行され、フィッシングサイトが表示されるようになります。

この脆弱性を持ったサイトが攻撃されるとどのような被害が起き得るのか

上記の例のようにXSSはWebサイトの利用者を攻撃の対象とします。

例えば、以下のような被害が出る可能性があります。

  • ユーザーのcookie情報を盗み、その情報を利用してそのユーザーでログインする
  • 不正なページへユーザーを誘導する
  • 不正なファイルをダウンロードさせる

Webサイトを直接攻撃することも可能です。
JavaScriptのhtmlを書き換える機能を使って、攻撃対象のサイトの内容を書き換えることができてしまいます。

なぜそのようなセキュリティホールが作り込まれてしまうのか

HTMLには特殊文字が存在します。
具体的には「’”<>&」といった文字です。
これらの特殊文字をHTML上に表示するには適切な方法で変換しなければなりません。
しかし、XSSの脆弱性のあるプログラムはこのような特殊文字を意識せずに作られてしまっています。

どのように対策をすればよいのか

入力時のチェックと出力時のチェックを行います。

入力時のチェック

具体的には、入力時に入力できる文字を制限します。
例えば、郵便番号を入力するフォームの場合は、数字と-しか入力できないようにします。
そうすれば、悪意のあるコード自体が入力できなくなります。
入り口でとめる作戦です。

注意点としては、入力文字のチェックは必ずサーバサイドで行わなければなりません。
PHP等のサーバサイドで実行されるプログラムでチェックする必要があるということです。
クライアントサイド(JavaScript)のチェックでは攻撃者がそのチェック機構自体を無効にすることが可能です。

出力時のチェック

実際には仕様上、入力文字を制限することができないことがあります。
例えばフリーフォームの場合、無闇に入力文字を制限するとユーザーは自由に文章を入力することができなくなってしまいます。

そこで、出力時に文字を無害化(サニタイジング)します。

サニタイジングについては、プログラム言語やフレームワークに専用の機能が用意されています。
その機能を使うことを強く推奨します。

例えばPHPであれば、htmlspecialcharsというhtmlの特殊文字を無害化する関数が用意されています。
http://php.net/manual/ja/function.htmlspecialchars.php

また、フレームワークはデフォルトでサニタイズされた文字が出力される仕組みになっているはずなので、そのようなフレームワークを使ったほうがよいでしょう。

参考リンク

Shellで日本語ドメインをPunycode(IDNドメイン)に変換する方法

Shellで日本語ドメインをIDNフォーマットに変換する方法を紹介します。
対象のOSはMacです。

libidnというGNUのライブラリがあるので、それを使います。

libidnのインストール

homebrewでインストールします。

1
$ brew install libidn

インストールしたら、idnコマンドが使えるようになります。

1
2
3
4
5
6
7
8
$ idn
libidn 1.32
Copyright 2002-2015 Simon Josefsson.
GNU Libidn is free software with ABSOLUTELY NO WARRANTY. For more
information about these matters, see <http://www.gnu.org/licenses/>.
Type each input string on a line by itself, terminated by a newline character.

idn: tld_check_4z: Missing input

libidnでPunycodeに変換する

以下のようにPunycodeに変換できます。

1
2
$ idn しょーやん.xyz
xn--68jwei3c27a.xyz

unicodeに変換する場合は-uオプションを使います。

1
2
$ idn -u xn--68jwei3c27a.xyz
しょーやん.xyz

digとidnを組み合わせて使う

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  dig `idn しょーやん.xyz` NS

; <<>> DiG 9.8.3-P1 <<>> xn--68jwei3c27a.xyz NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59533
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;xn--68jwei3c27a.xyz. IN NS

;; ANSWER SECTION:
xn--68jwei3c27a.xyz. 3578 IN NS dns01.muumuu-domain.com.
xn--68jwei3c27a.xyz. 3578 IN NS dns02.muumuu-domain.com.

;; Query time: 34 msec
;; SERVER: 192.168.74.20#53(192.168.74.20)
;; WHEN: Fri Jun 3 09:25:40 2016
;; MSG SIZE rcvd: 94)>>>>>>