SSブログ

ECPGでSELECT FOR UPDATE

Windows版のPostgreSQL 8.4に付いてきたECPGでSELECT ... FOR UPDATEをやってみたときの微妙なメモ。まあ、普通に動くので微妙ではないかもしれないですけど。ちなみに開発環境はVisual C++ 2005。

取り敢えず、テスト用に簡単なテーブルを作ってみる。

CREATE TABLE T_TEST (
    TEST_ID SERIAL NOT NULL PRIMARY KEY,
    TEST_STR VARCHAR(8) DEFAULT '' NOT NULL
);


序でに申し訳程度にレコードも足しておく。

INSERT INTO T_TEST (TEST_STR) VALUES ('aaaa');
INSERT INTO T_TEST (TEST_STR) VALUES ('bbbb');
INSERT INTO T_TEST (TEST_STR) VALUES ('cccc');
INSERT INTO T_TEST (TEST_STR) VALUES ('dddd');


以下のようなECPGに食わせるコードを書いてみる。

EXEC SQL
    BEGIN;

EXEC SQL
    SELECT TEST_ID 
     FROM T_TEST 
      WHERE TEST_ID > 0 FOR UPDATE;
...
EXEC SQL
    COMMIT WORK;
...


BEGIN;で明示的にトランザクションを開始してCOMMIT WORK;しているので、プリプロセッサecpg(1)に渡すときには-tオプションを付けます。で、エラーもなくVisual C++ 2005のビルドまで通るのですが、実行するとSQLCODE-202SQLSATTE07002なエラーを吐きます。INTO句がないからなのですが、エラーだからといって別にロックに失敗しているわけでもなくそこでトランザクションがROLLBACKしているわけでもなく正常に動作してたりします。まあ、デフォルトがEXEC SQL WHENEVER SQLERROR CONTINUE;なので処理を続行するのはわかるんですが、エラーって続行可能な場合を指すのかなと。SQLWARNING扱いでも良さそうな気が。兎も角、INTO句を付ければ解消しそうなので付けてみることに。返ってくる行数が事前にわかるわけでもないので、ここはDESCRIPTORを使って以下のように書いてみる。

EXEC SQL
    BEGIN;

EXEC SQL ALLOCATE DESCRIPTOR test_desc;

EXEC SQL
    SELECT TEST_ID 
     INTO DESCRIPTOR test_desc 
      FROM T_TEST 
       WHERE TEST_ID > 0 FOR UPDATE;

EXEC SQL DEALLOCATE DESCRIPTOR test_desc;
...
EXEC SQL
    COMMIT WORK;
...


別にdescriptor areaから値を取り出すわけでもないので何となくもったいない感はありますが特にエラーも吐かず実行できます。勿論、ちゃんとロックもかかります。で、マニュアルの32.7. Dynamic SQLを読んでみると、こんな記述が。

引用:PostgreSQL 8.4.6 Documentation(32.7. Dynamic SQL)

An EXECUTE command can have an INTO clause, a USING clause, both, or neither.


日本語だとここ。

引用:PostgreSQL 8.4.4文書(32.7. 動的SQL)

EXECUTEコマンドはINTO句、USING句、この両方を持つことも、どちらも持たないこともできます。


ん?動的SQLを使うとINTO句が省略できるのか?とか思って以下のようにやってみましたが、

EXEC SQL BEGIN DECLARE SECTION;
    ...
    const char *sfu_stmt 
     = "SELECT TEST_ID FROM T_TEST WHERE TEST_ID > ? FOR UPDATE;";
    ...
EXEC SQL END DECLARE SECTION;
...
EXEC SQL
    BEGIN;

EXEC SQL
    PREPARE test_query FROM :sfu_stmt;

EXEC SQL
    EXECUTE test_query USING 0;

EXEC SQL
    DEALLOCATE PREPARE test_query;
...
EXEC SQL
    COMMIT WORK;
...


同じようにSQLCODE-202SQLSATTE07002なエラーを吐きました。この場合もINTO句は要るようで、

EXEC SQL BEGIN DECLARE SECTION;
    ...
    const char *sfu_stmt 
     = "SELECT TEST_ID FROM T_TEST WHERE TEST_ID > ? FOR UPDATE;";
    ...
EXEC SQL END DECLARE SECTION;
...
EXEC SQL
    BEGIN;

EXEC SQL
    PREPARE test_query FROM :sfu_stmt;

EXEC SQL ALLOCATE DESCRIPTOR test_desc;

EXEC SQL
    EXECUTE test_query 
     INTO DESCRIPTOR test_desc USING 0;

