-
Notifications
You must be signed in to change notification settings - Fork 12
/
openvuln.yml
142 lines (126 loc) · 5.15 KB
/
openvuln.yml
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
---
- name: Collect facts from all devices in the Ansible Inventory
hosts: all
gather_facts: true
gather_subset: min
connection: network_cli
ignore_errors: true
- name: Collect ACI software version and query Cisco PSIRT OpenVuln API
hosts: localhost
gather_facts: false
vars:
known_vuln: [] # Empty default list in case known_vuln.yml not found
# aci:
# - { apic: <APIC-URL/IP>, aci_user: <username>, aci_pass: <password> }
host_list: # Needs at least an empty tag: and host: variable per list item #
- { os: 'nxos 7.0(3)I7(7)', tag: Test_NXOS1, host: N9K-1 }
# - { os: 'ios 12.2(53)SE1', tag: Test_blankCVSS, host: IOS-1 }
client_key: <Provided via Cisco API console>
client_secret: <Provided via Cisco API console>
slack_token: <Provided via custom slack app - incoming webhooks>
# influxdb_host:
# influxdb_username:
# influxdb_password:
# influxdb_name:
tasks:
- name: INCLUDE KNOWN VULN FILE
include_vars:
file: known_vuln.yml
name: known_vuln
ignore_errors: yes # In case the file doesn't exist #
- name: Query ACI fabric nodes
aci_rest:
host: "{{ item.apic }}"
username: "{{ item.aci_user }}"
password: "{{ item.aci_pass }}"
validate_certs: false
method: get
path: /api/node/class/firmwareRunning.json
loop: "{{ aci }}"
register: aci_firmware
when: aci is defined
# Complete the host_list with ACI, NX-OS, IOS-XE and IOS devices #
- name: ADD ACI DEVICES TO HOST_LIST
set_fact:
host_list: "{{ host_list | default ([]) + [{ 'os': 'aci 1' + item.1.firmwareRunning.attributes.peVer,
'tag': item.0.item.apic,
'host': item.1.firmwareRunning.attributes.dn.split('/')[2] }] }}"
loop: "{{ aci_firmware.results | default ([]) | subelements('imdata') }}" # Needs an empty list in case aci var is not defined! #
loop_control:
label: "{{ item.0.item.apic }} {{ item.1.firmwareRunning.attributes.dn.split('/')[2] }}"
when: aci is defined
- name: ADD IOS-(XE) AND NX-OS DEVICES TO HOST_LIST
set_fact:
host_list: "{{ host_list | default ([]) + [{ 'os': [ hostvars[item].ansible_network_os, hostvars[item].ansible_facts.net_version ] | custom_net_os_filter,
'tag': hostvars[item].group_names | join(' '),
'host': hostvars[item].inventory_hostname }] }}"
loop: "{{ groups['all'] }}"
when:
- hostvars[item].ansible_network_os is defined
- hostvars[item].ansible_facts.net_version is defined
# Query the Cisco PSIRT openVuln API
- name: CISCO OPENVULN API LOGIN
uri:
url: https://cloudsso.cisco.com/as/token.oauth2
headers:
Content-Type: application/x-www-form-urlencoded
method: POST
body:
grant_type: client_credentials
client_id: "{{ client_key }}"
client_secret: "{{ client_secret }}"
validate_certs: no
body_format: form-urlencoded
# environment:
# https_proxy: http://<proxy-url>:<port>
register: login
- name: GET CISCO PSIRT OPEN VULN
uri:
url: https://api.cisco.com/security/advisories/{{ item.os.split()[0] }}?version={{ item.os.split()[1] }}
headers:
Accept: application/json
Authorization: "{{ login.json.token_type }} {{ login.json.access_token }}"
method: GET
validate_certs: no
status_code: [200, 404, 406] # API reports 404 or 406 NO_DATA if no matching adv is found #
loop: "{{ host_list | unique(attribute='os') | sort(attribute='os') }}"
# environment:
# https_proxy: http://<proxy-url>:<port>
register: open_vuln
# Process API response #
- name: PARSE API RESPONSE
set_fact:
adv_list: "{{ open_vuln.results | custom_adv_filter }}"
- name: TEMPLATE OUT MARKDOWN REPORT
template:
src: openvuln.j2
dest: openvuln.md
- name: TEMPLATE OUT CSV REPORT
template:
src: openvuln_csv.j2
dest: openvuln.csv
# - name: SEND NOTIFICATION VIA SLACK
# slack:
# token: "{{ slack_token }}"
# msg: "{{ item.os }} has new advisory <{{ item.url }}|{{ item.id }}> with `CVSS {{ item.cvss }}`"
# loop: "{{ adv_list }}"
# loop_control:
# label: "Send message for {{ item.os }} {{ item.id }}"
# when: item.id not in known_vuln
# - name: SEND OPENVULN METRICS TO INFLUXDB
# influxdb_write:
# hostname: "{{ influxdb_host }}"
# username: "{{ influxdb_username }}"
# password: "{{ influxdb_password }}"
# database_name: "{{influxdb_name}}"
# data_points:
# - measurement: openvuln
# tags:
# os: "{{ item.os }}"
# adv: "{{ item.id }}"
# fields:
# value: "{{ item.cvss }}"
# loop: "{{ adv_list }}"
# loop_control:
# label: "Send metric {{ item.cvss }} for {{ item.os }} {{ item.id }}"
# when: item.id not in known_vuln