これは InterSystems FAQ サイトの記事です。
InterSystems 製品で利用できる ID およびアクセスの管理には、Kerberos、OS ベース、InterSystems ログイン(=インスタンス認証/パスワード認証)、2 要素認証、JWT 認証、LDAP 認証(AD も含む)、OAuth2 などが用意されていますが、これらのどの方法にも当てはめることのできない独自の管理方法をお持ちの場合に利用できる方法があり「代行認証」(または委譲認証)と呼びます。
ドキュメント:代行認証
このトピックでは、代行認証を行うまでの手続きについて解説します。
サンプルコードはこちら👉https://github.com/Intersystems-jp/FAQ-716
シナリオとして、アプリケーション用ユーザ名、パスワードを管理する専用テーブルがあるとしています。特定の REST API のログイン、またはターミナルアクセス利用時にこの情報を使用して代行認証を行う方法を解説します。
大まかな手順は以下の通りです。
[1] 専用ルーチンを作成する
[2] システム・セキュリティの認証/ウェブセッションオプションを変更する
[3] 使用するサービスに対して代行認証を有効化する
[4] テストする
[1] 専用ルーチンを作成する
以下の流れで作成します。
1、サンプルコードのダウンロード
2、コードのインポート
3、コードの修正
1、サンプルコードのダウンロード
https://github.com/Intersystems-jp/FAQ-716 を使用します。
git clone または、以下の画面例にあるように緑の [<> Code] ボタンをクリックし、[Download ZIP] からダウンロードを行ってください。
.png)
2、コードのインポート
ダウンロードしたコードを InterSystems 製品にインポートします。
%SYS ネームスペースに接続した状態でインポートします。
※ Zから始まるルーチンやパッケージ名はアップグレードインストールを行っても消去されないルールがあります。ダウンロードしたルーチン名のままインポートを行ってください。
インポート方法はお好みの方法をご利用ください。(IDE、管理ポータルなど)
.png)
3、コードの修正
例では、%SYS ネームスペースに ZTest.Credentials テーブルを用意し、ユーザ名とパスワードの管理が行われていると仮定しています(ユーザ名、パスワードの管理を行うテーブル、チェック用ルーチンやメソッドは任意のネームスペースに配置することができますが、例では、Zから始まる名称の専用テーブル(=クラス)を用意し、%SYS に配置しています)。
代行認証を行うときにユーザから入力されるユーザ名、パスワードは ZAUTHENTICATE ルーチンの ZAUTHETICATE() 関数で受け取ることができます。
シグニチャは以下の通りです。
ZAUTHENTICATE(ServiceName,Namespace,Username,Password,Credentials,Properties) PUBLIC {
引数の仕様は以下の通りです。
- ServiceName:認証時に使用しているサービス名が入ります。(例:%Service_Console)
- Namespace:認証通過時のアクセス先ネームスペース名
- Uesrname:認証時にユーザが入力したユーザ名
- Paswword:認証時にユーザが入力したパスワード
- Credentials:(未使用)
- Properties:参照渡し。Username のユーザに対する属性を指定できます(ログインロールなど指定できます)
詳しくは、ドキュメントもご参照ください。「代行認証-シグニチャ」
ZAUTHENTICATE() 関数に、代行認証を使用するように設定したサービスから渡される認証情報を元に、アプリケーション用データを利用したユーザ名、パスワードのチェックを行い、認証の成功/失敗を評価します。
例えば、ターミナルアクセス時:%Service_Console、iris session:%Service_Terminal を利用したときのチェックは以下のように記載します。
If (ServiceName="%Service_Console")||(ServiceName="%Service_Terminal") {
set result=##class(ZTest.Credentials).check($GET(Username),$GET(Password))
//認証失敗時
if result=0 {
return $SYSTEM.Status.Error($$$GeneralError,"ユーザ認証失敗 Username="_$GET(Username))
}
set Properties("Roles")="%Developer,%DB_USER"
set Properties("NameSpace")="USER"
return $SYSTEM.Status.OK()
}
特定の REST アプリケーション /hello に対して使用する場合は以下の通りです。
REST アクセス時、サーバ側では、HTTP 要求の内容を %request 変数に格納します。チェックとしては、 %request変数にインスタンスが格納されているかどうか、また、格納されている場合、Application プロパティに REST のエンドポイントとして設定したパス名が含まれているかをチェックします。
含まれている場合、アプリケーションで用意した認証チェックを実行します。
//特定のRESTアプリから来た場合
If $isobject($get(%request)) {
If %request.Application["/hello" {
set result=##class(ZTest.Credentials).check($GET(Username),$GET(Password))
//認証失敗時
if result=0 {
return $SYSTEM.Status.Error($$$GeneralError,"ユーザ認証失敗 Username="_$GET(Username))
}
set Properties("Roles")="%Developer,%DB_USER"
return $SYSTEM.Status.OK()
}
}
コード全体はこちらをご覧ください。
$SYSTEM.Status.OK() を戻すと認証が成功したことを意味します。
失敗時は、以下メソッドを使用してエラーの理由をエラーステータスとして戻せます
$SYSTEM.Status.Error($$$GeneralError,"任意文字列")
認証失敗の場合は ZAUTHENTICATE から返したエラーが監査に記録されるのでそれを確認できます。
メモ:サンプルコードでは、ログインしようとしたユーザにはアクセスが拒否されたことだけが通知され、認証失敗の理由までは表示されません。もし、失敗理由を含めて監査に記録したい場合は、ZAUTHENTICATE ルーチン内でエラー条件に合わせシステム提供マクロを使用しながらエラーを返す工夫が必要です。
詳しくは、[4] テストする をご参照ください。
[2] システム・セキュリティの認証/ウェブセッションオプションを変更する
ZAUTHENTICATE ルーチンの準備が整ったら、代行認証に関するシステムワイドの設定を変更します。
管理ポータル > [システム管理] > [セキュリティ] > [システム・セキュリティ] > [認証/ウェブセッションオプション]を開き、「委譲認証(または代行認証)を許可」にチェックを入れます。
.png)
[3] 使用するサービスに対して代行認証を有効化する
代行認証を使用する接続経路であるサービスの設定を行います。
管理ポータル > [システム管理] > [セキュリティ] > [サービス]
ターミナルにログインする場合のサービスは以下の通りです。
- Windowsのターミナルアクセスに対するサービスは、%Service_Console
- Windows以外で iris session を利用してIRISにログインするときのサービスは、%Service_Terminal
対象のサービスの認証方式を「委譲(または代行)」のみをチェックし、保存します。
%Service_Terminalの例
特定のREST用パスに対する設定は以下の通りです。(例:/hello のパスに対する設定)
管理ポータル > [システム管理] > [セキュリティ] > [アプリケーション] > [ウェブ・アプリケーション] > パス名選択 > 許可された認証方法:委譲(または代行)のみチェックして保存
.png)
[4] テストする
[4]-1 ターミナルにログイン
正しいユーザ名、パスワードの組み合わせを入力するとログインできます。
iris session でログインしたときの成功時の例(ユーザ名:jamesmichael)と失敗時の例(ユーザ名:SuperUser)です。
ユーザ名:jamesmichael のパスワードは、oj9`b`PJB{tH|\ です。
ダミーユーザのパスワードについては、ZTest.Credentials クラスの ceatedummydata()をご参照ください。
irisowner@46f7d0610414:/opt/src$ iris session iris
ノード: 46f7d0610414 インスタンス: IRIS
ユーザ名:jamesmichael
パスワード:**************
USER>write $username
jamesmichael
USER>h
irisowner@46f7d0610414:/opt/src$ iris session iris
ノード: 46f7d0610414 インスタンス: IRIS
ユーザ名:SuperUser
パスワード:***
アクセスが拒否されました。
ユーザ名:
[4]-2 RESTアプリのBasic認証でテスト
REST アプリのBasic認証にアプリ内で利用するユーザ名、パスワードの組み合わせを指定し、ログインできるか確認します。
認証を失敗すると 401 Unauthorized が返ります。
POSTMANでの実行例です。
.png)
失敗時の例です。
.png)
また、ログインが成功すると、「代行ユーザ」というタイプでInterSystems製品内ユーザとして登録されます。このユーザは、管理ポータルで削除以外の編集作業は行えないユーザとして登録されます(管理ポータル > システム管理 > セキュリティ > ユーザ )。
.png)
認証失敗を確認するには、監査を使用すると便利です。
監査は、[システム管理] > [セキュリティ] > [監査] > [監査データベースの閲覧] のページで確認できます(検索ボタンを押すとレコードの中身が表示されます)。
イベント:LoginFailure で記録されるので、該当行の詳細リンクをクリックします。
.png)
もし、監査が無効になっている場合には、以下メニューで監査を有効に設定し、確認してください。
[システム管理] > [セキュリティ] > [監査] > [監査を有効に]
監査が有効になっていない場合、システムイベント %System/%Login/Login とLoginFailure の状態を確認し、[Enabled] 列が[はい] になっていない場合は変更します。手順は以下の通りです。
[システム管理] > [セキュリティ] > [監査] > [システムイベントを構成]
%System/%Login/Login とLoginFailure の行の [Enabled] が [はい] になっているかご確認ください。[いいえ] になっている場合は、[状態変更] を1度クリックし [はい] に変更してください。
.png)