Arbitrary Function Introduction

Arbitrary Function is literally a code written by the user in the available languages (only Ruby so far) that will be executed in two scenarios: 1) On Gauntlet notifications or 2) On Script Authentication".

Figure 1.1 - Creating an Arbitrary Function
You can create arbitrary functions per asset (application/server) or per organization.

 

Characteristics of an Arbitrary Function

Although an Arbitrary Function is code as you're used to, there a few differences:

  • You'll receive a SandboxRequest: every function has access to a "sandbox_request" variable that contains a SandboxRequest object. For Script Authentication it could be ignored, but may be used on Notifications because arbitrary functions have access to the same values a webhook would send. More on that below.
  • You'll have to return a SandboxResponse object: it's a very simple object that has only two params: operation_result (bool) and extras (Hash). Operation result must be true and extras is only necessary when it's a function for "Script Authentication", because it has to return a Hash in the following structure: "{ headers: {}, cookies: {}";
  • Retries: Gauntlet will try to execute your function up to 10 times and will increase the time interval between attempts. It only happens if your code happens to fail, i.e., not returning a SandboxResponse with the parameters mentioned above;
  • Timeout: arbitrary functions have a 3 minutes timeout before considering the attempt as a failed one. It's important to know this because your logic must be indempotent;

 

Example for Notification

Below you'll find an example of an arbitrary function made to be executed when a scan starts.

# My code here
# Available gems besides native:
# [ "json", "nokogiri", "rest-client" ]
# P.S.: don't use 'return' or you'll get a syntax error
require "json"
require "rest-client"

# Load webhook data
# related to the current event
webhook_file = "#{sandbox_request.guest_volume}/webhook.json"
webhook = JSON.parse(File.open(webhook_file, "rb").read)

# Example of a POST HTTPS request
RestClient.post "https://my-app-to-handle-notifications.com", {
    user: 'user',
    password: 'password',
    ticket: {
        # Example of a field present in a webhook
        webhook_date: webhook["webhook"]["sent_at"]
    }
}

# Just keep this block below
SandboxResponse.new(
  operation_result: true,
  extras: {}
)

 

Example for Authentication

Below you'll find an example of an arbitrary function made to be executed to authenticate an application.

# My code here
# Available gems besides native:
# [ "json", "nokogiri", "rest-client" ]
# P.S.: don't use 'return' or you'll get a syntax error
require "rest-client"
require "nokogiri"

# Example request to get CSRF token
res = RestClient.get "https://my-app.com/login"

# Nokogiri to parse response body
# And extract CSRF Token
doc = Nokogiri::HTML(res.body)
csrf_token = doc.css("input[name='csrf_token']").first.attr("value")

# Authenticate
res = RestClient.post "https://my-app.com/login", {
  user: 'gauntlet-user',
  pass: 'strong-password',
  csrf_token: csrf_token
}

# Get 'X-JSON-WEB-TOKEN' header
header_with_session_id = res.headers["X-JSON-WEB-TOKEN"]

# Add our 'X-JSON-WEB-TOKEN' header
# To SandboxResponse extras
SandboxResponse.new(
  operation_result: true,
  extras: {
    :headers => {
      "X-JSON-WEB-TOKEN" => header_with_session_id
    },
    :cookies => {
      # There are no cookies
      # So the value here is empty
    }
  }
)