EXEC SQL DEALLOCATE DESCRIPTOR test_desc;

EXEC SQL
    DEALLOCATE PREPARE test_query;
...
EXEC SQL
    COMMIT WORK;
...


とすると特にエラーも吐かず実行できました。ちなみに、動的SQLじゃない場合と同様にどちらも正常に意図した通りに動いてはいます。でも、なんだか「INTO句やUSING句は書かなくて良い場合は書かなくてよい。」と言われているようでなんだか「赤く塗られたところは赤いです。」とか「500円のものは500円です。」と同じような感覚があり、そりゃそうだろうと言いたくなるような仕様ではあります。

後、最新のPostgreSQL 9.0.2 Documentationでもそうなんですが、ずっと、

引用:PostgreSQL 9.0.2 Documentation(32.7. Dynamic SQL)

EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;


と書かれていますが、:v1, :v2, :v3と書かないと動作しないはず。このあたりからしてECPGってあんまり使われてないんでしょうね。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Phreebird Suite 1.02お試し

まだまだデモレベルな感じですが、Dan Kaminsky氏ご提供のPhreebird Suite 1.02phreebirdをお試し程度に使ってみる。大雑把にいえば、DNSSEC未対応のDNSサーバーのレコードに署名を付けてくれるプロキシーのようです。

モノは、

http://s3.amazonaws.com/dmk/phreebird_suite_1.02.tar.gz

あたりにあるようです。後、プレゼンらしきものが、

http://www.slideshare.net/dakami/phreebird-suite-10-introducing-the-domain-key-infrastructure

なんかにあります。

テスト環境は、某βテスト中のクラウド/VPSのCentOS5.5。まずは、インストール。取り敢えず、取得と展開

$ wget \
    http://s3.amazonaws.com/dmk/phreebird_suite_1.02.tar.gz
$ tar xpvzf  phreebird_suite_1.02.tar.gz
$ cd phreebird_suite_1.02


まずは、依存するライブラリとかのインストール

$ su
# sh depbuild.sh
# exit
$


うまくいかなければ、depsディレクトリにcdしてアーカイブ展開して./configure && make && make installとか各々のドキュメントの指示に従う等してインストールします。

そして本体のインストール。

$ su
# make && make install


後は、ldconfig(8)を実行しておきます。

# cat > /etc/ld.so.conf.d/phreebird.conf
/usr/local/lib
# ldconfig


で、使い方。

# phreebird -?


とすると簡単なヘルプが出ます。ZSKを作成します。

# phreebird -g


とするとカレントディレクトリにdns.keyという名前で秘密鍵が出来ます。アルゴリズムはRSASHA1_NSEC3。できるモノはldns-keygen(8)dnssec-keygen(8)で作られるモノと同じなので、他のアルゴリズムを使いたい場合、そっちで作っても構わないのですが、Private-key-formatv1.3なモノは使えないようなので、イマドキのdnssec-keygen(8)なんぞで作る場合は-Cオプションを付ける必要があるようです。

後は、適当なコンテンツDNSサーバ(Authoritative Server)を指定して起動します。以下は、適当なコンテンツDNSサーバのIPアドレスが192.0.2.2だった場合。

# phreebird -b 192.0.2.2:53


-bを指定しなければ、ローカルの50053に向くようです。

後は、dig(1)とかで、動作確認。

$ dig +dnssec +multiline @127.0.0.1 example.jp. soa


キャッシュDNSサーバ(Recursive Server)といいますかフルリゾルバに向けてやると漏れなく署名付けてくれたりします。すでに付いているものは署名し直されることになります。
ちなみに、rootのhint fileが設定されていないコンテンツDNSサーバー、たとえば、

zone "." {
    type hint;
    file "/dev/null";
};


になっているものや、zone "."がないコンテンツDNSサーバー(*1)に向けてやって、

$ dig +dnssec @127.0.0.1 . ns


とかすると、Segmentation faultで落ちます。




*1: コンテンツDNSサーバーって普通そうだとは思いますけど。
タグ:DNSSEC phreebird
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

cron(8)でZSKを作る件

引用:auto-dnssec maintain; を試してみる

ま、取り敢えず、これで上位へのDSやDLVの登録なんかを除けば、鍵を作り足し忘れない限り、大丈夫そうな状態が作れる感じ。適切なoffset値でdnssec-keygen(8)にtiming optionを指定してcron(8)あたりで呼べば、作成もなんとかなるのかも。


