0

I am currently trying to prepare a JSON body for an API call, which should look something like this

curl -XPOST -H 'Authorization: Bearer ***API*KEY***' -H 'Content-Type: application/json' http://127.0.0.1:9000/api/alert -d '{
  "title": "Other alert",
  "description": "alert description",
  "type": "external",
  "source": "instance1",
  "sourceRef": "alert-ref",
  "severity": 3,
  "tlp": 3,
  "artifacts": [
    { "dataType": "ip", "data": "127.0.0.1", "message": "localhost" },
    { "dataType": "domain", "data": "thehive-project.org", "tags": ["home", "TheHive"] },
  ],
  "caseTemplate": "external-alert"
}'

The problem however is that my json body which I create with powershell has weird characters and don't see where the problem is. This is my JSON Body

{
    "tlp":  1,
    "source":  "Test",
    "title":  "Test Alert1",
    "artifacts":  "{\r\n    \"dataType\":  \"ip\",\r\n    \"data\":  \"127.0.0.1\"\r\n}",
    "type":  "external",
    "sourceRef":  "1",
    "description":  "Test",
    "severity":  1
}

I create this JSON body as follows. I have already tried CustomObjects and Hashtables, but always get the same output

$body = @{
            title = "$title"
            description = "$Alert_Description"
            type ="external"
            source ="$Source"
            sourceRef ="$SourceRef"
            severity = $Severity
            tlp = $tlp
            $artifacts = [PSCustomObject]@{
            dataType=ip
            data=127.0.0.1}  
        }| ConvertTo-Json
        $JsonBody = $body | ConvertTo-Json

Can somebody give me a hint? I have no clue anymore

2 Answers2

3

First, fix your hashtable so that it creates the intended JSON representation, and only apply ConvertTo-Json once:

$body = [ordered] @{
  title       = $title
  description = $Alert_Description
  type        = 'external'
  source      = $Source
  sourceRef   = $SourceRef
  severity    = $Severity
  tlp         = $tlp
  artifacts   = , [pscustomobject] @{
    dataType = 'ip'
    data     = '127.0.0.1'
  }  
} | ConvertTo-Json
  • Variables don't need enclosing in "..." unless you explicitly want to convert their values to strings.

  • Literal textual information such as ip does require quoting ('...', i.e. a verbatim string literal, is best).

  • The artifacts property is an array in your sample JSON, so the unary form of ,, the array constructor operator is used to wrap the [pscustomobject] instance in a single-element array.

    • If you have multiple objects, place , between them; if the array was constructed previously and stored in a variable named, say, $arr, use artifacts = $arr.
  • Use of [ordered], i.e. the creation of an ordered hashtable isn't strictly necessary, but makes it easier to compare the resulting JSON representation to the input hashtable.

  • Generally keep in mind that explicit use of a -Depth argument with ConvertTo-Json is situationally required in order to ensure that properties aren't truncated - see this post for more information. However, with the hashtable in your question this happens not to be a problem.


Second, since you're sending the json to an external program, curl (note that in Windows PowerShell you'd have to use curl.exe in order to bypass the built-in curl alias for Invoke-WebRequest, an additional escaping step is - unfortunately - required up to at least v7.1 - though that may change in v7.2: The " instances embedded in the value of $body must manually be escaped as \", due to a long-standing bug in PowerShell:

curl -XPOST -H 'Authorization: Bearer ***API*KEY***' -H 'Content-Type: application/json' `
  http://127.0.0.1:9000/api/alert -d ($body -replace '([\\]*)"', '$1$1\"')

Note: With your particular sample JSON, -replace '"', '\"' would do.

See this answer for more information.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • The main problem was the "" around the variables, I didn't know that this creates some weird characters.. But I'm a bit confused about the artifacts part. I've tried to add two abjects to the artifacts properties like that, but it didn't work $collection = New-Object System.Collections.ArrayList $collection.Add([pscustomobject] @{dataType = 'username' data = $Username}) $collection.Add([pscustomobject] @{dataType = 'username' data = $Username}) artifacts = $collection.ForEach($_) – Stefan Röthlisberger Aug 25 '21 at 10:46
  • @StefanRöthlisberger: Enclosing a variable reference in `"..."` in essence calls `.ToString()` on the variable, using the invariant culture, and has special handling for arrays, which stringify as a space-separated list of their (stringified) elements (try `"$(1,2,3)"`. As for the `artifacts` part: `artifacts = $collection` – mklement0 Aug 25 '21 at 12:23
1

Slap a "-Depth 50" on your ConvertTo-Json, that should solve your issue.

Like here: ConvertTo-Json flattens arrays over 3 levels deep

  • While this is a good tip in general, `-Depth` is not required to get a full JSON representation of the hashtable in the question (it isn't nested deeply enough to be a problem), whereas there are other, obvious problems with the code. – mklement0 Aug 25 '21 at 12:32