5.11. コマンドバックエンド

5.11.1. 概要

unicornidm.conf

5.11.2. 説明

バックエンドセクションのうち、 typecommand となっているバックエンドは、 ユーザー追加、更新などの各種操作と共に実行するコマンドの設定を行います。

Unicorn ID Manager v3 ではこのコマンドのことを コマンドバックエンド と呼びます。 これは LDAPバックエンドなどその他のバックエンドと同じように動作します。

5.11.3. リファレンス

5.11.3.1. unicornidm.conf のパラメーター

type

バックエンドのタイプを指定します。 command に設定してください。

description

バックエンドの説明文を指定します。

バージョン 3.18.7 で追加.

user_add_command

ユーザー登録の際の追加コマンドを指定します。

user_modify_command

ユーザー更新の際の追加コマンドを指定します。

user_enable_command

ユーザー有効化の際の追加コマンドを指定します。

user_disable_command

ユーザー無効化の際の追加コマンドを指定します。

user_change_password_command

ユーザーのパスワード変更の際の追加コマンドを指定します。

user_delete_command

ユーザー削除の際の追加コマンドを指定します。

user_rename_command

ユーザー名のリネームの際の追加コマンドを指定します。

group_add_command

グループ登録の際の追加コマンドを指定します。

group_modify_command

グループ更新の際の追加コマンドを指定します。

group_delete_command

グループ削除の際の追加コマンドを指定します。

group_rename_command

グループ名のリネームの際の追加コマンドを指定します。

group_add_members_command

グループにメンバーを追加する際の追加コマンドを指定します。

group_delete_members_command

グループからメンバーを削除する際の追加コマンドを指定します。

5.11.3.2. テンプレートファイル

以下は command バックエンドのテンプレートファイルの例です。:

User = {
    "userName": userName,
    "mail": mail,
    "password": password,
    "homeDirectory": default(unixHomeDirectory, "/home/%(userName)s"),
    "gidNumber": default(gidNumber, 100),
}


Group = {
    "groupName": groupName,
}

5.11.4. 基本的な設定

ユーザー追加時だけコマンドを実行させるための設定手順を説明します。

  1. 実行したいコマンドを Unicorn ID Manager が動作しているサーバーの適当なディレクトリに置いて、 uwsgi.confuid/gid パラメータで指定したユーザー・グループで実行できるようにしてください。

  2. unicornidm.conf に以下のように設定してください。

[backend:<コマンドバックエンドの名前>]
type = command
user_add_command = <手順1 で設定したコマンドへの絶対パス> something {name}
  1. テンプレートファイル templates/<コマンドバックエンドの名前>.py を作成し、以下のように書いてください。 これはRPMパッケージをインストールすると作成される templates/command-example.py の中身と同じです。

User = {
    "userName": userName,
    "mail": mail,
    "password": password,
    "homeDirectory": unixHomeDirectory,
}


Group = {
    "groupName": groupName,
}

注釈

"userName": userName,"groupName": groupName, の行は変更しないでください。

上記バックエンドをターゲットに紐付けると、そのターゲットからの操作でコマンドが実行されます。

この設定により、コマンドバックエンド以外の全てのバックエンドでユーザー登録操作が成功すると、設定したコマンドが実行されるようになります。

上記設定の場合、コマンドの第一引数に something が、 第二引数に追加したユーザーの userName フロントエンド属性の値が渡されます。 他のユーザーの属性情報は、手順3 で設定した属性のみがコマンドの標準入力に JSON として渡されます。そのフォーマットについては コマンドの標準入力に渡される JSON を参照してください。

他の操作で実行したいコマンドについても同様の方法で設定できます。 グループへの操作に対しても同様です。

5.11.5. 動作詳細

5.11.5.1. コマンド実行タイミング

設定したコマンドは指定した操作が1回実行される度に1度実行されます。

結果詳細画面で見える表の1行分が1回の操作にあたります。 例えばCSVファイルのアップロードによる一括処理はおおよそCSVの1行が1回の操作になります。 ユーザー有効化操作は確実にCSVの1行が1操作になります。 Web UI からのユーザー有効化操作は1回ボタンを押して実行するとそれが1回分の操作になります。 逆にユーザー追加処理はユーザー追加操作1回とグループへのメンバー追加操作複数回に分かれる場合があります。 この場合ユーザー追加に設定したコマンドが1回実行され、メンバー追加操作に設定したコマンドが複数回実行されます。

コマンドはコマンドバックエンド以外の全てのバックエンドでの操作が完了した後に実行されます。 これは unicornidm.conf でどの順番でバックエンドを書いたかに依らずこの挙動になります。

