OAuth 2.0のRWSとかOWSとかって何?

今OAuth 2.0のDraft 08を読んでいる。
http://tools.ietf.org/html/draft-ietf-oauth-v2-08

んで、途中で以下のような記述があってなんのこっちゃと思ったのが1時間前。

  • RWS
  • OWS
  • #

んで、先ほど、冒頭の以下記述から答えがわかった次第。

This document uses the Augmented Backus-Naur Form (ABNF) notation of
[I-D.ietf-httpbis-p1-messaging]. Additionally, the realm and auth-
param rules are included from [RFC2617].

要は、以下が答えだったということで、メモです。
http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-09

  • RWS = Required White Space
  • OWS = Optional White Space
  • # = 以下

A construct "#" is defined, similar to "*", for defining comma-
delimited lists of elements. The full form is "#element"
indicating at least and at most elements, each separated by a
single comma (",") and optional whitespace (OWS, Section 1.2.2).

(思索)RESTでID変更

/{collection} 
/{collection}/{id} 

といったパスで参照可能なRESTfulなリソース群があったとしよう。
さて、ここであるリソース、例えば/books/123のIDを456に変えたいとしたら、どうするのが美しいのか?

  1. PUTでやる
  2. リソースを消して創りなおす。

いまさらだが、今、こういう問題に直面して明確な答えが自分の中にないことに気付いた。

