Edited at

情報銀行のプラットフォームとして利用できるかもしれないPersonium(PDS) を検証してみる 5 <APIでアクセスしてみる>


環境を構築し Personium がどういうプロダクトなのかが分かったところで、ゆるりと… APIを叩きながらアカウント(Account)・ロール(Role)・ACL などについて触ってみましょう。

ここまでに環境を構築し、一旦「Personiumとは」とちょっと脱線しましたが、やはり触ってみて仕組みの考え方や使い勝手などを、感じるのが一番ですね。

前のエントリー「情報銀行のプラットフォームとして利用できるかもしれない… 検証用のPDS(Personium) 構築してみる。<ざっくりとPersoniumとは>」で『Personium はサーバーサイドでAPIを提供するサービスです。』と記載していますので、たぶんいろんなことがAPIでデータの登録や参照などができるのでしょう… たぶんそうです。

アプリケーションからAPIを呼んでいろんなことをするのだから、たぶんコマンドラインから curl を利用して、あたかも自分がアプリケーションのように振舞うことにより、アプリケーションと Personium がどんな会話をしてどんなデータをやり取りしているかもわかるはずです。

まずはヤってみましょう!



参考:curl のインストール

curl がインストールされていない場合、以下を参考にインストールしましょう。


curl インストールの確認

まずは自分の環境に、curl がインストールされているか確認しましょう。

まずMacにはインストール済みなので、バージョンが表示されます。

ちなみにMacにインストールする場合は $ brew install curl でインストールできます。


Mac.


$ curl --version
curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy

未インストールと思われる Windows では?


Windows.

C:\>curl --version

'curl' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。


Windows版 curl のインストール

ここ(https://curl.haxx.se/windows/)から、curl-7.64.0-win64-mingw.zip をダウンロードし(32bit版なら curl-7.64.0-win32-mingw.zip)、伸張します。

伸張したディレクトリを適当な場所に移動し、そのディレクトリ内の ¥bin¥ をPATHに追加します。

 例) PATH=C:¥curl-7.64.0-win64-mingw¥bin;


Windows.

C:\>curl --version

curl 7.64.0 (x86_64-pc-win32) libcurl/7.64.0 OpenSSL/1.1.1a (Schannel) zlib/1.2.11 brotli/1.0.7 WinIDN libssh2/1.8.0 nghttp2/1.36.0
Release-Date: 2019-02-06
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz brotli TLS-SRP HTTP2 HTTPS-proxy MultiSSL

これで私の環境では、MacでもWindowsでも curl を実行できるようになりました。

では、これからが本題です!!



1.APIを叩く(何をどうして良いかもわからず…)