コマンドを実行するかどうかはそれら先に実行が終わったバックエンドの結果を元に決まります。 現状の仕様ではコマンドが実行されるのはそれらバックエンド全てで操作が成功した場合だけです。 一つでもバックエンドが操作に失敗するとコマンドは実行されません。

Unicorn ID Manager の管理者アカウントは操作実行前にコマンドバックエンドを実行するかどうかを選択することができます。 ブラウザの場合は操作実行前の画面に表示されるバックエンド選択チェックボックスで選択できます。 unicornidm-tool(8) ではオプションで選択できます。

一般ユーザーにはコマンド実行の選択権はありません。

5.11.5.2. コマンドの成功・失敗

コマンドバックエンドにも他のバックエンドと同じように操作の成功・失敗の概念があります。 コマンドバックエンドの操作の成否はブラウザの結果画面や unicornidm-tool(8) で他のバックエンドと同じように確認することができます。

コマンドが 0 以外のステータスコードで終了した場合、そのコマンドは失敗したと扱われます。 ステータスコード 0 で終了した場合は成功とみなされます。

失敗したコマンドの標準エラー出力は操作結果詳細画面でエラーメッセージとして表示されます。 対して成功した場合には操作結果詳細画面には何も表示されません。 コマンドの成否に関わらず、標準出力と標準エラー出力は unicornidm.log に出力されます。 これら出力は全て UTF-8 でデコードされて表示されます。

5.11.5.3. コマンドの文法

コマンドは unicornidm.conf に1行の文字列として設定します。 例えば以下のように設定します。

user_delete_command = rm -rf /home/osstech/student\ directory/{name}

コマンドはシェル上で実行するコマンドのように字句解析(文字列分割)され、実行されます。 この字句解析は Python の標準ライブラリである shlex を使用しています。

注意

実際にシェルを経由して実行しているわけではないので、シェルの機能が使えるわけではありません。 例えばパイプやリダイレクションは利用できません。 コマンドとして設定した実行ファイルが直接実行されます。

字句解析の結果の最初の文字列が 実行するコマンドのファイル名として実行されます。 上記例の場合 rm が実行ファイル名だとみなされ、コマンドの残りの部分は引数として rm へ渡されます。 もちろん PATH 環境変数などは考慮されます。 この実行ファイルは Unicorn ID Manager が動いているサーバー上になければなりません。

ヒント

他のサーバー (UNIX, Windows どちらでも)にあるコマンドを実行したい場合はご相談ください。

5.11.5.3.1. コマンドライン中の属性展開

コマンドの中の {属性名} (上記例の {name} など)はそのバックエンド属性の値に変換されます。 この変換は上記のシェルに似た字句解析の後に行われます。 使用できる属性名は操作によって変わります。

唯一 name という属性名はどの操作でも同じ意味で使用できます。 これはユーザーの場合 userName フロントエンド属性の、グループの場合 groupName フロントエンド属性の値に変換されます。

バージョン 4.0.0 で非推奨: userName, groupName は環境変数から取得するようにしてください。 それぞれ、 UIDM_USERNAME, UIDM_GROUPNAME という環境変数名で渡されます。 コマンドの環境変数から渡される情報 を参照してください。

5.11.5.4. コマンドの標準入力に渡される JSON

