Cisco Email Security の新しい API を触ってみよう



### はじめに
この投稿では Cisco Email Security 製品である ESA と SMA の新しい API について紹介します。

### ESA と SMA について 
ESA と SMA は Cisco のセキュリティソリューションのうち Email Security に分類される製品です。
ESA (Email Security Appliance) はメールゲートウェイとしてアンチウイルス、アンチスパム、AMP といった各種セキュリティスキャンを提供します。
SMA (Security Managaement Appliance) は ESA の集中管理をアウトオブバンドで提供します。基本的な機能は ESA だけで全て利用できますが、中大規模の構成ではレポートや検索、隔離メールの保管などを集中管理するために SMA を導入することが多いです。

ESA、SMA は 2007 年に買収された Ironport 社[^1]のコンテンツセキュリティソリューションのラインナップに由来し 、Office 365 や Exchange、G Suite など組織で運用されているメールボックスを保護するためのセキュリティゲートウェイを提供します。
アプライアンスでの提供のほか、ESX、KVM、Hyper-V といったハイパーバイザ上で動く仮想マシンでの提供もしています。
また近年では、シスコの運用するクラウドで提供される Cloud Email Security (CES) という SaaS 型ソリューションもご好評いただいています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/0f9c356d-78ec-ad9b-611d-a8090ecb98ee.png)

### ESA と SMA の新しい API
AsyncOS 12.0 から新しいダッシュボードおよび API が公開されました。
管理 GUI の上にある「Email Security Appliance is getting a new look. Try it !」というリンク から新しいダッシュボードへ行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/778a7b3b-f901-f4b5-ae4d-99de6620e3da.png)

右上の `?` > `API Help: Swagger` から、API ドキュメントのページに遷移します。 
余談ですが swagger とは RESTful API を記述するための標準的なインターフェイス記述言語です。Cisco でも [Firepower Management Center (FMC)](https://www.cisco.com/c/ja_jp/products/security/firewalls/index.html#~management) や [DNA Center](https://www.cisco.com/c/ja_jp/products/cloud-systems-management/dna-center/index.html) など様々な製品で利用されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/4fa07386-6add-1901-13e0-b503d7ff8be3.png)
`https://{esa_or_sma_ip_address}:4431/swagger#/` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/42a36724-41a1-3be6-b57e-4d8cbb0e4ae8.png)