取り敢えず、こんな感じのcrontab(5)named(8)の実行ユーザーで作って試してみる。GNU dateが使える環境前提ですけど。

SHELL=/bin/sh
MAILTO=""
#
13 * * * * /usr/sbin/dnssec-keygen -r /dev/urandom -3 -a RSASHA256 \
 -b 1024 -i 1h \
 -A `/bin/date -u -d "1 hour" "+\%Y\%m\%d\%H\%M\%S"` \ 
 -I `/bin/date -u -d "2 hours 10 minutes" "+\%Y\%m\%d\%H\%M\%S"` \ 
 -D `/bin/date -u -d "2 hours 20 minutes" "+\%Y\%m\%d\%H\%M\%S"` \ 
 -K /var/named/chroot/var/named/keys/example.jp \
 -n ZONE example.jp > /dev/null 2>&1 \
 && /usr/sbin/rndc loadkeys example.jp. > /dev/null 2>&1


問題なさそうなら、-iの値を1moぐらいにして、hourmonthにして、10 mintutes3 daysぐらいにして実機でやってみようかな。

dnssec-keygen(8)ってman読むと、-P-Adefault is "now"って書いてますけど、-Aだけ書いて-P付けなかったら-Pには-Aの値が採用されるんですね。おもいっきり-iの説明に書いてますけど見落としてた。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

続・auto-dnssec maintain; を試してみる

所有ドメインを使って、auto-dnssec maintain;な設定で、暫くISC DLVして遊んでみているわけなんですが…。

引用:auto-dnssec maintain; を試してみる

これで、Kexample.jp.+008+12199とKexample.jp.+008+59595が署名に使用され、Wed Oct 27 22:45:55 JST 2010 を過ぎればKexample.jp.+008+58539がゾーンに公開され、Thu Oct 28 00:42:57 JST 2010を過ぎればKexample.jp.+008+59595が署名に使われなくなったりしてくれます。


PublishとDeleteに関して言及を避けているわけですが、まあ、単刀直入にいえばPublishとDeleteのお時間には勝手には何も起きなかったわけでして、まあ、そのあたりどうなのかなと暫く使ってみてまして…。

レコードの追加・削除・変更等のきっかけがあれば、そのときのkey-directory等で指定されたディレクトリにある鍵に応じてPublishもDeleteもActivateもInactiveも行ってくれるんですが、結論から言いますと、auto-dnssec maintain;の設定の下で、

# rndc loadkeys zone [class [view]]


を実行してやると、その時点でkey-directoryに指定されたディレクトリにある鍵に応じた処理を時の経過と共に行ってくれるようです。"ようです"というのが微妙な表現ですが、例えば、Activateに関していえば、Activateに指定されている時間に署名をしてくれたりしてくれなかったりでなんだか微妙な感じです。ログに

next key event: 08-Nov-2010 23:10:48.521


という感じで、次に起こる鍵の追加や削除や署名に関することが起こる日時が示されるのですが、key-directory等で指定されたディレクトリにある鍵のPublishとActivateとInactiveとDeleteに指定されている時間を時系列に並べて調べてみると、なぜだか、たまに飛ばされてしまうものがあるようです。傾向としてはActivateな時間とInactiveな時間にあって、PublishとDeleteな時間にはないようです。というか今のところPublishとDeleteな時間には体験してないです。大雑把にいえば、Activateな時間に署名が自動的に付くこともあれば付かないこともある、Inactiveな時間を過ぎた時間にDelete等のSOA RRのシリアルが変更されるようなイベントが入ってもInactiveな鍵で署名され続けたりすることがあります。何度か、同じ時間差条件でテストしてみましたけど、取り敢えず、傾向は読めないです。バグなんですかね?

まあ、そんな感じなので、新しい鍵がActivateなお時間に特に署名されることがないまま古い鍵がDeleteされる時間が訪れ、そのタイミングで新しい鍵がActivateになったりとTTL的に微妙な状態が起こったりするときもあります。

後、

# rndc sign zone [class [view]]


という、そのときのkey-directory等に指定されたディレクトリにある鍵を読み込んでActivateな時間を過ぎている鍵で署名してくれるコマンドもあるのですが、これもたまに微妙な動作します。既に Inactiveな鍵で署名を付けたりしてくれることがありました。「あれ?」と思って、短い有効期間の鍵でテストしているので、その時間の短さが影響しているのかもしれませんけど、loadkeysを含めて、今のところ手放しにおまかせするのは少々躊躇われるところかもしれません。何か使い方を間違えているのかもしれませんけど。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

auto-dnssec maintain; を試してみる

