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.
- OpenAPI parameter names have the format "{location}/{name}", where
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 theURL
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. Whenlocation
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. Whenlocation
is "header", the value ofname
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.