Refactored ScoutSuiteDataParser.js to improve the readability of scoutsuite data extraction process

temp
This commit is contained in:
VakarisZ 2021-01-13 11:03:13 +02:00
parent 7e07489807
commit 7b60d4d2e6
2 changed files with 99 additions and 63 deletions

View File

@ -17,8 +17,8 @@ export default function RuleDisplay(props) {
<p className={'checked-resources-title'}>Resources checked: </p>
<p>{props.rule.checked_items}</p>
</div>
{props.rule.references.length !== 0 ? getReferences() : ''}
{props.rule.items.length !== 0 ? getResources() : ''}
{getReferences()}
{getResources()}
</div>);
function getReferences() {
@ -30,12 +30,14 @@ export default function RuleDisplay(props) {
rel="noopener noreferrer"
key={reference}>{reference}</a>)
})
if (references.length) {
return (
<div className={'reference-list'}>
<p className={'reference-list-title'}>References:</p>
{references}
</div>)
}
}
function getResources() {
let resources = []
@ -46,14 +48,16 @@ export default function RuleDisplay(props) {
resources.push(<ResourceDropdown resource_path={item}
template_path={template_path}
scoutsuite_data={props.scoutsuite_data}
key={template_path+i}/>)
key={template_path + i}/>)
}
if (resources.length) {
return (
<div className={'reference-list'}>
<p className={'reference-list-title'}>Flagged resources (<b>{props.rule.flagged_items}</b>):</p>
{resources}
</div>)
}
}
}
RuleDisplay.propTypes = {

View File

@ -3,72 +3,104 @@ export default class ScoutSuiteDataParser {
this.runResults = runResults
}
/*
itemPath contains path to a specific value e.g. s3.buckets.da1e7081077ce92.secure_transport_enabled"
templatePath contains a template path for resource we would want to display e.g. s3.buckets.id
/**
*
* @param itemPath contains path to a specific value e.g. s3.buckets.da1e7081077ce92.secure_transport_enabled
* @param templatePath contains a template path for resource we would want to display e.g. s3.buckets.id
* @returns {*[]|*}
*/
getResourceValue(itemPath, templatePath) {
let resourcePath = this.fillTemplatePath(itemPath, templatePath);
return this.getValueAt(resourcePath);
return this.getObjectValueByPath(resourcePath, this.runResults);
}
fillTemplatePath(itemPath, templatePath) {
let itemPathArray = itemPath.split('.');
let templatePathArray = templatePath.split('.');
let resourcePathArray = templatePathArray.map((val, i) => {return val === 'id' ? itemPathArray[i] : val})
let resourcePathArray = templatePathArray.map((val, i) => {
return val === 'id' ? itemPathArray[i] : val
})
return resourcePathArray.join('.');
}
getValueAt(path) {
return this.getValueAtRecursive(path, this.runResults)
}
getValueAtRecursive(path, source) {
let value = source;
let current_path = path;
/**
* Retrieves value from ScoutSuite data object based on path, provided in the rule
* @param path E.g. a.id.c.id.e
* @param source E.g. {a: {b: {c: {d: {e: [{result1: 'result1'}, {result2: 'result2'}]}}}}}
* @returns {*[]|*} E.g. ['result1', 'result2']
*/
getObjectValueByPath(path, source) {
let key;
// iterate over each path elements
while (current_path) {
// check if there are more elements to the path
if (current_path.indexOf('.') != -1) {
key = current_path.substr(0, current_path.indexOf('.'));
}
// last element
else {
key = current_path;
while (path) {
key = this.getNextKeyInPath(path);
source = this.getValueForKey(key, path, source);
path = this.trimFirstKey(path);
}
try {
// path containing an ".id"
if (key == 'id') {
let v = [];
let w;
for (let k in value) {
// process recursively
w = this.getValueAtRecursive(k + current_path.substr(current_path.indexOf('.'), current_path.length), value);
v = v.concat(
Object.values(w) // get values from array, otherwise it will be an array of key/values
);
}
return v;
}
// simple path, just return element in value
else {
value = value[key];
}
} catch (err) {
console.log('Error: ' + err)
return source;
}
// check if there are more elements to process
if (current_path.indexOf('.') != -1) {
current_path = current_path.substr(current_path.indexOf('.') + 1, current_path.length);
getNextKeyInPath(path) {
if (path.indexOf('.') !== -1) {
return path.substr(0, path.indexOf('.'));
} else {
return path;
}
// otherwise we're done
else {
current_path = false;
}
/**
* Returns value from object, based on path and current key
* @param key E.g. "a"
* @param path E.g. "a.b.c"
* @param source E.g. {a: {b: {c: 'result'}}}
* @returns {[]|*} E.g. {b: {c: 'result'}}
*/
getValueForKey(key, path, source) {
if (key === 'id') {
return this.getValueByReplacingUnknownKey(path, source);
} else {
return source[key];
}
}
/**
* Gets value from object if first key in path doesn't match source object
* @param path unknown.b.c
* @param source {a: {b: {c: [{result:'result'}]}}}
* @returns {[]} 'result'
*/
getValueByReplacingUnknownKey(path, source) {
let value = [];
for (let key in source) {
value = this.getObjectValueByPath(this.replaceFirstKey(path, key), source);
value = value.concat(Object.values(value));
}
return value;
}
/**
* Replaces first key in path
* @param path E.g. "one.two.three"
* @param replacement E.g. "four"
* @returns string E.g. "four.two.three"
*/
replaceFirstKey(path, replacement) {
return replacement + path.substr(path.indexOf('.'), path.length);
}
/**
* Trims the first key from dot separated path.
* @param path E.g. "one.two.three"
* @returns {string|boolean} E.g. "two.three"
*/
trimFirstKey(path) {
if (path.indexOf('.') !== -1) {
return path.substr(path.indexOf('.') + 1, path.length);
} else {
return false;
}
}
}