BIND-9.7.2-P2auto-dnssec maintain;を試したメモ。

ARMを見る限り、auto-dnssecに指定できる値としては、allow|maintain|create|offがあるみたいですけど、allowは、dnssec-signzone(8)-Sで使えるSmart signingに毛が生えた程度な感じだし、完全放置プレイができそうなcreateは、まだ未実装みたいなので、取り敢えず、一番便利そうなmaintainを試してみることに。大雑把にいえば、timing metadataを付けた鍵を用意しておけば、そのtimingで鍵をゾーンにpublishedにしたり、ゾーンでactiveにしたりInactiveにしたりrevokeにしたり、ゾーンからdeleteしたりしてくれるシロモノのようです。

お試しの環境はCentOS 5.5で、ディレクトリ構成なんかはchrootな場合のデフォルトです。起動オプションは、

# /usr/sbin/named -u named -t /var/named/chroot


になります。用意するゾーンはテストなのでexample.jp.にして、鍵は、/var/named/chroot/var/named/keys/example.jpに置くことにして、ゾーンファイルは、/var/named/chroot/var/named/dynamicに置くことにします。まず、下準備。

$ su -
# cd /var/run/named
# ln -s /var/named/chroot/var/run/named/session.key .
# cd /var/named/chroot/var/named
# mkdir -m 770 dynamic
# chown -R named:named dynamic
# mkdir -m 770 keys
# chown -R named:named keys
# su - named --shell=/bin/bash
$ cd /var/named/chroot/var/named/keys
$ mkdir -m 770 example.jp
$ cd example.jp


んで、鍵を作ります。お試しするだけなので、賞味期限は短めで。まずは、KSK。

今すぐゾーンに公開され署名に使用され、1 日後署名に使用されなくなり、2 日後ゾーンから消えるものを。

$ /usr/sbin/dnssec-keygen -f KSK -r /dev/urandom -3 -a RSASHA256 \
 -b 2048 -I +86400 -D +172800 -n ZONE example.jp
Generating key pair........+++ .........................................................+++
Kexample.jp.+008+12199
$ cat Kexample.jp.+008+12199.key
; This is a key-signing key, keyid 12199, for example.jp.
; Created: 20101027123754 (Wed Oct 27 21:37:54 2010)
; Publish: 20101027123754 (Wed Oct 27 21:37:54 2010)
; Activate: 20101027123754 (Wed Oct 27 21:37:54 2010)
; Inactive: 20101028123754 (Thu Oct 28 21:37:54 2010)
; Delete: 20101029123754 (Fri Oct 29 21:37:54 2010)
example.jp. IN DNSKEY 257 3 8 ...
$


次に、ZSK。2つ作ります。

今すぐゾーンに公開され署名に使用され、3 時間後署名に使用されなくなり、4 時間後ゾーンから消えるものと、1 時間後ゾーンに公開され、2 時間後署名に使用され、5 時間後署名に使用されなくなり、6 時間後ゾーンから消えるものを。

$ /usr/sbin/dnssec-keygen -r /dev/urandom -3 -a RSASHA256 \
 -b 1024 -I +10800 -D +14400 -n ZONE example.jp
Generating key pair...++++++ ..............++++++
Kexample.jp.+008+59595
$ cat Kexample.jp.+008+59595.key
; This is a zone-signing key, keyid 59595, for example.jp.
; Created: 20101027124257 (Wed Oct 27 21:42:57 2010)
; Publish: 20101027124257 (Wed Oct 27 21:42:57 2010)
; Activate: 20101027124257 (Wed Oct 27 21:42:57 2010)
; Inactive: 20101027154257 (Thu Oct 28 00:42:57 2010)
; Delete: 20101027164257 (Thu Oct 28 01:42:57 2010)
example.jp. IN DNSKEY 256 3 8 ...
$ /usr/sbin/dnssec-keygen -r /dev/urandom -3 -a RSASHA256 \
 -b 1024 -P +3600 -A +7200 -I +18000 -D +21600 -n ZONE example.jp
Generating key pair..........++++++ ..............++++++
Kexample.jp.+008+58539
$ cat Kexample.jp.+008+58539.key
; This is a zone-signing key, keyid 58539, for example.jp.
; Created: 20101027124555 (Wed Oct 27 21:45:55 2010)
; Publish: 20101027134555 (Wed Oct 27 22:45:55 2010)
; Activate: 20101027144555 (Wed Oct 27 23:45:55 2010)
; Inactive: 20101027174555 (Thu Oct 28 02:45:55 2010)
; Delete: 20101027184555 (Thu Oct 28 03:45:55 2010)
example.jp. IN DNSKEY 256 3 8 ...
$


