PowerShell & Qualys: Get Asset Group Info – Part 2

Today I decided to write another post regarding PowerShell and Qualys Vulnerability Management API.  This post will focus on gathering information about your enrolled Asset Groups.   You can find the complete script on GitHub: https://github.com/MSAdministrator/POSH-Guard/blob/master/Get-QualysAssetGroupInformation

We start of by opening up PowerShell ISE and using our handy “Snippet” shortcut:

PowerShell_ISE_CTRL_+_J

We select the “Cmdlet (Advanced function) – complete” option in the “Snippet” context menu.  Once we have our advanced function template, we then proceed by entering a name for our Qualys Asset Group function.

Since we will be gathering some additional information about our Asset Groups, I am going to name my function:


function Get-QualysAssetGroupInformation

Next, we will start by filling out our “Help” info.  At this point, a lot of people skip this step; I HIGHLY recommend that you do not.  It will help you and anyone else viewing your code, understand what your intention was when writing this function.

Next, we start by looking at our advanced functions template within the body of this function.  The first thing you will see is some default parameters for [CmdletBinding].  With my function, I’m going to weed these parameters down a bit, as they are not really needed.  Your function should look something like this when complete:

function Get-QualysAssetGroupInformation
{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  HelpUri = 'https://raw.githubusercontent.com/MSAdministrator/POSH-Guard/master/Get-QualysAssetGroupInformation',
                  ConfirmImpact='Medium')]
    [Alias()]
    Param
    (
        # Param1 help description
        [parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage="Please provide a credential obejct")]
                   [ValidateNotNullOrEmpty()]
                   [System.Management.Automation.CredentialAttribute()]$credential
        ) 

    Begin
    {
    }
    Process
    {
        
    }
    End
    {
    }
}

After we have the base of this function setup and ready to go, we will start off by adding some code into our Begin block.  Remember, the Begin block will always run once for every call to the function.

	$results = @()
	$assetGroupInfo = @()
        [xml]$assetGroupInfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/asset_group_list.php" -Credential $credential

Here I am setting my $assetGroupInfo and a $results variable as empty array’s/hash-table’s. Next, I’m casting my $assetGroupInfo variable as an XML object. This ensures that we receive XML from Invoke-RestMethod Cmdlet.

If we want to make sure that any errors are caught, we should add a Try/Catch block to our Invoke-RestMethod call. Your code should look like this:

 Begin
    {
        $results = @()
        $assetGroupInfo = @()

        Try
        {
            [xml]$assetGroupInfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/asset_group_list.php" -Credential $credential
        }
        Catch
        {
            Write-Debug "Error using Invoke-RestMethod: $_"
        }
    }

Now we move to the Process block. This is where we will be parsing our data into our objects. As I mentioned above, we are wanting to gather all our Asset Groups Titles, their assigned IP Addresses, their role, and the users login ID. To do this, we must loop through each item, or branch returned by our query above. Each $item can be considered as an Asset Group. Additionally, we need to loop through each of the users assigned to that Asset Group.

Once we have that data, we want to create a Custom PSObject to hold all of this data. Your code should look like this:

Process
{
	foreach ($item in $assetGroupInfo.SelectNodes("/ASSET_GROUP_LIST/ASSET_GROUP"))
	{
		for ($u=0; $u -lt $($item.ASSIGNED_USERS.ASSIGNED_USER.LOGIN).count;$u++)
		{
			$tempAssetGroupInfo = @()
		                            
                                $props = @{
				userlogin=$($item.ASSIGNED_USERS.ASSIGNED_USER[$u].LOGIN.InnerText)
				userrole=$($item.ASSIGNED_USERS.ASSIGNED_USER[$u].ROLE.InnerText)
                                           assetgrouptitle=$($item.TITLE.InnerText)
                                           ip=$($item.SCANIPS.IP)
                                          }
		
			$tempAssetGroupInfo = New-Object PSObject -Property $props
		        
                                $results += $tempAssetGroupInfo
		}
	}
}

Now, we can either simply put the following line in our End block:

return $results

But, I actually like it to be saved into an XML file. This means that I can use this data with other functions without having to call Qualys again. To be quite frank, as you may know, Qualys is not the fastest website/service out there. Don’t get me wrong, the scanning engines are fast, but their database(s) – not so much.

To return both the object and export the results to an XML, we can just add this one line of code:

Export-Clixml -Path "$env:USERPROFILE\Desktop\QualysData\assetgroupinfo.xml" -InputObject $results

That’s it. We now have a function that can return some details about our Asset Groups within Qualys. Next time, I will focus on creating a function that gathers our enrolled IP Addresses, split’s them into a single list.

Hint: Qualys loves IP ranges (192.168.0.1-192.168.0.123) and their API calls return it the same way. 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s