Skip to content

Sift Configuration

Sift reads configuration from the Platform or from a local file in YAML or JSON format. The file must conform to the configuration schema. The configuration schema has the following top-level keys. The schema of each key is described in a section below.

  • analysis: Analysis contains configuration parameters that control how the analysis is performed. See "Analysis".
  • environmentID: ID of Environment (defined in Platform) in which the analysis is being performed. This may also be overridden with CLI flag --env.
  • labels: Labels are user-defined key-value pairs that are added as metadata for an analysis run. Labels may also be specified on the CLI with flag --label. Labels specified on the CLI are merged with labels in the configuration file.
  • targets: Targets are the APIs that will be analyzed. See "Targets".

Configuration parameters that are required are marked as such in the descriptions below. A value for a configuration parameter may contain a template expression - see Configuration Templating for details.

Example Configuration

analysis:
  analyzers:
  - kind: OpenAPIConformance
  - kind: BrokenObjectLevelAuth
  - kind: BUA
  - kind: EmailExposure
  - kind: ServerError
  - kind: PolicyEvaluator
    policy: filename
    rules:
    - rule: nameOfRuleInPolicyFile
      severity: high
  - kind: ConfigurableInjection
    attacks:
      - file: InjectionStringsFile
        name: faultName
        severity: high
  - kind: ConfigurableHeaderInjection
    attacks:
      - file: HeaderInjectionStringsFile
        name: faultName
        severity: high
        header: User-Agent
  fuzzLimit: 5
  generators:
  - context: /createApplication
    rules:
    - kind: Regex
      params:
        expr: "TL-[0-9]{8}"
      pattern: loan_id
      type: string
    - kind: IntRange
      params:
        max: 850
        min: 300
      pattern: fico
      type: number
    - kind: IntRange
      params:
        max: 130
        min: 18
      pattern: age
      type: number
  - context: /createAccessToken/input/body
    rules:
    - kind: IntConstant
      params:
        value: 42
      pattern: expiresAt
      type: number
  platformURL: http://localhost:8080
  sequenceLimit: 3
  timeLimit: 10m25s
environmentID: 00000000-0000-0000-0000-000000000000
labels:
  env: dev
targets:
- API: 00000000-0000-0000-0000-000000000000
  URL: http://localhost:8888/
  authorization:
    user1:
      kind: static
      location: header
      name: Authorization
      value: Bearer eyXXXXXXXXXXXXX
    user2:
      kind: static
      location: header
      name: Authorization
      value: Basic ZGVtbzpwQDU1dzByZAo=
    user3:
      kind: basic
      username: demo
      password: p@55w0rd
    user4:
      kind: dynamic
      location: header
      name: Authorization
      command: bearer_token_gen.py
      timeout: 300
    user5:
      kind: dynamic-http-header
      command: http_header_gen.js
      timeout: 300
  definition:
    file: examples/VAmPI/openapi3.yaml
    path: ""
    type: API_KIND_OPENAPI
  operations:
    excludeID:
    - deleteUser
    includeID:
    - createApplication
    - createAccessToken
  popToken:
    privateKey: ./path/to/popPrivateKey.pem
    header: X-Authorization
    fields:
    - http-method
    - uri
    - body
  timeout: 5s
  traceHeader: Sift-Request

Analysis

analysis contains configuration parameters that control how an analysis run is performed.

Analyzers

analyzers is a list of Analyzers to use during an analysis run. Each analyzer looks for specific kinds of faults. If the analyzers list is empty, then Sift will only load the API definition, construct a Resource Graph, and send the API defnition and Resource Graph to the Platform.

Each item in the list is a map that contains a required key kind, which specifies the kind of analyzer to enable in the analysis. Some analyzers have additional configuration parameters that must be specified in the map. The analyzer descriptions in the Analyzers page contain the configuration name of each kind of analyzer and any additional parameters required by an analyzer.

Fuzz Limit

fuzzLimit configures that number of attempts that are made to invoke each operation when constructing sequences of operations.

Generators

generators is an array of Generator Scopes that configure the input value generators used to produce values for input variables of an operation. When a Generator is not configured for a particular value, Sift intelligently generates values based on its understanding of the API definition.

