Cant seem to do a post call on via api (reports)

Quick and dirty script…

cant figure out why im getting a 400,

import site
import rapid7
import requests, time


hostname = "https://sv03tmcr7.dot.ca.gov:3780"
username = "username"
password = "mysecurepassword#eAHM/I8W1"


time_date = time.strftime("%Y_%m_%d-%H:%M:%S")
scanName = 'test'+"_"+time_date
url1 = hostname + "/api/3/reports"

parameters = {
    "format": 'sql-query',
    "language": 'en-US',
    "name": scanName,
    "query": 'SELECT * FROM dim_asset ORDER BY ip_address',
    "scope": 
        {"scan": 326644,
        "sites": 28},
    #"scope": {"sites": [str(site_id)],"scan": str(scan_id)},
    "template": 'basic-vulnerability-check-results',
    "timezone": 'America/Los_Angeles',
    "version": '2.3.0',
    "path":'monthly_reports/site/corporate'
    }

print(parameters)
#configure report
response1= requests.post(url=url1,auth=(username,password),params=parameters,headers={'Content-Type':'application/json'},verify=False)
print(response1)

https://help.rapid7.com/insightvm/en-us/api/index.html#operation/createReport
my main bulk of thee script was taken from a working example of ansible-collection-rapid7/r7_insightvm_report.py at main · GSLabDev/ansible-collection-rapid7 · GitHub

There’s a couple things going on here

  1. The authentication is probably throwing an error because it’s expecting a base64 encoded version of “username:password” not just “username, password”.
  2. You’re trying to do a SQL Query so the “template” field in the parameters is unnecessary.
  3. I assume ‘path’ is coming from the function sheet you linked to but you’re not calling the function sheet so the path variable doesn’t exist in our API endpoint, it would be ‘storage’

Interesting that this python module doenst use it…ansible-collection-rapid7/r7_insightvm_report.py at main · GSLabDev/ansible-collection-rapid7 · GitHub

I’m very curious of how that code sample works. There very well may be something I’m missing as I’m reading through the script there. However, below is a sample script output from Postman for using this API endpoint if it helps.

note that I did a base64 encode of “username:password” which is being used here as dXNlcm5hbWU6cGFzc3dvcmQ=

Just swap out that value and the console IP/FQDN

import requests
import json

url = "https://your console:3780/api/3/reports"

payload = json.dumps({
  "filters": {
    "severity": "all",
    "statuses": [
      "potentially-vulnerable",
      "vulnerable-version",
      "vulnerable"
    ]
  },
  "format": "sql-query",
  "language": "en-US",
  "name": "SQL-example",
  "query": "SELECT * FROM dim_asset ORDER BY ip_address",
  "scope": {
    "assetsInOnlyMostRecentScanOfSite": False,
    "scan": 100
  },
  "timezone": "America/Los_Angeles",
  "version": "2.3.0"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json;charset=UTF-8',
  'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

Wow, thanks so much!! I like that output a lot better (more detailed)

i was also able to use postman in some simple get requests (though maybe post request is slightly different)

Postman definitely helps a lot for building the APIs. For one, it does the basic auth for you. The POST calls are slightly different as you need to define the JSON body. You can download our swagger file and import to Postman to make it tons easier. The only thing thats difficult here is that the reports endpoint has a lot of different options when building the body depending on the report you intend to create.

thanks again! i got it working, i havent seen post requests calls made like that before! still lots to learn in python :slight_smile: