Updated app OpenAPI parser

This commit is contained in:
frikky
2020-10-17 10:51:28 +02:00
parent 722d832d88
commit 3ef76fc85f
6 changed files with 179 additions and 2008 deletions
@@ -1,235 +0,0 @@
components:
schemas:
tmp0:
properties:
cb_version:
type: string
company_name:
type: string
copied_mod_len:
type: string
digsig_issuer:
type: string
digsig_prog_name:
type: string
digsig_publisher:
type: string
digsig_result:
type: string
digsig_result_code:
type: string
digsig_sign_time:
type: string
digsig_subject:
type: string
endpoint:
type: string
event_partition_id:
type: string
facet_id:
type: string
file_desc:
type: string
file_version:
type: string
group:
type: string
host_count:
type: string
internal_name:
type: string
is_64bit:
type: string
is_executable_image:
type: string
last_seen:
type: string
legal_copyright:
type: string
md5:
type: string
observed_filename:
type: string
orig_mod_len:
type: string
original_filename:
type: string
os_type:
type: string
product_name:
type: string
product_version:
type: string
server_added_timestamp:
type: string
signed:
type: string
timestamp:
type: string
watchlists:
type: string
type: object
tmp1:
properties:
message:
type: string
type: object
tmp2:
properties:
childproc_count:
type: string
cmdline:
type: string
comms_ip:
type: string
crossproc_count:
type: string
emet_config:
type: string
emet_count:
type: string
filemod_count:
type: string
filtering_known_dlls:
type: string
group:
type: string
host_type:
type: string
hostname:
type: string
id:
type: string
interface_ip:
type: string
last_server_update:
type: string
last_update:
type: string
modload_count:
type: string
netconn_count:
type: string
os_type:
type: string
parent_id:
type: string
parent_name:
type: string
parent_pid:
type: string
parent_unique_id:
type: string
path:
type: string
process_md5:
type: string
process_name:
type: string
process_pid:
type: string
processblock_count:
type: string
regmod_count:
type: string
segment_id:
type: string
sensor_id:
type: string
start:
type: string
terminated:
type: string
unique_id:
type: string
username:
type: string
type: object
tmp3:
properties:
message:
type: string
type: object
securitySchemes: {}
info:
contact:
email: frikky@shuffler.io
name: '@frikkylikeme'
url: https://twitter.com/frikkylikeme
description: Automated generation of Carbon Black Response
title: Carbon Black Response
version: 1.0.0
openapi: 3.0.2
paths:
tmp0:
post:
description: Carbon Black Response Binary Search
parameters:
- description: Query
in: query
name: Query
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp0'
description: Successful request
summary: Carbon Black Response Binary Search
tmp1:
post:
description: Carbon Black Response Isolate Sensor
parameters:
- description: Hostname of a sensor to isolate.
in: query
name: Hostname
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp1'
description: Successful request
summary: Carbon Black Response Isolate Sensor
tmp2:
post:
description: Carbon Black Response Process Search
parameters:
- description: Query
in: query
name: Query
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp2'
description: Successful request
summary: Carbon Black Response Process Search
tmp3:
post:
description: Carbon Black Response Unisolate Sensor
parameters:
- description: Hostname of a sensor to unisolate.
in: query
name: Hostname
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp3'
description: Successful request
summary: Carbon Black Response Unisolate Sensor
@@ -384,14 +384,17 @@ components:
whiteListClassification:
type: string
type: object
securitySchemes: {}
securitySchemes:
BasicAuth:
scheme: basic
type: http
info:
contact:
email: frikky@shuffler.io
name: '@frikkylikeme'
url: https://twitter.com/frikkylikeme
description: Automated generation of Cyberreason
title: Cyberreason
description: Automated generation of Cyberreason Cyberreason
title: Cyberreason Cyberreason
version: 1.0.0
openapi: 3.0.2
paths:
@@ -399,15 +402,17 @@ paths:
post:
description: CyberReason Block or Unblock an Item
parameters:
- description: Either 'blacklist' or 'whitelist'
- description: IP, Domain, or Hash CSV values to blacklist or whitelist
example: ''
in: query
name: Action
name: Values
required: true
schema:
type: string
- description: IP, Domain, or Hash CSV values to blacklist or whitelist
- description: Either 'blacklist' or 'whitelist'
example: ''
in: query
name: Values
name: Action
required: true
schema:
type: string
@@ -436,24 +441,28 @@ paths:
description: CyberReason isolate a host by port
parameters:
- description: IP to block
example: ''
in: query
name: IP
required: true
schema:
type: string
- description: Direction to block traffic, one of 'ALL', 'INCOMING', 'OUTGOING'
in: query
name: Direction to block
required: true
schema:
type: string
- description: Port to block
example: ''
in: query
name: Port
required: true
schema:
type: string
- description: Direction to block traffic, one of 'ALL', 'INCOMING', 'OUTGOING'
example: ''
in: query
name: Direction to block
required: true
schema:
type: string
- description: If true will isolate, false will remove from isolation
example: ''
in: query
name: Block
required: true
@@ -471,24 +480,27 @@ paths:
post:
description: Check CyberReason for a domain
parameters:
- description: Domain to search for
example: ''
in: query
name: Domain
required: true
schema:
type: string
- description: Limit of results to return
example: ''
in: body
name: Limit
required: false
schema:
type: string
- description: Timeout
example: '12000'
in: body
name: Timeout (ms)
required: false
schema:
type: string
- description: Domain to search for
in: query
name: Domain
required: true
schema:
type: string
responses:
'200':
content:
@@ -501,24 +513,27 @@ paths:
post:
description: Check CyberReason for a hash
parameters:
- description: Hash to search for
example: ''
in: query
name: Hash
required: true
schema:
type: string
- description: Limit of results to return
example: ''
in: body
name: Limit
required: false
schema:
type: string
- description: Timeout
example: '12000'
in: body
name: Timeout (ms)
required: false
schema:
type: string
- description: Hash to search for
in: query
name: Hash
required: true
schema:
type: string
responses:
'200':
content:
@@ -531,24 +546,27 @@ paths:
post:
description: Check CyberReason for a IP
parameters:
- description: IP to search for
example: ''
in: query
name: IP
required: true
schema:
type: string
- description: Limit of results to return
example: ''
in: body
name: Limit
required: false
schema:
type: string
- description: Timeout
example: '12000'
in: body
name: Timeout (ms)
required: false
schema:
type: string
- description: IP to search for
in: query
name: IP
required: true
schema:
type: string
responses:
'200':
content:
@@ -557,3 +575,5 @@ paths:
$ref: '#/components/schemas/tmp5'
description: Successful request
summary: CyberReason Query for IP
tags:
- Endpoint Security & Management
File diff suppressed because it is too large Load Diff
@@ -1,166 +0,0 @@
components:
schemas:
tmp0:
properties:
bid:
type: string
cve:
type: string
description:
type: string
msb:
type: string
osvdb:
type: string
source:
type: string
type: object
tmp1:
properties:
data:
type: string
domains:
type: string
hostnames:
type: string
ip:
type: string
location.area_code:
type: string
location.city:
type: string
location.country_code:
type: string
location.country_name:
type: string
location.dma_code:
type: string
location.latitude:
type: string
location.longitude:
type: string
location.postal_code:
type: string
location.region_code:
type: string
org:
type: string
os:
type: string
port:
type: string
transport:
type: string
type: object
tmp2:
properties:
devicetype:
type: string
domains:
type: string
hostnames:
type: string
ip_str:
type: string
isp:
type: string
location.area_code:
type: string
location.city:
type: string
location.country_code:
type: string
location.country_name:
type: string
location.dma_code:
type: string
location.latitude:
type: string
location.longitude:
type: string
location.postal_code:
type: string
org:
type: string
os:
type: string
port:
type: string
product:
type: string
timestamp:
type: string
title:
type: string
type: object
securitySchemes: {}
info:
contact:
email: frikky@shuffler.io
name: '@frikkylikeme'
url: https://twitter.com/frikkylikeme
description: Automated generation of Shodan
title: Shodan
version: 1.0.0
openapi: 3.0.2
paths:
tmp0:
post:
description: Search across a variety of data sources for exploits
parameters:
- description: Search query used to search the database of known exploits
in: query
name: Query
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp0'
description: Successful request
summary: Shodan Exploit Search
tmp1:
post:
description: Search all services that have been found on the given host IP
parameters:
- description: Host IP address
in: query
name: IP
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp1'
description: Successful request
summary: Shodan Host
tmp2:
post:
description: Search the SHODAN database
parameters:
- description: Keyword to search Shodan for
in: query
name: Query
required: true
schema:
type: string
- description: 'Max number of results to return. Default: ''Infinite'''
in: body
name: Limit
required: false
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/tmp2'
description: Successful request
summary: Shodan Search
@@ -1,149 +0,0 @@
components:
schemas:
tmp0:
properties:
bios_uuid:
type: string
fqdn:
type: string
hostname:
type: string
id:
type: string
ipv4:
type: string
ipv6:
type: string
mac_address:
type: string
netbios_name:
type: string
operating_system:
type: string
ssh_fingerprint:
type: string
system_type:
type: string
type: object
tmp1:
properties:
agent_name:
type: string
fqdn:
type: string
id:
type: string
ipv4:
type: string
ipv6:
type: string
last_seen:
type: string
mac_address:
type: string
operating_system:
type: string
type: object
tmp2:
properties:
hostcount:
type: string
name:
type: string
owner:
type: string
policy:
type: string
scan_end:
type: string
scan_start:
type: string
status:
type: string
targets:
type: string
uuid:
type: string
type: object
tmp4:
properties:
count:
type: string
plugin_family:
type: string
plugin_name:
type: string
severity:
type: string
vulnerability_state:
type: string
type: object
securitySchemes: {}
info:
contact:
email: frikky@shuffler.io
name: '@frikkylikeme'
url: https://twitter.com/frikkylikeme
description: Automated generation of Tenable Tenable.io
title: Tenable Tenable.io
version: 1.0.0
openapi: 3.0.2
paths:
tmp0:
post:
description: Returns information about the specified asset.
parameters:
- description: The UUID of the asset.
in: query
name: Asset UUID
required: true
schema:
type: string
responses:
'200':
description: Successful request
summary: Tenable.io Asset Info
tmp1:
post:
description: Returns a list of up to 5000 assets.
parameters: []
responses:
'200':
description: Successful request
summary: Tenable.io List Assets
tmp2:
post:
description: Returns details for the given scan.
parameters:
- description: The ID of the scan.
in: query
name: Scan ID
required: true
schema:
type: string
responses:
'200':
description: Successful request
summary: Tenable.io Scan Details
tmp3:
post:
description: Launches a scan.
parameters:
- description: The ID of the scan.
in: body
name: Scan ID
required: true
schema:
type: string
responses:
'200':
description: Successful request
summary: Tenable.io Scan Launch
tmp4:
post:
description: Retrieves a list of recorded vulnerabilities.
parameters: []
responses:
'200':
description: Successful request
summary: Tenable.io Vulnerabilities
+128 -44
View File
@@ -1,5 +1,14 @@
import requests
import yaml
import json
# USAGE:
# 1. Find the item here:
# https://apphub.swimlane.com/swimbundles/swimlane/sw_alienvault_threatcrowd
# 2.
# https://jsonlint.com/
# META: data["meta"]. Stuff like count. May be useful :)
def parse_data(data):
openapi = {
@@ -21,14 +30,61 @@ def parse_data(data):
}
}
category = data["category"]
filename = "%s.yaml" % data["title"].replace(" ", "_").lower()
openapi["info"]["title"] = data["title"]
openapi["info"]["description"] = "Automated generation of %s" % data["title"]
data = data["swimbundle"]
filename = "%s.yaml" % data["product"].replace(" ", "_").lower()
openapi["info"]["title"] = "%s %s" % (data["vendor"], data["product"])
openapi["info"]["description"] = "Automated generation of %s" % (openapi["info"]["title"])
# data["description"]
# https://swagger.io/docs/specification/authentication/
try:
asset = data["asset"]
inputparams = asset["inputParameters"]
try:
openapi["servers"] = [inputparams["api_url"]["example"]]
except KeyError as e:
#print(inputparams)
#print("Field error: %s" % e)
pass
authset = False
try:
tmpauth = inputparams["api_user"]
tmpauth = inputparams["api_key"]
openapi["components"]["securitySchemes"] = {
"BasicAuth": {
"type": "http",
"scheme": "basic"
}
}
authset = True
except KeyError as e:
pass
try:
tmpauth = inputparams["username"]
tmpauth = inputparams["password"]
openapi["components"]["securitySchemes"] = {
"BasicAuth": {
"type": "http",
"scheme": "basic"
}
}
authset = True
except KeyError as e:
pass
if not authset:
print("AUTH NOT SET: %s" % inputparams)
except KeyError as e:
print("KeyError asset: %s" % e)
cnt = 0
paramnames = []
for task in data["tasks"]:
method = "post"
@@ -45,51 +101,52 @@ def parse_data(data):
},
}
#taskname = task["name"]
#taskdescription = task["description"]
taskcategory = task["family"]
taskname = task["name"]
paramnames.append(taskname)
# This doesn't really do much except build the return value structures
for parameter in task["input_parameters"]:
example = parameter["example"]
for key, value in task["inputParameters"].items():
schema = "string"
inVar = "query"
if parameter["type"] == 6:
if value["type"] == 6:
inVar = "body"
schema = "string"
schemaset = False
if parameter["type"] != 1:
if (parameter["type"] == 7):
if value["type"] != 1:
if (value["type"] == 7):
schema = "boolean"
schemaset = True
if schema == "string" and schemaset:
print("Should change type: %d" % parameter["type"])
print("Should change type: %d" % value["type"])
print(task["name"])
print(parameter["name"])
print()
print(value["name"])
example = ""
try:
example = value["example"]
except KeyError:
pass
if len(example) == 1:
print("Change to number?")
if example.startswith("{"):
print("Change to json object?")
if example.startswith("["):
print("Change to array object?")
# Not sure how to tackle this
description = ""
try:
description = value["description"]
except KeyError:
pass
openapi["paths"]["tmp%d" % cnt][method]["parameters"].append({
"in": inVar,
"name": parameter["name"],
"required": parameter["required"],
"description": parameter["description"],
"schema": {"type": schema}
"name": value["name"],
"required": value["required"],
"example": example,
"description": description,
"schema": {"type": schema},
"in": inVar
})
if len(task["available_output_variables"]) > 0:
openapi["paths"]["tmp%d" % cnt][method]["responses"]["200"]["content"]: {
if len(task["availableOutputVariables"]) > 0:
openapi["paths"]["tmp%d" % cnt][method]["responses"]["200"]["content"] = {
"application/json": {
"schema": {
"$ref": "#/components/schemas/tmp%d" % cnt
@@ -97,19 +154,30 @@ def parse_data(data):
}
}
#responses:
# '200':
# content:
# application/json:
# schema:
# $ref: '#/components/schemas/tmp1'
#description: Successful request
openapi["components"]["schemas"]["tmp%d" % cnt] = {
"type": "object",
"properties": {},
}
for output in task["available_output_variables"]:
openapi["components"]["schemas"]["tmp%d" % cnt]["properties"][output["key"]] = {"type": "string"}
for key, value in task["availableOutputVariables"].items():
if key == "response_code":
continue
openapi["components"]["schemas"]["tmp%d" % cnt]["properties"][key] = {
"type": "string"
}
cnt += 1
#print(openapi)
#print(filename)
print("%s: %d" % (openapi["info"]["title"], len(paramnames)))
return filename, openapi
@@ -121,11 +189,27 @@ def dump_data(filename, openapi):
print("Generated %s" % generatedfile)
if __name__ == "__main__":
url = "https://apphub.swimlane.com/api/v1/bundles/cjuspytpz00rh0hpjo5chqg10"
url = "https://apphub.swimlane.com/api/v1/bundles/cjyoy62ch04920lr26id5sr0e"
url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdc2yr02rs0fli6jrosiqb"
url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdat0u01ux0flipb68a0a0"
url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdhbwp07nf0fli23lyb52h"
data = requests.get(url).json()
filename, openapi = parse_data(data)
dump_data(filename, openapi)
#url = "https://apphub.swimlane.com/api/v1/bundles/cjuspytpz00rh0hpjo5chqg10"
#url = "https://apphub.swimlane.com/api/v1/bundles/cjyoy62ch04920lr26id5sr0e"
#url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdc2yr02rs0fli6jrosiqb"
#url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdat0u01ux0flipb68a0a0"
#url = "https://apphub.swimlane.com/api/v1/bundles/cjqrdhbwp07nf0fli23lyb52h"
url = "https://apphub.swimlane.io/api/swimbundles/swimlane/sw_alienvault_threatcrowd"
url = "https://apphub.swimlane.com/api/swimbundles/swimlane/sw_anomali_threatstream"
with open("swimlane_urls.json", "r") as tmp:
parsed = json.loads(tmp.read())
try:
category = parsed["data"][0]["swimbundleMeta"]["family"][0]
except KeyError:
category = ""
except IndexError:
category = ""
print("CATEGORY: %s" % category)
for data in parsed["data"]:
filename, openapi = parse_data(data)
openapi["tags"] = [category]
dump_data(filename, openapi)