本記事の目的
- Oracle Graph Server and Client 20.3.0.0.0 で新たに追加された認証・認可機能を試してみる
- 本環境での認証プロバイダはOracle Databaseを使用することとする
Oracle Graph Server and Client 20.3 から、新たに認証・認可機能が追加されました。
https://blogs.oracle.com/oraclespatial/graph-server-and-client-203-is-now-available
今回は、認証・認可機能をどのように使用するのかを試してみます。
前提条件
- 今回は、Oracle Databaseを認証プロバイダとして使用します
Oracle Graph Server and Client の認証フロー
上の図は、Graph Server and Clientにおける認証フローです。(画像はDocumentより引用しました。)
- ユーザは認証プロバイダ(本記事ではOracle Database)にログインします(本記事の手順4に該当します)
- 認証プロバイダはユーザに認証トークンを発行します(本記事の手順4に該当します)
- ユーザはセッションごとにGraph Server に認証トークンを送信します(本記事の手順5に該当します)
- Graph Serverは認証トークンを照合し、ユーザ情報(権限)を取得します(本記事の手順5に該当します)
シナリオ
本記事では、2人のユーザがそれぞれ下記に示す役割を担うことを想定します。
- graph_publisher
グラフを作成し、Graph VizへPublishすることができる。
- graph_reader
graph_publisherユーザがPublishしたグラフを読み取ることができる。
環境情報
$ cat /etc/oracle-release
Oracle Linux Server release 7.6
- Oracle Graph Server and Client 20.3.0.0.0 をインストール済みであること
(インストール方法はこちらを参考にしてください。)
手順
1. 検証用ユーザ・ロール作成
/*データベースに接続*/
$ sqlplus /nolog
SQL> conn / as sysdba
Connected.
/*PDBを確認*/
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCL READ WRITE NO
SQL> alter session set container=orcl;
Session altered.
/*ユーザ作成*/
SQL> create user graph_publisher identified by graph_publisher
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;
User created.
SQL> create user graph_reader identified by graph_reader
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;
User created.
/*作成したユーザに権限付与*/
SQL> grant connect, resource to graph_publisher;
Grant succeeded.
SQL> grant connect, resource to graph_reader;
Grant succeeded.
/*Graph Server and Client で使用するロールを作成*/
SQL> CREATE ROLE rl_graph_publisher;
Role created.
SQL> CREATE ROLE rl_graph_reader;
Role created.
/*作成したユーザにロールを付与*/
SQL> grant rl_graph_publisher to graph_publisher;
Grant succeeded.
SQL> grant rl_graph_reader to graph_reader;
Grant succeeded.
SQL> exit
2. /etc/oracle/graph/pgx.conf
を編集
$ cat /etc/oracle/graph/pgx.conf
{
"allow_idle_timeout_overwrite": true,
"allow_local_filesystem": true,
"allow_task_timeout_overwrite": true,
"authorization": [{
"pgx_role": "GRAPH_PUBLISHER",
"pgx_permissions": [{
"grant": "PGX_SESSION_CREATE" ★セッションを作成する権限
},
{
"grant": "PGX_SESSION_NEW_GRAPH" ★グラフを作成する権限
},
{
"grant": "PGX_SESSION_ADD_PUBLISHED_GRAPH" ★グラフをPublishする権限
}]
}, {
"pgx_role": "GRAPH_READER",
"pgx_permissions": [{
"grant": "PGX_SESSION_CREATE" ★セッションを作成する権限
},
{
"grant": "PGX_SESSION_GET_PUBLISHED_GRAPH" ★Publishされたグラフを取得する権限
}]
}],
"datasource_dir_whitelist":[],
"enable_gm_compiler": true,
"enterprise_scheduler_config": {
"analysis_task_config": {
"priority": "MEDIUM",
"weight": "<no-of-CPUs>",
"max_threads": "<no-of-CPUs>"
},
"fast_analysis_task_config": {
"priority": "HIGH",
"weight": 1,
"max_threads": "<no-of-CPUs>"
},
"num_io_threads_per_task": "<no-of-CPUs>"
},
"graph_algorithm_language": "JAVA",
"in_place_update_consistency_model": "ALLOW_INCONSISTENCIES",
"java_home_dir": "<system-java-home-dir>",
"max_active_sessions": 1024,
"max_queue_size_per_session": -1,
"max_snapshot_count": 0,
"memory_cleanup_interval": 60,
"path_to_gm_compiler": null,
"preload_graphs": [],
"pgx_realm": {
"implementation": "oracle.pg.identity.DatabaseRealm", ★認証プロバイダとしてOracle Databaseを指定
"options": {
"jdbc_url": "jdbc:oracle:thin:@localhost:1521/orcl", ★PDBへのJDBC URLを指定
"token_expiration_seconds": 14400,
"connect_timeout_milliseconds": 10000,
"max_pool_size": 64,
"max_num_users": 512
}
},
"release_memory_threshold": 0.25,
"session_idle_timeout_secs": 14400,
"session_task_timeout_secs": 0,
"strict_mode": true,
"tmp_dir": "/tmp"
}
3. Graph Server を起動
$ sudo systemctl start pgx
4. Token取得
Graph Server へのセッションを作成する際に必要となるTokenを取得します。
$ curl -X POST -H 'Content-Type: application/json' -d '{"username":"graph_publisher","password":"graph_publisher"}' http://localhost:7007/auth/token
以下のようなjsonが返ってきます(Tokenはドキュメントより引用)
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJraWQiOiJEYXRhYmFzZVJlYWxtIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJwZ0FkbWluIiwicm9sZXMiOlsicmVzb3VyY2UiLCJjb25uZWN0IiwiZ3JhcGhfYWRtaW5pc3RyYXRvciJdLCJpc3MiOiJvcmFjbGUucGcuaWRlbnRpdHkucmVzdC5BdXRoZW50aWNhdGlvblNlcnZpY2UiLCJleHAiOjE1OTAxMDU1MDV9.D14yGwvzW7zlyjxdiagknjB_wU3VSXnWKHFSYcLDkF2JclyMNE0MmtgJQ958BNFpvB-
ha0ODxn_H1mnIlk3Cq7aoLiXN9V2WoxpYPQSdTu1pU2cKo-NfKOJF_MaqnS-USw0XozovqtrEsnaWid8uF8vAS0WHt0Wm8nTtijoe99K__tvDgpYQH3cqicERPlBMRov9oOg-Rfuyg1o6CoGdgrNEMYG44RRJBXOBFCD15yJ2aUfMHU5fukAbh6aWmrkKbwwueUmgTdjhWlxooEwyF-C_LjksVPba2M5zRX-WOC6Zp8Lqxr6uqhxR1W4XpuQLLaD2Vw4OwpP7M5AldsS2MQ"
}
5. Graph Server へ接続
$ /opt/oracle/graph/bin/opg-jshell -b http://localhost:7007
enter authentication token (press Enter for no token): <上記で取得したaccess_tokenをコピペ>
6. グラフを作成しPublish
opg-jshell> import oracle.pgx.common.auth.*;
opg-jshell> var g = session.<Integer>newGraphBuilder(IdType.INTEGER).addVertex(1).addVertex(2).addVertex(3).addEdge(1,1,2).addEdge(2,1,3).build();
g ==> PgxGraph[name=anonymous_graph_1,N=3,E=2,created=1598162420874]
opg-jshell> g.publish();
opg-jshell> g.grantPermission(new PgxUser("graph_reader"), PgxResourcePermission.READ); //publishしたグラフの読み取り権限をユーザ(graph_reader)に付与
7. Graph Vizから結果を確認
graph_readerユーザでGraph Vizに接続します。
手順6において、graph_readerユーザに権限を付与しているので、graph_publisherユーザがPublishしたグラフを、graph_readerユーザも読み取ることができるようになっているはずです。
まずはgraph_readerユーザでGraph Vizに接続します。
確認すると、下図のように、graph_publisherユーザでPublishしたグラフをgraph_readerユーザも読み取ることができています!
想定通りの動作が確認できました。
ちなみに、graph_publisherユーザに読み取り権限を付与しない状態でグラフを確認しようとすると、下図のようなエラーが出力されてしまいます。
Appendix. 実機確認時に遭遇したエラー集
①java.lang.IllegalArgumentException: DatabaseRealm requires 'jdbc_url' to be configured in pgx.conf realm options
⇒認証プロバイダとしてOracle Databaseを指定した場合は、/etc/oracle/graph/pgx.conf
にてjdbc_urlを指定する必要がある
(修正前)
"pgx_realm": {
"implementation": "oracle.pg.identity.DatabaseRealm",
"options": {
"jdbc_url": "<REPLACE-WITH-DATABASE-URL-TO-USE-FOR-AUTHENTICATION>",
"token_expiration_seconds": 14400,
"connect_timeout_milliseconds": 10000,
"max_pool_size": 64,
"max_num_users": 512
}
},
(修正後)
"pgx_realm": {
"implementation": "oracle.pg.identity.DatabaseRealm",
"options": {
"jdbc_url": "jdbc:oracle:thin:@localhost:1521/orcl", ★
"token_expiration_seconds": 14400,
"connect_timeout_milliseconds": 10000,
"max_pool_size": 64,
"max_num_users": 512
}
},
②java.lang.IllegalStateException: cannot connect to server; requested http://localhost:7007/version?extendedInfo=true and expected status 200, got 401 instead
⇒サーバに接続する際は、Databaseで作成したユーザにロールを付与し、Tokenを取得する必要がある
https://docs.oracle.com/en/database/oracle/oracle-database/20/spgdg/using-inmemory-analyst-oracle-database.html#GUID-A08FC6AE-2807-4012-AD91-248062DA67C2
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: cannot connect to server; requested http://localhost:7007/version?extendedInfo=true and expected status 200, got 401 instead; response body = "{"type":"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1","status":401,"title":"unauthorized","detail":"missing or invalid authentication token code: PGX-ERROR-1SL24XWK00U5H","o:errorCode":"PGX-ERROR-1SL24XWK00U5H"}"
③oracle.pgx.common.auth.AuthorizationException
⇒権限が不足しています。各操作に必要な権限は下記Documentを参照。
https://docs.oracle.com/cd/E56133_01/latest/reference/security/authorization.html
opg-jshell> g.publish();
| Exception java.util.concurrent.CompletionException: oracle.pgx.common.auth.AuthorizationException: PgxUser(graph_publisher) does not have the SESSION_ADD_PUBLISHED_GRAPH permission required for this action code: PGX-ERROR-MXRML6YAEDJF
| at CompletableFuture.reportJoin (CompletableFuture.java:412)
| at CompletableFuture.join (CompletableFuture.java:2044)
| at PgxFuture.join (PgxFuture.java:135)
| at PgxGraph.publish (PgxGraph.java:4984)
| at (#2:1)
| Caused by: oracle.pgx.common.auth.AuthorizationException: PgxUser(graph_publisher) does not have the SESSION_ADD_PUBLISHED_GRAPH permission required for this action code: PGX-ERROR-MXRML6YAEDJF
| at ExceptionMarshaler.toUnserializedException (ExceptionMarshaler.java:107)
| at ExceptionMarshaler.unmarshal (ExceptionMarshaler.java:123)
| at RemoteUtils.parseExceptionalResponse (RemoteUtils.java:126)
| at HttpRequestExecutor.executeRequest (HttpRequestExecutor.java:198)
| at HttpRequestExecutor.post (HttpRequestExecutor.java:62)
| at RemoteCoreImpl$141.request (RemoteCoreImpl.java:3346)
| at RemoteCoreImpl$CoreRequest.request (RemoteCoreImpl.java:838)
| at RemoteCoreImpl$CoreRequest.request (RemoteCoreImpl.java:829)
| at AbstractAsyncRequest.execute (AbstractAsyncRequest.java:48)
| at RemoteCoreImpl.request (RemoteCoreImpl.java:399)
| at RemoteCoreImpl.publish (RemoteCoreImpl.java:3336)
| at PgxGraph.publishAsync (PgxGraph.java:3193)
| at PgxGraph.publishAsync (PgxGraph.java:3174)
| ...
参考資料
-
Oracle Graph Property Graph Developer’s Guide
~ 3.1 PGX User Authentication and Authorization
https://docs.oracle.com/en/database/oracle/oracle-database/20/spgdg/using-inmemory-analyst-oracle-database.html#GUID-FE3E0493-D720-4215-A28C-00F03F3BE5D6 -
Oracle Labs Parallel Graph AnalytiX (PGX)
~ Class PgxGraph
https://docs.oracle.com/cd/E56133_01/latest/javadocs/oracle/pgx/api/PgxGraph.html