A Generator Scope specifies a context and a set of Generator Rules that will be applied for parameters that match the context. Generator Scope has 2 fields:

  • context: a JSON Path of the form /{opID}/input/{parameterName}[/{fieldSelector}.
    • OpenAPI parameter names have the format "{location}/{name}", where location is one of "path", "query", "header", "cookie", "body". A "body" parameter does not have a name.
  • rules: an array of Generator Rules. The rules are evaluated in the order of the array, and the first rule that matches selects the Generator to use.

A Generator Rule matches a variable to a Generator that generates input values for the variable. A variable is matched to a rule by having equal type and a name that matches a regular expression. A Generator Rule has four fields:

  • kind: Kind of Generator to use for variables that match this rule.
  • params: Configuration parameters that are specific to the kind of Generator. This is a key-value map. Refer to kinds of Generators below for the parameters of a particular kind of Generator.
  • pattern: A regular expression (RE2 format) that matches the name of a variable. A variable's name is the last element of the JSON Path to the variable.
  • type: The type of the variable. One of "boolean", "integer", "number", "string".

Refer to the list of Generators for the available kinds and the parameters for each.

Platform URL

platformURL specifies the location of the Aptori Platform to which results of the analysis run will be published.

This value is overridden by presence of any of the following, from highest to lowest priority:

  • CLI flag --platform;
  • environment variable SIFT_PLATFORM_URL.

Sequence Limit

sequenceLimit configures the maximum length for an operation sequence that is constructed during an analysis run. If sequenceLimit is not specified, then the default behavior is to construct sequences of up to 100 operations in length.

Time Limit

timeLimit configures the maximum duration of an analysis run. The duration is a string that may use the following suffixes for time units: "h" for hours, "m" for minutes, "s" for seconds. For example, to set a 12.5 minute time limit, use the string "12m30s".

NOTE: sift performs initialization and final transmission to the Aptori Platform outside of the analysis time limit. If there is an external limit on runtime, then it is recommended to configure timeLimit to be 30 seconds less than the external limit.

Labels

labels are user-defined metadata assigned to an analysis run. labels is a map of user-defined key-value pairs of strings.

Additional labels may be added with CLI flag --label.

Targets

A target is an API that is analyzed by Sift. Each target specifies an API ID that has previously been defined in the Aptori Platform. Other parameters of a target configure the URL at which Sift can access the API, the location of the API definition, and authorization settings for requests to the API.

targets is an array of targets. Each target contains:

  • API: API ID defined in Aptori Platform.
  • URL: Base URL where an application is serving the API.
  • authorization: Parameters to configure authorization token for requests.
  • definition: Parameters to configure the location of the API definition.
  • header: Optional additional HTTP header fields to include in requests.
  • operations: Optional filters for which operations to test.
  • popToken: Optional parameters to add Proof-of-Possession (PoP) tokens to requests.
  • timeout: Request timeout duration.
  • traceHeader: HTTP header field to populate with a unique request identifier.

Definition

definition configures a location where Sift can find the API definition. Sift can load an API definition from a URL or a file on the local filesystem. Or, Sift can retrieve a specific revision of the API definition from the Platform. Only one of path, file, or revision should be specified. If multiple are specified, then the Sift will choose one according to precedence, from high to low: path, file, revision.

definition has the following fields:

  • type: Type of API definition. Supported types are "API_KIND_OPENAPI".
  • path: Absolute or relative URL to the API definition. If the URL is relative (starts with "/"), then it is resolved relative to the URL of the target API.
  • file: Filename on the local filesystem that contains API definition.
  • revision: Revision ID of an API definition that has been uploaded to the Platform.

Authorization

authorization configures authorization tokens to use in requests sent to a target API. authorization is map of user identity ID to an identity configuration. The user identity ID is a user-specified name for a user identity supplied in requests to the target API.

Each identity configuration contains a required kind key that specifies the kind of authorization for a user identity as one of:

  • static
  • basic
  • dynamic
  • dynamic-http-header

Each kind of authorization has additional configuration parameters, as described in the following sections.

Static

A static kind of authorization configures an authorization token value that is valid for the duration of an analysis run. Each static authorization has three required fields:

  • location: The location where the authorization token is passed in a request. This must be set to "header".
  • name: Name of the header key in which the authorization token value is passed in a request. When location is "header", name is the HTTP header key (e.g., "Authorization", "Api-Key").
  • value: The static token value that will be passed in the request.

For example, to set a Bearer JWT in the "Authorization" header, use the following identity configuration, where "{jwt}" is a placeholder for the JWT value.

kind: static
location: header
name: Authorization
value: Bearer {jwt}

This will configure Sift to send the following header in each request:

Authorization: Bearer {jwt}

Basic

A basic kind of authorization configures Sift to use HTTP Basic Authentication as authorization for a request. Each basic authorization has two required fields:

  • username: The username for HTTP Basic authorization.
  • password: The password for HTTP Basic authorization.

For example, the following identity configuration:

kind: basic
username: demo
password: p@55w0rd

will configure Sift to use the following authorization in each request:

Authorization: Basic {base64-encoded("demo:p@55w0rd")}

Dynamic

A dynamic kind of authorization configures Sift to use an authorization value that is provided at runtime by execution of a command and refreshed periodically according to a configured interval. Each dynamic authorization has the following required fields:

  • location: The location where the authorization token is passed in a request. Supported values are: "header".
  • name: Name of the header key in which the authorization token value is passed in a request. When location is "header", the value of name is the HTTP header key (e.g., "Authorization", "Api-Key").
  • command: Command to execute to generate an authorization token.
  • timeout: Interval in seconds at which the command will be executed.

Execution of command must produce a token value on its standard output (stdout). Any leading and trailing whitespace will be trimmed.

Since the command may need to interact with the target application, the URL of the target is set in environment variable "SIFT_TARGET_URL" when the command is executed.

For example, given the following authorization configuration:

kind: dynamic
location: header
name: Authorization
command: echo "Bearer jwt12345"
timeout: 300

Sift will execute command echo "Bearer jwt12345" at least once every 300 seconds, and use the output as the authorization token. In each request, the authorization token will be passed in the following HTTP header specified in the configuration:

Authorization: Bearer jwt12345

Alternately, different kinds of commands may be used and the authorization token may be passed in whichever header is specified in the configuration. For example, a Python script can be used in the command:

kind: dynamic
location: header
name: Api-Key
command: python getApiKey.py
timeout: 300

If the output of python getApiKey.py is "apiKey6543", then Sift will send the following HTTP header in each request:

Api-Key: apiKey6543

Dynamic-HTTP-Header

A dynamic-http-header kind of authorization configures Sift to use a set of HTTP headers that are provided at runtime by execution of a command, and refreshed periodically according to a configured interval. Each dynamic-http-header authorization has the following required fields:

  • command: Command to execute to generate HTTP headers.
  • timeout: Interval in seconds at which the command will be executed.

Execution of command must produce on its standard output (stdout) a set of HTTP headers, one per line, in the form "Key: Value". Any leading and trailing whitespace will be trimmed.

Since the command may need to interact with the target application, the URL of the target is set in environment variable "SIFT_TARGET_URL" when the command is executed.

As an illustrative example, consider the following authorization configuration:

kind: dynamic-http-header
command: auth.sh
timeout: 120

and the Bash script auth.sh:

#!/bin/bash
echo "Authorization: Bearer jwt12345"
echo "X-TenantId: abcdef54321"

Sift will execute the auth.sh command at least once every 120 seconds, and use the headers read from the output. In each request, the authorization headers will be added to any other headers configured by the user (see "Additional Headers") or added by Sift's generated test sequences. Authorization headers override other user configured headers.

For the example above, the following HTTP headers will be included in a request (along with any other headers, not shown).

Authorization: Bearer jwt12345
X-TenantId: abcdef54321

Any language may be used to implement the command. The following example illustrates how to use Javascript to obtain a JWT token from a login API, and output an HTTP Authorization header with the bearer token.

#!/usr/bin/env node

//
// Example login script for Sift dynamic-http-header authorization plugin.
//
// This script performs a POST request to a login endpoint and obtains a JWT
// token from the response.  It outputs the necessary "Authorization" header
// with the bearer token value to stdout.  All of the headers output by the
// script to stdout will be used by Sift to authorize requests for the virtual
// user associated with this script.
//

// WARNING: Do NOT store secrets in a script.  For illustration only!
const userEmail ='[email protected]';
const userPass = 'MySecret';

// Using environment variable SIFT_TARGET_URL ensures this script will work
// with any target URL in the Sift configuration (or on Sift command-line).
const base_url = process.env.SIFT_TARGET_URL;
const login_url = `${base_url}/api/v1/user/login`;

const payload = { 'email': userEmail, 'password': userPass };

fetch(login_url, {
    method: "POST",
    headers: { "Content-type": "application/json" },
    body: JSON.stringify(payload),
})
.then((response) => {
    if (response.status !== 200) {
        console.log(`Login failed: status=${response.status}`);
        process.exit(1);
    }
    response.json().
        then(resp => {
            console.log(`Authorization: Bearer ${resp.data.jwtToken}`);
        })
})
.catch(error => {
  console.error('Error during login:', error.message);
  process.exit(1);
});

Proof-of-Possession (PoP) Token

The popToken property of a Target is an optional property to configure Sift to add a Proof-of-Possession (PoP) token to each request. A PoP token signs details of a request with a private key. The popToken property contains the following subfields:

  • privateKey: A required filename that contains a RSA private key in PEM format.
  • header: A required parameter that contains the HTTP header key into which a PoP token is added to a request.
  • fields: An optional array of fields of an HTTP request to sign in a PoP token. The values may be any header key or one of the pre-defined keywords 'http-method, 'uri', 'body'. The field values are extracted and added into the PoP token's 'edts' claim in the order that they appear.

If fields is empty or not specified, then 'edts and 'ehts' will be set to all header keys of a request, followed by 'http-method', 'uri', 'body' (in that order).

A field may not be present in a particular request (e.g., missing body, missing header key). In that case, the field name remains in the 'ehts' claim and the value of the field is treated as an empty string (i.e., no bytes added to 'edts' for that field).

Example:

  popToken:
    privateKey: ./path/to/popPrivateKey.pem
    header: X-Authorization
    fields:
    - http-method
    - uri
    - body

Additional Headers

The header property of a Target configures additional HTTP headers to send in each request. The property is a map of key-value pairs. For example, the following configuration adds a "Referer" header to each request to a Target.

header:
  Referer: https://example.com

The headers will be used in a request sent on behalf of any user identity defined in the authorization of the Target.

Operations Filter

The operations property of a Target configures a filter that selects which operations from a target API are invoked during an analysis run. An operation will be invoked when all include filters match, and no exclude filter matches. Any filter that is empty or not specified defaults to match. Filters that may be specified:

  • includeID: an array of Operation IDs. Match if operation's ID is present in the array.
  • excludeID: an array of Operation IDs. Match if operation's ID is present in the array.
  • includePath: an array of regular expressions that match path of an OpenAPI operation. Match if operation is an OpenAPI operation and the path of the operation matches a regular expression in the array. Ignored for any non-OpenAPI operation.
  • excludePath: an array of regular expressions that match path of an OpenAPI operation. Match if operation is an OpenAPI operation and the path of the operation matches a regular expression in the array. Ignored for any non-OpenAPI operation.

Timeout

timeout configures the maximum duration for each request to a target. The value of timeout may be a number (in seconds) or a string that uses the following suffixes for time units: "h" for hours, "m" for minutes, "s" for seconds, "ms" for milliseconds. For example, a value of "1m30s" is equivalent to "90s" - both set the timeout to 90 seconds.

If timeout is not specified or value is zero, then the default timeout is 3 seconds. If the value is negative, then requests will not have a timeout (NOT RECOMMENDED).

Trace Header

If traceHeader is a non-empty string, then Sift will send a unique request identifier in this header field of the request. The identifier is unique among all requests sent to a particular target in a particular analysis run. The request identifier can be used to trace or correlate a request with application logs.

The value of traceHeader should not conflict with the name of any header parameter defined in the API definition because it will override values that Sift is trying to use to analyze the application.