とりあえず、まずは2つ前のエントリー「情報銀行のプラットフォームとして利用できるかもしれない… 検証用のPDS(Personium) 構築してみる。<Ansibleでインストールする>」で構築したユニット( https://personium.takky.org )にアクセスしてみましょう。

$ curl https://personium.takky.org

{"unit":{"path_based_cellurl_enabled":true,"url":"https:\/\/personium.takky.org\/"}}

「path_based_cellurl_enabled」と返ってきており、Google先生に翻訳をしてもらうと、『パスベースのcellurlが有効』とのことです。"ちょっと何言ってるかわからない…"という感は残りますが、"カロリーは0"ではないようですね。

もう少し手がかりが欲しいので、Headerも表示してみましょう!

$ curl -i https://personium.takky.org

HTTP/1.1 200
Date: Thu, 14 Feb 2019 08:45:42 GMT
Content-Type: text/plain
Content-Length: 84
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{"unit":{"path_based_cellurl_enabled":true,"url":"https:\/\/personium.takky.org\/"}}

「レスポンスコードがちゃんと 200 で返ってきてる」くらいの情報しか、追加の情報はありませんでした…

そこでまたもや頼りになる Google先生 に登場してもらいましょう!

以下のワードで検索してみましょう…

  personium curl  

image.png

一番上に「Personiumサービス チュートリアル」と「Personiumサービス マニュアル」と検索されます。開いてみるとどちらも同じようなドキュメントです。「Personiumサービス マニュアル」の方が説明が多く記載されているような気もします。

でも思い出しました…

最初のエントリー「情報銀行のプラットフォームとして利用できるかもしれない… 検証用のPDS(Personium) 構築してみる。<はじめに>」で、『3.「Personiumサービス」もある(あった…)』に、もう新規の申し込みは受け付けていないという記載があります。なのでこのドキュメントは参考にして良いのか不安ですよねぇ。


当初はこれらのドキュメントしかなかったのですが、サービス提供を受けていないユーザーの作業とは若干差異があるようで、OSSチームが以下のドキュメントを提供してくれました!!

メニュー構成もだいたい同じようで、若干の差異はあるものの、これにAPIでのアクセスの仕方がわかるかもしれません…

Personiumユニット管理 チュートリアル

image.png

今後は、これを参考にして API を叩いてみることにしましょう!!


2.APIを叩く(「Personiumユニット管理 チュートリアル」を参考に…)

「Personiumユニット管理 チュートリアル」を curl でページ内検索をしてみると… 14個ほど見るかるようです。

最初が 「 …すべてcURLを使用して… 」

イイデスネェ!!

image.png

2つ目が「 5-1. Cellの作成 」

Cellの作成… ハードル高そ〜!!

image.png

『何も入っていない空のCell(PDS)を作ります。』だそうです… それ以降の検索結果をみても説明は大差ありません。 まぁ弱音を吐かず、試してみることとしましょう。

image.png

{Personium_FQDN} {Token} のこの2つが変数となっていて、環境に合わせて変更する必要がありそうです。

なんとなく私も {Personium_FQDN} には"personium.takky.org"が入ることは予想できます。

しかし {Token} は何なのでしょ??

よくわかりませんが、分かるところだけいれて、実行しちゃいましょう!!

… 当然、"Token parse error." とうエラーで蹴られます。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X GET -i -k \
-H "Accept:application/json" -H "Authorization:Bearer {Token}"
HTTP/1.1 401
Date: Thu, 14 Feb 2019 09:33:38 GMT
Content-Type: application/json
Content-Length: 77
Connection: keep-alive
WWW-Authenticate: Bearer realm="https://personium.takky.org/"
X-Personium-Version: 1.7.4
Server: Personium

{"code":"PR401-AU-0006","message":{"lang":"en","value":"Token parse error."}}


3.Token について調べる

APIでアクセスするには、{Token} をリクエストのHeaderに与えなければいけないようなので、Tokenについてちょいと調べる必要がありそうです…


ありました!「5-1. Cellの作成」の少し上にありました! 「4. トークンについて」 に記載がありました。

ここにリンクが貼られている以下のドキュメントを参考に理解しましょう。

ユニットユーザ

  ユニットマスタートークン や ユニットユーザートークン があるようですね…

Ansible で構築したユニットの環境情報

  それぞれのアカウントやパスワードを調べるには、このドキュメントを参照します。

image.png


トークンのまとめ

トークンは以下のように整理できます。

この後のAPIを叩く際には「ユニット管理者トークン」が適切と思われますので、まずは「ユニット管理者トークン」利用して進めることとします。

トークンの種類
役割
備考

ユニットマスタートークン
ユニットに関するあらゆる操作ができるきわめて強い権限を持ったトークン
ユニットにトークンが設定されており、無効化することが望まれる

ユニット管理者トークン
ユニットの全セルに対して操作が可能な特別なユーザのトークン
ユーザー名とパスワードがユニットに設定されている。

ユニットユーザートークン
オーナーが一致するセルに対して操作が可能なユーザのトークン
一般的なユーザー権限

※ そしてこの後 curl のコマンド内でのユニット管理者の ユーザー名 / パスワード / トークン は

 {{unitAdminUser}} / {{unitAdminPassword}} / {{unitAdminToken}} のように記載することとします。


しかし気になるのは… ユニットマスタートークンは無効化が推奨されているので、無効化しない方が悪いのですが… ユニット管理者トークンについては無効化もできないうえに、平文のテキストで保持されているのは良いのでしょうか?? 個人的には簡単に確認ができるのは嬉しいのですが、これほどセキュリティに気を使った設計になっているのに、こんな大切なパスワードが… 今度口頭で、OSSチームの方に確認してみようと思います。


4.あらためて API を叩く!!

さて、ようやくAPIを叩く準備ができたような気がします。

手始めとして「5-1. Cellの作成」の最初の工程にある以下の状態を確認してみましょう。

「新たなCellを追加作成する前に、Cell一覧取得APIで事前の状態を確認してみましょう。 構築直後のPersoniumユニットには、ユニット管理用のCellのみ登録されている状態です。」


まずは「ユニット管理者トークン」を取得してみましょう。

以下のように curl コマンドを叩きます!

$ curl "https://personium.takky.org/unitadmin/__token" \

-X POST \
-d "grant_type=password&username={{unitAdminUser}}&password={{unitAdminPassword}}&p_target=https://personium.takky.org/" \
-H "Content-Type: application/x-www-form-urlencoded"

すると、access_token が返ってきています。実際にはひじょ〜に長い文字列の token が送られてきます。この token は3600秒(1時間)間有効のようです。

HTTP/1.1 200 

Date: Thu, 14 Feb 2019 11:29:49 GMT
Content-Type: application/json
Content-Length: 4378
Connection: keep-alive
Location: https://personium.takky.org/__token
X-Personium-Version: 1.7.4
Server: Personium

{
 "access_token":"{{unitAdminToken}}",
 "refresh_token_expires_in":86400,
 "refresh_token":"{{refreshToken}}",
 "p_target":"https:\/\/personium.takky.org\/",
 "token_type":"Bearer",
 "expires_in":3600
}

いい感じです。


では次にこのトークンを利用し、ドキュメントに沿ってCellの状態を確認してみましょう。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

返ってきました!!


ドキュメントに記載の通り、'unitadmin'のセルだけが存在するようです。

HTTP/1.1 200 

Date: Thu, 14 Feb 2019 11:39:57 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 251
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('unitadmin')",
     "etag":"W\/\"1-1549258115566\"",
     "type":"UnitCtl.Cell"
    },
    "Name":"unitadmin",
    "__published":"\/Date(1549258115566)\/",
    "__updated":"\/Date(1549258115566)\/"
   }
  ]
 }
}

