ServiceNowのパスワードリセット申請フォームの作成

#概要
今回はServiceNowのユーザパスワードをリセットする申請フォームを作成します。勿論、標準機能でもユーザは自分のパスワードを変更することはできます。しかし、ロックアウトされた場合は管理者にリセットをお願いすることになります。
また、類似した仕組みでServiceNow以外のパスワードリセットを行うことも可能です。

#設計
パスワードリセット処理で重要なのはパスワードをクリアテキストで扱わないことです。そのために、サービスカタログ用フォームのフィールド型を「マスク済み」型にして暗号化にします。

また、ServiceNowが提供しているGlideEncrypterクラスを3DES暗号アルゴリズムを利用した結果をFlow DesignerのUpdate Passwordアクションを利用してServiceNowのパスワードを変更します。他のサービス用のアクションを作成したら、他サービスのパスワードリセットも行うことができるようになります。

#実装
##申請フォームの作成
1.次なような申請フォームを作成します。
カタログアイテムの名前：Password Reset Form
フォームをポータルに表示する場合に価格や数量の入力は不要なので、「ポータルの設定」タブを選択して次の画面のように表示項目からチェックします。
2.ポータルの設定を行った後にユーザと新しいパスワードを入力するフィールドを定義します。
![password_reset_form_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/48f134ef-52f3-7ef8-3ea0-ecf8903a6fdc.png)
3.フィールド「ユーザ」はServiceNowのユーザテーブル（sys_user）を参照するようにします。要するに本フォームは既存ユーザのパスワードを変更することは出来ますが新規ユーザは登録はできません。
![password_reset_form_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/e823bb96-fee9-02c2-359f-95f0658afe20.png)
4.一般ユーザのみのパスワード変更を許可します。Webサービスや内部統合ユーザのパスワードは申請できないように条件を設定します。
![password_reset_form_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/bc39884e-c71e-c2a6-3a78-25830193e1c6.png)
5.パスワード入力フィールドはパスワードを非表示かつ暗号化するたまに「マスク済み」タイプにします。「1行テキスト」にすると入力中にパスワードが表示されますのでセキュリティリスクになります。
（スクリーンショットの言語が英語を変えてしまいました。）
![password_reset_form_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/859cf95f-8b3c-fa14-74ff-bd7803322206.png)
6.パスワードを暗号化して保存するように設定します。「マスク済み」はただ入力画面でパスワードを表示するか非表示にするかの設定です。テーブルでは暗号化されていなくて表示されます。暗号化してテーブルに登録するようにするには「タイプ仕様」タブを選択して「暗号化を使用」をチェックします。
![password_reset_form_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/7c7b4f42-d868-1e71-cbd0-5d26b73f3ef6.png)

##フローの作成
次のフローを作成します。申請されたらパスワードの変更を許可するか管理者に承認をお願いします。許可されない場合は申請を終了にします。
許可された場合はパスワードを変更します。ただし、フォームのパスワードはMasked型ですが、パスワード変更アクションのパラメータはPassword2型なので型を変換する必要があります。この変換をするアクションは作成する必要があります。
![password_reset_flow_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/2faafd0d-1839-de3a-7905-20e4e860efcd.png)
###アクションの作成
パスワードの型をMask型からPassword2型に変換して指定したユーザを取得するアクションを作成します。
1.アクション「convert mask to password2」を作成します。
アクション入力は次の通りです。

|ラベル|名前|タイプ|必須|
|---|---|---|---|
|req_item|req_item|Reference.Requested Item|必須|
![password_reset_action_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/51c08eec-cb18-e4d9-c3ec-14eb622bdd25.png)

2.スクリプトステップを追加します。パスワードを変更するユーザも必要なのでユーザ情報も取得します。
![password_reset_action_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/3a5612a8-5679-7694-6922-57273cc1ce20.png)

スクリプトステップの入力

|ラベル|値|コメント|
|---|---|---|
|req_item|action->req_item|アクション入力変数|

スクリプト
```
(function execute(inputs, outputs) {
    var encr = new GlideEncrypter(); 
  	outputs.password2 = encr.encrypt(inputs.req_item.variables.password.getDecryptedValue());
    outputs.sys_user = inputs.req_item.variables.user;
})(inputs, outputs);
```
inputs.req_item.variables.passwordとは入力フォームのMasked型で暗号化されたパスワードフィールです。.getDecryptedValue()で解読します。「inputs」とはこのメソッドの引数で渡されたパラメータです。内容はスクリプトステップの入力で定義された変数です。
「req_item」はスクリプトステップで定義された変数名です。「variables」とは要求アイテムの変数が格納されている変数名です。サービスカタログフォームのすべてのフィールはvariablesの下に格納されています。要求アイテムを日本語で開くと「変数」と表示されますが、英語で表示すると「variables」と表示されます。
![password_reset_action_2b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/3ca157c4-374b-d6c7-533a-296a2789c4ef.png)

GlideEncrypter()はServiceNowのユーザテーブルで利用されているパスワード型クラスです。解読したパスワードを再びGlideEncrypter.encrypt()で暗号化します。

スクリプトステップの出力

|ラベル|名前|タイプ|必須|
|---|---|---|---|
|password2|password2|Password (2 Way Encryption)|必須|
|sys_user|sys_user|Sys ID (GUID)|必須|