前者は、即ち例えば、/books/123 に対して {"id":"456, "foo":"bar"} などといったBODYでPUTリクエストを出すということで、その結果/books/123は参照不可能となり/books/456という新しいリソースができるということだ。これはさすがにRESTfulじゃない気がする。そもそもこの処理に対するレスポンスコードは201か?新しいリソースのURLはLocationヘッダで送るのか? なんて考えるとますますあやしい。。。ような気もしつつ、それはまだましだけど、やっぱり/books/123にPUTしたのに/books/123が消えるというのが最悪な感じ。

ということで、ID変更はリソースを消して創りなおすべし! というのを私の答えとしたいと思う。

導き出されること

では、IDを変更しろという内容のPUTリクエストを受け付けたらどうすべきか。
エラーを返すか、無視すべきということとなる。
たしかに実際、CouchDBでGETで返ってきたデータの"_id"を変更してPUTするとすんなり無視される。なるほど。

無視がいいかというと、できればエラーを返してあげるほうが正しい気がする。ではどんなステータスコードがいいか。409あたりかな?

ActionScript3のthis について。

ActionScript3のthis について少し迷った。これまでは、なんとなく以下のように感じながら、明確な理解をせずになんとかなっていた。

    • JavaScriptのthisとは違うなぁ。ちゃんとオブジェクト見続けている感じ。
    • その意味でJavaのthisとだいたい似てるけど、でも無名関数の中で使うときだけJavaScriptっぽい動きをするなぁ。

今回、ちょっと複雑なコードを書くようになり、ちゃんと理解しないといけない羽目になった。


http://livedocs.adobe.com/flex/3/html/help.html?content=03_Language_and_Syntax_21.html

The value of the this reference within the body of an instance method is a reference to the instance to which the method is attached.

A bound method, sometimes called a method closure, is simply a method that is extracted from its instance. Examples of bound methods include methods that are passed as arguments to a function or returned as values from a function. New in ActionScript 3.0, a bound method is similar to a function closure in that it retains its lexical environment even when extracted from its instance. The key difference, however, between a bound method and a function closure is that the this reference for a bound method remains linked, or bound, to the instance that implements the method. In other words, the this reference in a bound method always points to the original object that implemented the method. For function closures, the this reference is generic, which means that it points to whatever object the function is associated with at the time it is invoked.

    • クラス定義の中でメソッドとして書いた関数を取り出すと、Bound Methodとなって関数クロージャと同様にもとのインスタンスの環境を引き継ぐ。
    • 関数クロージャでは、thisキーワードが指すものは関数が実行されるcontextによって変化するが、
    • Bound Methodでは、thisキーワードが指すものは、メソッドが属するインスタンスであり続ける。

とのこと。すなわち:

    • メソッドの中のthisと非メソッド関数の中のthisは結構違う。
    • メソッドの中のthisはインスタンスを指し続けるが、
    • 非メソッド関数の中のthisはJavaScript的に何を指すかが走行環境によって決まる。

ということらしい。なるほどねぇーー^^ 最初に書いた「いい加減な理解」もまんざら間違ってなかったということか。

OAuthWRAPとSimple Web Token

OAuthWRAPを調べてるんだけど、SWT(Simple Web Token) とか JWT (JSON Web Token)という言葉がたくさん出てくる。まあ、名前やらサンプルやらからどんな仕様なのかだいたいは想像がつくんだけど、ちゃんとした仕様がなかなかみつからなかったので、見つけたリンクを以下に置いてみた。

http://groups.google.com/group/oauth-wrap-wg/files
http://oauth-wrap-wg.googlegroups.com/web/SWT-v0.9.5.1.pdf

ようするにHTTPのクエリパラメタみたいなフォーマットなんだけど、一つだけ署名用のHMACSHA256という必須項目がある。即ち、署名方式も仕様に含まれているということ。ただクエリパラメタ風にオブジェクトを書き下すことをSWTと呼ぶのかなと誤解してた。

というわけで、非対照暗号を使った署名は前提から外れてしまっているので、その点きをつけなくてはならない。
http://www.leastprivilege.com/IntegratingSimpleWebTokensSWTWithWCFRESTServicesUsingWIF.aspx

The downsides are - it is not a widely adopted token format (current spec version is 0.9.5.1) and the lack of asymmetric signatures (e.g. X.509 based). 

しかし、OAuthWRAPは(SWTを使うと楽ちんだよとはいっているが)Tokenのフォーマットは定めていないので、OAuthWRAPで非対照暗号を使った署名を使ったTokenのやりとりができないということにはならない。

セマンティックWebコンファレンス2010

セマンティックWebコンファレンス2010というイベントに行ってきた。自分にとって、セマンティックWebというと「RDFやOWLやSPARQLでオントロジーなのね。夢があっていいねぇ。」ということと、「Webっていいながら、実践になったとたん1個のサーバ上に閉じたマニアックな検索ができてるだけじゃん」といった具合の認識しかなかったわけだが、「Linked Open Data」(LOD)というテーマが、実はまさに自分がやりたい世界なのでは?ということで興味を持って参加した。実際、LODは僕が進みたい世界に非常に近かったので「よいラベル」と「そこに向かうコミュニティ」を見つけたという意味で大収穫だったといえる。

まず最初に国立情報学研究所の武田教授という人が最初の基調講演でぐっと盛り上げてくれた。Linked Open Dataというのは、SemWebの世界でのオントロジー構築云々概念的に高い部分はとりあえず置いておいて、世の中にバラバラにそろいつつある具体的なWebAPI群をつないで云々しようという本当のWeb志向の動きのことだそうだ。数年前にSemantic Webの世界はRDFやRDFS, OWLときれいに下から上へ技術スタックを構築したわけだが、みんながOWLやらオントロジーやら観念的な上位層にフォーカスしがちだった。おそらく、だから「一台のサーバでマニアックな役に立たない検索をやって喜んでいるだけ」と世の中(僕含めて)に見られてしまってきたのだろうが、その反省に立って一番下の「インスタンス」を「リンクする」という部分をもう一回ちゃんとやってみよう流れがLODなのだという風に見えた。実際のところ、以下サイトが2−3年前に出現したのがきっかけでその周りに色々なマシンリーダブルな「リンクされたインスタンスエコシステム」が英語圏で形成されてつつあることを指して、LODといっているらしい。

http://dbpedia.org/About

ちなにに、これを企業内でやる人がでてくれば、Linked Open Data(開かれたもの)ではなく Linked Closed DataとかLinked Enterprise Dataというのも考えられるので、技術としてはLinked Dataと呼んだほうが一般化されてていいのかな?

武田教授は最後のパネルディスカッションでもいいことをいっていた。ええと、表現はちょっとちがったけど、以下のようなこと。

LODはプログラムにとっての常識になる。
LODを参照しないプログラムは常識のないプログラムであり、
LODに情報提供しない企業や製品は機械の「常識」の中にいれてもらえなくなる。

自分はずっと、LOD的なもの(LODという言葉は知らなかったけど)をやりましょうと会社の中でいろんな人に話をしてきたんだけど、

    • で、何がどう儲かるの?
    • ウチの会社にとって何がうれしいの?
    • 社会にとっても何がうれしいの?
    • アプリの作り方が変わるわけ?

とか色々言われて、あまりうまく回答できずにここ1年苦しんできた。だから、LODというムーブメントが盛り上がってきたのは非常にうれしくて、これからはマシな回答ができるようになると思うし、正直なところ個人的には「LOD万歳! LODやるぞ〜」モードになったといってもいい。

まだ、彼らのいうLODを良く理解はできていないが、

    • 僕はATOM/RESTのAPIが相互参照しあう形をもってLOD的な世界をイメージしているのに対し、
    • 彼らはRDFやOWLの世界を前提としながら、LODという言葉を作っている

というギャップが今気になっている。

RDFベースでrssがつくられ、その考え方を受けてAtomやAtomPubが生まれているので、それぞれのノードが提供するインターフェースがRDFだろうとAtomPubだろうと、本質的な違いは少ないと思いつつ、

    • Atomの世界は、その上にAtomPubやGData, ODataがあってデータの更新に強い。
    • RDFの世界は、その上にOWLやら推論やらSPARQLやらがあってなんだか色々できそうだけど、データ更新とかは弱そう。

という気がしている。おそらく両方必要なんだろう。
WebというものはStaticなのかDynamicなのかといえば、Dynamicであることは明らかなわけで、その意味でやっぱりAPIには更新系I/Fは必須だと思うし、作り上げられらLinked Dataを使って価値のある情報を引き出すためには推論やら何やらができたほうがいい。すると、両者のマッピングを考えることに意味がありそうだ。
 (SemWebの人からすると、Atomは「RSSもどき」としかとらえてくれないこともあると思うけど。最初は)

それと、エンティティとリレーション(Triple)をどこでどう持つのかという問題についても、それぞれの技術の生い立ちから来る文化的な差があると思っている。

とにかく、相手(SemWeb)を知らないと議論ができないので、会場で「実践Semantic Web」という本を買った。まずは読んで勉強してみたい。

自宅と実家をOpenVPNでつなぐ!

前回、自宅と実家をVPNでつなごうという計画の思いつきから、さまざまな失敗談を書いた。今回は、ちゃんとつながったということの報告と、設定メモについて記す。

ちなみに、自宅⇔実家間は車で1-2時間ほどかかる。我が家には(自宅・実家ともに)この手の設定をできる人間は自分しかいないので作業はなかなか面倒だった。リモートで作業できるようにするために、少なくとも一度実家に帰らなくてはならない。しかも、失敗したらもう一度帰らなくてはならない。VPN設定のためだけに妻と子供をほったらかして休日つぶして行き来するのもアレだし、実家に遊びに行くついでの作業としてやらなくてはいけないという制約もあり、なかなか緊張感のある作業だった。

計画

まずは何はともあれ計画である。前回のさまざまな試行錯誤の末に、「OpenVPNでつなごう」というところまでは決まった。それを前提としたもうちょっと詳細な計画である。

OpenVPNVPNを張る方法としてLayer2でやる方法(TAP)とLayer3でやる方法(TUN)がある。
今回、自分は自宅(横浜市戸塚区)と実家(東京都東久留米市)の2拠点を結んでDLNAで息子の写真を両親に見せることが主目的である。そのためDLNA的にブロードキャストが通らなくてはならないし、まあ、双方で使っている端末数なんてのも知れているため、Layer2の方法を選んだ。

IPアドレス割当計画

ブリッジ接続で同一ネットワークにするということで、以下のように設定することとした。実家、自宅のBuffaloルータにそれぞれ設定した。

192.168.1.1 - 10 自宅の固定IP機器群
192.168.1.11 - 20 実家の固定IP機器群
192.168.1.128 - 169 自宅のDHCP機器群
192.168.1.180 - 220 実家のDHCP機器群

OpenVPN接続計画

前述のとおり、実家側はBuffalo無線LANルータをDD-WRT化したので、これを使うことができる。自宅側もルータで設定できればいいのだが、DD-WRT化できないBuffaloルータを半年前に買ったばかりだったのでそれができない。しかし幸い自宅には24時間運用のLinuxサーバを立てているのでそこにOpenVPNを入れることとした。

OpenVPNは、クライアント・サーバで動くプログラムなので、どちらかをクライアントにしてどちらかをサーバにする必要がある。自宅側は固定グローバルIP無料というありがたいプロバイダで固定IPもらっているため、こっちをサーバにすることとした。

自宅(横浜市戸塚区)側の設定

色々試行錯誤して、そのプロセスについてはここにメモるまえに忘れちゃったんだけど、結論として動くようになった設定ファイルの内容を以下に記しておく。そういうわけで、無駄な設定なんかか含まれているかもしれないけど・・^^

OpenVPNサーバの設定
mode server
port 1194

# dev tap って書くだけでよさそうだけど。
dev tap0
dev-type tap

# 一応TLS鍵作ってやってみた。
tls-server
ca ca.crt
cert server.crt
key server.key  

dh dh1024.pem
client-to-client
keepalive 10 120
comp-lzo

user nobody
group nogroup

persist-key
persist-tun

status openvpn-status.log
verb 3
/etc/network/interfaces の設定

前述設定でOpenVPNを起動すると、tap0という仮想ネットワークインターフェースが立ち上がる。でも、それだけじゃ何も嬉しくなくて、サーバの物理NIC(eth0)とをブリッジでつないでやる必要がある。まずは、コマンドでそのあたりを試して、接続試験を行った。ping 192.168.1.11 (実家のルータのLAN側アドレス)が通ったときは、思わず「おおっ」と思った。

ただ、そのままだとサーバを再起動したときに切れちゃうし、毎回手でコマンド打つのはいやな(有り得ない)ので、ネットワークを起動したり再起動したりしたときに自動接続するよう設定した。

auto lo
iface lo inet loopback

allow-hotplug eth0
auto eth0
iface eth0 inet static
        #address 0.0.0.0
        address 192.168.1.2
        netmask 255.255.255.0
        network 192.168.1.0

auto br0
iface br0 inet static
        address 192.168.1.2
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        gateway 192.168.1.1
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers localhost, 192.168.1.1
        dns-search forton.shimono.net

        pre-up /usr/sbin/openvpn --mktun --dev tap0
        pre-up /sbin/ifconfig tap0 0.0.0.0 promisc up
        pre-up /sbin/ifconfig eth0 0.0.0.0 promisc up
        pre-up /usr/sbin/brctl addbr br0
        pre-up /usr/sbin/brctl addif br0 eth0
        pre-up /usr/sbin/brctl addif br0 tap0
        post-down /usr/sbin/brctl delif br0 eth0
        post-down /usr/sbin/brctl delif br0 tap0
        post-down /usr/sbin/brctl delbr br0
        post-down /usr/sbin/openvpn --rmtun --dev tap0
        post-down /sbin/ifconfig eth0 down

実家(東京都東久留米市)側の設定

OpenVPNクライアントの設定

実家側はDD-WRT化したBuffaloルータのopenvpnクライアント機能を使う

この設定をしたら、自宅(サーバ)側のopenvpnのログに実家(クライアント)から接続に来た旨が表示された。(verboseレベルを5ぐらいにあげておいた。)

ブリッジの設定

ただ、これだけだとダメで、実家側もブリッジの設定をしてやる必要がある。sshDD-WRT化されたルータに入って、自宅側でやったのと同様のブリッジ設定をした。

こちらも、ルータ再起動の度に設定するのはいやだったので、起動スクリプトとして仕込んでみた。

実は、ちょっとDDWRT的にこれでいいのか良く分からない。ルータ再起動でちゃんとつながるかというと、どうもつながっていない気もするのだが、すくなくともこの画面からポチっと押せばつながるようにはなったのでよしとしよう。(それでstartupのところとcustom scriptのところに両方書いてある)

とりあえず以上、不完全な情報だが覚えている範囲で記しておく。(設定して動いたらもう疲れちゃって・・・ 1ヶ月以上経ってから書いてるもので、すんません)

VPNで自宅と実家を結ぶぞ!

3連休、実家に帰ったところ、何を思ったか「OpenVPNで自宅と実家を結ぶ」というアイディアに取り付かれてしまった。
「実家の両親に孫(私の息子)の写真やら何やらをDLNAでスライドショーにして見せる」というユースケースが実現したかったこともある。ネットワーク関連良く分かってない自分の自己研鑽という意味あいもある。

ということで、俺プロジェクト「自宅と実家でVPN」を始動した。

色々なVPN

まずVPNってものが何者であるか、ちゃんとわかってなかったので調べてみた。結果、世の中には大体以下のような技術方式があることが分かった。

また、ユースケースとしては以下のようなものがあることも分かった。

    • 拠点間接続 (site-to-site)
      • 東京本社と神奈川支社を結ぶ
      • 自宅と別荘を結ぶ
    • Road Warrior
      • 営業マン等が社外から社内につなぐ
      • 外出先で自宅のPCにつなぐ

今回実現したいユースケースは「拠点間接続」なのは明らかだ。

これに向いた技術方式がどれであるか?昔は拠点間VPNといえばIPSecで決まりだったようだが、IPSecは複雑でコストが嵩みがちであり、かつ他の方法でも拠点間接続できるということで、最近はIPSec固定でもないらしい。そこで、まずはPPTP接続を試してみることにした。実家の側のルータをDD-WRT化してこれを一つのエンドポイントとし、自宅のほうは24時間運用のUbuntu自宅サーバがあるので、これを使うこととした。

ルータのOpenWRT化

さて、実家の無線LANルータはBuffaloのWHR2-G54というヤツだったのだが、これをDD-WRT化しようと調べてみると、残念!DD-WRTは実家のルータに対応していないことがわかった。しかし、DD-WRTのもととなっているOpenWRTには辛うじて対応していそうだったので、OpenWRT化することにした。

TFTPをつかってファームウェアを送りつけるというのは初めての経験だったのだが、タイミングを見計らって何度かトライしたら、OpenWRT化には成功した。SSHログインしていろいろできるようにもなった。

しかし、OpenWRTを入れたはいいが、使い方が難しい。実は最初、何も考えずに入れた最新ファームウェアでは無線が一切使えなくなってしまった。WHR2-G54の中に入っている無線チップのbroadcomというメーカとOpenWRTが知財云々で争っているようで、おそらくそれで最新のファームでは無線がサポートされなくなっているようだ。OpenWRTのバージョンを一つ古いものにしたところ、ちゃんと無線も使える状態になった。

また、OpenWRT化して初めて気付いたのだが、通信速度が激遅くなってしまった。おそらく何か設定すれば高速化できるのだろうが、その情報を調べるべくググるのが、すでにめちゃめちゃストレスフル・・うーん。まいったなぁ。

超ストレスフルなネット環境の中、pptpまわりのことを1から勉強しはじめたのだが、何だか難しくてかつ情報があまり見つけられず、更にブルーになってくる。OpenVPN方式に乗り換えたくなってきた。そこでopenvpnをおもむろにipkgだっけ? のコマンドでインストールしようとしたのだが、ブロック数が足らないとかなんとかで怒られてしまい入らない。。OpenVPNへの浮気はとりあえず忘れてPPTPの勉強を進めることにしたが、超低速ネットでろくにググれないと勉強も進まないため、とりあえず一旦元の純正ファームに戻すことにした。

再びTFTPで純正ファーム送りつけて再起動。しかし、ブラウザで画面を開いたところBuffaloの画面は出てこずOpenWRTの画面が出てきた・・
「あ・・戻せないジャン・・」
かなりブルーになってきた。
状況を整理しよう。

  • OpenVPNはこのルータではできそうにない」
  • PPTPの情報をしらべるにも速度が落ちてしまって超ストレス」
  • 「もう純正ファームにも戻せない」
  • 「OpenWRTはそれ自体扱いが難しい」

これだけ悪条件が揃うと、まさにこれは四面楚歌。
「そもそも、OpenWRT自体を使いこなすことは今回の目的ではない」
ということで、結局、このルータはボツにして、DD-WRT対応の別のルータを買うことにした。このルータも、もう5年ぐら使ったんだし、よしとしよう。

WHR-G300NのDD-WRT

せっかく買うのなら11n対応がいいなぁってことで、DD-WRTのページで対応ルータを調べたところ、BuffaloのWHR-G300Nが対応しているとのこと。早速近所のPC-Depotで7000円ぐらいで購入。箱をあけてすぐにDD-WRT化するのは少々ためらわれたが、目的達成のためにはしょうがない。すぐにDD−WRT化に着手した。

はじめは、先ほど同様TFTPでファームファイルを送りつけようとトライしたのだが、新しいルータでは送りつけるタイミングがつかめず上手く行かなかった。調べたところルータにファームファイルを取って行ってもらう方法ってのもあったのでこれを試した。結果DD-WRT化には成功した。

DD-WRTの画面を見ながら、さきほど、OpenWRTの硬派すぎる世界に負けた私は、素直に思ったよ。
DD-WRTってすばらしい。」
僕のようなヘタレには、OpenWRTは無理っす。DD-WRTじゃなきゃダメっす!

PPTPをためす

やっとルータ改造の世界から抜け出せたので、VPN計画に戻れる。
DD-WRTのメニューを見たところ、Service>VPNの項目にPPTPのサーバになるための設定とクライアントになるための設定があった。

サーバになるほうの設定は、だいたい意味がわかったのでとりあえず設定をしてみた。

さて、クライアント側である。クライアントは、ここ実家ではなく、自宅側にあるUbuntu自宅サーバ側での設定だ。SSHでログインして pptp-linuxなるパッケージをインストールして色々いじってみた。

結論・・・ よーわからん。。

ヘタレな僕にはPPPとPPTPの関連がよくわからなかったっすよ。ていうか、正直なところ何がわからずに挫折したかも忘れちゃった。

グーグル先生に聞いてみても、僕のようなヘタレでわかるような情報もなかなか見つからず、一方OpenVPNに関しては色々情報もありそうで、結構OpenVPNのほうがセキュリティ的にも他の面でもイケテルらしいってことも分かってきた。

また、今触っているDD-WRTopenvpn対応していないが、WHR-G300Nをopenvpn対応版のDD-WRTにすることも出来そうだったのでPPTPはやめてOpenVPNでやる方向で考えることにした。早速DD-WRTのページの情報にしたがい、ルータのファームをopenVPN対応版に入替えた。先ほどの
[Services]>[VPN]タブの中にメニューが増えてOpenVPNのサーバやクライアントになるための設定ができるようになった。

次回、OpenVPNでの自宅・実家接続について書く。