ようやくAPIを正しく叩くことができるようになりました!!

ここまで来らシメたもんです。 勢いに乗ってセルやユーザーを作成したり、いろんなオブジェクトにアクセしたりしてみましょう。


5.ユニット管理者トークンの取得

セルを操作するには、ユニット管理者ぐらいの権限は必要でしょうから、一旦この権限のトークンで操作しましょう。

$ curl "https://personium.takky.org/unitadmin/__token" \

-X POST -i \
-d "grant_type=password&username={{unitAdminUser}}&password={{unitAdminPassword}}&p_target=https://personium.takky.org/" \
-H "Content-Type: application/x-www-form-urlencoded"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 06:13:35 GMT
Content-Type: application/json
Content-Length: 4378
Connection: keep-alive
Location: https://personium.takky.org/__token
X-Personium-Version: 1.7.4
Server: Personium

{
 "access_token":"{{unitAdminToken}}",
 "refresh_token_expires_in":86400,
 "refresh_token":"{{refreshToken}}",
 "p_target":"https:\/\/personium.takky.org\/",
 "token_type":"Bearer",
 "expires_in":3600
}


6.セルの操作

セルは前の章で、Personium の構造上必須である"unitadmin"のみが存在することを確認していますので、今後アプリケーション等で利用するセルを作成しましょう。

今回は、以下の2つを作成することにします。


1つめのセル("えらいセル")の作成

ではまず、1つめのセル名を"えらいセル"として作成してみましょう。

curl "https://personium.takky.org/__ctl/Cell" \

-X POST -i -k \
-d "{\"Name\":\"えらいセル\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 400
Date: Fri, 15 Feb 2019 06:26:18 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 1160
Connection: keep-alive
X-Personium-Version: 1.7.4
Content-Language: en
Server: Personium

<!doctype html>
<html lang="en"><head><title>HTTP Status 400 – Bad Request</title>
<style type="text/css">
h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;}
h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;}
body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;}
b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;}
p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}
a {color:black;}
a.name {color:black;}
.line {height:1px;background-color:#525D76;border:none;}</style></head>
<body>
<h1>HTTP Status 400 – Bad Request</h1>
<hr class="line" />
<p><b>Type</b> Status Report</p>
<p><b>Message</b> Bad Request</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).</p>
<hr class="line" /><h3>Apache Tomcat/9.0.10</h3></body></html>

