Skip to content

Walkthrough: Uploading and analyzing a trace using the Cryptosense Analyzer API

Aim

This walkthrough will guide you through the process of uploading a trace file using the Cryptosense Analyzer v2 API, triggering an analysis of the uploaded trace and viewing the results of the analysis.

The walkthrough is divided into two stages:

  1. Finding a project and a profile to use.
  2. Uploading the trace to S3 and importing it.
  3. Launching an analysis of the trace and viewing the results.

Prerequisites

Before you begin, make sure that you have the following pieces of information available:

  • Your Cryptosense API key.
    • This key can be found at the API page of the analyzer.
    • If you do not have API access enabled, then the link above will return a 404 error. To enable API access, please contact support.
  • A trace to upload.
    • For instructions on generating a trace, please see our guide for Java.
    • In the instructions below, the name of the trace is assumed to be trace_name.cst.gz.

As well as the information above, you will need a client to interact with API. In this walkthrough, we use the open-source curl HTTP client, which is available for most platforms.

Part 1: Finding the project and the profile

The following query will list projects you have access to, with IDs and names:

query {
  viewer {
    organization {
      projects {
        edges {
          node {
            id
            name
          }
        }
      }
      profiles {
        edges {
          node {
            id
            name
          }
        }
      }
    }
  }
}

Example response:

{
  "data": {
    "viewer": {
      "organization": {
        "projects": {
          "edges": [
            {
              "node": {
                "id": "UHJvamVjdDoy",
                "name": "Java Application"
              }
            },
            {
              "node": {
                "id": "UHJvamVjdDox",
                "name": ".NET Application"
              }
            }
          ]
        },
        "profiles": {
          "edges": [
            {
              "node": {
                "id": "UHJvZmlsZTox",
                "name": "Cryptosense 2020"
              }
            },
            {
              "node": {
                "id": "UHJvZmlsZToy",
                "name": "NIST"
              }
            }
          ]
        }
      }
    }
  }
}

Make a note of the IDs of the project and profile that you would like to use in the next sections.

Part 2: Uploading the trace

In this section, we will upload a trace and add it to the project we have selected.

Retrieve S3 authenticated POST details from the API

Before uploading the trace file directly to AWS S3, it is necessary to generate a new set of authentication parameters using the API, which can then be used in an authenticated POST request directly to the AWS S3 API.

Use the following query to request a set of authentication parameters:

mutation {
  generateTraceUploadPost(input: {}) {
    url
    formData
  }
}

Example response:

{
  "data": {
    "generateTraceUploadPost": {
      "url": "<object_storage_url>",
      "formData": "{\"key\": \"<key>\", \"policy\": \"<policy>\", \"x-amz-signature\": \"<signature>\", \"x-amz-date\": \"<date>\", \"x-amz-algorithm\": \"<algorithm>\", \"x-amz-credential\": \"<credential>\", \"success_action_status\": 201, \"acl\": \"private\"}"
    }
  }
}

Make a note of the returned values to use in the next step.

Upload the trace directly to S3

Use the following command to upload a trace using the AWS S3 API (example with curl):

curl \
    --request POST \
    --form key=<key> \
    --form acl=private \
    --form policy=<policy> \
    --form x-amz-signature=<signature> \
    --form x-amz-credential=<credentials> \
    --form x-amz-date=<current date> \
    --form x-amz-algorithm=<"AWS4-HMAC-SHA256" \
    --form success_action_status=201 \
    --form Content-Type=<content_type> \
    --form file=@<path to trace_name.cst.gz> \
    <object_storage_url>

The Content-Type field must appear before the file field. Its value should be application/gzip for gzipped traces and empty otherwise. Note the presence of the @ character in the file field - this must be present for the upload to work correctly.

For more information on the AWS S3 API please refer to the [official documentation][s3_post_api].

This will return a 201 response with the following format:

<?xml version="1.0" encoding="UTF-8"?>
<PostResponse>
  <Bucket>cryptosense-traces</Bucket>
  <Key>KEY</Key>
  <ETag>ETAG</ETag>
  <Location>LOCATION</Location>
</PostResponse>

Import the trace using the Cryptosense Analyzer REST API

Use the following command to import the uploaded trace with the following command:

mutation {
  createTrace(
    input: {
      projectId: "<project_id>",
      name: "<name>",
      key: "<key>",
      size: <size>
    }
  ) {
    trace {
      id
    }
  }
}

In the above query:

  • <project_id> is the ID of the project retrieved in the previous part.
  • <name> is a name of your choice, provided no other trace with that name exists in the project.
  • <key> must be the same value for key that you used to upload the trace in the previous query.
  • <size> must be the size of trace_name.cst.gz in bytes.

Response:

{
  "data": {
    "createTrace": {
      "trace": {
        "id": "<trace_id>"
      }
    }
  }
}

Make a note of the trace ID, as it is needed for later steps in this process.

Verification: Check the uploaded trace has been successfully imported

Once the trace has been imported, check the status of the trace with the following query:

query {
  node(id: "<trace_id>") {
    __typename

    ... on TraceFailed {
      reason
    }
  }
}

In the query above, <trace_id> should be replaced by the ID you obtained in the previous section.

If the trace has been processed, this will return the following response:

{
  "data": {
    "__typename": "TraceDone"
  }
}

If the trace is still being processed, the typename will be TracePending instead. You will have to wait and try the query again until it is TraceDone.

If trace processing failed, you will get the following response:

{
  "data": {
    "__typename": "TraceFailed",
    "reason": "<reason_for_the_failure>"
  }
}

Part 3: Analyze the Uploaded Trace

Launch the analysis

To launch an analysis of the uploaded trace, use the following command:

mutation {
  analyze(
    input: {
      traceId: "<trace_id>",
      profileId: "<profile_id>"
    }
  ) {
    report {
      id
    }
  }
}

This will return a response of the form:

{
  "data": {
    "report": {
       "id": "<report_id>"
    }
  }
}

Check the state of the report

Once the analysis has been launched, you can check the status of the report the same way as you did for the initial processing of the trace:

query {
  node(id: "<report_id>") {
    __typename

    ... on ReportFailed {
      reason
    }
  }
}

In the spirit of GraphQL, you can also request more attributes from the report. Below is a query that will list the first 10 instances of the report, and the first two stack trace frames for each call in each instance:

query {
  node(id: "<report_id>") {
    __typename
    ... on ReportFailed {
      reason
    }
    ... on ReportDone {
      instances(first: 10) {
        pageInfo {
          hasNextPage
          endCursor
        }
        edges {
          node {
            id
            data
            severity
            calls {
              edges {
                node {
                  stackTrace(first: 2) {  # The second frame is the call site.
                    edges {
                      node {
                        class
                        method
                        file
                        line
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}