はじめに
この記事はシスコの同志による Advent Calendar の一部として投稿しています
- 2017年版: https://qiita.com/advent-calendar/2017/cisco
- 2018年版: https://qiita.com/advent-calendar/2018/cisco
- 2019年版: https://qiita.com/advent-calendar/2019/cisco
- 2020年版: https://qiita.com/advent-calendar/2020/cisco
- 2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
- 2021年版: https://qiita.com/advent-calendar/2021/cisco
- 2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2
- 2022年版: https://qiita.com/advent-calendar/2022/cisco
本記事は2022年版Advent Calendarの5日目の投稿になり、私自身としては3回目の投稿となります。昨年は非常に長ったらしい記事(チャットボットを使ったCisco DNA Centerの有効活用)になっていたので、今年はシンプルに仕上げました。
SecureXとは
みなさん、SecureXって聞いたことありますでしょうか?SecureXはシスコのXDR機能を備えたクラウドネイティブなプラットフォームです。しかも、シスコのセキュリティ製品をどれか一つ持っていれば無料で使用することが可能です。どんなことが出来るかは下記リンクを参照頂くとして、今回は沢山あるSecureXの機能の中でも、Orchestration機能について紹介します。
Orchestrationと言うとなんか色々と準備しないと出来ないんじゃないか?とか考えてしまいがちですが、SecureXを利用することで、クラウド上のPython環境やプリビルドのモジュールを使うことで出来るようになり、複数の製品をSecureXをハブとして簡単にAPI連携が出来るようになります。
ですので、クラウド上に無料で使えるPython環境があると考えて頂いてもある意味間違いではないです。
今回の取組
今回はこんな無料のクラウドPython環境を使って、クラウドDNSセキュリティのUmbrellaとクラウドコラボレーションツールのWebexを簡易に連携させてみたいと思います。具体的には、DNSセキュリティで検知した悪意あるドメインの直近5つをWebexのスペースに投稿するという非常にシンプルなワークフローを作成します。
ワークフロー概要
今回のワークフローは下記になります。
- Umbrella Report APIを使って過去1日にクエリした悪意あるドメイン情報を入手
- Webex APIを使って悪意あるドメイン情報を投稿
事前準備
ということで、UmbrellaとWebexのAPIを利用しますので、それぞれの準備が必要になります。
Umbrella API
Umbrellaダッシュボードにおいて、[Admin] -> [API Keys]から[Add]を押して、下記の内容でReport用のAPIキーを追加します。
出力されたAPI KeyとKey Secretを大切に保管します。
Webex API
Token作成
下記URLから、以下の内容でBotを追加します。
https://developer.webex.com/my-apps/new/bot
- Bot name: <適当>
- Bot username: <重複しない適当な名前>
- Icon: <適当に選択するかアップロード>
- App Hub Description: <ボットの利用用途等>
出力されたBot access tokenを大切に保管します。
スペースにBot追加
スペースのId取得
下記URLからBotを追加したスペースのIdを取得して大切に保管します。
https://developer.webex.com/docs/api/v1/rooms/list-rooms
これで事前準備は完了です。
作業詳細
SecureXにログイン
下記から多要素認証含めてSecureXにログインします。
https://sso-apps.security.cisco.com/dashboard
初めてSecureXにログインする方は手順がございますので、下記URLが大変良くまとまっていますので参考にしてください。
シスココミュニティサイト
また、Orchestration機能は最低1つのシスコセキュリティ製品とのインテグレーションが必要ですので、Umbrellaの場合は下記URLを参考にして下さい。
UmbrellaのSecureX統合
Workflowの枠を作成
[Orchestration]をクリックした先で、[New Workflow]をクリックして下記を入力
- Display Name: <適当>
- Description: <ワークフローの説明>
変数の登録
今回利用する下記変数を図のように全て[Workflow]の右側に定義可能な[Variables]にローカル変数として登録します。
Name | Type | SCOPE | VALUE | Required |
---|---|---|---|---|
umbrella_key | Secure String | Local | <先ほど保存した値> | False |
umbrella_org | Secure String | Local | <自身のOrganization Id> | False |
umbrella_secret | Secure String | Local | <先ほど保存した値> | False |
webex_roomid | Secure String | Local | <先ほど保存した値> | False |
webex_token | Secure String | Local | <先ほど保存した値> | False |
Umbrellaパートの作成
左の[Activities]から[Execute Python Script]を画面中央にドラッグアンドドロップして、下記のパラメータを入力します。
- Diplay Name: umbrella_report
- Description: <適当>
- Script to execute on target: <下記項のUmbrellaパートのPythonコードをコピペ>
- Script Variable: message_umb
- Property Name: message_umb
- Property Type: Secure String
コードをコピペした部分について、変数はGUI上で呼び出す必要がありますので、下記の変数については下記図のようなやりかたで、GUI上からそれぞれ呼び出してください。
- umbrella_key
- umbrella_secret
- org_id
UmbrellaパートのPythonコード
Umbrellaパートで動作するPythonコードです。基本コピペですが、変数部分については上記に記載の通り、GUI上から変数を呼び出してください。
import requests
import json
from requests.auth import HTTPBasicAuth
url = "https://api.umbrella.com/auth/v2/token"
payload={}
headers = {
'Content-Type': 'application/json'
}
umbrella_key = "<ローカル変数からUmbrella_key呼び出し>"
umbrella_secret = "<ローカル変数からUmbrella_secret呼び出し>"
org_id = "<ローカル変数からUmbrella_org呼び出し>"
response_token = requests.request("POST", url, auth=HTTPBasicAuth(umbrella_key, umbrella_secret), headers=headers, data=payload)
response_token = response_token.json()
print(response_token["access_token"])
url_report = "https://reports.api.umbrella.com/v2/organizations/" + org_id + "/activity/dns?from=-1days&to=now&limit=5&categories=124,68,66,64"
payload_report={}
headers_report = {
'Authorization': 'Bearer ' + response_token["access_token"],
'Content-Type': 'application/json'
}
response_report = requests.request("GET", url_report, headers=headers_report, data=payload_report)
if response_report.history:
print("Request was redirected")
for resp in response_report.history:
print(resp.status_code, resp.url)
print("Final destination:")
print(response_report.status_code, response_report.url)
response_report = requests.request("GET", response_report.url, headers=headers_report, data=payload_report, allow_redirects=True)
else:
print("Request was not redirected")
response_report = response_report.json()
#print(json.dumps(response_report, indent=4))
domainlist = ""
if len(response_report["data"]) == 0:
message_umb = "安心してください。最近悪意あるドメインにはアクセスしていません。" + "\n"
else:
message_umb = "次のドメインは悪意あるドメインの可能性があります。ご注意下さい。"+ "\n"
domains.")
for i, domain in enumerate(response_report["data"]):
domainlist = domainlist + str(i+1) + ". " + response_report["data"][i]["domain"] + "\n"
message_umb += domainlist
print(message_umb)
(参考) Umbrella Reporting APIの仕様
重要なことですが、Umbrella Reporting APIは下記URLに記載されている通り、US、EU以外の場所からのリクエストについては、リダイレクト(302)される仕様になっています。
If an HTTP client request does not originate from the same continent as the location of the Umbrella data warehouse, the Umbrella server responds with 302 Found.
Umbrella Reporting API - Cisco DevNet
そのため、Pythonのrequestについても、リダイレクトしてもAuthorization情報を維持するような書き方にする必要があります。
コード該当箇所抜粋
if response_report.history:
print("Request was redirected")
for resp in response_report.history:
print(resp.status_code, resp.url)
print("Final destination:")
print(response_report.status_code, response_report.url)
response_report = requests.request("GET", response_report.url, headers=headers_report, data=payload_report, allow_redirects=True)
else:
print("Request was not redirected")
Webexパートの作成
左の[Activities]から[Execute Python Script]を画面中央にドラッグアンドドロップして、下記のパラメータを入力します。
- Diplay Name: webex_post
- Description: <適当>
- Script to execute on target: <下記項のWebexパートのPythonコードをコピペ>
コードをコピペした部分について、変数はGUI上で呼び出す必要がありますので、下記の変数については下記図のようなやりかたで、GUI上からそれぞれ呼び出してください。
- message
- webex_token
例)messageの呼び出し方
*messageは事前に定義した変数ではなく、Umbrellaパートのアウトプットである、スクリプト変数になるので注意が必要です。
WebexパートのPythonコード
Webexパートで動作するPythonコードです。基本コピペですが、変数部分については上記に記載の通り、GUI上から変数を呼び出してください。
import requests
import json
### umbrella_reportのコードのアウトプット(message_umb)をmessageにセット
message = """<スクリプト変数からmessage_umb呼び出し>"""
### ローカル変数で定義したWebexトークンをwebex_tokenにセット
webex_token = "<ローカル変数からwebex_token呼び出し>"
w_headers = {
'Authorization': 'Bearer ' + webex_token,
'Content-type': "application/json"
}
def send_message(message):
print(message)
w_payload = json.dumps({
"roomId": "<ローカル変数からwebex_roomid呼び出し>",
"text": message
})
host = "https://webexapis.com/"
api = "v1/messages"
url = host + api
response = requests.request("POST", url, headers=w_headers, data=w_payload, verify=False)
r_json = response.json()
print(r_json)
send_message(message)
これで完成です。早!
動作確認
早速、動作するか試してみましょう。画面右上の[Validate]を押して問題なければ、そのまま[Run]をクリックします。何事も無ければ添付のように作成したモジュールが緑色に変わるはずです。
実行にかかった時間は2.2秒のようです。
さらにWebexにメッセージが投稿されているはずです。
*私の環境ではMalware, Phishing, C&C以外に検証用にTelephonyでも検知するようにしております。
(おまけ)スケジュール登録
私は毎朝8時30分に通知して欲しいので、下記の内容で設定しています。
Scheduleの作成
[Orchestration] -> [Schedules]から[New Schedule]をクリックして下記のように登録します。
- Display Name: <適当>
- Calender: Daily
- Timezone: (UTC+09:00) Osaka, Sapporo, Tokyo
- Start time: 8:30 AM
- Number of runs per day: 1
Workflowへの関連付け
[Workflow]画面の右側で[Trigger]から[Add Trigger]で作成した[Schedule]を登録します。
- Name: <適当>
- Type: Schedule
- Schedule: Umbrella-Webex-Integration (上記で作成したSchedule)
まとめ
- 手元で動作するPythonスクリプトがあれば、簡単にSecureXへ移行可能
- 従来の製品の機能では連携出来ないような仕組みも、SecureXをハブとして実現可能
- シスコのセキュリティ製品を1つ持っておれば無料でクラウドPython環境を利用可能
免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。