なんかダメらしいです。たぶんセル名に日本語は使えないのかもしれません…

では"admincell"というセル名にしてみましょう。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X POST -i \
-d "{\"Name\":\"admincell\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201
Date: Fri, 15 Feb 2019 06:37:13 GMT
Content-Type: application/json
Content-Length: 249
Connection: keep-alive
Location: https://personium.takky.org/__ctl/Cell('admincell')
DataServiceVersion: 2.0
ETag: W/"1-1550212633751"
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":{
   "__metadata":{
    "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('admincell')",
    "etag":"W\/\"1-1550212633751\"",
    "type":"UnitCtl.Cell"
   },
   "Name":"admincell",
   "__published":"\/Date(1550212633751)\/",
   "__updated":"\/Date(1550212633751)\/"
  }
 }
}

HTTP/1.1 201 で返ってきた。イケたんじゃないでしょうか??


2つめのセル("ふつうのセル")の作成

つぎは、"ふつうのセル"なのですが2バイト文字はダメそうなので… "UserCell"としましょう。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X POST -i \
-d "{\"Name\":\"UserCell\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 400
Date: Fri, 15 Feb 2019 06:45:44 GMT
Content-Type: application/json
Content-Length: 98
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{
 "code":"PR400-OD-0006",
 "message":{
  "lang":"en",
  "value":"request body format error. field [Name]"
 }
}

ありゃりゃ??

もしかして… セル名には大文字も使えないのでしょうか? "usercell"にしてみましょう。

curl "https://personium.takky.org/__ctl/Cell" \

-X POST -i \
-d "{\"Name\":\"usercell\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201
Date: Fri, 15 Feb 2019 06:48:48 GMT
Content-Type: application/json
Content-Length: 247
Connection: keep-alive
Location: https://personium.takky.org/__ctl/Cell('usercell')
DataServiceVersion: 2.0
ETag: W/"1-1550213328486"
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":{
   "__metadata":{
    "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('usercell')",
    "etag":"W\/\"1-1550213328486\"",
    "type":"UnitCtl.Cell"
   },
   "Name":"usercell",
   "__published":"\/Date(1550213328486)\/",
   "__updated":"\/Date(1550213328486)\/"
  }
 }
}


セル名には、アルファベットでかつ小文字を使用しなければイケけないようですね!! 注意が必要です。


では、セルの状態を確認してみましょう。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 06:54:15 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 713
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('unitadmin')",
     "etag":"W\/\"1-1549258115566\"",
     "type":"UnitCtl.Cell"
    },
    "Name":"unitadmin",
    "__published":"\/Date(1549258115566)\/",
    "__updated":"\/Date(1549258115566)\/"
   },{
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('admincell')",
     "etag":"W\/\"1-1550212633751\"",
     "type":"UnitCtl.Cell"
    },
    "Name":"admincell",
    "__published":"\/Date(1550212633751)\/",
    "__updated":"\/Date(1550212633751)\/"
   },{
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('usercell')",
     "etag":"W\/\"1-1550213328486\"",
     "type":"UnitCtl.Cell"
    },
    "Name":"usercell",
    "__published":"\/Date(1550213328486)\/",
    "__updated":"\/Date(1550213328486)\/"
   }
  ]
 }
}

ちゃんと、"unitadmin""admincell""usercell"が確認できます。

OKのようです!!


ちなみに、セルの削除は…

$ curl "https://personium.takky.org/__ctl/Cell(Name='usercell')" \

-X DELETE -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 204
Date: Fri, 15 Feb 2019 07:08:00 GMT
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

確認してみましょう。

$ curl "https://personium.takky.org/__ctl/Cell" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 07:09:34 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 483
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('unitadmin')",
     "etag":"W\/\"1-1549258115566\"","type":"UnitCtl.Cell"
    },
    "Name":"unitadmin",
    "__published":"\/Date(1549258115566)\/",
    "__updated":"\/Date(1549258115566)\/"
   },{
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/__ctl\/Cell('admincell')",
     "etag":"W\/\"1-1550212633751\"",
     "type":"UnitCtl.Cell"
    },
    "Name":"admincell",
    "__published":"\/Date(1550212633751)\/",
    "__updated":"\/Date(1550212633751)\/"
   }
  ]
 }
}

