l'essentiel est invisible pour les yeux

Friday, July 18, 2008

OpenID動向 - Trusted Data Exchangeがユーザ属性ポータビリティの切り札になるか?

第三回 Liberty Alliance 技術セミナーで=natさんの基調講演を公聴してきて、OpenID関連の動向を仕入れたのでメモ。

OPとRP間で属性情報を交換するための拡張として、SREGやAXがあるが、AXも今ひとつ普及するに至っていない。(myopenid.comとVeriSignだけ?)また、プライバシポリシーや利用規約の問題もあり、日本企業では、ユーザ属性をサードパーティに公開出来ない事も多い。

基本的に、AXとSREGの違いは、

  • 交換可能な属性をコミュニティベースで提案&決定する
  • 属性を識別するために、プリミティブな値でなく、ネームスペースURIを使う
  • OPに要求する属性の個数が指定可能
  • RPがOPに対して属性の保存をする事が可能。(ただし、使われているプロバイダは知らない。)


が挙げられるが、根本的な問題は、OpenIDのユーザ属性として、クレジットカード番号や電話番号などプライバシー性の高い情報を使う事など、気が狂っていると思われている事だ。AXへの本格的な以降が進まないのは、結局OpenIDで扱うユーザ属性は、ニックネームやメールアドレスのみで、SREGで十分に事が足りているからではないだろうか。

さて、単純なユーザ属性の交換と、OP側でのユーザの許可の仕組みしか提供していないAXに代わる仕様として、Trusted Data Exchangeが=natさん、=masakiさん (NRI)から提出されている。

TXのコンセプトには次のような物が含まれる。
  • 契約ベースの属性提供
  • XML Encryption/XML Signatureによる暗号化•書名
  • 非同期な属性提供 (非否認性を持った契約ベース)
  • RPの信憑性を判断するReputation Platform (現状のホワイトリストに代わる)
仕様は既に、提案済みで、仕様が取り込まれる方向で話が進んでいる様子。OpenIDによるログインフォームは、会員登録の敷居を下げる。結果的に、サービスを利用する敷居が下がり、クレジットカートや住所などの個人情報が信頼できないRPに渡る可能性が高くなる。ユーザ属性ポータビリティには、Reputation Platformの構築は、急務であると言える。

年内に取り込まれるだろうか?

もう一つの最新動向は、PAPEの仕様拡張。PAPEと言えば、OpenIDの認証強度を明示するためのOpenID拡張だが、採用するセキュリティモデルを明示的に指定するための仕様を提案しているとの事。現状のPAPEでは、NISTの定めるセキュリティモデルを指定できるだけであるが、日本のFISCの基準を採用する際には、次のように指定できるとの事だ。


openid.pape.auth_level.fisc:2
openid.pape.auth_level.ns.fisc: http://www.fisc.or.jp/ex/authlevel


See also: まちゅダイアリー - SAML と OpenID と CardSpace

Tuesday, July 15, 2008

[Rails] Gears on Rails helps developers to write fully offline functionnal web applications

Google anounced about Gears on Rails, see Take your Rails application offline with the Gears on Rails project. We can listen to audio interview. This is Rails plugin to manipulate offline data from RoR.We can install GoR as Rails plugin is as follows:


% sudo gem install json_pure
% rails gor_demo && cd gor_demo
% ruby script /plugin install http://gearsonrails.googlecode.com/svn/trunk/acts_as_local


It need to add acts_as_local method in your controller in order to use it.

acts_as_local :except => [:hello]

def create_local
'
post = Post.build(params("post"));
Post.create_local(post);
window.location.reload( false );
'
end


Sorry, I never use GoR yet, but It seems interesting, so i may use it. See Gears on Rails in order to see how to write view and controller for more details.

Monday, July 14, 2008

[Erlang tips] Sometimes to call mnesia:wait_for_tables is required

Hmm..,
I spent three hours for a Mnesia's strange error message, so write tips about error I'm confused. The tables on Mnesia often need a time to prepare their tables, and if tables aren't available, then we'll see storange error message.

% db_test.erl


write_db_test() ->
start(), % Start the server, mnesia and create required tables.
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).

You may see the error is as follows:

