#はじめに
Cisco製品には様々な製品でAPIが用意されていますが、今回はISEのERS(External RESTful Services) APIを利用してPython(ver3.6.3)スクリプトを作成してみました。
#ISE ERS(External RESTful Services) API について
ガイドはこちら
###事前準備
ISE ERS(External RESTful Services) APIを利用するためには、まず初めにISEの管理画面から、Administration->System->SettingsのERS Settingsで、ERSを有効にする必要があります。
さらに、Administration->Sytem->Admin AccessのAdmin Uers設定で、ESR APIへアクセスするための管理者IDとパスワードを作成します。
Admin Groupsは、ERS Adminを選択します。
APIについては、上記のCCOガイドに詳細な記載がないので、ERSを有効にした後、https://(ise ip address):9060/ers/sdkに作成した管理者IDとパスワードでアクセスするとAPIの詳細やスクリプト例を確認することができます。
#想定するユースケース
ユーザ様から、ISEが高機能なことは理解しているのだけど、管理者用のUIが(英語だし)複雑で使いにくい、もっとシンプルにUIをカスタマイズしたい、あるいは既存のシステムと連携させたい、という声をよくお聞きします。そういった場合に活用できるのがAPIです。
今回は、大学様や病院様での使用が多い有線のMacアドレス認証でのISEの利用を想定し、ISEの管理者UIにアクセスすることなくAPI経由で、ISEが管理している端末情報を取得するスクリプトを作成します。取得結果は、txtファイルに保存すると同時に、SparkのbotからSparkのRoomに結果をPostすることとします。
#利用するAPI
Endpoint API (GET-All)
Request:
Method: GET
URI: https://(ise ip address):9060/ers/config/endpoint
HTTP 'Content-Type' Header:application/json
Response:
JSON
{
"SearchResult" : {
"total" : 2,
"resources" : [ {
"id" : "id1",
"name" : "name1",
"description" : "description1"
}, {
"id" : "id2",
"name" : "name2",
"description" : "description2"
} ],
"nextPage" : {
"rel" : "next",
"href" : "link-to-next-page",
"type" : "application/xml"
},
"previousPage" : {
"rel" : "previous",
"href" : "link-to-previous-page",
"type" : "application/xml"
}
}
}
EndPoints Identity Group (GET-By-Id)
Request:
Method: GET
URI: https://(ise ip address):9060/ers/config/endpointgroup/{id}
HTTP 'Content-Type' Header:application/json
Response:
JSON
{
"EndPointGroup" : {
"id" : "id",
"name" : "name",
"description" : "description",
"systemDefined" : true
}
}
#スクリプト解説
###STEP0: Basic認証ヘッダを作成する
import base64
user='ersadmin' ## ISEのERS Adminのユーザ名
password='Password123' ## ISEのERS Adminのパスワード
creds = str.encode(':'.join((user, password)))
auth_header = bytes.decode(base64.b64encode(creds))
###STEP1: Pythonのrequestモジュールを使用して端末情報を取得する
import requests
import json
iseip='X.X.X.X' ## ISEのIPアドレス
url = "https://"+iseip+":9060/ers/config/"
url_endpoint = url+"endpoint"
headers = {
'accept': "application/json",
'authorization': 'Basic ' + header, ## STEP0で生成したbasic認証ヘッダー
'cache-control': "no-cache",
}
##全ての端末情報をjson形式で取得
response = requests.get( url_endpoint, verify=False,headers=headers).json()
##ディクショナリのキーを指定し、必要な情報を取り出す
o_json = json.dumps(response["SearchResult"]["resources"])
####注意点
response = requests.get( uri,verify=False,headers)
SSL証明書が正しくない場合にはデフォルトでSSL認証エラーを出すため、正しい証明書を入れるか、verify=Falseでverifyを無効にしない場合、[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failedのエラーが返されます。verify=Falseを書いた場合も、下記のWarningが出ます。
/usr/lib/python3.6/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Warningは、下記で無効にし出力させないようにすることができます。
import urllib3
from urllib3.exceptions import InsecureRequestWarning
urllib3.disable_warnings(InsecureRequestWarning)
###STEP2: 結果をファイルに保存
import datetime
now = datetime.datetime.now()
file_name = "{0:%Y%m%d.%H%M}".format(now) ##ファイル名に作成した時間を記録
f = open(file_name + "_endpoints_list.txt","w")
for x in message: ##STEP1でリスト化した要素を改行を入れながらファイルに記述
x2 = x.replace('\\n','\n')
f.write(str(x2))
f.close()
###STEP3: SparkのbotからRoomにAPI経由で取得結果をpost
SPARK APIについては、developerサイトで詳細な情報を得られます。今回はMessages APIを利用して取得した情報をpostします。
#スクリプト全体
import requests
import urllib3
from urllib3.exceptions import InsecureRequestWarning
urllib3.disable_warnings(InsecureRequestWarning)
import base64
import json
import sys
import datetime
iseip='X.X.X.X' ## ISEのIPアドレス
ACCESS_TOKEN="***********" ## SPARK botのアクセストークン
ROOM_ID="*********" ## SPARKのROOM ID
def get_authheader():
user='ersadmin' ## ISEのERS Adminのユーザ名
password='Password123' ## ISEのERS Adminのパスワード
creds = str.encode(':'.join((user, password)))
auth_header = bytes.decode(base64.b64encode(creds))
return auth_header
APIAuth = get_authheader()
def get_endpoint_info(header):
url = "https://"+iseip+":9060/ers/config/"
url_endpoint = url+"endpoint"
url_endpointgroup = url+"endpointgroup"
##ヘッダー情報
headers = {
'accept': "application/json",
'authorization': 'Basic ' + header,
'cache-control': "no-cache",
}
##全ての端末情報を取得
response = requests.get( url_endpoint, verify=False,headers=headers).json()
o_json = json.dumps(response["SearchResult"]["resources"])
msg=[]
## 取得した端末情報から、macアドレス情報と端末が所属するグループIDを取得
for item in response["SearchResult"]["resources"]:
href = item["link"]["href"]
response_href = requests.get(href, verify=False,headers=headers).json()
r = json.dumps(response_href["ERSEndPoint"]["groupId"])
gid = r.split('"')
## 所属するグループIDからグループ名を取得
gname_url = url_endpointgroup+"/"+gid[1]
gname_r = requests.get( gname_url, verify=False,headers=headers).json()
gname = json.dumps(gname_r["EndPointGroup"]["name"])
gname2 = gname.replace('"','')
##端末のmacアドレス情報と端末が所属するグループ名をリスト化
msg.append('mac address:'+ item["name"]+', identity group name:'+gname2+'\\n')
return msg
## Sparkへ結果をpost
def postMsg(roomId, markdown):
accessToken_hdr= 'Bearer '+ACCESS_TOKEN
spark_header={'Authorization':accessToken_hdr,'Content-Type': 'application/json;charset=utf-8'} ##ヘッダーの作成
the_data = '{"roomId":"' + roomId + '","markdown":"' + markdown +'"}' ## 使用するbotのroom IDと、postする情報を指定
uri = 'https://api.ciscospark.com/v1/messages' ## Messgae API URI
resp=requests.post(uri,data=the_data,headers=spark_header)
print (resp)
if __name__ == '__main__':
APIAuth = get_authheader()
message=get_endpoint_info(APIAuth)
num=len(message)
## Sparkへリストのままpostできないため、要素を連結
m=''
for x in message:
m += x+'\\n'
## 取得結果をテキストファイルに保存
now = datetime.datetime.now()
file_name = "{0:%Y%m%d.%H%M}".format(now)
f = open(file_name + "_endpoints_list.txt","w")
for x in message:
x2 = x.replace('\\n','\n')
f.write(str(x2))
f.close()
data ='Total number of endpoints managed by ISE is :'+' '+ str(num)+'\\n\\n'+ m
postMsg(ROOM_ID,data)
#実行結果
[root@localhost naogawa]# python3 ./get-all-internal-endpoint.py
<Response [200]>
[root@localhost naogawa]# ls
20171204.0652_endpoints_list.txt get-all-internal-endpoint.py
[root@localhost naogawa]# cat 20171204.0652_endpoints_list.txt
mac address:00:00:5E:00:01:01, identity group name:Profiled
mac address:00:0C:29:73:CB:DA, identity group name:Profiled
mac address:00:0C:29:8F:93:85, identity group name:Profiled
mac address:00:0C:29:94:E1:39, identity group name:Profiled
mac address:00:0C:29:BB:CE:BD, identity group name:Profiled
mac address:00:0C:29:C9:B1:CA, identity group name:Profiled
mac address:00:0C:29:D0:AC:AC, identity group name:Profiled
mac address:00:0C:29:F3:30:B6, identity group name:Profiled
mac address:00:24:97:CE:DF:A0, identity group name:Profiled
mac address:00:38:DF:20:49:48, identity group name:Profiled
mac address:00:38:DF:3E:3C:F0, identity group name:Profiled
mac address:00:A3:D1:88:B9:00, identity group name:Profiled
mac address:00:B0:64:FC:D6:65, identity group name:Profiled
mac address:00:B0:64:FC:D6:99, identity group name:Profiled
mac address:00:B0:64:FD:05:84, identity group name:Profiled
mac address:1C:DF:0F:1D:7F:D6, identity group name:Profiled
mac address:2C:86:D2:8B:B7:C0, identity group name:Profiled
mac address:2C:86:D2:FE:C8:C0, identity group name:Profiled
mac address:50:7A:55:DD:C1:EF, identity group name:Profiled
mac address:58:8D:09:08:98:68, identity group name:Profiled
[root@localhost naogawa]#
#最後に
APIを活用すれば、ユーザ様の様々な要件に柔軟に対応することができます。ぜひ、APIの活用をご検討ください。