Posting a BOM file for Dependency-Track with PowerShell

Today I was asked a “HEEEELLLLPPP” question at the end of the day. I typically like those types of questions so I was fully engaged! As a result, I was quite activated for a couple of hours, so I decided to make a blog out of it directly!

Let me provide a little context. The help question was related to Dependency-Track. I won’t go into details on the tool itself but if you are interested I would start at the dependencytrack.org website. Back to the question, there was a working PostMan call but getting a PowerShell script to posting a BOM (Bill Of Material) through posting Form Data is not as simple as you would expect, so this is where we were stuck…

First, the easy part, getting a version of Dependency-Track running locally. This gist shows you that a few lines can get you started with a container to do just that. It is easy to configure and allows you to be up-and-running in no time.

docker pull owasp/dependencytrack
docker volume create name dependencytrack
docker run d m 8192m p 8080:8080 name dependencytrack v dependencytrack:/data owasp/dependencytrack

While we had a working PostMan Call, we could make use of the PostMan code examples, combined with lot’s of extra search result tabs in my browser, as well as good discussion and screen sharing session we came to the following working script.

try {
Set-Location $PSScriptRoot
$ProjectGuid = "d78bc750-d6db-4805-9836-5d77075ec37a"
$ApiKey = "6Ue2f8uVfRiVGpdowjWfF3yW02ryA7Uc"
$Uri = "http://localhost:8080/api/v1/bom"
$FileName = "bom.xml"
$ContentType = "multipart/form-data"
$xml = Get-Content (Join-Path $PSScriptRoot $FileName) Raw
$httpClientHandler = [System.Net.Http.HttpClientHandler]::new()
$httpClient = [System.Net.Http.Httpclient]::new($httpClientHandler)
$multipartContent = [System.Net.Http.MultipartFormDataContent]::new()
$projectHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
$projectHeader.Name = "project"
$projectContent = [System.Net.Http.StringContent]::new($ProjectGuid)
$projectContent.Headers.ContentDisposition = $projectHeader
$multipartContent.Add($projectContent)
$bomHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
$bomHeader.Name = "bom"
$bomContent = [System.Net.Http.StringContent]::new($xml)
$bomContent.Headers.ContentDisposition = $bomHeader
$multipartContent.Add($bomContent)
$httpClient.DefaultRequestHeaders.Add("X-API-Key", $ApiKey);
$response = $httpClient.PostAsync($Uri, $multipartContent).Result
$response.Content.ReadAsStringAsync().Result
}
catch {
Write-Host $_
}
finally {
if ($null -ne $httpClient) {
$httpClient.Dispose()
}
if ($null -ne $response) {
$response.Dispose()
}
}

There is no magic but creating the objects to be able to properly post MultipartFormDataContent is not something I do on a daily basis. While we were happy with the working solution, I was not completely satisfied with this result. There must be other ways of doing this. One another way I found is using another API call that also allows larger content. That will come in handy when parsing a combination of BOM files!

try {
$xml = Get-Content (Join-Path $PSScriptRoot ".\bom.xml") Raw
$ProjectGuid = "d78bc750-d6db-4805-9836-5d77075ec37a"
$ApiKey = "6Ue2f8uVfRiVGpdowjWfF3yW02ryA7Uc"
$Uri = "http://localhost:8080"
$Body = ([PSCustomObject] @{
project = $ProjectGuid
bom = ([Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($xml)))
} | ConvertTo-Json)
$Header = @{ 'X-API-Key' = $ApiKey }
Invoke-RestMethod Method Put Uri "$Uri/api/v1/bom" Headers $Header ContentType "application/json" Body $Body
}
catch {
Write-Host $_
}

This file is something like you would expect in the first place. Much more condensed and lot less typing and types flying around. Also working with the Invoke-RestMethod is a lot more common. Great improvement found during the troubleshooting! Convenient is that this also works in PowerShell Core!

I hope this post helps you when you are in search of posting some BOM files to Dependency-Track with PowerShell!

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.