2005年04月07日

鍵用途

拡張領域で、鍵用途関連のパラメタをどう定義するかを決定した。
extendedKeyUsageにcriticalを設定していないが、
これは設定してもいいかもしれない。
EEsignは、署名用、EEauthは、SSLのクライアント認証用という位置付け。
RAAAは、EEauthと同様とする。

[EEsign]
keyUsage = critical,digitalSignature,nonRepudiation,keyEncipherment,keyAgreement
extendedKeyUsage = codeSigning,emailProtection
basicConstraints = critical,CA:false

[EEauth]
keyUsage = critical,digitalSignature,keyEncipherment,keyAgreement
extendedKeyUsage = clientAuth
basicConstraints = critical,CA:false

[Server]
keyUsage = critical,digitalSignature,keyEncipherment,keyAgreement
extendedKeyUsage = serverAuth
basicConstraints = critical,CA:false

[CA]
keyUsage = critical,cRLSign,keyCertSign
extendedKeyUsage = serverAuth,timeStamping
basicConstraints = critical,CA:true,pathlen:2

Posted by fujino at 17:30 | Comments (0) | TrackBack

2005年04月03日

SOAPで呼び出される各サーバープロセスのメソッド名

●EEserver
○ees_set_access_info(session_id,access_key_hash,email,kanji_name,romaji_name)
 1.RAserverのCGIよりセッション情報を受け取る。
 2.EEに証明書発行手続きのメールを送信する。

※SMTPエラーについて
存在しないメールアドレスを書いた時に、通信エラーと出てしまう。

・ees_issue_p12(p12_password,session_id,access_key)
 1.EEserverのCGIよりリクエストを受け取る。
 2.RAserverのras_issue_p12を呼び出す。
 3.2が失敗したらリトライ。

●RAserver
○ras_issue_p12(p12_password,session_id)
 1.EEserverのサーバープロセスより証明書発行のリクエストを受け取る。
 2.セッション管理ファイルより証明書情報を読み出す。
 3.IAサーバのias_issue_p12を呼び出し、証明書発行のリクエストを送信する。
 4.IAサーバからPKCS12と証明書を受け取る。
 5.LDAPに証明書を登録する。

●IAserver
○ias_issue_p12(p12_password,key_length,o,ou,cn,emailAddress,issuerAltName,friendy_name)
 1.RAserverより証明書発行のリクエストを受けとる。
 2.証明書を発行してRAserverに返す。

Posted by tashiro at 22:00 | Comments (6) | TrackBack

Net::SMTPのエラー

メールを送るときに、メールアドレスが存在しない場合、なぜか、

  Net::SMTPServerBusy
450: Recipient address rejected:...
というようなエラーが出る。要するに、そんなユーザ知らんよ、とSMTPサーバが言っている訳だが、Ruby的に返されるクラスはNet::SMTPServerBusy。ま、いいんだけどね…

Posted by fujino at 16:23 | Comments (0) | TrackBack

SOAP&Rubyでのエラー処理

Ruby上のSOAPの場合、サーバ上のエラーをクライアント側でどのように検知するか、と言う話。簡単に言うと
  • raiseされる例外クラスが、サーバとクライアントで共に定義されている場合:クライアントでもその例外クラスをrescueすることができる
  • そうでない場合:クライアント側ではRunTimeErrorとして扱われる
ということだ。では、例題プログラムで確認しよう。まず、サーバ側:

#!/usr/bin/env ruby
require 'webrick'
require 'soap/rpc/httpserver'
require 'soap/rpc/driver'

class MyError < StandardError; end

class RAServer < SOAP::RPC::HTTPServer
  def on_init
   @log.level = Logger::Severity::DEBUG
   add_method(self,'myerror')
  end

  def myerror
    raise MyError,"This is an error."
    return 0
  end
end

server = RAServer::new(
                       :SOAPHTTPServerApplicationName => "myerror",
                       :SOAPDefaultNamespace => "http://localhost/soap/",
                       :BindAddress => "0.0.0.0",
                       :Port => 1969,
                       :AccessLog => []
                       )


trap(:INT) do
  server.shutdown
end

server.start
要するに、独自に定義したMyErrorをraiseするサービスだ。次にクライアント側:
#!/usr/bin/env ruby
require 'webrick'
require 'soap/rpc/httpserver'
require 'soap/rpc/driver'

