0
votes

I'm trying to connect to our McAfee ESM using a PowerShell API call.

The API calls for parameters to be submitted to it in JSON form. I've tried to use the PowerShell ConvertTo-Json commandlet with a hash and i've also tried to use just straight json text.

$headers = @{
    'Content-Type' = 'application/json'
    'Accept' = 'application/json'
    }    


$body_json = {"datasource": {
        "parentId": "123456789000",
        "name": "(name)",
        "id": "(value)",
        "typeId": 0,
        "childEnabled": false,
        "childCount": 0,
        "childType": 0,
        "ipAddress": "(ipAddress)",
        "zoneId": 0,
        "url": "(url)",
        "enabled": false,
        "idmId": 123456789000,
        "parameters": [{
            "key": "(key)",
            "value": "(value)"
        }]
    }}

$body_json_converted = @{
      datasource = @(
        @{
           parentId = 123456789000
           name = "name"
           id = "value"
           typeId = 0
           childEnabled = $false
           childCount = 0
           childType = 0
           ipAddress = "ipAddress"
           zoneId = 0
           url = "url"
           enabled = $false
           idmId = 123456789000
           parameters = @( @{
                key = "key"
                value = "value"
           })
    })
} | ConvertTo-Json -Depth 4


Invoke-RestMethod $url -Body $body_json_converted -Method Post -Headers $headers

Invoke-WebRequest $url -Body $body_json -Method Post -Headers $headers

I expect to get a result back saying that it has sucessfully created the data source or to tell me that i'm missing a parameter of some sort. What i'm actually getting is

Invoke-RestMethod : Cannot deserialize instance of [ERROR] 'com.mcafee.siem.api.data.datasource.EsmDataSourceDetail' out of START_ARRAY [ERROR] token

This appears to be almost an identical issue to this user:

Powershell Invoke-Webrequest w/ JSON Body - Can not deserialize...? but the user doesn't explain how he/she fixed it.

Edit: The McAfee ESM has an API help page for the particular API call to add a data source. All of the other API calls are documented the same. Here is the majority of the content from it:

Description Add a data source.

Parameters datasource Type: EsmDataSourceDetail Description: datasource to add Return Value ("return" JSON root element IS returned) Type: EsmDataSourceId Description: datasource id of the datasource that was just added Example REST Call (with JSON if applicable) https://siem/rs/esm/dsAddDataSource

Example JSON Content:

{"datasource": {
    "parentId": {"id": 123456789000},
    "name": "(name)",
    "id": {"id": "(id)"},
    "typeId": {"id": 0},
    "childEnabled": false,
    "childCount": 0,
    "childType": 0,
    "ipAddress": "(ipAddress)",
    "zoneId": 0,
    "url": "(url)",
    "enabled": false,
    "idmId": 123456789000,
    "parameters": [{
        "key": "(key)",
        "value": "(value)"
    }]
}}
1
How are you sure the format of your JSON is correct? Do you have reference documentation you can share regarding the format for the body of the posted content? - Jason Shave
What happens if you add -ContentType 'application/json' to the Invoke-RestMethod - Theo
I added the documentation for the API call to the original post Jason. At the top of the script i have the $headers variable which includes the ContentType of 'application/json'. - shawnzzzy

1 Answers

0
votes

Looks like your $body_json_converted is wrong based on your JSON example.

You've specified datasource as an array with a table in it. In the other two examples its just a table. parentId also looks like it should be a table.

[ordered] just makes it easier to compare.

So, I would try:

$body_json_converted = @{
      datasource = [ordered]@{
           parentId = @{
               id = 123456789000
           }
           name = "name"
           id = "value"
           typeId = 0
           childEnabled = $false
           childCount = 0
           childType = 0
           ipAddress = "ipAddress"
           zoneId = 0
           url = "url"
           enabled = $false
           idmId = 123456789000
           parameters = @( @{
                key = "key"
                value = "value"
           })
    }
} | ConvertTo-Json -Depth 4

Output from above:

PS > $body_json_converted
{
  "datasource": {
    "parentId": {
      "id": 123456789000
    },
    "name": "name",
    "id": "value",
    "typeId": 0,
    "childEnabled": false,
    "childCount": 0,
    "childType": 0,
    "ipAddress": "ipAddress",
    "zoneId": 0,
    "url": "url",
    "enabled": false,
    "idmId": 123456789000,
    "parameters": [
      {
        "key": "key",
        "value": "value"
      }
    ]
  }
}

If you'd prefer you can also just add the JSON directly instead of converting:

$jsonObject = 
@"
{"datasource": {
    "parentId": {"id": 123456789000},
    "name": "(name)",
    "id": {"id": "(id)"},
    "typeId": {"id": 0},
    "childEnabled": false,
    "childCount": 0,
    "childType": 0,
    "ipAddress": "(ipAddress)",
    "zoneId": 0,
    "url": "(url)",
    "enabled": false,
    "idmId": 123456789000,
    "parameters": [{
        "key": "(key)",
        "value": "(value)"
    }]
}}
"@