コマンドには標準入力から JSON 形式で操作対象ユーザー/グループの情報が渡されます。 渡される情報は操作によって変わります。

  • 追加操作の場合

    追加するユーザー/グループの属性が、テンプレートファイルで定義した形式で渡されます。 ただし、 userName, groupName 属性だけは取り除かれます。 JSON の構造はJSONオブジェクトのキーに属性ID が、値部にその属性の値が文字列の配列として渡されます。 オブジェクトのネストはなく、フラットな key-value 型のJSONオブジェクトになります。

    例えば リファレンス のテンプレートファイルだと、以下のような JSON が渡されます。

    {
        "mail": ["user1@example.com"],
        "password": ["weak-password"],
        "homeDirectory": ["/home/user1"],
    }
    
  • 更新操作の場合

    更新対象の属性 のみ が渡されます。 つまり、ブラウザ操作による更新では画面に映った属性の中で値を修正したものだけが渡されます。 CSV による更新操作ではCSVのヘッダーに書いた属性だけが渡されます。(ただし userName, groupName は渡されません)

    JSON の構造は追加のときと同様、属性ID がJSONオブジェクトのキーになりますが、値の部分の構造が追加のときと違います。

    例えば、以下のような JSON が渡されます。

    {
        "mail": {
            "add": ["user1+alias1@example.com"],
            "delete": ["user1@example.com"]
        },
        "homeDirectory": {
            "add": ["/home/bjensen"],
            "delete": -1
        }
    }
    

    上の例は mail 属性も homeDirectory 属性も更新しようとした場合です。 例えば、 mail 属性しか更新しようとしなかった場合には、上記 JSON から homeDirectory のフィールドがなくなったものが渡されます。

    値の部分の構造は以下のようになります。

    {
        "add": ["added-value1", "added-value2"],
        "delete": ["deleted-value1", "deleted-value2", "deleted-value3"]
    }
    

    add フィールドに追加しようとした値が、 delete フィールドに削除しようとした値が渡されます。 追加、削除しようとした値がない場合には、対応するフィールド自体が渡されません。

    例(追加しようとした値がない場合):

    {
        "delete": ["deleted-value1", "deleted-value2"],
    }
    

    例(削除しようとした値がない場合):

    {
        "add": ["added-value1", "added-value2"],
    }
    

    CSV の -- (ハイフン2つ)接頭辞を使った場合や、接頭辞を使わなかった場合は、どの属性内の値を削除しようとしているのかが分からないので、文字列のリストの代わりに -1delete フィールドの値になります。

    例(-- 接頭辞を使った場合):

    {
        "delete": -1
    }
    

    例(接頭辞を使わなかった場合):

    {
        "add": ["added-value1"],
        "delete": -1
    }
    

    ブラウザの画面操作で更新をした場合には、 Unicorn ID Manager の内部キャッシュとブラウザからのデータの差分を更新しようとするため、 delete-1 が来ることはありません。

  • 削除操作の場合

    削除前の ユーザー/グループの属性が渡されます。 構造は追加操作の場合と同じです。ただし、 password 属性は渡されません。

  • 名前変更操作の場合

    新しい名前のみが、以下のような JSON が渡されます。

    ユーザーの名前変更の場合( bjensen に名前を変更しようとした):

    {
        "newUserName": "bjensen"
    }
    

    グループの名前変更の場合( group2 にグループ名を更新しようとした):

    {
        "newGroupName": "group2"
    }
    
  • パスワード変更操作の場合

    新しいパスワードのみが、以下のような JSON が渡されます。

    {
        "password": "new-P@ssw0rd"
    }
    
  • ユーザー有効化/無効化操作の場合

    JSON は渡されません。標準入力には1バイトも渡りません。 そのため、他の操作と同じようにコマンド側で JSON をパースしようとするとエラーになります(空文字列は JSON のフォーマットとは違うため)。

  • メンバー追加/削除操作の場合

    追加/削除しようとしたメンバーの userName が渡されます。

    どちらの操作でも以下のような JSON になります。

    {
        "members": ["user1", "user2", "user3"]
    }
    

5.11.5.5. コマンドの環境変数から渡される情報

コマンドには環境変数で情報が渡されます。環境変数名には UIDM_ という接頭辞が付きます。

以下の情報が渡されます。

UIDM_OPERATION_NAME

実行している操作の名前 (ex: add, change_password) が渡されます。

UIDM_USERNAME

ユーザーに対する操作のときのみ渡されます。 操作対象ユーザーの userName が値になります。

UIDM_GROUPNAME

グループに対する操作のときのみ渡されます。 操作対象グループの groupName が値になります。

UIDM_RESOURCE_TYPE

ユーザーに対する操作の場合は User グループに対する操作の場合は Group という値が渡されます。

バージョン 3.20.3 で追加.

UIDM_BACKEND_NAME

実行しているバックエンドの名前 (ex: command-example) が渡されます。

バージョン 3.20.3 で追加.

UIDM_BACKEND_NAMES

同時に実行した全てのバックエンドの名前がカンマ区切りで渡されます。 コマンドバックエンドの名前は含まれません。 (ex: ldap-example,ad-example)

バージョン 3.20.3 で追加.

UIDM_COMMAND_NAMES

同時に実行した全てのコマンドバックエンドの名前がカンマ区切りで渡されます。(ex: command1,command2)

バージョン 3.20.3 で追加.

UIDM_SUBMITTER

操作を実行した管理者の名前が渡されます。

バージョン 3.20.3 で追加.

UIDM_START_TIME

操作を実行開始した時刻が渡されます。 出力形式はPython標準ライブラリである datetimeisoformat 関数に依存します。 (ex: 2022-12-20T15:17:08+00:00)

バージョン 3.20.3 で追加.

UIDM_IP_ADDRESS

操作を実行した接続元のIPアドレスが渡されます。(ex: 127.0.0.1, ::1)

バージョン 3.20.3 で追加.

UIDM_IP4_ADDRESS

操作を実行した接続元がIPv4アドレスだった場合に UIDM_IP_ADDRESS と同様の値が渡されます。

バージョン 3.20.3 で追加.

UIDM_IP6_ADDRESS

操作を実行した接続元がIPv6アドレスだった場合に UIDM_IP_ADDRESS と同様の値が渡されます。

バージョン 3.20.3 で追加.