"usercell"が無くなっています。Ok!!


7.アカウントの操作

次は、アカウントを操作してみましょう。

ん? でも… 『セル ≒ ユーザー』だって、前のエントリー(<ざっくりとPersoniumとは>)に記載していますね。なぜアカウントがあるんでしょ??

ここが Personium を触っていて、わかりづらく難しいポイントなのですが『ユーザー ∈ グループ』という考え方ることもできたり、そしてアカウントにより権限を変えたり… と、このような利用の仕方も想定しているため、『セル ≒ ユーザー』のなかに 複数のアカウント が存在できるの"だそう"です。


1つめのアカウント("えらいアカウント")の作成

まずは、アカウントの確認。 当然、存在していませんよね?!

$ curl "https://personium.takky.org/admincell/__ctl/Account" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 08:06:57 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 20
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[]
 }
}


"えらいアカウント"アカウントの作成

アカウント名は"admin"とします。そして同時に、任意のパスワード {{passWord}} も指定します。

$ curl "https://personium.takky.org/admincell/__ctl/Account" \

-X POST -i \
-d "{\"Name\":\"admin\"}" \
-H "X-Personium-Credential:{{passWord}}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201
Date: Fri, 15 Feb 2019 08:14:15 GMT
Content-Type: application/json
Content-Length: 310
Connection: keep-alive
Location: https://personium.takky.org/admincell/__ctl/Account('admin')
DataServiceVersion: 2.0
ETag: W/"1-1550218455398"
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":{
   "__metadata":{
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('admin')",
    "etag":"W\/\"1-1550218455398\"",
    "type":"CellCtl.Account"
   },
   "Name":"admin",
   "LastAuthenticated":null,
   "Type":"basic",
   "Cell":null,
   "__published":"\/Date(1550218455398)\/",
   "__updated":"\/Date(1550218455398)\/"
  }
 }
}

201で返ってきているので、イイ感じです。


ではもう一つの"ふつうのアカウント"(user)の作成し、確認してみましょう。

$ curl "https://personium.takky.org/admincell/__ctl/Account" \

-X POST -i \
-d "{\"Name\":\"admin\"}" \
-H "X-Personium-Credential:{{passWord}}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201
Date: Fri, 15 Feb 2019 08:20:49 GMT
Content-Type: application/json
Content-Length: 308
Connection: keep-alive
Location: https://personium.takky.org/admincell/__ctl/Account('user')
DataServiceVersion: 2.0
ETag: W/"1-1550218849564"
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":{
   "__metadata":{
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')",
    "etag":"W\/\"1-1550218849564\"",
    "type":"CellCtl.Account"
   },
   "Name":"user",
   "LastAuthenticated":null,
   "Type":"basic","Cell":null,
   "__published":"\/Date(1550218849564)\/",
   "__updated":"\/Date(1550218849564)\/"
  }
 }
}

$ curl "https://personium.takky.org/admincell/__ctl/Account" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 08:21:43 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 1085
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('admin')",
     "etag":"W\/\"1-1550218455398\"",
     "type":"CellCtl.Account"
    },
    "Name":"admin",
    "LastAuthenticated":null,
    "Type":"basic",
    "Cell":null,
    "__published":"\/Date(1550218455398)\/",
    "__updated":"\/Date(1550218455398)\/",
    "_Role":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('admin')\/_Role"
     }
    },
    "_ReceivedMessageRead":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('admin')\/_ReceivedMessageRead"
     }
    }
   },{
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')",
     "etag":"W\/\"1-1550218849564\"","type":"CellCtl.Account"
    },
    "Name":"user",
    "LastAuthenticated":null,
    "Type":"basic",
    "Cell":null,
    "__published":"\/Date(1550218849564)\/",
    "__updated":"\/Date(1550218849564)\/",
    "_Role":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')\/_Role"
     }
    },
    "_ReceivedMessageRead":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')\/_ReceivedMessageRead"
     }
    }
   }
  ]
 }
}


