Skip to content

API

Info

Ostorlab added support for Universal Binary JSON encoding. UBJSON provides several performance benefits and adds support for binary data types. For more information about the format and available libraries, check out the following link UBJSON Spec. Support for JSON is still available and either can be specified using the content type header.

Overview

Ostorlab provides a GraphQL API to perform all tasks, from creating scan, access scans progress to listing vulnerabilities.

graphiql

GraphQL offers several benefits, like performance, reduced number of requests and removes the need for API versioning.

The next section will describe how to use the API, how to experiment and test it.

If you are not familiar with GraphQL, we recommend this tutorial to get familiar with the technology and syntax.

Access

Sandbox

You can use the GraphiQL web application to experiment with the API. GrapiQL is accessible at https://api.ostorlab.co/apis/graphql. The API is accessible to authenticated users only. Make sure you are authenticated at https://api.ostorlab.co/portal/login/ .

sandbox

Scripts

Typical usage of the API is for automation around deployment pipelines or automating the creation and monitoring of a large number of scans.

For the authentication process, you have two options:

  • Token based authentication
  • API Key authentication
Token based authentication

The token can be retrieved from https://api.ostorlab.co/apis/token/ by submitting the username and password. A token linked to the user will be created. The token is then set in an Authorization header with the value Token {value} to authenticate subsequent requests to https://api.ostorlab.co/apis/graphql_token.

import requests
import json


query = '''
query {
  scans {
    scans {   
      id
      title
      progress
    }
  }
}
'''

# Retrieve authentication token.
request = requests.post(url='https://api.ostorlab.co/apis/token/',
                      json={"username":"user1","password":"xxxxxx"})
json_data = json.loads(request.text)
if "token" in json_data:
  token = json_data["token"]
  # Set token in Authorization header.
  headers = {"Authorization": f"Token {token}"}
  # Post query request.
  request = requests.post(url='https://api.ostorlab.co/apis/graphql_token/',
                          json={"query": query},
                          headers=headers)
  print(request.json())
