【ServiceNow】Requested Itemの添付ファイルを取得したい

### はじめに

- バージョン
  - ServiceNow: Rome


　テーブル``Requested Item[sc_req_item]``には、以下のようにファイル添付することが
可能です。今回は、これらの添付ファイルをAPI経由でダウンロードする方法を調査しました。

![request_item.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/c52fa07b-213b-75dd-e051-95a0d7782316.png)

### 1. サンプルコード

　今回作成したコードは以下です。シンプルさ重視のためエラー回避等はしておりません  
ので、実際に使用する際は適宜修正願います。


```python
import requests
import os
from typing import List

# Set the request parameters
BASE_URL = "https://devXXXXXX.service-now.com"
USER = "admin"
PASSWORD = "password"
REQUESTED_ITEM_SYS_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"    # Requested ItemのSys ID
OUTPUT_DIR = "/tmp/output"


def get_requested_item_file_list(
    base_url: str, user: str, password: str, requested_item_sys_id: str
) -> List:
    url = base_url + "/api/now/attachment?table_sys_id=" + requested_item_sys_id
    headers = {"Accept": "application/json"}
    response = requests.get(url, auth=(user, password), headers=headers)
    return response.json()["result"]


def save_requested_item_file_content(
    base_url: str,
    user: str,
    password: str,
    requested_item_sys_id: str,
    output_dir: str,
) -> None:
    ritm_file_list = get_requested_item_file_list(
        base_url, user, password, requested_item_sys_id
    )
    for ritm_file_item in ritm_file_list:
        output_path = os.path.join(output_dir, ritm_file_item["file_name"])
        with open(output_path, mode="wb") as f:
            f.write(
                requests.get(
                    ritm_file_item["download_link"], auth=(user, password)
                ).content
            )


if __name__ == "__main__":
    save_requested_item_file_content(
        BASE_URL, USER, PASSWORD, REQUESTED_ITEM_SYS_ID, OUTPUT_DIR
    )
```

**ポイント**

1. Requested Itemのファイル一覧取得用URL
   - 関数get_requested_item_file_listにおいて、Requested Itemのファイル一覧取得用
   のURLにアクセスします。URLは以下のようになります。

     ```text
     https://devXXXXXX.service-now.com/api/now/attachment?table_sys_id={{ Requested ItemのSys ID }}
     ```

2. 関数get_requested_item_file_listの結果
   - 関数get_requested_item_file_listより以下のような、Requested Itemのファイルに関する
   情報が得られます。関数save_requested_item_file_contentでは、この中のキーである  
   ``file_name(ファイル名)``と``download_link(ファイルのダウンロードに必要なURL)``を使用します。

     ```json
     [
         {
             "size_bytes": "8139",
             "file_name": "RITM0010057_file1.xlsx",
             "sys_mod_count": "1",
             "average_image_color": "",
             "image_width": "",
             "sys_updated_on": "2022-06-20 09:35:47",
             "sys_tags": "",
             "table_name": "sc_req_item",
             "sys_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(RITM0010057_file1.xlsxのSys ID)",
             "image_height": "",
             "sys_updated_by": "system",
             "download_link": "https://devXXXXXX.service-now.com/api/now/attachment/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/file",
             "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
             "sys_created_on": "2022-06-20 09:35:46",
             "size_compressed": "5704",
             "compressed": "true",
             "state": "available",
             "table_sys_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(Requested ItemのSys ID)",
             "chunk_size_bytes": "700000",
             "hash": "ハッシュ値",
             "sys_created_by": "admin"
         },
         以下、省略
     ]
     ```

### 2. 拡張子について

　今回は、拡張子がcsv/xlsx/txt形式の3種類を試しましたが、yml形式はそもそも
Requested ItemにUpload出来ませんでした。
どうやら、テーブル``System Properties[sys_properties]``の以下内容が
影響しているようです。

- glide.attachment.extensions
  - ファイル添付可能な拡張子の一覧(デフォルト: 空欄)
- glide.security.file.mime_type.validation
  - MIMEタイプを確認するか(デフォルト: true)

　個人用のDeveloper環境では、``glide.security.file.mime_type.validation``
をfalseにしたらUploadできるようになりましたが、悪意のあるファイルがアップロードされる
可能性を考えると本番環境では変更するのは厳しいと思われます。（全体設定に影響する
部分なので設定変更時は注意してください）

### 参考記事

[Restrict file extensions (instance security hardening) - ServiceNow Product Documentation](https://docs.servicenow.com/bundle/rome-platform-administration/page/administer/security/reference/restrict-file-extensions.html)
[Upload MIME type restriction (instance security hardening) - ServiceNow Product Documentation](https://docs.servicenow.com/bundle/rome-servicenow-platform/page/administer/security/reference/upload-mime-type-restriction.html)
[Attachment API - ServiceNow Developers](https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_AttachmentAPI)