恒例の削除も…

$ curl "https://personium.takky.org/admincell/__ctl/Account('admin')" \

-X DELETE -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 204
Date: Fri, 15 Feb 2019 08:31:41 GMT
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

$ curl "https://personium.takky.org/admincell/__ctl/Account" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 08:33:04 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 550
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')",
     "etag":"W\/\"1-1550218849564\"",
     "type":"CellCtl.Account"
    },
    "Name":"user",
    "LastAuthenticated":null,
    "Type":"basic",
    "Cell":null,
    "__published":"\/Date(1550218849564)\/",
    "__updated":"\/Date(1550218849564)\/",
    "_Role":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')\/_Role"
     }
    },
    "_ReceivedMessageRead":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')\/_ReceivedMessageRead"
     }
    }
   }
  ]
 }
}


当然、user ユーザー1件が登録されています。 OK!!


8.ロールの操作

次はロールを操作してみましょう。

まぁ、まだロールは一つも作っていないの、最初の確認は端折りましょう…


削除しなかった"user"アカウントにひも付ける"adminrole"ロールを作成しましょう。

$ curl "https://personium.takky.org/testcell/__ctl/Role" \

-X POST -i \
-d "{\"Name\":\"adminrole\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201
Date: Fri, 15 Feb 2019 08:56:08 GMT
Content-Type: application/json
Content-Length: 297
Connection: keep-alive
Location: https://personium.takky.org/admincell/__ctl/Role(Name='adminrole',_Box.Name=null)
DataServiceVersion: 2.0
ETag: W/"1-1550220968702"
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":{
   "__metadata":{
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)",
    "etag":"W\/\"1-1550220968702\"",
    "type":"CellCtl.Role"
   },
   "Name":"adminrole",
   "__published":"\/Date(1550220968702)\/",
   "__updated":"\/Date(1550220968702)\/",
   "_Box.Name":null
  }
 }
}


ではこちらも、確認してみましょう。

$ curl "https://personium.takky.org/admincell/__ctl/Role" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 08:59:21 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 958
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "__metadata":{
     "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)",
     "etag":"W\/\"1-1550220968702\"",
     "type":"CellCtl.Role"
    },
    "Name":"adminrole",
    "_Box.Name":null,
    "__published":"\/Date(1550220968702)\/",
    "__updated":"\/Date(1550220968702)\/",
    "_Box":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)\/_Box"
     }
    },
    "_Account":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)\/_Account"
     }
    },
    "_ExtCell":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)\/_ExtCell"
     }
    },
    "_ExtRole":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)\/_ExtRole"
     }
    },
    "_Relation":{
     "__deferred":{
      "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)\/_Relation"
     }
    }
   }
  ]
 }
}

Roleという箱があるだけのような状態ですね。


このロール(adminrole)に先ほど作成したアカウント(user)をひも付けましょう。

$ curl "https://personium.takky.org/admincell/__ctl/Role('adminrole')/\$links/_Account" \

-X POST -i \
-d "{\"uri\":\"https://personium.takky.org/admincell/__ctl/Account('user')\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 204
Date: Fri, 15 Feb 2019 09:15:35 GMT
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium


そして、確認。

$ curl "https://personium.takky.org/admincell/__ctl/Role(Name='adminrole')/\$links/_Account" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 09:52:36 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 94
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')"
   }
  ]
 }
}

Linkは作成できているようです。


ちなみにこのロールとアカウントのLinkは、上記では「ロールにアカウント」をLinkしましたが、「アカウントにロール」をLinkすることもできます。

#### 「ロールにアカウント」をLinkした設定を一旦削除

$ curl "https://personium.takky.org/admincell/__ctl/Role(Name='adminrole')/\$links/_Account(Name='user')" \
-X DELETE -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 204
Date: Fri, 15 Feb 2019 09:41:10 GMT
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

#### 「アカウントにロール」をLinkする
$ curl "https://personium.takky.org/admincell/__ctl/Account(Name='user')/\$links/_Role" \
-X POST -i \
-d "{\"uri\":\"https://personium.takky.org/admincell/__ctl/Role(Name='adminrole')\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 204
Date: Fri, 15 Feb 2019 09:41:24 GMT
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

