はじめに
X-Roadは、エストニアの政府機関や、政府機関と連携を行う企業(銀行など)の間で使われている情報連携を行うための技術です。
X-Roadはソースコードはgithub.com/nordic-institute/X-Roadにあるものの、Docker Imageやダウンロードしてすぐ動くパッケージがなかったので使ってみた系の記事があまりありませんでした。
最近、Planetway社でX-Roadを手軽に試せるDocker Imageを公開しました[hub.docker.com]。
この記事では、X-Roadを知らない方向けに、事前知識を端折りながらまずはX-Roadを使ってみることから始めます。
# full disclosure 私はPlanetway社の中の人です
docker-compose upでX-Road Security Serverを立ち上げる
Docker Imageが公開されているのです。
何はともあれローカルで立ち上げてみましょう。
作業用のディレクトリを作り、Docker Hubのドキュメントにある内容をコピーしてdocker-compose.yml
ファイルを作成します。
% cat docker-compose.yml
version: '3.7'
services:
ss01:
image: planetway/xroad-securityserver:6.24.1-1
command: bash -c "/files/initdb.sh && /files/cmd.sh"
depends_on:
- postgres
environment:
# JP-TEST or JP
- PX_INSTANCE=JP-TEST
- PX_MEMBER_CLASS=COM
- PX_MEMBER_CODE=0170121212121
- PX_SS_CODE=qiita-demo-01
- PX_TSA_NAME=TEST of Planetway Timestamping Authority 2020
- PX_TSA_URL=https://tsa.test.planetcross.net
- PX_TOKEN_PIN=jXq+rlg2VS
- PX_ADMINUI_USER=admin
- PX_ADMINUI_PASSWORD=Secret222
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- PX_SERVERCONF_PASSWORD=serverconf
- PX_MESSAGELOG_PASSWORD=messagelog
- PX_OPMONITOR_PASSWORD=opmonitor
- PX_POPULATE_DATABASE=true
- PX_ENROLL=true
ports:
- "2080:2080"
- "4000:4000"
- "5500:5500"
- "5577:5577"
- "5588:5588"
- "8000:80"
- "8443:443"
volumes:
# .p12 files and keyconf.xml
- "px-ss-signer:/etc/xroad/signer"
# mlog.zip files are stored here, and ./backup contains backups
- "px-ss-xroad:/var/lib/xroad"
postgres:
image: postgres:10
environment:
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
volumes:
- "px-ss-postgres:/var/lib/postgresql/data"
volumes:
px-ss-postgres:
px-ss-signer:
px-ss-xroad:
Docker Hubのドキュメントでは環境変数を...と省略しているところはとりあえず適当に埋めます。
PX_SS_CODE
はX-Roadメンバー(X-Roadに参加する組織)の中のSecurity Serverを表すユニークな文字列です。ここからコピペする際には、ユニークな文字列に変更してください。
そしてdocker-compose up
してSecurity ServerとPostgreSQLをまとめて起動します。
% docker-compose up
Creating network "px-ss-docker_default" with the default driver
Creating px-ss-docker_postgres_1 ... done
Creating px-ss-docker_ss01_1 ... done
Attaching to px-ss-docker_postgres_1, px-ss-docker_ss01_1
postgres_1 | The files belonging to this database system will be owned by user "postgres".
postgres_1 | This user must also own the server process.
postgres_1 |
postgres_1 | The database cluster will be initialized with locale "en_US.utf8".
postgres_1 | The default database encoding has accordingly been set to "UTF8".
postgres_1 | The default text search configuration will be set to "english".
postgres_1 |
postgres_1 | Data page checksums are disabled.
postgres_1 |
postgres_1 | fixing permissions on existing directory /var/lib/postgresql/data ... ok
postgres_1 | creating subdirectories ... ok
postgres_1 | selecting default max_connections ... 100
postgres_1 | selecting default shared_buffers ... 128MB
postgres_1 | selecting default timezone ... Etc/UTC
postgres_1 | selecting dynamic shared memory implementation ... posix
postgres_1 | creating configuration files ... ok
ss01_1 | 2021-01-11 09:00:06,566 Creating /var/lib/xroad/backup
ss01_1 | 2021-01-11 09:00:06,655 Generating new internal.[crt|key|p12] files
ss01_1 | /CN=0874c65254b7 -subj
ss01_1 | Generating a RSA private key
ss01_1 | ............................................................+++++
ss01_1 | ............+++++
ss01_1 | writing new private key to '/etc/xroad/ssl/internal.key'
ss01_1 | -----
ss01_1 | 2021-01-11 09:00:07,004 Generating new proxy-ui-api.[crt|key|p12] files
...
# しばらく待つと
ss01_1 | {"timestamp":"2021-01-11T09:03:10.183Z","level":"INFO","thread":"main","logger":"org.springframework.boot.web.embedded.tomcat.TomcatWebServer","message":"Tomcat started on port(s): 4000 (https) with context path ''","context":"X-Road Proxy Admin REST API"}
↑の最後の行が出てきたら、
https://localhost:4000/ をブラウザで開いてみしょう。
X-Road Security Serverの管理画面です。
Safariでは"接続はプライベートではありません", Chromeでは"この接続ではプライバシーが保護されません"と表示されますが、理解しているので先に進みます。
ログイン画面では環境変数のPX_ADMINUI_USER
とPX_ADMINUI_PASSWORD
でログインします。
X-Roadとは
今一体何を立ち上げたのでしょうか。
Security Serverとは何でしょうか。
図1 Deployment view of X-Road (赤い線は筆者による強調)
docker-compose.yml
に書いたplanetway/xroad-securityserver
Docker Imageは、上図のClient Security Server, Service Security Serverの青い箱に当たるソフトウェアです。
X-Roadの情報連携とは、Service Clientという組織内のClient Information Systemから、Service Providerという組織内のService Information Systemが提供する機能を使うことを表します。
Security Serverは、Client Information Systemから見るとForward Proxyの役割を果たし、Service Information Systemから見るとReverse Proxyの役割を果たします。Security ServerはClient Information SystemとService Information Systemをインターネットを通してつなげるセキュアなトンネルを構築します。
Client Information SystemとClient Security Serverの間、そしてService Information SystemとService Security Serverの間は、SOAPとRESTプロトコルを話します。
X-Roadの情報連携をやってみましょう。
認証用証明書のActivate、Security Serverの登録とSubsystemの登録
planetway/xroad-securityserver
Docker Imageは、Security Server立ち上げ時のセットアップ手順をいくつか自動的に実行しますが、情報連携を行う=HTTPリクエストをSecurity Serverに送る、までにはまだいくつかステップがあります。
認証用証明書をActivateしましょう。
https://localhost:4000/ を開き、ログインします。
"KEYS AND CERTIFICATES" をクリック -> "Token: softToken-0"の左の ">" をクリック -> "TEST of Planetway Intermediate L1 Organizations CA 2020 ..." をクリック -> "ACTIVATE" をクリックします。
認証用証明書をActivateしました。
Security Serverの登録リクエストを送りましょう。
バツを押してその画面を閉じ、"KEYS AND CERTIFICATES" をクリック -> "Register" ボタンを押します。
"127.0.0.1"と入力し "ADD" ボタンを押します。
これでSecurity Serverの登録リクエストを送信したことになります。
図1のCentral Serverでは、X-Roadに参加する組織と、それぞれの組織が運用するSecurity Serverのカタログを管理しています。Security Serverの登録リクエストは、Central ServerのカタログにこのSecurity Serverを登録してもらうためのリクエストです。
次にSubsystemの登録を行います。
"CLIENTS" をクリック -> "Add Subsystem" ボタンを押します。
"Subsystem Code"には"democlient"と入力し、"ADD SUBSYSTEM"ボタンを押します。
"CLIENTS"を押し以下のように表示されていれば(Docker Demo Company (Owner)とdemoclientの行に緑の円と"REGISTERED"が表示されていれば)Subsystemの登録は完了です。
図1におけるService Client組織に所属するClient Information System情報システムをdemoclientと言う名前で登録しました。
Security ServerのConnection TypeをHTTPに変更する
もうそろそろです。
Client Information SystemとClient Security Serverの間は、デフォルトではHTTPSを使用します。この記事では簡略化するためHTTPに変更します。
同管理画面で、"CLIENTS" をクリック -> "democlient" の文字のところをクリック -> "INTERNAL SERVERS" をクリックします。下図のように、"CONNECTION TYPE"を"HTTP"に変更してください。
HTTPリクエストをSecurity Serverに送る
Service Provider側は、この記事では、予めPlanetway社が提供するものを利用しましょう。Planetway社では、現在時刻を返すtimeというX-Roadサービスをデモとして提供しています。
以下のようにcurlのコマンドを実行してください。
% curl -v "http://localhost:8000/r1/JP-TEST/COM/0170368015672/demoprovider/time" -H "X-Road-Client: JP-TEST/COM/0170121212121/democlient"
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /r1/JP-TEST/COM/0170368015672/demoprovider/time HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.64.1
> Accept: */*
> X-Road-Client: JP-TEST/COM/0170121212121/democlient
>
< HTTP/1.1 200 OK
< Date: Wed, 13 Jan 2021 12:33:54 GMT
< Content-Type: text/plain;charset=utf-8
< x-road-id: JP-TEST-b3fcf843-4d50-4108-b25a-22b5993ad0c9
< x-road-client: JP-TEST/COM/0170121212121/democlient
< x-road-service: JP-TEST/COM/0170368015672/demoprovider/time
< x-road-request-id: f13d39d1-c5a7-4fc5-bd2f-ac002e2dc2e7
< x-road-request-hash: N02MYtDKDzpT1QN7uUQlgUa+I5Vu5ImpX1WKxj/fByjKCUITbWgAlySJwfSt0xQU1AzaPG0RiEqoONQBxXD0jQ==
< Content-Length: 41
<
{"now":"2021-01-13T12:33:54.692995982Z"}
と表示されれば成功です!
このcurlコマンドを紐解いていきます。
localhost:8000
私の環境では、DockerはmacOS用のDocker Desktopで動作させています。この記事冒頭のdocker-compose.yml
ではports以下に- 8000:80
とありました。これはlocalhost:8000
をDocker containerの80番ポートに転送します。Docker container内のSecurity Serverはポート80番でlistenしています。
/r1/JP-TEST/COM/0170368015672/demoprovider/time
Information SystemとSecurity Serverの間のプロトコルは、X-Road: Message Protocol for RESTと言うプロトコルにしたがいます。URLのpath部分はMessage Protocol for REST文書の中でserviceId
として記載があります。
r1
はプロトコルのバージョン。
JP-TEST
はX-RoadインスタンスのIDです。X-Roadのインスタンスとは、図1に表される箱全部を含んだまとまりで、あるGoverning Authority/運営機関と、運営機関が提供する環境で情報連携を行う組織群を含みます。JP-TEST
はPlanetway社が運営機関を務めています。他にEE
(エストニア), FI
(フィンランド)などがあります。
COM
はX-Roadに参加する組織が法人であることを表します。他にGOV
などがあります。
0170368015672
はPlanetway社を表すX-Road Member IDです。0170121212121
はDocker Imageの使用者が使えるテスト用のX-Road Member IDです。
demoprovider
はPlanetway社の情報システムを表すSubsystem IDです。
time
はX-Road Serviceコードです。
X-Road-Client: JP-TEST/COM/0170121212121/democlient
というヘッダの値は、Client Information Systemを表しています。
Security Serverはアクセスコントロールの機能も含みます。予めtimeサービスは、JP-TEST/COM/0170121212121/democlient
から呼び出せるよう設定済みです。
time X-Road Serviceの実体
timeサービスは以下のようなGolangのコードとして実装しています。
package main
import (
"encoding/json"
"net/http"
"os"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
t := time.Now()
enc := json.NewEncoder(w)
err := enc.Encode(map[string]interface{}{
"now": t,
})
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
}
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.HandleFunc("/", handler)
http.ListenAndServe(":"+port, nil)
}
普通のJSONを返すAPIサーバですね。http.HandleFunc
の第一引数が/
であることに注意。これが図1のService Information Systemに当たります。
いくつか私が面白いと思う点を書きます。
-
Security ServerがInformation Systemから見るとシンプルなトンネルであること
このGolangのサーバをローカルで実行し、立ち上がったサーバにcurlでHTTPリクエストを送る手順と、インターネットのどこかでPlanetway社が提供するtimeサービスを呼び出す手順の違いが小さいこと。
X-Road-Client
リクエストヘッダ、URLのpath部分だけです。 -
X-Roadのセキュリティ面はInformation Systemには見えない
よくある外部APIと比較するとどうでしょう。Bearer tokenのようなものもクライアント証明書も何も見えません。認証や認可はSecurity Serverが隠蔽しています。
-
curlのリクエスト送り先はSecurity Server
知る必要があるのは、組織のID、その中のサービスIDからなる
serviceId
だけです。相手のURLは知る必要がありません。インターネットのレイヤの上に綺麗にRPCのレイヤをのっけています。
まとめ
DockerでX-Road Security Serverを立ち上げ、それを通して時刻を返すデモサービスを呼び出すcurlコマンドを実行しました。
続く