DependencyTrack / dependency-track

Dependency-Track is an intelligent Component Analysis platform that allows organizations to identify and reduce risk in the software supply chain.
https://dependencytrack.org/
Apache License 2.0
2.7k stars 578 forks source link

"An inactive Parent cannot be selected as parent" on creating a child project of newly created project #4337

Open IanAtPico opened 2 weeks ago

IanAtPico commented 2 weeks ago

Current Behavior

DependencyTrack 4.11.7

When I create, from PowerShell a DependencyTrack project, and then create a child project with the parent set to the first project's uuid, I get an error ""An inactive Parent cannot be selected as parent". I have checked, with breakpoints so I can check in the DependencyTrack UI that the parent project has been created, and that it is active. The answer is 'yes' to both. Previous instances of this error in the issues appear to be marked as closed.

The aim is to have a script that goes into our Azure DevOps pipeline, so that when we build we automatically get a SBoM in DependencyTrack. The reason for needing the project tree structure is so that we can have nested projects in DependencyTrack based on customer build, platform, main release etc.

I've searched the issues here and seen that you have to specify the project as active. I do. Same problem. I've also seen someone suggest using POST calls to set it inactive and then active. I do. Same problem. I've also done this using breakpoints, so that I can check the DependencyTrack UI to ensure that the data is correct.

The parent project is created exactly as I'd expect, however the child isn't. The parent is shown as active in the DependencyTrack UI.

Is this still a bug, or am I doing something wrong? I'm really not sure what to try next.

Here's my code to create the parent project:

function CreateDependencyTrackProject([Parameter(Mandatory=$true)][string]$ProjectName)
{
    $uuid = ""
    Write-Host "Create project '$ProjectName'"
    $url = "$_url/api/v1/project"
    Write-Host $url
    $headers = GetHeadersForCreateProject 
    $body = (@{
        name = $ProjectName    
        classifier = "APPLICATION"
        active = [bool]::Parse('True')

    } | ConvertTo-Json)

    $response = Invoke-RestMethod -Uri $url -Method Put -Headers $headers -Body $body   
    if ($response -eq $null)
    {
        Write-Host "NULL RETURNED"
        return ""
    }
    else
    {
        if ($response.uuid -eq $null)
        {
            Write-Host "Project not created"
            return ""
        }
        $uuid = $response.uuid
        Write-Host "new project's uuid: $uuid"
        ForceSetProjectActive -ProjectName $ProjectName -ProjectUuid $uuid
        return $uuid
    }
    return  ""
}

Here's my code to toggle the active state of the project:

function ForceSetProjectActive([Parameter(Mandatory=$true)][string]$ProjectName, [Parameter(Mandatory=$true)][string]$ProjectUuid)
{
    Write-Host "Set project inactive then active"
    $url = "$_url/api/v1/project"
    $headers = GetHeadersForCreateProject 

    $body = (@{
        name = $ProjectName
        uuid = $ProjectUuid
        active = [bool]::Parse('False')
    } | ConvertTo-Json)
    Write-Host "Set project inactive" 
    $response = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body
    Write-Host $response.active

    $body = (@{
        name = $ProjectName
        uuid = $ProjectUuid
        active = [bool]::Parse('True')

    } | ConvertTo-Json)
    Write-Host "Set project active" 
    $response = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body
    Write-Host $response.active

}

Here's my code to create the child project:

function CreateDependencyTrackChildProject(
        [Parameter(Mandatory=$true)][string]$OEM,
        [Parameter(Mandatory=$true)][string]$Version,
        [Parameter(Mandatory=$true)][string]$ParentUuid
        )
{
    Write-Host "First, get the parent project"
    GetProject $OEM $uuid
    $ProjectName = "$OEM $Version"
    $uuid = ""
    Write-Host "Create project '$ProjectName' as child of '$ParentUuid'"
    $url = "$_url/api/v1/project"
    $headers = GetHeadersForCreateProject 

    $body = (@{
        name = $ProjectName    
        classifier = "APPLICATION"
        active =  [bool]::Parse('True')
        author = ""
        version = $version
        parent = {
            name = $OEM
            uuid = $ParentUuid
            active = [bool]::Parse('True')
            }
    } | ConvertTo-Json)

    $response = Invoke-RestMethod -Uri $url -Method Put -Headers $headers -Body $body

    if ($response -eq $null)
    {
        Write-Host "NULL RETURNED"
        return ""
    }
    else
    {
        if ($response.uuid -eq $null)
        {
            Write-Host "Project not created"
            return ""
        }
        $uuid = $response.uuid
        Write-Host "new project's uuid: $uuid"
        return $uuid
    }

    return  ""
}

This is the raw error I get:

Invoke-RestMethod : An inactive Parent cannot be selected as parent

Steps to Reproduce

  1. Run Powershell script
  2. It creates the parent project in CreateDependencyTrackProject - SUCCESS
  3. It calls the CreateDependencyTrackChildProject function to create the child project - ERROR

Expected Behavior

Child project to be created.

Dependency-Track Version

4.11.x

Dependency-Track Distribution

Container Image

Database Server

N/A

Database Server Version

No response

Browser

Google Chrome

Checklist

IanAtPico commented 2 weeks ago

UPDATE: I've got this working.

In CreateDependencyTrackChildProject, I changed the body for Invoke-RestMethod from:


    $body = (@{
        name = $ProjectName    
        classifier = "APPLICATION"
        active =  [bool]::Parse('True')
        author = ""
        version = $version
        parent = {
            name = $OEM
            uuid = $ParentUuid
            active = [bool]::Parse('True')
            }
    } | ConvertTo-Json)

to:

    $body = @"
    {"name": "$ProjectName","classifier":"APPLICATION","active":true, "parent":{"uuid":"$ParentUuid"}}
"@

    $response = Invoke-RestMethod -Uri $url -Method Put -Headers $headers -Body $body