Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


python -m pip install -U pip requests 

Step One – Connect to the iQSonar Host

To access the REST-API we use HTTP with basic authentication. in Python we do this using the "requests" library. You must update this URL to reflect your host, and update the username and password to reflect the credentials for your instance of iQSonar. The "X-fetch-count" variable in the header tells us the total number of devices which have been scanned. In this example we will stop after the first 200 if the Scan Engine has scanned that many. You can look at some of the other worked examples in PowerShell for examples showing paging through the results.

The line "data = r.json()" takes the JSON results and parses it into a Python array variable.

Code Block
languagepy
titleConnect to the remote host
#!/usr/bin/python3
import requests
# Set this to your own host name/login/password)
r = requests.get('http://iqsonar-host/api/v1/devices',auth=('admin','password'))

max = r.headers['X-fetch-count']
data = r.json()

The line "#!/usr/bin/python3" lets Python know that this is a Python 3 script.

Step Two – Iterate over the array of devices

At this point in the script, we have a variable data which contains the JSON output from the Rest API. 

The data structure is a JSON array of objects, each object contains an array of device attributes:

  • device_id
  • host_name
  • serial_number
  • manufacturer
  • model
  • last_scan
  • self

The "self" item is a link to the full details on the device.

Code Block
languagepy
titleIterate over devices
# set some counters
noapps=0
nodb = 0
gotone=0

count = len(data)
i = 0
while (i < count):
    row = data[i]
    gotone=0
        
    if ( 'host_name' in row ):
        hostname = row['host_name']
    else:
        hostname = '(no hostname)'
        
    url2 = row['self']
    r2 = requests.get(url2,auth=('admin','password'))
    device = r2.json()
    if ('total_memory_mb' in device):
        ram = device['total_memory_mb']
    else:
        ram = '(unknown ram)'
    if ('cpu' in device):   
        cpu = device['cpu'][0]['cpu_model']
        # remove commas from the cpu string so as to keep the CSV output valid
        cpu = cpu.replace(',','')
    else:
        cpu = '(unknown cpu)' 
    status = hostname + ': ' + str(ram) + 'MB RAM, ' + str(cpu)

Step Three – Process the Applications link

One caveat - as of Elcano R2, the applications link exists even when the device does not have any scanned applications. Following the link in these cases results in an exception - so we use a TRY/CATCH block to work around this.

Code Block
languagepy
titleGet application details
    # Having got Hostname, Ram and CPU, lets look for databases?
    if ('applications' in device):        
        url3 = device['applications']
        r3 = requests.get(url3,auth=('admin','password'))
        # the URL might not be valid. If no applications, server will return a 500 error
        try:
            apps = r3.json()            
        except:
            noapps += 1
        else:
            numapps = len(apps)
            j=0
            while (j < numapps):
                # Deal with the application entries
                j+=1    

With each application, we're only interested if it is a database application... for any other application type we're going to ignore it.

The database name is stored in apps[j]['product']['name'], but not all applications have product names... hence the nested IF blocks to test if the variable is defined.

If the application name contains "SQL" (Microsoft SQL Server), "Oracle" or "Informix" then we want to list the application along with the edition.

Code Block
languagepy
titleDeal with each application
#
            while (j < numapps):
                if ('product' in apps[j]):
                    if ('name' in apps[j]['product']):
                        if ('SQL' in apps[j]['product']['name']):
                            status = status + '\n  ' + str(apps[j]['product']['name']) + ' '+ str(apps[j]['edition'])
                            gotone+=1
                        if ('Oracle' in apps[j]['product']['name']):
                            status = status + '\n  ' + str(apps[j]['product']['name']) + ' '+ str(apps[j]['edition'])
                            gotone+=1
                        if ('Informix' in apps[j]['product']['name']):
                            status = status + '\n  ' + str(apps[j]['product']['name']) + ' '+ str(apps[j]['edition'])
                            gotone+=1

Outside the loop, we want to only print results if the database has been discovered. If there was no database gotone will be 0, so we only print the status line where gotone is greater than zero.

The final test is to see whether we've got more results. Code to actually process more than one batch of devices is left as an exercise for the reader.

Code Block
languagepy
titleDisplay results
#
    if (gotone > 0):
        print (status)
    i+=1
if (max > count):
    print( "There is another page of results in the REST-API if you want to get it" )
else:
    print("That's all folks")


...