Skip to content

Commit

Permalink
Add API scanning
Browse files Browse the repository at this point in the history
Update browserApp Job schema.
Add aPi Job schema.
Increased the coolDown.timeout (this is the duration after a Test Run
completes until the orchestrator will take another order) from 50 to 60
seconds. In testing we noticed AWS was still pulling ECS tasks down at
50 seconds.
  • Loading branch information
binarymist committed Dec 6, 2021
1 parent 438fa32 commit 5a1b7f9
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 10 deletions.
4 changes: 2 additions & 2 deletions config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ const schema = {
job: {
version: {
doc: 'The version of the Job accepted by this API.',
format: ['0.1.0-alpha.1', '1.0.0-alpha.3', '2.0.0-alpha.3'],
default: '2.0.0-alpha.3'
format: ['0.1.0-alpha.1', '1.0.0-alpha.3', '2.0.0-alpha.3', '3.0.0-alpha.3'],
default: '3.0.0-alpha.3'
}
},
outcomes: {
Expand Down
250 changes: 249 additions & 1 deletion src/api/orchestration/schemas/job.aPi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,254 @@ const init = (config) => {
internals.config = config;
};

const schema = {};
const schema = {
$schema: 'http://json-schema.org/draft-07/schema#',
$ref: '#/definitions/Job',
definitions: {
Job: {
type: 'object',
additionalProperties: false,
properties: {
data: { $ref: '#/definitions/Data' },
included: {
type: 'array',
items: { $ref: '#/definitions/TopLevelResourceObject' }
}
},
required: [
'data',
'included'
],
title: 'Job'
},
Data: {
type: 'object',
additionalProperties: false,
properties: {
type: { type: 'string', enum: ['Api'] },
attributes: { $ref: '#/definitions/DataAttributes' },
relationships: { $ref: '#/definitions/Relationships' }
},
required: [
'attributes',
'relationships',
'type'
],
title: 'Data'
},
DataAttributes: {
type: 'object',
additionalProperties: false,
properties: {
version: { type: 'string', get const() { return internals.config.job.version; } },
sutAuthentication: { $ref: '#/definitions/SutAuthentication' },
sutIp: { type: 'string', oneOf: [{ format: 'ipv6' }, { format: 'hostname' }] },
sutPort: { type: 'integer', minimum: 1, maximum: 65535 },
sutProtocol: { type: 'string', enum: ['https', 'http'], default: 'https' },
loggedInIndicator: { type: 'string', minLength: 1 },
loggedOutIndicator: { type: 'string', minLength: 1 }
},
oneOf: [
{ required: ['loggedInIndicator'] },
{ required: ['loggedOutIndicator'] }
],
required: [
'sutAuthentication',
'sutIp',
'sutPort',
'sutProtocol',
'version'
],
title: 'DataAttributes'
},
SutAuthentication: {
type: 'object',
additionalProperties: false,
properties: {
emissaryAuthenticationStrategy: { type: 'string', enum: ['MaintainJwt'], default: 'MaintainJwt' },
route: { type: 'string', pattern: '^/[-?&=\\w/]{1,1000}$' }
},
required: [
'route'
],
title: 'SutAuthentication'
},
Relationships: {
type: 'object',
additionalProperties: false,
properties: {
data: {
type: 'array',
items: { $ref: '#/definitions/ResourceLinkage' }
}
},
required: [
'data'
],
title: 'Relationships'
},
ResourceLinkage: {
type: 'object',
additionalProperties: false,
properties: {
type: { type: 'string', enum: ['tlsScanner', 'appScanner'] },
id: { type: 'string' }
},
required: ['id', 'type'],
if: { properties: { type: { enum: ['tlsScanner'] } } },
then: { properties: { id: { type: 'string', pattern: 'NA' } } },
else: {
if: { properties: { type: { enum: ['appScanner'] } } },
then: { properties: { id: { type: 'string', pattern: '^\\w[-\\w]{1,200}$' } } }
},
title: 'ResourceLinkage'
},
TopLevelResourceObject: {
type: 'object',
additionalProperties: false,
properties: {
type: { type: 'string', enum: ['tlsScanner', 'appScanner'] },
id: { type: 'string' },
attributes: {},
relationships: {}
},
required: [
'attributes',
'id',
'type'
],
if: { properties: { type: { enum: ['tlsScanner'] } } },
then: {
properties: {
id: { type: 'string', pattern: 'NA' },
attributes: { $ref: '#/definitions/AttributesObjOfTopLevelResourceObjectOfTypeTlsScanner' }
}
},
// If we want to use flags for regex, etc, then need to use ajv-keywords: https://github.com/epoberezkin/ajv-keywords#regexp
else: {
if: { properties: { type: { enum: ['appScanner'] } } },
then: {
properties: {
id: { type: 'string', pattern: '^\\w[-\\w]{1,200}$' },
attributes: { $ref: '#/definitions/AttributesObjOfTopLevelResourceObjectOfTypeAppScanner' }
}
}
},
title: 'TopLevelResourceObject',
errorMessage: {
properties: {
type: 'should be one of either tlsScanner or appScanner',
id: 'If type is tlsScanner, the id should be NA. If type is appScanner, the id should be a valid appScanner.'
}
}
},

AttributesObjOfTopLevelResourceObjectOfTypeTlsScanner: {
type: 'object',
additionalProperties: false,
properties: {
tlsScannerSeverity: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] },
alertThreshold: { type: 'integer', minimum: 0, maximum: 9999 }
},
required: [],
title: 'AttributesObjOfTopLevelResourceObjectOfTypeTlsScanner'
},

AttributesObjOfTopLevelResourceObjectOfTypeAppScanner: {
type: 'object',
additionalProperties: false,
properties: {
username: { type: 'string', pattern: '^([a-zA-Z0-9_-]{1,100}|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z0-9]{2,})$' }, // https://www.py4u.net/discuss/1646374
aScannerAttackStrength: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH', 'INSANE'] },
aScannerAlertThreshold: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH'] },
alertThreshold: { type: 'integer', minimum: 0, maximum: 9999 },
sitesTreePopulationStrategy: { type: 'string', enum: ['ImportUrls', 'OpenApi', 'Soap', 'GraphQl'], default: 'ImportUrls' },
spiderStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
scannersStrategy: { type: 'string', enum: ['ApiStandard'], default: 'ApiStandard' },
scanningStrategy: { type: 'string', enum: ['ApiStandard'], default: 'ApiStandard' },
postScanningStrategy: { type: 'string', enum: ['ApiStandard'], default: 'ApiStandard' },
reportingStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
openApi: { $ref: '#/definitions/OpenApi' },
soap: { $ref: '#/definitions/Soap' },
graphQl: { $ref: '#/definitions/GraphQl' },
importUrls: { $ref: '#/definitions/ImportUrls' },
excludedRoutes: {
type: 'array',
items: { type: 'string' },
uniqueItems: true,
minItems: 0
}
},
oneOf: [
{ required: ['openApi'] },
{ required: ['soap'] },
{ required: ['graphQl'] },
{ required: ['importUrls'] }
],
required: ['username'],
title: 'AttributesObjOfTopLevelResourceObjectOfTypeAppScanner'
},

OpenApi: {
type: 'object',
additionalProperties: false,
properties: {
importFileContentBase64: { type: 'string', pattern: '^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{3}=|[A-Za-z\\d+/]{2}==)?$' }, // https://regexland.com/base64/
importUrl: { type: 'string', format: 'uri' }
},
oneOf: [
{ required: ['importFileContentBase64'] },
{ required: ['importUrl'] }
],
required: [],
title: 'OpenApi'
},

Soap: {
type: 'object',
additionalProperties: false,
properties: {
importFileContentBase64: { type: 'string', pattern: '^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{3}=|[A-Za-z\\d+/]{2}==)?$' }, // https://regexland.com/base64/
importUrl: { type: 'string', format: 'uri' }
},
oneOf: [
{ required: ['importFileContentBase64'] },
{ required: ['importUrl'] }
],
required: [],
title: 'Soap'
},

GraphQl: {
type: 'object',
additionalProperties: false,
properties: {
importFileContentBase64: { type: 'string', pattern: '^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{3}=|[A-Za-z\\d+/]{2}==)?$' }, // https://regexland.com/base64/
importUrl: { type: 'string', format: 'uri' },
// If the following are not set, then no changes to Zaproxy defaults are made.
maxQueryDepth: { type: 'integer', minimum: 0, maximum: 100 }, // Zaproxy default: 5
maxArgsDepth: { type: 'integer', minimum: 0, maximum: 100 }, // Zaproxy default: 5
optionalArgsEnabled: { type: 'boolean' }, // Zaproxy default: true
argsType: { type: 'string', enum: ['INLINE', 'VARIABLES', 'BOTH'] }, // Zaproxy default: 'BOTH'
querySplitType: { type: 'string', enum: ['LEAF', 'ROOT_FIELD', 'OPERATION'] }, // Zaproxy default: 'LEAF'
requestMethod: { type: 'string', enum: ['POST_JSON', 'POST_GRAPHQL', 'GET'] } // Zaproxy default: 'POST_JSON'
},
oneOf: [
{ required: ['importFileContentBase64'] },
{ required: ['importUrl'] }
],
required: [],
title: 'GraphQl'
},

ImportUrls: {
type: 'object',
additionalProperties: false,
properties: { importFileContentBase64: { type: 'string', pattern: '^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{3}=|[A-Za-z\\d+/]{2}==)?$' } }, // https://regexland.com/base64/
required: ['importFileContentBase64'],
title: 'ImportUrls'
}
}
};