### 環境の準備
[dcloud](http://dcloud.cisco.com/) や [cisco.com ダウンロードページ](https://software.cisco.com/download/home/284900944/type/282975113/release/13.5.1) などを利用して ESA (version 13.5.1) を用意します。（API を操作するだけなら SMA は必須ではありません）
シスコでは 45 日間の[評価用ライセンス](https://community.cisco.com/t5/セキュリティ-ドキュメント/esa-評価ライセンスの取得方法/ta-p/3948698)を提供しています。

今回 API リクエスト/レスポンスの確認には Postman を利用しました。
ESA、SMA ではユーザごとにクエリの権限を定義することができますが、ここではデフォルトの管理者 admin ユーザの情報を利用します。

### API の有効化
`Network > IP Interfaces` から API サービス（AsyncOS API）を有効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/2dc23186-ade9-b633-8aef-713b42a7503e.png)


### API の種類
ESA、SMA で用意されている API は大きく3種類に分けられます。
1. Tracking API
2. Reporting API
3. Quarantine API
です。

その他にもシステム情報などを取得する汎用 API がありますが、ここでは1~3の API についてそれぞれサンプルリクエストとレスポンスを紹介します。

### よく使うアトリビュート

残念ながら swagger のページではあまりリソースアトリビュートについての紹介がされていないので、よく使うアトリビュートを例示しておきます。[SMA プログラミングガイド](https://www.cisco.com/c/ja_jp/td/docs/security/security_management/sma/sma12-0/api/b_SMA_API_12/b_SMA_API_12_chapter_01.html)にも詳しく紹介されています。

|アトリビュート  | Syntax |例  |
|---|---|---|
|startDate/EndDate  | srting(ISO8601)  | startDate=2020-11-02T19:00:00.000Z&endDate=2020-12-02T19:00:00.000Z  |
|searchOption|string|searchOption=message|
|Offset  |srting  |Offset=0  |
|Limit  |srting  |Limit=10  |
|quarantineType|string|qiarantineType=spam|
|MID|string|MID=185|
|ciscoHost  |string  |ciscoHost=All_Hosts  |



### 使い方その1: メッセージの検索 (Tracking API)

Tracking API を使うことで、ESA で処理されたメッセージを検索できます。ESA および SMAの の管理 GUI では「メッセージトラッキング」という検索機能を提供していますが、その機能を API 経由で同様に提供します。

Request の例 (環境の都合で SMA を利用)

```
curl --location --request GET 'https://10.71.132.156:4431/sma/api/v2.0/message-tracking/messages?startDate=2020-11-25T19:00:00.000Z&endDate=2020-12-02T19:00:00.000Z&ciscoHost=All_Hosts&searchOption=messages&offset=0&limit=5' \
--header 'Accept: application/json, text/plain, */*' \
--header 'Authorization: Basic XXXXXXXXXXXXXXXXX'
```

Postman だとこのようなパラメータとなりました。（Authorization、Headers タブの画像は割愛）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437531/7617377b-3cc3-a6f8-81b1-7f4311c70336.png)

<details><summary> Response Body </summary><div>

```json
{
    "meta": {
        "num_bad_records": 0,
        "totalCount": 5
    },
    "data": [
        {
            "attributes": {
                "senderDomain": "exchange.local",
                "direction": "outgoing",
                "icid": 3604,
                "senderGroup": "RELAYLIST",
                "sender": "test@exchange.local",
                "replyTo": "N/A",
                "timestamp": "02 Dec 2020 11:46:32 (GMT +09:00)",
                "hostName": "esa.exchange.local",
                "subject": "test mail",
                "mid": [
                    4802
                ],
                "isCompleteData": "N/A",
                "messageStatus": {
                    "4802": "Delivered"
                },
                "mailPolicy": [
                    "test-out-policy"
                ],
                "senderIp": "10.71.132.151",
                "verdictChart": {
                    "4802": "20100200"
                },
                "allIcid": [
                    3604
                ],
                "recipient": [
                    "test@lab.local"
                ],
                "sbrs": "None",
                "serialNumber": "420F0ED81071F77BD799-069761D569A1"
            }
        },
        {
            "attributes": {
                "senderDomain": "exchange.local",
                "direction": "outgoing",
                "icid": 3603,
                "senderGroup": "RELAYLIST",
                "sender": "mailuser@exchange.local",
                "replyTo": "N/A",
                "timestamp": "02 Dec 2020 11:45:43 (GMT +09:00)",
                "hostName": "esa.exchange.local",
                "subject": "this is test",
                "mid": [
                    4801
                ],
                "isCompleteData": "N/A",
                "messageStatus": {
                    "4801": "Delivered"
                },
                "mailPolicy": [
                    "test-out-policy"
                ],
                "senderIp": "10.71.132.151",
                "verdictChart": {
                    "4801": "20100200"
                },
                "allIcid": [
                    3603
                ],
                "recipient": [
                    "test@lab.local"
                ],
                "sbrs": "None",
                "serialNumber": "420F0ED81071F77BD799-069761D569A1"
            }
        },
        {
            "attributes": {
                "senderDomain": "qualysguard.com",
                "direction": "incoming",
                "icid": 3546,
                "senderGroup": "UNKNOWNLIST",
                "sender": "qgmrfrom@qualysguard.com",
                "replyTo": "N/A",
                "timestamp": "02 Dec 2020 10:51:07 (GMT +09:00)",
                "hostName": "esa.exchange.local",
                "subject": "(empty subject)",
                "mid": [
                    4800
                ],
                "isCompleteData": "N/A",
                "messageStatus": {
                    "4800": "Dropped"
                },
                "mailPolicy": [
                    "TEST_IN_POLICY"
                ],
                "senderIp": "64.102.12.47",
                "verdictChart": {
                    "4800": "20000000"
                },
                "allIcid": [
                    3546
                ],
                "recipient": [
                    "qgmrtest@qualysguard.com"
                ],
                "sbrs": "None",
                "serialNumber": "420F0ED81071F77BD799-069761D569A1"
            }
        },
        {
            "attributes": {
                "senderDomain": "N/A",
                "direction": "",
                "icid": 3524,
                "senderGroup": "N/A",
                "sender": "(no sender)",
                "replyTo": "N/A",
                "timestamp": "02 Dec 2020 10:50:56 (GMT +09:00)",
                "hostName": "esa.exchange.local",
                "subject": "(empty subject)",
                "mid": [
                    4799
                ],
                "isCompleteData": "N/A",
                "messageStatus": {
                    "4799": "Aborted"
                },
                "mailPolicy": [],
                "senderIp": "N/A",
                "verdictChart": {
                    "4799": "00000000"
                },
                "allIcid": [
                    3524
                ],
                "recipient": [
                    "test321",
                    "test321@smtpdomain.com"
                ],
                "sbrs": "N/A",
                "serialNumber": "420F0ED81071F77BD799-069761D569A1"
            }
        },
        {
            "attributes": {
                "senderDomain": "qualys.com",
                "direction": "",
                "icid": 3477,
                "senderGroup": "N/A",
                "sender": "test@qualys.com",
                "replyTo": "N/A",
                "timestamp": "02 Dec 2020 10:50:46 (GMT +09:00)",
                "hostName": "esa.exchange.local",
                "subject": "(empty subject)",
                "mid": [
                    4798
                ],
                "isCompleteData": "N/A",
                "messageStatus": {
                    "4798": "Aborted"
                },
                "mailPolicy": [],
                "senderIp": "N/A",
                "verdictChart": {
                    "4798": "00000000"
                },
                "allIcid": [
                    3477
                ],
                "recipient": [
                    "(no recipient)"
                ],
                "sbrs": "N/A",
                "serialNumber": "420F0ED81071F77BD799-069761D569A1"
            }
        }
    ]
}
```
</div></details>


### 使い方その2: レポート情報の取得 (Reporting API)

ESA、SMA の管理画面から PDF および CSV 形式で各種統計情報をレポートとして取得することができますが、Reporting API は同様の内容を API 経由で提供します。

今回は受信メールのトラフィックサマリを取得してみます。

Request の例 (環境の都合で SMA を利用)

```
curl --location --request GET 'https://10.71.132.156:4431/sma/api/v2.0/reporting/mail_incoming_traffic_summary?startDate=2019-05-01T19:00:00.000Z&endDate=2019-05-12T23:00:00.000Z&device_type=esa' \
--header 'Accept: application/json, text/plain, */*' \
--header 'Authorization: Basic XXXXXXXXXXXXXXXXX' \
```

<details><summary> Response Body </summary><div>

```json
{
    "meta": {
        "totalCount": -1
    },
    "data": {
        "type": "mail_incoming_traffic_summary",
        "resultSet": [
            {
                "failed_dkim": 0
            },
            {
                "total_graymail_recipients": 0
            },
            {
                "detected_spam": 699
            },
            {
                "malicious_url": 2
            },
            {
                "total_spoofed_emails": 0
            },
            {
                "verif_decrypt_success": 0
            },
            {
                "detected_virus": 8
            },
            {
                "threat_content_filter": 0
            },
            {
                "blocked_invalid_recipient": 23
            },
            {
                "marketing_mail": 0
            },
            {
                "ims_spam_increment_over_case": 0
            },
            {
                "total_mailbox_auto_remediated_recipients": 0
            },
            {
                "detected_spam_certain": 460
            },
            {
                "detected_spam_suspect": 239
            },
            {
                "blocked_dmarc": 0
            },
            {
                "total_threat_recipients": 4381
            },
            {
                "total_recipients": 5860
            },
            {
                "verif_decrypt_fail": 0
            },
            {
                "detected_amp": 1
            },
            {
                "bulk_mail": 0
            },
            {
                "social_mail": 0
            },
            {
                "total_clean_recipients": 1479
            },
            {
                "detected_virus_per_msg": 8
            },
            {
                "failed_spf": 0
            },
            {
                "blocked_reputation": 3648
            }
        ]
    }
}
```
</div></details>

### 使い方その3: スパム隔離されたメールの検索 (Quarantine API)

ESA のアンチスパムエンジンでスパムと判定されたメッセージはスパム隔離領域へと一旦隔離されます。

Request の例 (環境の都合で SMA を利用)

```
curl --location --request GET 'https://10.71.132.156:4431/sma/api/v2.0/quarantine/messages?limit=3&offset=0&orderBy=date&orderDir=desc&quarantineType=spam&startDate=2020-10-01T00:00:00.000Z&endDate=2020-10-22T23:59:00.000Z' \
--header 'Accept: application/json, text/plain, */*' \
--header 'Authorization: Basic XXXXXXXXXXXXXXXXX' \
```

<details><summary> Response Body </summary><div>

```json

    "meta": {
        "totalCount": 429
    },
    "data": [
        {
            "attributes": {
                "envelopeRecipient": [
                    "test@exchange.local"
                ],
                "toAddress": [
                    ""
                ],
                "subject": "[SUSPICIOUS MESSAGE] [WARNING: ATTACHMENT UNSCANNED]mutt",
                "date": "21 Oct 2020 11:44 (GMT +09:00)",
                "fromAddress": [
                    "root <root@centos7.lab.local>"
                ],
                "size": "3.80K"
            },
            "mid": 1175
        },
        {
            "attributes": {
                "envelopeRecipient": [
                    "test@exchange.local"
                ],
                "toAddress": [
                    "<test@exchange.local>"
                ],
                "subject": "[SUSPICIOUS MESSAGE] mail from sendmail",
                "date": "21 Oct 2020 11:44 (GMT +09:00)",
                "fromAddress": [
                    "<test@lab.local>"
                ],
                "size": "3.80K"
            },
            "mid": 1176
        },
        {
            "attributes": {
                "envelopeRecipient": [
                    "test@exchange.local"
                ],
                "toAddress": [
                    "test@exchange.local"
                ],
                "subject": "[SUSPICIOUS MESSAGE] [WARNING: ATTACHMENT UNSCANNED]t",
                "date": "21 Oct 2020 11:44 (GMT +09:00)",
                "fromAddress": [
                    "test <test@lab.local>"
                ],
                "size": "4.20K"
            },
            "mid": 1177
        },
        {
            "attributes": {
                "envelopeRecipient": [
                    "test@exchange.local"
                ],
                "toAddress": [
                    "<test@exchange.local>"
                ],
                "subject": "[SUSPICIOUS MESSAGE] mail from sendmail",
                "date": "21 Oct 2020 11:44 (GMT +09:00)",
                "fromAddress": [
                    "<test@lab.local>"
                ],
                "size": "3.80K"
            },
            "mid": 1178
        },
        {
            "attributes": {
                "envelopeRecipient": [
                    "test@exchange.local"
                ],
                "toAddress": [
                    "<test@exchange.local>"
                ],
                "subject": "[SUSPICIOUS MESSAGE] mail from sendmail",
                "date": "21 Oct 2020 11:44 (GMT +09:00)",
                "fromAddress": [
                    "<test@lab.local>"
                ],
                "size": "3.80K"
            },
            "mid": 1179
        }
    ]
}
```
</div></details>

さらに`MID`を指定し`/sma/api/v2.0/quarantine/messages/details`へリクエストすることでメッセージのヘッダ情報だけでなくボディまで取得します。

Request の例 (環境の都合で SMA を利用)

```
curl --location --request GET 'https://10.71.132.156:4431/sma/api/v2.0/quarantine/messages/details?quarantineType=spam&mid=1175' \
--header 'Accept: application/json, text/plain, */*' \
--header 'Authorization: Basic XXXXXXXXXXXXXXXXX' \

```


<details><summary> Response Body </summary><div>

```json
{
    "data": {
        "attributes": {
            "envelopeRecipient": [
                "test@exchange.local"
            ],
            "toAddress": [
                null
            ],
            "attachments": [],
            "messageBody": "Received: from esa.lab.local (HELO esa.exchange.local) ([10.71.132.155])\r\n  by sma.lab.local with ESMTP; 21 Oct 2020 11:44:06 +0900<br />\nIronPort-SDR: /Vqm0yy7GzDsZpg6N/9WnSmjMj8QW9x/ih9Fob4SkfpjP+CkKABP+BIQYkAZlZdQb51NXmX9EH\r\n a4bfGzczysHOARRr13b/OFfBYrZEXB/nHGWP3g8sgbmDqQwJeyHq7LTM9Qpy0s0jk43PyLMSgV\r\n HFdAYEE5n3lBky5yIlr4tqXkXfZv0OKS7wjMIDd1HzVIFn9kIbmNOuMLByJzuVVC0IdsaQLUv4\r\n a6zjonEV2hX9lHWjy55ak/K/Jqsz1xCAxI5OZo5qkvnnC4f4KIsaMIQu4NSGAxRiqdekqkIZRi\r\n igw=<br />\nX-IronPort-AV: E=Sophos;i=\"5.77,399,1596466800\"; \r\n   d=\"scan'208\";a=\"4699\"<br />\nIronPort-SDR: rx49EAn8DzQRFx9gKtza0j8bq/C80bfnNN1csjmZ4VAtQKwNby7wmcWsExtstpXq0wkNigqKHZ\r\n X4YV5/NY+3BgkjZwDOAlbr2v7HL55dzf+OqpFw1Rfe7bjLUu5sIVnTk1J8ujOaHXQteV40xZ5V\r\n 8S27nDRd+ZYv9j+2aU1jH6wZ+6ss0xsXmjr7t2TetSk3CYl26D6n4RuoYqdpcVoFb+lgPDMIAx\r\n faJ/l6H0GGsI4C5FfNIgp035l2QzpQd1F4f8/lVR6WUxPsemJo60cm0sSwzQolzneXdYjltcn3\r\n XqtkaSwJGyc67DTgBMHxwRDh<br />\nX-IronPort-Anti-Spam-Filtered: true<br />\nX-IronPort-Anti-Spam-Result: =?us-ascii?q?A0Hg/P/aADRf/5aERwpfHQICCRQFBYF?=\r\n =?us-ascii?q?6BQwBAYMXgSIRgSwBEJNjggGBOSKBHl6PE4MKPYNVFwUsAQEBFg0KEAQBAQI?=\r\n =?us-ascii?q?NhGIcLgEBAQGBRiY3Bg4CAwEBAQMCBQIBBAMCAQEFAgEBAgJxW2FhgUeBFx4?=\r\n =?us-ascii?q?HAzEIBEMBDAGBWgEBAWguDz0JDAEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQE?=\r\n =?us-ascii?q?BAQEBAQEBAQEBAQEBAQEBAQEBBAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE?=\r\n =?us-ascii?q?BAQEBAQEBAQEBAQEEAg0CUgIYLwEWWgEtJApHEQclBHaCTLV0gTSEDgGBQ4R?=\r\n =?us-ascii?q?xEIE4AYV/gVFPhH4MgUBAgn+EPAKFCh+CLQSMHAiPBEKaECkFgmyBGIEpgXe?=\r\n =?us-ascii?q?CXIFPkScwgmwBgTSbdBFBhBxZE4cAkBKQKwGGXIF8gQWBWQp0AQFLCUQDAQE?=\r\n =?us-ascii?q?PAgEFAgEKAQGSDoplZQJKCYhEiC0B?=<br />\nX-IronPort-AV: E=Sophos;i=\"5.76,304,1592838000\"; \r\n   d=\"txt'?scan'208\";a=\"3933\"<br />\nX-Amp-Result: UNSCANNABLE<br />\nX-Amp-File-Uploaded: False<br />\nX-IPAS-Result: A0Hg/P/aADRf/5aERwpfHQICCRQFBYF6BQwBAYMXgSIRgSwBEJNjggGBOSKBHl6PE4MKPYNVFwUsAQEBFg0KEAQBAQINhGIcLgEBAQGBRiY3Bg4CAwEBAQMCBQIBBAMCAQEFAgEBAgJxW2FhgUeBFx4HAzEIBEMBDAGBWgEBAWguDz0JDAEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEEAg0CUgIYLwEWWgEtJApHEQclBHaCTLV0gTSEDgGBQ4RxEIE4AYV/gVFPhH4MgUBAgn+EPAKFCh+CLQSMHAiPBEKaECkFgmyBGIEpgXeCXIFPkScwgmwBgTSbdBFBhBxZE4cAkBKQKwGGXIF8gQWBWQp0AQFLCUQDAQEPAgEFAgEKAQGSDoplZQJKCYhEiC0B<br />\nX-IronPort-Original-Subject: mutt<br />\nX-IronPort-Redirect-Domain: secure-web.cisco.com/%(auth)s/%(url)s<br />\nSubject: [SUSPICIOUS MESSAGE] [WARNING: ATTACHMENT UNSCANNED]mutt<br />\nReceived: from centos7.lab.local ([10.71.132.150])\r\n  by esa.exchange.local with ESMTP; 12 Aug 2020 23:42:05 +0900<br />\nReceived: by centos7.lab.local (Postfix, from userid 0)\r\n\tid ECC8A18180BB; Wed, 12 Aug 2020 23:49:11 +0900 (JST)<br />\nDate: Wed, 12 Aug 2020 23:49:11 +0900<br />\nFrom: root &lt;root@centos7.lab.local&gt;<br />\nCc: test@exchange.local<br />\nMessage-ID: &lt;20200812144911.GA24116@centos7.lab.local&gt;<br />\nMIME-Version: 1.0<br />\nContent-Type: multipart/mixed; boundary=\"bg08WKrSYDhXBjb5\"<br />\nContent-Disposition: inline<br />\nUser-Agent: Mutt/1.5.21 (2010-09-15)<br /><br />\nmutt\r<br>\n",
            "date": "21 Oct 2020 11:44 (GMT +09:00)",
            "fromAddress": [
                "root <root@centos7.lab.local>"
            ],
            "subject": "[SUSPICIOUS MESSAGE] [WARNING: ATTACHMENT UNSCANNED]mutt"
        },
        "mid": 1175
    }
}
```
</div></details>

### まとめ
Cisco Email Security の新しい API のリクエスト例を紹介しました。
今回は GET による情報の取得のみでしたが、POST 操作で隔離されたメールを解放したり、管理者へ転送したりと様々な操作が API 経由で実施できます。是非触ってみてください。

### 参照
https://docs.ces.cisco.com/docs/api
https://www.cisco.com/c/ja_jp/products/security/email-security/index.html
https://www.cisco.com/c/ja_jp/td/docs/security/security_management/sma/sma12-0/api/b_SMA_API_12/b_SMA_API_12_chapter_01.html

[^1]: ESA で処理されたメールヘッダにはいまだに旧社名が残っていたりするため知っておいて損はないと思います。