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:
- Finding a project and a profile to use.
- Uploading the trace to S3 and importing it.
- 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 Java Tracer manual.
- 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
method
}
}
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\"}",
"method": "POST"
}
}
}
Make a note of the returned values to use in the next step. If the CAP instance is using
the PUT method to upload traces (as indicated by the method
field), refer to
Appendix: PUT upload.
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 forkey
that you used to upload the trace in the previous query.<size>
must be the size oftrace_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 {
# The second frame is the call site.
stackTrace(first: 2) {
edges {
node {
class
method
file
line
}
}
}
}
}
}
}
}
}
}
}
}
Appendix: PUT upload
In certain environments, the CAP server will be configured to use the PUT method to upload
traces. The API call to generateTraceUploadPost
will return something like this:
{
"data": {
"generateTraceUploadPost": {
"url": "<object_storage_url>/uploads/1234?X-Amz-...",
"formData": "",
"method": "PUT"
}
}
}
Take note of the URL that is returned.
To upload the file to the storage backend, use the following cURL command:
curl \
--request PUT \
--data-binary=@<path to trace_name.cst.gz> \
<url>