class MyError < StandardError; end

s = SOAP::RPC::Driver::new("http://localhost:1969/","http://localhost/soap/")
s.add_method("myerror")
s.wiredump_file_base = "myerror"
s.options["protcol.http.receive_timeout"]=300

ret = s.myerror
では実行してみよう。まずサーバ側を実行すると、正しく起動される。続いてクライアント側を実行する。
fujino@chimera{~/Works/MyError}$ ./error-client.rb
./error-server.rb:15:in `myerror': This is an error. (MyError)
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/router.rb:259:in `call'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/router.rb:259:in `rpc_call'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/router.rb:240:in `call'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/router.rb:86:in `route'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/soaplet.rb:108:in `do_POST'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/soaplet.rb:103:in `with_headerhandler'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/soaplet.rb:103:in `do_POST'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/webrick/httpservlet/abstract.rb:35:in `__send__'
         ... 15 levels...
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/driver.rb:275:in `call'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/driver.rb:302:in `myerror'
        from /CACAnet/app/ruby-1.8.2/lib/ruby/1.8/soap/rpc/driver.rb:297:in `myerror'
        from ./error-client.rb:13
fujino@chimera{~/Works/MyError}$
というわけで、クライアント側でもMyErrorが定義してあるので、MyErrorをrescueできている。
Posted by fujino at 14:54 | Comments (0) | TrackBack

2005年04月02日

非同期、と思ったけど

実装するのは結構大変だ、と言うが前のエントリの考察で判明した。
そもそも論にまで立ち戻って考えてみて、もっとも大きな問題は、EEに対するウェブの応答時間が長くなることだ。であれば、そこだけを非同期にすればよいのではないか、という議論になった。
すなわち、EEからのウェブアクセスに対しては、「発行要求を受付けました」と即時応答し、別のプロセスがRAserverに対してPKCS#12発行を要求する。ここから先は、上り(req)下り(resp)別の非同期方式ではなく、同期方式で行く。ユーザへの応答時間は気にする必要はないので、何十秒かかっても構わない。タイムアウトすれば、しばらく待ってリトライしてもいいのではないか。

Posted by fujino at 17:57 | Comments (0) | TrackBack

非同期サービスとサービス命名規則

現状のシステムは、同期サービスで実現されている。この方式だと、各サーバ間の通信の途中、サーバの負荷が高い場合等に処理を保留された場合に問題が発生する。例えば、EEからのHTTPリクエストがタイムアウトしてしまう等だ。
この問題を解決するために、非同期サービスで実装する。つまり、今まで一つのSOAPメソッドであったものを、
- サーバ上の要求(req)用のメソッドと、
- 応答受付(resp)用のメソッド
の二つに分ける。

サービス名の命名だが、これはシステム全体で一意になった方が良かろう、ということで、命名規則を作った。
[サーバ名]_[サービス名]_[方向]
ここで言う方向とは、上で述べたreqおよびrespのことである。
サーバ名を付けるのは例えば、PKCS#12ファイルの発行を要求するメソッド(issue_p12)は、RAserverにもCAにも存在する。何故なら、EEからのPKCS#12発行要求は、EEserverで受付けられ、これがSOAPでRAserverに送られ、RAserverからCAへSOAPで送られるためだ。

この方式を採用すると、サーバからクライアントへの通信(resp)のあて先がどこになるのかを、サーバが知る必要がある。これに関しては、
- SOAPの通信元IPを何らかの方法で知る
- クライアントからサーバへの通信(req)のパラメータに埋め込む
の二つが考えられる。前者が自然だが、SOAPの下位層をIPに固定したり、ポート番号を固定することになる。後者は面倒ではあるが柔軟であるので、後者で実装する。
後者でクライアントからサーバへ渡すべき情報は、URIのみになる。SOAPのRPC呼び出しには、URIの他にメソッド名が必要になるが、これは上の命名規則で決まっているので、渡さなくても問題はない。

書くのを忘れていたが、この非同期方式を採用すると、上り(req)下り(resp)の通信が一対であることを確認するため、セッションIDつける必要がある。

Posted by fujino at 16:03 | Comments (0) | TrackBack