ちなみに、metadataの20101027124555みたいな日時はUTCなもの、Wed Oct 27 21:45:55 2010みたいなのはJSTです。そして、テスト用に簡単なexample.jp.ゾーンファイルを作成。

$ cd ../../dynamic
$ cat > example.jp.zone.signed
$ORIGIN example.jp.
$TTL 3600
@       IN      SOA     localhost.example.jp.  hostmaster.example.jp.    (
                                2010102701      ; Serial
                                10800           ; Refresh
                                1200            ; Retry
                                604800          ; Expire
                                1200    )       ; Minimum TTL

                        IN      NS      localhost.example.jp.
                0       IN      NSEC3PARAM 1 0 10 1234ab
localhost               IN      A       127.0.0.1
$


まあ、かなり適当です。

次に、named.conf(5)optionsview

dnssec-enable yes;


を足して、zoneを以下のように追加します。

zone "example.jp." {
	type master;
	file "dynamic/example.jp.zone.signed";
	key-directory "/var/named/keys/example.jp";
	update-policy local;
	auto-dnssec maintain;
};


尚、お試しならばzonednssec-secure-to-insecure yes;を足しておいた方が幸せかもしれません。ちなみに、update-policy local;ですが、名前からするとDynamic DNSなupdateをローカルに限定してくれそうですが、ARMによると、

update-policy { grant local-ddns zonesub any; };


と完全に等価ですので、例えば、

view "world" {
        match-clients { any; };
        match-destinations { 外側のインターフェースのIPアドレス; };
        ...
};


みたいなviewに追加した場合、デフォルトのTSIG session keyを他のホストにコピーすればリモートからもupdateがかけられます。尚、デフォルトのTSIG session keyの場所や名前も変えられるようで、options

session-keyfile "/var/run/named/session.key";
session-keyname "local-ddns";
session-keyalg "hmac-sha256";


とか記述すればできます。ちなみに、上記はデフォルト値です。

これで、準備ができたので、reloadしてloadkeysします(*1)

# rndc reload
# rndc loadkeys example.jp.


これで、Kexample.jp.+008+12199とKexample.jp.+008+59595が署名に使用され、Wed Oct 27 22:45:55 JST 2010 を過ぎればKexample.jp.+008+58539がゾーンに公開され、Thu Oct 28 00:42:57 JST 2010を過ぎればKexample.jp.+008+59595が署名に使われなくなったりしてくれます(*2)

ゾーンへの RR の追加などは、nsupdate(1)で行います。ローカルから更新できるview内にあるのであれば、

# nsupdate -l


なんぞで、そうでなければ、

# nsupdate -k /var/run/named/session.key


とかして、serverを指定するなりすれば更新できます。別解としては、

# rndc freeze example.jp.


して、/var/named/chroot/var/named/dynamic/example.jp.zone.signedをエディタで編集し、SOA RRのシリアルを上げて、

# rndc thaw example.jp.


する手もあります。ちなみに、鍵に timing metadata が付いていて、ちゃんとkey-directoryが指定されていれば、auto-dnssec off;でもnsupdate(1)等で更新すれば適切に署名してくれます。

ただ、key-directoryを指定せずデフォルト以外の場所に鍵を置いていたりすると、署名の有効期限が近づいたときに、named(8)が勝手に署名の更新をかけようとして鍵が見つからないので、署名の除去をしたりするのはなんだかなといった感じ。DNSSECなゾーンはDynamic DNSが使えるように設定しとかないと面倒な状態になるみたいですね。auto-dnssec off;なら署名の期限切れなんて自己責任にしてくれてもいいんじゃないかなと。設定であるのかな。取り敢えず、rndc freezeしとけば、そういう更新は起こりませんけど、なんか使い方が違う気がしますし。

ま、取り敢えず、これで上位へのDSやDLVの登録なんかを除けば、鍵を作り足し忘れない限り、大丈夫そうな状態が作れる感じ。適切なoffset値でdnssec-keygen(8)にtiming optionを指定してcron(8)あたりで呼べば、作成もなんとかなるのかも。




*1: rndc loadkeysに関する記述を追加(Nov 09, 2010)。まあ、reloadしてるんで問題ないんですけど、鍵追加したときにはloadkeysしようねという意味で。
*2: うまく動作しない場合もあるみたいです(Nov 09, 2010)。
nice!(0)  コメント(0)  トラックバック(4) 
共通テーマ:日記・雑感

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。