1+ import requests
2+ import base64
3+ import getpass
4+ import json
5+
6+ class Application :
7+ def __init__ (self , app_id , name ):
8+ self .app_id = app_id
9+ self .name = name
10+
11+ def getApplications (headers , params , org_id ):
12+ url = f"{ contrast_url } /api/ng/{ org_id } /applications"
13+ response = requests .get (url , headers = headers , params = params )
14+ return response
15+
16+ def getServers (headers , servers_href ):
17+ url = f"{ contrast_url } /api{ servers_href } "
18+ print (f" Fetching servers from: { url } " )
19+ response = requests .get (url , headers = headers )
20+ return response
21+
22+ def read_creds_file (filename = "../.creds" ):
23+ """Read credentials from a .creds file"""
24+ creds = {}
25+ try :
26+ with open (filename , "r" ) as f :
27+ for line in f :
28+ line = line .strip ()
29+ if line and not line .startswith ("#" ):
30+ key , value = line .split ("=" , 1 )
31+ creds [key ] = value
32+ except FileNotFoundError :
33+ print (f"Warning: { filename } file not found. Please input values." )
34+ return creds
35+
36+ # Read credentials from .creds file
37+ creds = read_creds_file ()
38+
39+ # Set the default for re-using within your organization.
40+ contrast_url = creds .get ("CONTRAST_URL" , "" )
41+ org_id = creds .get ("ORG_ID" , "" )
42+ username = creds .get ("USERNAME" , "" )
43+ api_key = creds .get ("API_KEY" , "" )
44+ service_key = creds .get ("SERVICE_KEY" , "" )
45+ app_id = creds .get ("APP_ID" , "" )
46+
47+ headers = {
48+ "Accept" : "application/json"
49+ }
50+ params = {
51+ "expand" : ["apps" , "vulns" , "metadata" ]
52+ }
53+
54+ def main ():
55+ global contrast_url , org_id , username , api_key , service_key
56+
57+ msg = f"Enter your Contrast URL (blank will use default '{ contrast_url } '): "
58+ contrast_url_input = input (msg )
59+ if contrast_url_input .strip ():
60+ contrast_url = contrast_url_input
61+ else :
62+ while not contrast_url_input .strip () and not contrast_url .strip ():
63+ print ("Contrast URL cannot be blank." )
64+ contrast_url_input = input (msg )
65+ contrast_url = contrast_url_input
66+
67+ msg = f"Enter your Organization ID (blank will use default '{ org_id } '): "
68+ org_id_input = input (msg )
69+ if org_id_input .strip ():
70+ org_id = org_id_input
71+ else :
72+ while not org_id_input .strip () and not org_id .strip ():
73+ print ("Organization ID cannot be blank." )
74+ org_id_input = input (msg )
75+ org_id = org_id_input
76+
77+ msg = f"Enter your username (blank will use default '{ username } '): "
78+ username_input = input (msg )
79+ if username_input .strip ():
80+ username = username_input
81+ else :
82+ while not username_input .strip () and not username .strip ():
83+ print ("Username cannot be blank." )
84+ username_input = input (msg )
85+ username = username_input
86+
87+ msg = f"Enter your API key (blank will use default '****************************'): "
88+ api_key_input = getpass .getpass (msg )
89+ if api_key_input .strip ():
90+ api_key = api_key_input
91+ else :
92+ while not api_key_input .strip () and not api_key .strip ():
93+ print ("API key cannot be blank." )
94+ api_key_input = getpass .getpass (msg )
95+ api_key = api_key_input
96+
97+ msg = f"Enter your service key (blank will use default '************'): "
98+ service_key_input = getpass .getpass (msg )
99+ if service_key_input .strip ():
100+ service_key = service_key_input
101+ else :
102+ while not service_key_input .strip () and not service_key .strip ():
103+ print ("Service key cannot be blank." )
104+ service_key_input = getpass .getpass (msg )
105+ service_key = service_key_input
106+
107+ auth_str = f"{ username } :{ service_key } "
108+ auth_b64 = base64 .b64encode (auth_str .encode ()).decode ()
109+ headers ["Authorization" ] = f"Basic { auth_b64 } "
110+ headers ["API-Key" ] = api_key
111+
112+ response = getApplications (headers , params , org_id )
113+ if response .status_code == 200 :
114+ data = response .json ()
115+ with open ("output.json" , "w" ) as f :
116+ json .dump (data , f , indent = 2 )
117+ print ("Applications response saved to output.json" )
118+
119+ if data .get ("applications" ):
120+ application_list = data ["applications" ]
121+ print (f"Total Applications: { len (application_list )} " )
122+
123+ for app in application_list :
124+ app_name = app .get ("name" , "N/A" )
125+ app_id = app .get ("app_id" , "N/A" )
126+ metadata_entities = app .get ("metadataEntities" , [])
127+
128+ print (f"\n Application: { app_name } (ID: { app_id } )" )
129+
130+ # Output metadata entities
131+ if metadata_entities :
132+ print (f" Metadata Entities:" )
133+ for entity in metadata_entities :
134+ print (f" { json .dumps (entity , indent = 6 )} " )
135+ else :
136+ print (f" Metadata Entities: None" )
137+
138+ # Get the links array from the application
139+ links = app .get ("links" , [])
140+
141+ # Find the servers link
142+ servers_href = None
143+ for link in links :
144+ if link .get ("rel" ) == "servers" :
145+ servers_href = link .get ("href" )
146+ break
147+
148+ if servers_href :
149+ print (f"DEBUG: servers_href = { servers_href } " )
150+ servers_response = getServers (headers , servers_href )
151+
152+ if servers_response .status_code == 200 :
153+ servers_data = servers_response .json ()
154+ servers = servers_data .get ("servers" , [])
155+
156+ for server in servers :
157+ server_name = server .get ("name" , "N/A" )
158+ server_id = server .get ("server_id" , "N/A" )
159+ print (f" - Server: { server_name } (ID: { server_id } )" )
160+ else :
161+ print (f" Error fetching servers: { servers_response .status_code } " )
162+ else :
163+ print (" No servers link found for this application" )
164+ else :
165+ print ("No applications found in response." )
166+ return
167+ else :
168+ print (f"Error: { response .status_code } - { response .text } " )
169+
170+ if __name__ == "__main__" :
171+ main ()
0 commit comments