2013/12/10

redmineのREST APIを利用してwikiページを作成するときのメモ

普段PUTリクエストなんて使わないのでよくわかりませんでした。
いろいろ試行錯誤したので、取り急ぎメモだけ。

#!/usr/bin/ruby

require 'net/http'
require 'uri'

api_key = 'fxcxaxfxcx9x2x4xdxdx1x8x3xbxbxdx4x4x1xfx0x2x3'
redmine_base = 'http://127.0.0.1:3000'
project_identifier = 'tteesstt'
wiki_title = 'testpage2'
request_path = '/projects/' + project_identifier + '/wiki/' + wiki_title +'.xml'
wiki_body  = ''
wiki_body << ''
wiki_body << ''
wiki_body << 'hogefuga'
wiki_body << 'ahhahha'
wiki_body << ''

url = URI.parse(redmine_base + request_path)
req = Net::HTTP::Put.new(url.path)
req['Content-Type'] = 'text/xml'
req['X-Redmine-Api-Key'] = api_key
req.body = wiki_body

res = Net::HTTP.start(url.host, url.port){ |http| http.request(req) }
p res.body

2013/10/09

z-pushとの闘い

まずは何も考えずダウンロードしてみる。

http://z-push.sourceforge.net/soswp/

# tar xzf z-push-2.1.0-1750.tar.gz
# cd z-push-2.1.0-1750
# ls
INSTALL  LICENSE  backend  config.php  include  index.php  lib  tools  version.php  z-push-admin.php  z-push-top.php

とりあえずINSTALLを読む。

サーバ要件:PHP5.1以上

ということは、PHP5.1とapacheの環境があればよいということか。

まずはDNS名(app.example.net)を用意する。

続いて鍵+証明書を作り、これをSSLサイトに食わせておく。

# openssl req -x509 -days 365 -newkey rsa:2048 -nodes -keyout app.example.net.key -out app.example.net.crt

インストールは書いてある通りにやってみよう。prefixは/usr/localにしてみる。
# sudo tar xzf z-push-2.1.0-1750.tar.gz -C /usr/local/share
# mkdir /var/lib/z-push /var/log/z-push
# chown apache:apache /var/lib/z-push /var/log/z-push
# vi /etc/httpd/conf.d/ssl.conf
# httpd -t
# service httpd reload

--- /etc/httpd/conf.d/ssl.conf      (before)
+++ /etc/httpd/conf.d/ssl.conf      (after)
@@ -81,5 +81,14 @@
        AllowOverride   all
   </Directory>

+
+       Alias /Microsoft-Server-ActiveSync /usr/local/share/z-push/index.php
+  <directory /usr/local/share/z-push>
+       php_flag magic_quotes_gpc off
+       php_flag register_globals off
+       php_flag magic_quotes_runtime off
+       php_flag short_open_tag on
+  </Directory>
+
  </VirtualHost>
 </IfModule>
というわけで、予想通りはまる。
なんか言ってる。
PHP-MAPI extension is not available

調べてみたところ、一部のパッケージが足りていなかったもよう。
# yum install php-imap php-soap php-process

と思ったら、php-processはPHP5.3のパッケージなのね。
あきらめて、php-*系のパッケージを全部捨てて、php53-*をインストール。

# rpm -e php php-たくさん
# yum install php-process php

やってみたがまだ動かぬ。
php-mapiってどこにあるんだよ!!
とりあえず「php-mapi rpm」で適当に探してくる。

.....fedoraprojectに落ちてたぽい。

# rpm -ivh php53-mapi-7.0.13-1.el5.i386.rpm
エラー: 依存性の欠如:
libicudata.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libicui18n.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libicuuc.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libinetmapi.so.1 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libmapi.so.0 は php53-mapi-7.0.13-1.el5.i386 に必要とされています

ぬおー。片っ端から探していれちまえ。
# rpm -ivh libmapi-7.0.13-1.el5.i386.rpm php53-mapi-7.0.13-1.el5.i386.rpm
エラー: 依存性の欠如:
libboost_filesystem-mt.so.5 は libmapi-7.0.13-1.el5.i386 に必要とされています
libboost_system-mt.so.5 は libmapi-7.0.13-1.el5.i386 に必要とされています
libical.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
libicalss.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
libvmime.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
zarafa-client = 7.0.13-1.el5 は libmapi-7.0.13-1.el5.i386 に必要とされています

