-
Notifications
You must be signed in to change notification settings - Fork 0
/
sparci.py
148 lines (123 loc) · 4.98 KB
/
sparci.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import json
from textwrap import dedent
import click
import requests
import websocket
from requests.packages import urllib3
from spark.rooms import Room
from spark.session import Session
urllib3.disable_warnings()
@click.command()
@click.option('--spark-key', help="Your Spark API key\n(available at developer.ciscospark.com)", prompt=True,
hide_input=True)
@click.option('--spark-room', help="The room you wish updates to be posted to", prompt=True)
@click.option('--apic-address', help="DNS or IP address of your APIC", prompt=True)
@click.option('--apic-user', help="User with enough priviledges to read aaaModLR", prompt=True)
@click.option('--apic-pass', help="APIC user password", prompt=True, hide_input=True, confirmation_prompt=True)
@click.option('--debug', help="Show detailed websocket information")
@click.option('--action', type=click.Choice(['all', 'creation', 'modification', 'deletion']), default="all",
help="Filter events based on the action type")
@click.option('--user', help="Filter events generated by this user", default="")
@click.option('--dn-filter', help="Filter events based on this DN wildcard", default="")
def sparci(spark_key, spark_room, apic_address, apic_user, apic_pass, action='all', user="", dn_filter="",
debug=False):
def on_message(ws, message):
message = json.loads(message)
message = message["imdata"][0]["aaaModLR"]
print "Websocket Message: {descr}".format(descr=message["attributes"]["descr"])
spark_message = dedent("""
New APIC Event!
{descr}
DN: {affected}
Change Set: {changeSet}
""".format(**message["attributes"])).lstrip('\n').rstrip('\n')
room.send_message(ss, spark_message)
print " - Update sent to Spark room {room}".format(room=room)
def on_error(ws, error):
print error
def on_close(ws):
print "### closed ###"
def on_open(ws):
# Convert "all" to ""
if action == "all":
action_wcard = ""
else:
action_wcard = action
query = dedent("""
https://{apic_address}/api/node/class/aaaModLR.json?
subscription=yes&
order-by=aaaModLR.created|desc&
page=0&
page-size=15&
&query-target-filter=
and(
wcard(aaaModLR.user, "{user}"),
wcard(aaaModLR.ind, "{action_wcard}"),
wcard(aaaModLR.affected, "{dn_filter}")
)
""".format(
apic_address=apic_address,
user=user,
action_wcard=action_wcard,
dn_filter=dn_filter)).replace('\n', '')
resp = s.get(query, verify=False)
if not resp.ok:
exit("Failed to subscribe to aaaModLR")
print ""
print "==================================================="
print "Sparci"
print "==================================================="
print ""
print "Authenticating with Spark"
ss = Session('https://api.ciscospark.com', spark_key)
try:
room = Room.get(ss, spark_room)
except ValueError:
exit(" Exiting as I failed to authenticate your Spark API key")
if type(room) == list:
print " So, I couldn't find the room {spark_room}, but I did find:".format(spark_room=spark_room)
for r in room:
print " -", r
print " maybe try one of those?"
exit()
else:
print " Found Spark room {room}".format(room=room)
print ""
print "Authenticating with APIC"
data = {
"aaaUser": {
"attributes": {
"name": apic_user,
"pwd": apic_pass
}
}
}
s = requests.Session()
s.headers.update({'Content-Type': 'application/json'})
r = s.post('https://{apic_address}/api/aaaLogin.json'.format(apic_address=apic_address), json=data, verify=False)
if not r.ok:
exit(" Failed to authenticate with APIC")
auth = r.json()["imdata"][0]["aaaLogin"]
token = auth["attributes"]["token"]
print " Session token = {token}...".format(token=str.join('', token[0:15]))
print ""
print "==================================================="
print "Subscribing to system audit logs"
print "==================================================="
print ""
if action != "all":
print "Action Filter:", action
if user:
print "User Filter:", user
if dn_filter:
print "Dn Filter:", dn_filter
if debug:
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://{apic_address}/socket{token}".format(apic_address=apic_address, token=token),
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.on_open = on_open
ws.run_forever()
if __name__ == "__main__":
sparci(auto_envvar_prefix="SPARCI")