TOKEN_RESPONSE=$(curl -X POST https://api.ostorlab.co/apis/token/ --header "Content-Type: application/json" --data '{"username": "user1", "password":"xxxxxx"}')
TOKEN=$(echo $TOKEN_RESPONSE | jq '.token' | tr -d '"')
curl -v -X POST https://api.ostorlab.co/apis/graphql_token \
--header 'Content-Type: application/json' \
--header "Authorization: Token $TOKEN" \
--data '{"query": "query {scans { scans { id title  progress }}}"}'
API Key authentication

The API key can be retrieved from your dashboard https://report.ostorlab.co. You need to click on Library then API keys menu. Click the new button to generate a new key and copy the api key (You can add a name and an expiry date to your key), do not forget to click the save button to save your key.

The API key is used as the value of the header's key the key X-Api-Key to authenticate subsequent requests to https://api.ostorlab.co/apis/graphql_token.

import requests

query = '''
query {
  scans {
    scans {   
      id
      title
      progress
    }
  }
}
'''

# Set api key in Authorization header.
api_key = "XXXXXXXXXXX"
headers = {"X-Api-Key": f"{api_key}"}
# Post query request.
request = requests.post(url='https://api.ostorlab.co/apis/graphql_token/',
                      json={"query": query},
                      headers=headers)
print(request.json())
curl -v -X POST https://api.ostorlab.co/apis/graphql \
--header 'Content-Type: application/json' \
--header "X-Api-Key: $API_KEY" \
--data '{"query": "query {scans { scans { id title  progress }}}"}'  

Reference

Ostorlab maintains a self documenting scheme, see documentation explorer at the top right corner in the GrapiQL menu. See also the example section for common queries.

Examples

List Scans

To list all the scans owned by the organisation of the current user:

query {
  scans {
    scans {   
      id
      title
      progress
    }
  }
}

List Scans by Filter

To list scans for a particular Mobile Application, use the target argument to specify the application package name or bundle id.

{
  scans(page: 1, numberElements: 100, target: "com.ubercab.fleet") {
    scans {
      id
      progress
      packageName
      assetType
    }
  }
}

The scans API supports other filters like targetAssetTypes, riskRatings, progress and can be ordered and sorted using orderBy and sort arguments:

{
  scans(page: 1, numberElements: 100, orderBy: RiskRating) {
    scans {
      id
      progress
      riskRating
      packageName
      assetType
    }
  }
}

output

Scan Details

To retrieve the details of a single scan using its id:

query {
  scan(scanId: 26095) {
    id
    title
    assetType
    createdTime
    riskRating
  }
}

Vulnerability Details

To retrieve the list and details of vulnerabilities of a scan:

query {
  getScan(scanId: 26095) {
    vulnerabilities {
        vulnerabilities {
          detail {
            title
            description
            recommendation
            cvssV3Vector
          }
          customCvssV3BaseScore
        }
    }
  }
}

Scan Progress

To determine scan current progress stage (scheduled, scanning or done):

query {
  scans {
    scans{
      id
      packageName
      progress
    }
  }
}

Create New Scan

To create a scan, files are uploaded as a multipart http request.

mutation newMobileScan($title: String!, $assetType: String!, $application: Upload!, $scanProfile: String!) {
      createMobileScan(title: $title, assetType:$assetType, application: $application, scanProfile: $scanProfile) {
        scan {
            id
        }
      }
    }

An example of an Android scan:

import requests
import json

with open('app.apk', 'br') as application:
    query = '''mutation newMobileScan($title: String!, $assetType: String!, $application: Upload!, $scanProfile: String!) {
                createMobileScan(title: $title, assetType:$assetType, application: $application, scanProfile: $scanProfile) {
                  scan {
                    id
                  }
                }
              }
            '''
    data = {
        'operations': json.dumps({'query': query,
                                  'variables': {'title': 'fake_title', 'assetType': 'android', 'application': None,
                                                'scanProfile': 'Fast Scan'}}),
        'map': json.dumps({
            '0': ['variables.application'],
        })
    }
    resp = requests.post('https://api.ostorlab.co/apis/graphql/', data=data, files={'0': application.read(),}, headers={"Authorization": f"Token {token}"})
curl -v -X POST https://api.ostorlab.co/apis/graphql \
--header 'Accept: application/json' \
--header "X-Api-Key: $API_KEY" \
--form 'operations={"query": "mutation newMobileScan($title: String!, $assetType: String!, $application: Upload!, $scanProfile: String!) { 
createMobileScan(title: $title, assetType:$assetType, application: $application, scanProfile: $scanProfile) {scan { id }  }}", 
"variables": {"title": "My application", "assetType": "android", "application": null, "scanProfile": "Fast Scan"}}' \
--form 'map={"0": ["variables.application"]}' \
--form "0=@/path/to/your/app.apk"

Create a new scan with authentication

Creating a scan with a credentials is a two-step process. First, credentials are added to the credentials store and a credential id is returned, and then a scan creation request is sent specifying the ids of the credentials to use in that scan.

For instance to create a simple login password credential. You can use the following:

mutation newTestCredential {
  createTestCredentials(testCredentials: {loginPassword: {login: "login1", password: "password1"}}) {
    testCredentials {
      __typename
      ... on LoginPasswordTestCredentials {
        id
      }
    }
  }
}

Which will return the ID as the following:

{
  "data": {
    "createTestCredentials": {
      "testCredentials": {
        "__typename": "LoginPasswordTestCredentials",
        "id": "901"
      }
    }
  }
}

To pass the credential Id, you must add the argument credentialIds with the list of Ids:

mutation newMobileScan($title: String!, $assetType: String!, $application: Upload!, $scanProfile: String!) {
  createMobileScan(title: $title, assetType: $assetType, application: $application, scanProfile: $scanProfile, credentialIds: [901]) {
    scan {
      id
    }
  }
}