{badmatch,{aborted,{no_exists,ready_queue}}}


It seems it need to call mnesia:wait_for_tables.

% db_test.erl

write_db_test() ->
start(), % Start the server, mnesia and create required tables.
mnesia:wait_for_tables([person], 3000),
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).

I think that error message "{no_exists, table_name}" is not human friendly.

Friday, July 04, 2008

[Erlang] How to package an application with erlware(faxien and sinan commands)

We usually need to package system and repositories in order to create a big application. Erlware is a repository for Erlang programs and it provides softaware to create a package and release it to the world. There are pretty cool, it is just thing I want to. This entry introduces that how to create an application as package and install to system.

I create a HAVAL bindings for Erlang in order to learn how to create linked-in driver.
See Tutorial for how to create Erlang linked-in driver.

In this entry, I introduce how to create an application provides API for HAVAL bindings for Erlang. We need to install Faxien and Sinan previously.

0. Dicied a names of application and start to development a pakcage.
Create required directories for the application.

% mkdir haval && cd haval && mkdir -p cmds doc bin lib
% ls .
bin/ cmds/ doc/ lib/ releases/
%
Create directories for HAVAL bindings.
% mkdir -p lib/haval && cd lib/hava && mkdir src ebin include priv/lib
Configuration file named "_build.cfg" for this application.
% cat > _build.cfg
project : {
name : haval
vsn : "1.0.0"
},

repositories : ["http://repo.erlware.org/pub", "http://repo.martinjlogan.com/pub"]
1. Create an application
Create a HAVAL bindings for Erlang in this entry. This includes following source codes:
HAVAL bindings is provides as linked-in driver, these source are in lib/haval/c_src directory.
  • Makefile
  • config.h
  • haval.c
  • haval.h
  • haval_drv.o
2. Build the shared library
HAVAL bindings requires shared library named "erl_drv.so", we may think want to integrate building task for linked-in driver to the package manager(Faxien). But unfortunately I don't know that, so I need to research for handling shared library.

All sources are here.

Do make task manually here.
% cd lib/haval/c_src
% make # Copy haval_drv.so haval/priv/lib
3. Build the application.
It 'sinan' command is used for building the application. We need to run background server with 'sinserv' command before compile them.
% sinserv # Placed in "/usr/local/erlware/release_packages/sinan-0.10.0.12/bin/sinserv" in my enviroment
Build the application with 'sinan' command. We can see help when '+help' command is passed.
% sinan +help
sinan [args] [task]
local args (+) and server args. local args may be any of the following
+url : The url to connect to and control
+help : This help message

Server args are much more complex. There are always sane defaults so
you shouldn't need them, but you may. To get information about server
args read the sinan documentation.
%
% sinan # Default task is build
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] Building ~/haval-1.0.0/lib/haval/src/haval_server.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_sup.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_app.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval.erl
[build] stop
run complete
% ls _build/development/apps/haval-1.0.0 # Generated following sources
c_src/ ebin/ include/ priv/ src/
%
Create a package for release. This package is generated underneath "_build/development/apps/" directory.
% sinan release
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] stop
[release] start
[release] stop
run complete
%
4. Install the application locally.
Some of tasks are required in order to install the application. At first, we need to prepare the directory for released package, copy "_build/development/release" to "releases/haval-1.0.0/" and copy "_build/development/haval-1.0.0" to "releases/haval-1.0.0".
% mkdir releases/haval-1.0.0/ && mkdir lib
% cp -r _build/development/release releases/haval-1.0.0/
% cp -r _build/development/apps/haval-1.0.0 releases/haval-1.0.0/lib

Install the application locally, there will be deployed on "/usr/local/erlware/release_packages/haval-1.0.0/". We can use 'faxien' command in order to handle the packages (local and remote). Please execute "faxien help commands" for more details.

% faxien install-release releases/haval-1.0.0
ok
% ls /usr/local/erlware/release_packages/haval-1.0.0/
LICENCE README lib/ release/
Run and test.
% erl
Erlang (BEAM) emulator version 5.6.2 [source] [smp:2] [async-threads:0] [kernel-poll:false]

Eshell V5.6.2 (abort with ^G)
1> haval:start().
ok
2> haval:haval_string("test").
"593C9AED973BB51A3C852FB4E051D7C26686B9468B4E405350CB6805DC1B99E6"
3> haval:haval_file("_build.cfg").
"5A114E356FBB0CCCED8C7574B7A71780C8F33D3A9B37B8642126B78429B2988F"
4>
5. Test the application
We can use EUnit for testing the application, and do test with following command:
% sinan test

Tuesday, July 01, 2008

Manipulate Erlang binary term format in C/C++ with ei library

Erlang includes ei library for handling Erlang binary term format. This entry introduces how to use this library.

1. Pass the one string to C driver from Erlang.
It's pretty simple case, and pass one string argument to C driver from Erlang. It should be passed port_control/3 or erlang:port_control/3 after all arguments should be encoded as binary. The "index" variable are used for pointing position in the buffer.

% echo.erl


-define(DRV_ECHO, 1).

echo(Str) ->
control(?DRV_ECHO, Str).

control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_table, port),
Bin = term_to_binary(Data), % XXX: All arguments will be encoded as binary term format.
Res = port_control(Port, Cmd, Bin),
binary_to_term(Res).

% echo_drv.c

#define DRV_ECHO 1

static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;

switch(command) {
case DRV_ECHO:
// It must call ei_decode_version at the beginning when argument is Erlang binary term format.

// All ei_xxx functions return 0 if it will be success, else return -1
ei_decode_version(buf, &index, &ver); // Value of 'index' will become 1.

// Get size of string in order to allocate buffer for argument
ei_get_type(buf, &index, &type, &size); // value of 'type' equal ERL_STRING_EXT

// Allocate memory for buffer
arg1 = new char[size + 1]; // Extra bite is required for NULL string.
/* do something */
}
}


Type of Erlang term
It can obtain type of Erlang term with result of ei_get_type function. All value of types are defined in ei.h.

#define ERL_SMALL_INTEGER_EXT 'a'
#define ERL_INTEGER_EXT 'b'
#define ERL_FLOAT_EXT 'c'
#define ERL_ATOM_EXT 'd'
#define ERL_REFERENCE_EXT 'e'
#define ERL_NEW_REFERENCE_EXT 'r'
#define ERL_PORT_EXT 'f'
#define ERL_PID_EXT 'g'
#define ERL_SMALL_TUPLE_EXT 'h'
#define ERL_LARGE_TUPLE_EXT 'i'
#define ERL_NIL_EXT 'j'
#define ERL_STRING_EXT 'k'
#define ERL_LIST_EXT 'l'
#define ERL_BINARY_EXT 'm'
#define ERL_SMALL_BIG_EXT 'n'
#define ERL_LARGE_BIG_EXT 'o'
#define ERL_NEW_FUN_EXT 'p'
#define ERL_FUN_EXT 'u'

#define ERL_NEW_CACHE 'N' /* c nodes don't know these two */
#define ERL_CACHED_ATOM 'C'


2. Pass the List
It should call ei_decode_list_header function when parse the list term. It must be called when parse the list term.

% echo_list.erl

-define(DRV_ECHO_LIST, 1).

echo(List) when is_list(List) ->
control(?DRV_ECHO_LIST, List).

control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_list_table, port),
Bin = term_to_binary(Data), % XXX: All arguments will be encoded as binary term format.
Res = port_control(Port, Cmd, Str),
binary_to_term(Res).


% echo_drv.c

#define DRV_ECHO 1

static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;

switch(command) {
case DRV_ECHO_LIST:
// It must call ei_decode_version at the beginning when argument is Erlang binary term format.

// All ei_xxx functions return 0 if it will be success, else return -1
ei_decode_version(buf, &index, &ver); // Value of 'index' will become 1.

// Get size of string in order to allocate buffer for argument
ei_get_type(buf, &index, &type, &size);

// Check the type
if(type == ERL_LIST_EXT) {
// It must be called at the begginning when hanle the list term.
ei_decode_list_header(buf, &index, &arity);

printf("number of elements: %d\n", arity);

// Check the type of first element in the list
ei_get_type(buf, &index, &type, &size);

swithc(type) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
// do something
break;
case ERL_STRING_EXT:
// do something
break;
}
}
}
}