#### ロールからアカウントのLinkを確認
$ curl "https://personium.takky.org/admincell/__ctl/Role('adminrole')/\$links/_Account" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 10:00:34 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 94
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Account('user')"
   }
  ]
 }
}

#### アカウントからロールのLinkを確認
$ curl "https://personium.takky.org/admincell/__ctl/Account(Name='user')/\$links/_Role" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 09:49:08 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 116
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
 "d":{
  "results":[
   {
    "uri":"https:\/\/personium.takky.org\/admincell\/__ctl\/Role(Name='adminrole',_Box.Name=null)"
   }
  ]
 }
}

ここまではなんとか… 想定通りに進められているようです。


9.ACLの操作

ここまでセルにアカウントが作成されているので、なにかコンテンツにアクセする方法を習得しましょう。そのためにはたぶん… ACLでアクセス権限などが正しく設定される必要があると思われますが、まだロールには何も設定していません。なので以下に記す profile.json を例に操作していきましょう。

っということで profile.json についてなのですが、ゆくゆく説明することになる「ホームアプリ(HomeApp)」などで、セルのプロフィールをセットするファイルが利用されるので、それを作成しACLの効果などを探っていきましょう。


まずは profile.json を unitadmin の権限で admincell に作成します。

このサンプルのAPIでは、「"Image":」のセクションには私のアイコン(にゃんこの すず ちゃん)の画像を Base64 フォーマットに変換した文字列を与えています。"触ってみる"レベルの場合はそのまま使っても良いですが、にゃんこアレルギーの方はちょっと気をつけてください。

$ curl "https://personium.takky.org/admincell/__/profile.json" \

-X PUT -i \
-d "{\"DisplayName\":\"<APIでアクセスしてみる>\",\"Description\": \"<APIでアクセスしてみる>のサンプルで利用するファイル\",\"Image\": \"data:image/png;base64,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\"}" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 100 Continue

HTTP/1.1 201
Date: Fri, 15 Feb 2019 10:42:54 GMT
Content-Length: 0
Connection: keep-alive
ETag: "1-1550227374873"
X-Personium-Version: 1.7.4
Server: Personium

profile.json のアップロードが完了したようです…


unitadmin ユーザーでアクセスしてみましょう。

$ curl "https://personium.takky.org/admincell/__/profile.json" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 10:45:22 GMT
Content-Type: application/x-www-form-urlencoded
Content-Length: 32568
Connection: keep-alive
ETag: "1-1550227374873"
Accept-Ranges: bytes
X-Personium-Version: 1.7.4
Server: Personium

{
 "DisplayName":"<APIでアクセスしてみる>",
 "Description": "<APIでアクセスしてみる>のサンプルで利用するファイル",
 "Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAABsCAYAAACPZlfNAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoaAgcXq84KswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAgAElEQVR42jy8y64kTZLf9zMzd4/IzFNV3727Od3DAW+gKEgLQgs9hMCFXkA7r<省略>MvYFmcAAAAASUVORK5CYII="
}

ファイルそのまま返ってきているようですね。


次は、先ほど登録したユーザー("user")でアクセスしてみましょう。

まずは、ユーザー("user")のトークンの取得です。

$ curl "https://personium.takky.org/admincell/__token" \

-X POST -i \
-d "grant_type=password&username=user&password={{passWord}}" \
-H "Content-Type: application/x-www-form-urlencoded"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 10:59:47 GMT
Content-Type: application/json
Content-Length: 331
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{
 "access_token":"{{userToken}}",
 "refresh_token_expires_in":86400,
 "refresh_token":"{{userRefreshToken}}",
 "token_type":"Bearer",
 "expires_in":3600
}

トークンが取得できました。

「ユニット管理者トークン」のトークンよりは、だいぶ短いトークンですね!?


では本題の、profile.json を取得してみましょう。

$ curl "https://personium.takky.org/admincell/__/profile.json" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{userToken}}"

HTTP/1.1 403
Date: Fri, 15 Feb 2019 11:06:30 GMT
Content-Type: application/json
Content-Length: 90
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{
 "code":"PR403-AU-0002",
 "message":{
  "lang":"en",
  "value":"Necessary privilege is lacking."
 }
}

