Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add visualization of newly extracted data #672

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions src/components/Menu/MenuContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,31 @@ const MenuContainer = () => {
}
}
} else {
for (let key in processedData) {
let props = processedData[key].props;
if (props.length === 0) continue;
let chunked = props.chunk();
let statement = processedData[key].statement;

for (let chunk of chunked) {
await uploadData(statement, chunk);
if (Array.isArray(processedData)) {
for (let data in processedData) {
data = processedData[data];
for (let key in data) {
let props = data[key].props;
if (props.length === 0) continue;
let chunked = props.chunk();
let statement = data[key].statement;

for (let chunk of chunked) {
await uploadData(statement, chunk);
}
}
}
}
else {
for (let key in processedData) {
let props = processedData[key].props;
if (props.length === 0) continue;
let chunked = props.chunk();
let statement = processedData[key].statement;

for (let chunk of chunked) {
await uploadData(statement, chunk);
}
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/js/ingestion_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@
* @property {Array.<TypedPrincipal>} DcomUsers
* @property {Array.<TypedPrincipal>} PSRemoteUsers
* @property {Array.<TypedPrincipal>} AffectedComputers
* @property {boolean} BlockInheritance
* @property {LinkType} Unenforced
* @property {LinkType} Enforced
*/

/**
* @typedef {Object} LinkType
* @property {Dictionary.<string,int>} PasswordPolicies
* @property {Dictionary.<string,int>} LockoutPolicies
* @property {Dictionary.<string,bool>} SMBSigning
* @property {Dictionary.<string,bool>} LDAPSigning
* @property {Dictionary.<string,int>} LMAuthenticationLevel
*/

/**
Expand Down
206 changes: 199 additions & 7 deletions src/js/newingestion.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { groupBy } from 'lodash/collection';

let unenforcedDomainProperties = {};
let enforcedDomainPropertyKeys = {};
const TRUST_DIRECTION_INBOUND = 'Inbound';
const TRUST_DIRECTION_OUTBOUND = 'Outbound';
const TRUST_DIRECTION_BIDIRECTIONAL = 'Bidirectional';
Expand Down Expand Up @@ -34,6 +36,12 @@ export const ADLabels = {
Contains: 'Contains',
GPLink: 'GPLink',
TrustedBy: 'TrustedBy',
PasswordPolicies: 'PasswordPolicies',
LockoutPolicies: 'LockoutPolicies',
SMBSigning: 'SMBSigning',
LDAPSigning: 'LDAPSigning',
LMAuthenticationLevel: 'LMAuthenticationLevel',
GPOChanges: 'GPOChanges',
};

const AzureApplicationAdministratorRoleId =
Expand Down Expand Up @@ -527,14 +535,25 @@ export function buildContainerJsonNew(chunk) {
/**
* @param {Array.<OU>} chunk
* @return {{}}
*/
*/
export function buildOuJsonNew(chunk) {
let queries = {};
queries.properties = {
statement: PROP_QUERY.format(ADLabels.OU),
props: [],
};

let computerStatement = PROP_QUERY.format(ADLabels.Computer);
let computerQuery = {};
let computerProperties = [];
let blockInheritanceComputers = [];

// sort OU from the children to the parent using the length of the distinguished name
chunk.sort((a,b) => {
return b.Properties.distinguishedname.length - a.Properties.distinguishedname.length;
});

// OU are processed from the bottom up, so the default behavior is to not override already set properties
for (let ou of chunk) {
let properties = ou.Properties;
let links = ou.Links;
Expand All @@ -543,6 +562,7 @@ export function buildOuJsonNew(chunk) {
let identifier = ou.ObjectIdentifier.toUpperCase();
properties.objectid = identifier;
let aces = ou.Aces;
let blockInheritance = ou.GPOChanges.BlockInheritance;

processAceArrayNew(aces, identifier, 'OU', queries);

Expand All @@ -551,6 +571,104 @@ export function buildOuJsonNew(chunk) {
map: properties,
});

// add GPOChanges properties to the affected computers
let computers = ou.GPOChanges.AffectedComputers;
let ouProperties = {"unenforced": {}, "enforced": {}};
let linkType = [ou.GPOChanges.Unenforced, ou.GPOChanges.Enforced];

// add enforced and unenforced properties separatly
for (let index=0;index<linkType.length;index++) {
ouProperties[Object.keys(ouProperties)[index]] = {
// password policies
"minimumPasswordAge": linkType[index].PasswordPolicies.MinimumPasswordAge,
"maximumPasswordAge": linkType[index].PasswordPolicies.MaximumPasswordAge,
"minimumPasswordLength": linkType[index].PasswordPolicies.MinimumPasswordLength,
"passwordComplexity": linkType[index].PasswordPolicies.PasswordComplexity,
"passwordHistorySize": linkType[index].PasswordPolicies.PasswordHistorySize,
"clearTextPassword": linkType[index].PasswordPolicies.ClearTextPassword,
// lockout policies
"lockoutDuration": linkType[index].LockoutPolicies.LockoutDuration,
"lockoutBadCount": linkType[index].LockoutPolicies.LockoutBadCount,
"resetLockoutCount": linkType[index].LockoutPolicies.ResetLockoutCount,
"forceLogoffWhenHourExpire": linkType[index].LockoutPolicies.ForceLogoffWhenHourExpire,
// SMB signings
"requiresServerSMBSigning": linkType[index].SMBSigning.RequiresServerSMBSigning,
"enablesServerSMBSigning": linkType[index].SMBSigning.EnablesServerSMBSigning,
"requiresClientSMBSigning": linkType[index].SMBSigning.RequiresClientSMBSigning,
"enablesClientSMBSigning": linkType[index].SMBSigning.EnablesClientSMBSigning,
// LDAP signing
"requiresLDAPClientSigning": linkType[index].LDAPSigning.RequiresLDAPClientSigning,
// LM authentication level
"lmCompatibilityLevel": linkType[index].LMAuthenticationLevel.LmCompatibilityLevel
};
};

// add properties
for (let index=0;index<computers.length;index++){
let computerIdentifier = computers[index].ObjectIdentifier.toUpperCase();
let found = false;

// remove unenforced OU properties overlapping with domain enforced properties
if(Object.keys(enforcedDomainPropertyKeys).includes(computerIdentifier)){
for (let key of enforcedDomainPropertyKeys[computerIdentifier]){
delete ouProperties["unenforced"][key];
}
}

// unenforced properties
if(!blockInheritanceComputers.includes(computerIdentifier)){
// add, if the computer is already affected by properties
for (let prop of computerProperties){
if(prop.objectid === computerIdentifier){
// add properties which do not exist yet and are not enforced at the domain level
for(let [key, value] of Object.entries(ouProperties["unenforced"])){
if(prop.map[key] === undefined && (!Object.keys(enforcedDomainPropertyKeys).includes(computerIdentifier) || !enforcedDomainPropertyKeys[computerIdentifier].includes(key)) && value !== undefined){
prop.map[key] = value;
}
}
found = true;
}
}

// create, if the computer has not already been affected by properties
if(!found){
computerProperties.push({
objectid: computerIdentifier,
map: Object.assign({}, ouProperties["unenforced"]),
});
}

if(blockInheritance){
// add the computer to the block inheritance array
blockInheritanceComputers.push(computerIdentifier);
// remove unenforced properties set by domains
delete unenforcedDomainProperties[computerIdentifier];
}
}

// enforced properties
// add, if this computer is already affected by properties
for (let prop of computerProperties){
if(computerIdentifier === prop.objectid){
for(let [key, value] of Object.entries(ouProperties["enforced"])){
// override the property if it is empty or an not enforced at domain level
if(value !== undefined && (!Object.keys(enforcedDomainPropertyKeys).includes(computerIdentifier) || !(enforcedDomainPropertyKeys[computerIdentifier].includes(key)))){
prop.map[key] = value;
}
}
found = true;
}
}

// create,if the computer has not already been affected by properties
if(!found){
computerProperties.push({
objectid: computerIdentifier,
map: Object.assign({}, ouProperties["enforced"]),
});
}
}

let format = [ADLabels.OU, '', ADLabels.Contains, NON_ACL_PROPS];
let grouped = groupBy(children, GROUP_OBJECT_TYPE);

Expand Down Expand Up @@ -578,8 +696,6 @@ export function buildOuJsonNew(chunk) {
});
insertNew(queries, format, props);

let computers = ou.GPOChanges.AffectedComputers;

format = [
'',
ADLabels.Computer,
Expand Down Expand Up @@ -664,7 +780,27 @@ export function buildOuJsonNew(chunk) {
insertNew(queries, format, flattened);
}
}
return queries;

// Finally add domain unenforced properties, without overriding existing properties
for (let domainComputerId of Object.keys(unenforcedDomainProperties)){
for (let prop of computerProperties){
if(domainComputerId === prop.objectid){
for (let [key, value] of Object.entries(prop.map)){
if(unenforcedDomainProperties[domainComputerId][key] !== undefined && value === undefined){
prop.map[key] = unenforcedDomainProperties[domainComputerId][key];
}
}
}
}
}
computerQuery = {
properties: {
statement: computerStatement,
props: computerProperties,
}
};

return [queries, computerQuery];
}

/**
Expand All @@ -679,13 +815,64 @@ export function buildDomainJsonNew(chunk) {
props: [],
};

let computerStatement = PROP_QUERY.format(ADLabels.Computer);
let computerQuery = {};
let computerProperties = [];

for (let domain of chunk) {
let properties = domain.Properties;
let children = domain.ChildObjects;
let identifier = domain.ObjectIdentifier;
let aces = domain.Aces;
let links = domain.Links;
let trusts = domain.Trusts;
let computers = domain.GPOChanges.AffectedComputers;

// add GPOChanges properties to the affected computers
let domainProperties = {"unenforced": {}, "enforced": {}};
let linkType = [domain.GPOChanges.Unenforced, domain.GPOChanges.Enforced];
for (let index=0;index<linkType.length;index++) {
domainProperties[Object.keys(domainProperties)[index]] = {
// password policies
"minimumPasswordAge": linkType[index].PasswordPolicies.MinimumPasswordAge,
"maximumPasswordAge": linkType[index].PasswordPolicies.MaximumPasswordAge,
"minimumPasswordLength": linkType[index].PasswordPolicies.MinimumPasswordLength,
"passwordComplexity": linkType[index].PasswordPolicies.PasswordComplexity,
"passwordHistorySize": linkType[index].PasswordPolicies.PasswordHistorySize,
"clearTextPassword": linkType[index].PasswordPolicies.ClearTextPassword,
// lockout policies
"lockoutDuration": linkType[index].LockoutPolicies.LockoutDuration,
"lockoutBadCount": linkType[index].LockoutPolicies.LockoutBadCount,
"resetLockoutCount": linkType[index].LockoutPolicies.ResetLockoutCount,
"forceLogoffWhenHourExpire": linkType[index].LockoutPolicies.ForceLogoffWhenHourExpire,
// SMB signings
"requiresServerSMBSigning": linkType[index].SMBSigning.RequiresServerSMBSigning,
"enablesServerSMBSigning": linkType[index].SMBSigning.EnablesServerSMBSigning,
"requiresClientSMBSigning": linkType[index].SMBSigning.RequiresClientSMBSigning,
"enablesClientSMBSigning": linkType[index].SMBSigning.EnablesClientSMBSigning,
// LDAP signing
"requiresLDAPClientSigning": linkType[index].LDAPSigning.RequiresLDAPClientSigning,
// LM authentication level
"lmCompatibilityLevel": linkType[index].LMAuthenticationLevel.LmCompatibilityLevel
};
};

// add properties for each affected computer
// a computer can belong to one domain max
for (let index=0;index<computers.length;index++){
let computerIdentifier = computers[index].ObjectIdentifier.toUpperCase();

// store unenforced propertiesto manage precedences with OU properties
unenforcedDomainProperties[computerIdentifier] = domainProperties["unenforced"];

// add enforced properties
computerProperties.push({
objectid: computerIdentifier,
map: Object.assign({}, domainProperties["enforced"]),
});
// store defined property keys
enforcedDomainPropertyKeys[computerIdentifier] = Object.keys(domainProperties["enforced"]).filter(key => domainProperties["enforced"][key] !== undefined);
}

processAceArrayNew(aces, identifier, 'Domain', queries);

Expand Down Expand Up @@ -721,8 +908,6 @@ export function buildDomainJsonNew(chunk) {
});
insertNew(queries, format, props);

let computers = domain.GPOChanges.AffectedComputers;

format = [
'',
ADLabels.Computer,
Expand Down Expand Up @@ -861,7 +1046,14 @@ export function buildDomainJsonNew(chunk) {
}
}

return queries;
computerQuery = {
properties: {
statement: computerStatement,
props: computerProperties,
}
};

return [queries, computerQuery];
}

const baseInsertStatement =
Expand Down