えー。zarafa-clientが出てきたってことは、結局zarafaから落とした方がいいの?
でもさっきからEPELのパッケージ使ってるし….よし、ポリシーを緩めてEPEL解禁!
# rpm -ivh epel-release-5-4.noarch.rpm
# yum install php53-mapi
Dependencies Resolved
========================================================================================================================
Package                           Arch               Version                                  Repository          Size
========================================================================================================================
Installing:
php53-mapi                        i386               7.0.13-1.el5                             epel               217 k
Installing for dependencies:
boost141-filesystem               i386               1.41.0-4.el5                             epel                73 k
boost141-system                   i386               1.41.0-4.el5                             epel                25 k
libgsasl                          i386               0.2.29-1.el5                             epel               100 k
libical                           i386               0.48-1.el5                               epel               202 k
libmapi                           i386               7.0.13-1.el5                             epel               904 k
libntlm                           i386               1.0-1.el5                                epel                43 k
libvmime                          i386               0.9.2-0.1.20110626svn.el5                epel               887 k
zarafa-client                     i386               7.0.13-1.el5                             epel               1.3 M
zarafa-common                     i386               7.0.13-1.el5                             epel                22 k
Transaction Summary
========================================================================================================================
Install      10 Package(s)
Upgrade       0 Package(s)
Total download size: 3.7 M

Is this ok [y/N]: 

まぢで?そういうオチ?
とりあえず入れてみる…..入った。
気を取り直してapacheリロード。
# httpd -t
Syntax OK
# service httpd reload

とりあえず500はなくなった。

続いて、config.phpをいじって、imapバックエンドを使うように変更。
--- /usr/local/share/z-push/config.php     (before)
+++ /usr/local/share/z-push/config.php     (after)
@@ -45,7 +45,7 @@
*  Default settings
*/
// Defines the default time zone, change e.g. to "Europe/London" if necessary
-    define('TIMEZONE', '');
+    define('TIMEZONE', 'Asia/Tokyo');
// Defines the base path on the server
define('BASE_PATH', dirname($_SERVER['SCRIPT_FILENAME']). '/');
@@ -90,7 +90,7 @@
define('LOGFILE', LOGFILEDIR . 'z-push.log');
define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
define('LOGLEVEL', LOGLEVEL_INFO);
-    define('LOGAUTHFAIL', false);
+    define('LOGAUTHFAIL', true);


// To save e.g. WBXML data only for selected users, add the usernames to the array
@@ -185,7 +185,7 @@
*  Backend settings
*/
// the backend data provider
-    define('BACKEND_PROVIDER', '');
+    define('BACKEND_PROVIDER', 'BackendIMAP');