ハイ。皆さんの想定通り、エラーです!! エラーコードは「PR403-AU-0002」ですね。

こんな時はドキュメントとして提供されているエラーメッセージ一覧を参照しましょう。

"Necessary privilege is lacking."ということで、英語がからっきしダメな私は Google先生 にお伺いをたて"必要な特権が不足しています。"ということであると把握しました。

image.png

ようやく、ACLを設定する必要がある!というところにたどり着きましたぁ。長かった…


ACLを設定しましょう。


API には以下のような意味が含まれてい(ると思い)ます。


  • https://personium.takky.org/admincell/__/profile.json     ← profile.jsonファイルに対して

  • xml:base="https://personium.takky.org/admincell/__role/__/"  ← __ ボックスにひも付いている

  • <D:href>adminrole</D:href>                    ← adminroleロールへ

  • <D:privilege><p:read/></D:privilege>              ← read権限を付与する

curl 'https://personium.takky.org/admincell/__/profile.json'  \

-X ACL -i \
-d '<D:acl xmlns:D="DAV:" xmlns:p="urn:x-personium:xmlns" xml:base="https://personium.takky.org/admincell/__role/__/"><D:ace><D:principal><D:href>adminrole</D:href></D:principal><D:grant><D:privilege><p:read/></D:privilege></D:grant></D:ace></D:acl>' \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 11:34:20 GMT
Content-Length: 0
Connection: keep-alive
ETag: "3-1550227374873"
X-Personium-Version: 1.7.4
Server: Personium


さて、ACLでread権限を付与できましたので、先ほど権限が足りずにエラーとなったAPIを叩いてみましょう!!

$ curl "https://personium.takky.org/admincell/__/profile.json" \

-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{userToken}}"

HTTP/1.1 200
Date: Fri, 15 Feb 2019 11:44:47 GMT
Content-Type: application/x-www-form-urlencoded
Content-Length: 32568
Connection: keep-alive
ETag: "3-1550227374873"
Accept-Ranges: bytes
X-Personium-Version: 1.7.4
Server: Personium

{
 "DisplayName":"<APIでアクセスしてみる>",
 "Description": "<APIでアクセスしてみる>のサンプルで利用するファイル",
 "Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAABsCAYAAACPZlfNAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoaAgcXq84KswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAgAElEQVR42jy8y64kTZLf9zMzd4/IzFNV3727Od3DAW+gKEgLQgs9hMCFXkA7r<省略>MvYFmcAAAAASUVORK5CYII="
}


ぅお〜〜!! できましたー。 一応APIをcurlで叩いて、アカウントやACLの操作などを体験することができました。



APIでアクセスしてみた時のまとめ


  • APIを叩くためにcurlを利用する。

  • curlを使って「ユニット管理者トークン」取得することができる。

  • 「ユニット管理者トークン」で認証すると、全てのセルに対して全ての処理を実行できる。

  • 「ユニット管理者トークン」で、アカウント・ロール・ACLなどを設定し、コンテンツを取得することができた

  • 「ユニット管理者トークン」で設定されたアカウントの「ユーザートークン」を取得することができる。

  • 「ユーザートークン」ではアカウントがひも付いているロールに適切な権限が設定されていないと、コンテンツなどにアクセスができない。

  • ロールに設定する権限は、ACLにより操作できる。

  • ACLが適切に設定された「ユーザートークン」で、コンテンツにアクセスすることができた。


このエントリーではこの辺で終わりとします。 続けて WebDav や OData と、そして ExtCell と ExtRole についてAPIを触りながら理解を深めてみようと思います。



メニュー

  • 1.APIを叩く(何をどうして良いかもわからず…)
  • 2.APIを叩く(「Personiumユニット管理 チュートリアル」を参考に…)
  • 3.Token について調べる
  • トークンのまとめ
  • 4.あらためて API を叩く!!
  • 5.ユニット管理者トークンの取得
  • 6.セルの操作
  • 7.アカウントの操作
  • 8.ロールの操作
  • 9.ACLの操作
  • ACLを設定しましょう。
  • さて、ACLでread権限を付与できましたので、先ほど権限が足りずにエラーとなったAPIを叩いてみましょう!!
  • APIでアクセスしてみた時のまとめ
  • メニュー