module.exports = { init, schema };
14 changes: 7 additions & 7 deletions src/api/orchestration/schemas/job.browserApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const schema = {
additionalProperties: false,
properties: {
tlsScannerSeverity: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] },
alertThreshold: { type: 'integer', minimum: 0, maximum: 1000 }
alertThreshold: { type: 'integer', minimum: 0, maximum: 9999 }
},
required: [],
title: 'AttributesObjOfTopLevelResourceObjectOfTypeTlsScanner'
Expand All @@ -188,21 +188,21 @@ const schema = {
password: { type: 'string' },
aScannerAttackStrength: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH', 'INSANE'] },
aScannerAlertThreshold: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH'] },
alertThreshold: { type: 'integer', minimum: 0, maximum: 1000 },
alertThreshold: { type: 'integer', minimum: 0, maximum: 9999 },
sitesTreePopulationStrategy: { type: 'string', enum: ['WebDriverStandard'], default: 'WebDriverStandard' },
spiderStrategy: { type: 'string', enum: ['BrowserAppStandard'], default: 'BrowserAppStandard' },
spiderStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
scannersStrategy: { type: 'string', enum: ['BrowserAppStandard'], default: 'BrowserAppStandard' },
scanningStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
postScanningStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
scanningStrategy: { type: 'string', enum: ['BrowserAppStandard'], default: 'BrowserAppStandard' },
postScanningStrategy: { type: 'string', enum: ['BrowserAppStandard'], default: 'BrowserAppStandard' },
reportingStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
excludedRoutes: {
type: 'array',
items: { type: 'string', pattern: '^/[-?&=.*\\w/]{1,1000}$' },
items: { type: 'string' },
uniqueItems: true,
minItems: 0
}
},
required: [],
required: ['username'],
title: 'AttributesObjOfTopLevelResourceObjectOfTypeAppScanner'
},

Expand Down

0 comments on commit 5a1b7f9

Please sign in to comment.