/**********************************************************************************
*  Search provider settings

んで、imap側のconfig.phpもいじる。
--- /usr/local/share/z-push/backend/imap/config.php     (before)
+++ /usr/local/share/z-push/backend/imap/config.php     (after)
@@ -46,13 +46,13 @@
// ************************

// Defines the server to which we want to connect
-define('IMAP_SERVER', 'localhost');
+define('IMAP_SERVER', '127.0.0.1');
// connecting to default port (143)
-define('IMAP_PORT', 143);
+define('IMAP_PORT', 993);
// best cross-platform compatibility (see http://php.net/imap_open for options)
-define('IMAP_OPTIONS', '/notls/norsh');
+define('IMAP_OPTIONS', '/tls/norsh');

// overwrite the "from" header if it isn't set when sending emails
// options: 'username'    - the username will be set (usefull if your login is equal to your emailaddress)

で、iPhone側でExchangeアカウントをセット。
やってみるが"Connection Serfer Failed."などと言って一歩も動かない。
アカウント追加時の認証チェックは通っていたぽいので、パスワード周りは間違っていないはず。。。

しかし動かず。
とりあえず、いろんなところのデバッグフラグをONにしてみる。

--- /usr/local/share/z-push/config.php (before)
+++ /usr/local/share/z-push/config.php (after)
@@ -89,7 +89,7 @@
     define('LOGFILEDIR', '/var/log/z-push/');
     define('LOGFILE', LOGFILEDIR . 'z-push.log');
     define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
-    define('LOGLEVEL', LOGLEVEL_INFO);
+    define('LOGLEVEL', LOGLEVEL_DEBUG);
     define('LOGAUTHFAIL', true);

--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh');
+define('IMAP_OPTIONS', '/tls/norsh/debug');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is
equal to your emailaddress)

しかしまだ動かない。
webでアクセスしてみても、しばらく待ってから再度認証を求められ、その直前に下記のようなログが出る。
/usr/local/share/z-push-2.1.0-1750/backend/imap/imap.php:99 imap_open(): Couldn't open stream {127.0.0.1:993/imap/tls/norsh/debug} (2)

気づいた。オレオレ証明書じゃん。
というわけで、接続オプションを変更。
--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh/debug');
+define('IMAP_OPTIONS', '/tls/norsh/novalidate-cert');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is
equal to your emailaddress)
まだ動かない。
imap_open()でコケると言っているが、dovecotのログがぜんぜんにぎやかじゃない。どーゆーことだ???
ということは、認証かセッション確立でこけてると予想。
imap_open()を使って直接たたいてみる。

imap_open("{127.0.0.1/tls/norsh/novalidate-cert}INBOX", $username, $password);


しっかり60秒待ってからエラーが表示された。
うーん、セッション確立の影響だなぁ。

で、下記のように変えてみた。
--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh/novalidate-cert');
+define('IMAP_OPTIONS', '/ssl/norsh/novalidate-cert');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is equal to your emailaddress)

StartTLSによるSSL確立ではなく、最初からSSLで突っ込むようにしてみた。
お!動いた!!



というわけで、今回の反省。
いろんな環境を整理して調査にあたる必要がありますね。
  • imapのSSL状態。 どっちが直接の原因となるかは分からないけど、iPhoneでUse SSLを有効にしてるため、もしくはdovecot.confで「protocols=imaps」としているため、のいずれかもしくは両方の理由により、imap_open()のフラグに「/ssl」が必要。「/tls」ではだめ。
  • 証明書。 自前でやる場合はそんなにお金かけてられないので、往々にしてオレオレ証明書を利用することに。dovecotから見れば、z-pushは当然普通のクライアントなので、当然証明書はチェックされます。なので、人的介入無しに証明書エラーをくぐり抜ける必要があります。
  • ログはよく観察すること! いろんなログ(今回の場合はapache/dovecot/z-push)を見ましたが、特定のログだけを見ていても気づかないことが多いです。それぞれのコンポーネントがどのように連携しているのか?イベントが発生したタイミングで、どのログが流れてどのログが流れないのか?このあたりをちゃんと考慮してログを見ると、どこの部分でエラーが発生しているかのアタリがつけやすくなります。
というわけで、おしまいっ

2013/03/04

logwatchについてるpostfixのスクリプトをちょっと直してみた

logwatchでpostfixのログをパースさせてたんですが、最近Unmatched Entriesが増えてきたので、
Unmatchedを減らすべく、既存のフィルタを改造してみました。

対象にしたのはこれ。

# rpm -q logwatch
logwatch-7.3-9.el5_6

オリジナルを直接触るのは気が引けるので、ローカル用にコピーします。
# cp -p /usr/share/logwatch/scripts/services/postfix /etc/logwatch/scripts/services/
# vi /etc/logwatch/scripts/services/postfix

というわけで、オリジナル版のフィルタとdiffを取ってみました。

# diff -u /usr/share/logwatch/scripts/services/postfix /etc/logwatch/scripts/services/postfix
--- /usr/share/logwatch/scripts/services/postfix     2011-03-31 06:57:37.000000000 +0900
+++ /etc/logwatch/scripts/services/postfix     2013-03-02 10:37:16.000000000 +0900
@@ -224,7 +224,7 @@
    } elsif (($User) = ($ThisLine =~ /^[a-zA-Z0-9]+: to=\<([^ ]*)>,(?: orig_to=\<(?:[^ ]*)>,)? .*, status=bounced .*: User unknown in virtual (alias|mailbox) table/)) {
       # another unknown user probably could combine with local unknown but again my perl is weak
       $UnknownUsers{$User}++;
-   } elsif (($Dest, $Relay, $Msg) = ($ThisLine =~ /^[a-zA-Z0-9]+: to=\<([^ ]*)>,(?: orig_to=\<(?:[^ ]*)>,)? relay=([^ ]*).*, delay=-?[0-9]+, status=bounced \(([^)]*)/ )) {
+   } elsif (($Dest, $Relay, $Msg) = ($ThisLine =~ /^[a-zA-Z0-9]+: to=\<([^ ]*)>,(?: orig_to=\<(?:[^ ]*)>,)? relay=([^ ]*).*, delay=[^ ]*,(?: delays=[^ ]*,)?(?: dsn=[^ ]*,)? status=bounced \(([^)]*)/ )) {
       # unknown user
       # $Msg = " hello "
       # print "bounce message from " . $Dest . " msg : " . $Relay . "\n";
@@ -394,6 +394,10 @@
       $UnknownWarnings{$Warn}++;
    } elsif (($Host,$Filter) = ($ThisLine =~ /RCPT from ([^ ]*\[[^ ]*\]): <[^ ]*\[[^ ]*\]>: Client host triggers FILTER (\S*)/)) {
       $HostTrigFilter{"$Host,$Filter"}++;
+   } elsif ( ($Server, $Helo) = ($ThisLine =~ /^NOQUEUE: reject: RCPT from ([^ ]*\[[^ ]*\]): 450 4.7.1 Client host rejected: cannot find your hostname, [^ ]*; from=<[^ ]*> to=<[^ ]*> proto=[^ ]* helo=<([^ ]*)>$/)) {
+      $InvalidClientHostName{"$Server"}++;
+   } elsif ( ($Server, $Helo) = ($ThisLine =~ /^NOQUEUE: reject: RCPT from ([^ ]*\[[^ ]*\]): 504 5.5.2 <[^ ]*>: Helo command rejected: need fully-qualified hostname; from=<[^ ]*> to=<[^ ]*> proto=[^ ]* helo=<([^ ]*)>$/)) {
+      $InvalidHeloName{"RCPT from $Server: HELO=$Helo"}++;
    } else {
       push @OtherList,$ThisLine;
    }
@@ -691,6 +695,40 @@
    }
 }

+if (keys %InvalidClientHostName) {
+   if($Detail >= 5) {
+      print "\n\nInvalid client hostname:\n";
+      foreach $Message (sort {$a cmp $b} keys %InvalidClientHostName) {
+         print "   $Message: $InvalidClientHostName{$Message} Time(s)\n";
+      }
+   }
+   else {
+      $n=0;
+      $mn=scalar(keys %InvalidClientHostName);
+      foreach $Message (keys %InvalidClientHostName) {
+         $n+=$InvalidClientHostName{$Message};
+      }
+      print "\n\nInvalid client hostname:\n: $mn Message(s), $n Time(s)";
+   }
+}
+
+if (keys %InvalidHeloName) {
+   if($Detail >= 5) {
+      print "\n\nInvalid HELO command:\n";
+      foreach $Message (sort {$a cmp $b} keys %InvalidHeloName) {
+         print "   $Message: $InvalidHeloName{$Message} Time(s)\n";
+      }
+   }
+   else {
+      $n=0;
+      $mn=scalar(keys %InvalidHeloName);
+      foreach $Message (keys %InvalidHeloName) {
+         $n+=$InvalidHeloName{$Message};
+      }
+      print "\n\nInvalid HELO command:\n: $mn Message(s), $n Time(s)";
+   }
+}
+
 if (keys %LocalBounce) {
    if ($Detail >= 5) {
       print "\n\nLocal Bounce:\n";

各chunkのコメントです。
1つめ
bounceした記録の書式が多少変わっていたので、オリジナルの機能を失わないように正規表現を書き足してみました。
2つめ
postfixで下記の設定をした時に出るエラーに対応してみました。
  smtpd_client_restrictions = reject_unknown_client
  smtpd_helo_restrictions = reject_non_fqdn_hostname
3つめ
2つめでマッチしたログの出力部分です。

/etc/logwatch配下に置いたスクリプトは標準のスクリプトに優先して使われるようで、
期待通りの動作となりました。