3.アクションの出力を定義します。

|ラベル|名前|タイプ|必須|値|コメント|
|---|---|---|---|---|---|
|password2|password2|step -> Script step -> password|必須|スクリプトステップ出力のpassword2変数|
|sys_user|sys_user|SysID (GUID)|必須|step -> Script step -> sys_user |スクリプトステップのsys_user変数|
![password_reset_action_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/7e5b3540-0ab4-8ed1-1e5f-fd1058a2a9ed.png)

![password_reset_action_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/8894f2a3-7a6d-1c4b-d364-74bed388e89e.png)

###フローの定義
次のフローを作成します。スクリーンショットに表示されている番号は次のスクリーンショットのアクション番号です。
![password_reset_flow_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/d49523d3-58c4-762f-549f-33cc634171d8.png)
1.フォームが入力されたらフローを実行するので起動条件（TRIGGER)を「Service Catalog」にします。
![password_reset_flow_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/36f538d0-582b-94a7-8947-e55859f6f37a.png)
2.最初に承認を依頼します。下の例では承認をServiceNow Adminグループメンバーにお願いするように設定しています。実運用の場合はServiceNowユーザ管理グループを作成してそれを指定することもできます。メンバーが一人の場合でもユーザではなく、担当者が退職や移席される場合もあるのでグループを作成してそれを指定することを推奨します。
![password_reset_flow_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/8c54b49a-f1b0-8341-466d-3b6ae9709558.png)
3.承認結果により分岐します。右側の処理はEndで終了されないと、継続して左側の処理が実行されます。多くの場合は右側にエラーの場合の処理を記述して、左に正常系処理を記述します。
申請はキャンセルされる場合もありますので、「却下」された場合よりも承認されない場合を条件にします。
「1-> Approval State」「次の値ではない」「承認済み」
![password_reset_flow_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/c2815e5a-a5f6-fefd-ef2b-cfcdd385728c.png)
4.承認されない場合の処理を追加します。
承認されない場合は次のように設定します。

|フィールド|値|コメント|
|---|---|---|
|ステージ|Task Request Rejected|申請を却下した|
|ステータス|完了してクローズ|申請を閉じる|

![password_reset_flow_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/e1ddadd2-f8ed-f2d7-57bb-900dca755281.png)

5.承認された場合の処理を追加します。
先ずは申請されたパスワードの型変換とユーザ情報の取得を行います。
作成されたアクションを呼び出します。申請を引数として渡します。
![password_reset_flow_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/fa5595e1-bc0b-ab6a-dd5e-9b0ecbb5e7f7.png)
6.取得したユーザのsys_idを元にユーザレコードを取得します。
![password_reset_flow_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/4ef1d079-6445-a573-b8a4-c548562e534f.png)
7.ユーザパスワードを変更します。取得したユーザレコードと変換したパスワードを引数として渡します。
これでフローの定義は完了です。必要に応じてフローのテストを行います。
![password_reset_flow_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/378fb5bc-ee10-bb36-c052-e65949647835.png)

###アクション有効化
フォームを入力したらフローが実行されるようにします。
アクション及びフローを有効にして、フォームに割り当てます。また、アクション及びフローは有効にされるまではアップデートセットに含まれません。
1.作成したアクションを開いて右上の「公開」ボタンを押下します。
![password_reset_action_publish_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/c93ac56b-2263-9c9c-91f6-77cb780c0d74.png)
2.公開されるとステータスは「Published」に変わります。アクションはリビジョン管理されています。もしアクションを修正した場合は「保存」した後に再び「公開」を押下されるまでは古いリビジョンでアクションが使われ続けます。
![password_reset_action_publish_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/70cce720-3ec8-b65b-0365-a847bcf35e1d.png)

###フローの有効化
フローを有効にします。フローを有効するまではフォームと紐づけることはできません。
1.作成したフローを開いて「有効化」ボタンを押下します。
![password_reset_flow_activate_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/b1d215cf-a10b-5762-2bde-a284761c149a.png)
2.確認ダイアログが表示されるので「OK」ボタンを押下します。
フローを有効化するまでは手動で「テスト」ボタンを押下しないとフローは実行されませんでしたが、有効化するとトリガーの条件に一致すると実行されるようになります。
今回は要求アイテムが申請されると実行するように指定しているので影響は少ないですが、例えばトリガーの条件を毎日指定した時間に実行するように設定した場合は、フローを有効化すると毎朝実行されるようになります。
![password_reset_flow_activate_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/a54a7faf-18cd-15e5-af6e-3ab6e35e740b.png)
3.フローが有効化されるとステータスは「Publish」に変わり、有効化ボタンも「非アクテブ化」に変わります。
![password_reset_flow_activate_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/7fb372bb-df5e-f047-0fcd-4af1fe85c50c.png)

###フォームにフローの割り当て
最後に有効にしたフローを申請フォームに割り当てます。
1.申請フォームを開き、「プロセスエンジン」タブを選択します。
項目「フロー」に作成したフローを指定して、「更新」ボタンを押下します。
![password_reset_assign_flow_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/2ebdb22f-12a6-385e-5d5a-a5b6036e598c.png)

これで要求アイテムからパスワード変更申請を登録するとフローが実行されるようになりました。

以上