Skip to content

Commit

Permalink
Create global state object for async requests (#493) (#513)
Browse files Browse the repository at this point in the history
* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #491

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #493

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #493

Signed-off-by: Jovan Cvetkovic <[email protected]>

* [FEATURE] Create global state object for async requests #493

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Feature] update detector details component #504

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Create global state object for async requests
#493

Signed-off-by: Jovan Cvetkovic <[email protected]>

---------

Signed-off-by: Jovan Cvetkovic <[email protected]>
(cherry picked from commit 24c8ec2)

Co-authored-by: Jovan Cvetkovic <[email protected]>
  • Loading branch information
1 parent be9de2e commit 2e0116d
Show file tree
Hide file tree
Showing 22 changed files with 819 additions and 426 deletions.
339 changes: 140 additions & 199 deletions cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,128 @@ const testMappings = {

const cypressDNSRule = dns_rule_data.title;

const createDetector = (detectorName, dataSource, expectFailure) => {
// Locate Create detector button click to start
cy.get('.euiButton').filter(':contains("Create detector")').click({ force: true });

// Check to ensure process started
cy.waitForPageLoad('create-detector', {
contains: 'Define detector',
});

// Enter a name for the detector in the appropriate input
cy.get(`input[placeholder="Enter a name for the detector."]`).focus().realType(detectorName);

// Select our pre-seeded data source (check cypressIndexDns)
cy.get(`[data-test-subj="define-detector-select-data-source"]`)
.find('input')
.focus()
.realType(dataSource);

cy.intercept({
pathname: '/_plugins/_security_analytics/rules/_search',
query: {
prePackaged: 'true',
},
}).as('getSigmaRules');

// Select threat detector type (Windows logs)
cy.get(`input[id="dns"]`).click({ force: true });

cy.wait('@getSigmaRules').then(() => {
// Open Detection rules accordion
cy.get('[data-test-subj="detection-rules-btn"]').click({ force: true, timeout: 5000 });

cy.contains('table tr', 'DNS', {
timeout: 120000,
});
});

// Check that correct page now showing
cy.contains('Configure field mapping');

if (!expectFailure) {
// Select appropriate names to map fields to
for (let field_name in testMappings.properties) {
const mappedTo = testMappings.properties[field_name].path;

cy.contains('tr', field_name).within(() => {
cy.get(`[data-test-subj="detector-field-mappings-select"]`).click().type(mappedTo);
});
}
}

// Click Next button to continue
cy.get('button').contains('Next').click({ force: true });

// Check that correct page now showing
cy.contains('Set up alerts');

// Type name of new trigger
cy.get(`input[placeholder="Enter a name for the alert condition."]`)
.focus()
.realType('test_trigger');

// Type in (or select) tags for the alert condition
cy.get(`[data-test-subj="alert-tags-combo-box"]`)
.find('input')
.focus()
.realType('attack.defense_evasion')
.realPress('Enter');

// Select applicable severity levels
cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ force: true });
cy.contains('1 (Highest)').click({ force: true });

// Continue to next page
cy.contains('Next').click({ force: true });

// Confirm page is reached
cy.contains('Review and create');

// Confirm field mappings registered
cy.contains('Field mapping');

if (!expectFailure) {
for (let field in testMappings.properties) {
const mappedTo = testMappings.properties[field].path;

cy.contains(field);
cy.contains(mappedTo);
}
}

// Confirm entries user has made
cy.contains('Detector details');
cy.contains(detectorName);
cy.contains('dns');
cy.contains(dataSource);
cy.contains('Alert on test_trigger');

// Create the detector
cy.get('button').contains('Create').click({ force: true });
cy.waitForPageLoad('detector-details', {
contains: detectorName,
});

cy.contains('Attempting to create the detector.');

// Confirm detector active
cy.contains(detectorName);
cy.contains('Active');

if (!expectFailure) {
cy.contains('Actions');
}

cy.contains('Detector configuration');
cy.contains('Field mappings');
cy.contains('Alert triggers');
cy.contains('Detector details');
cy.contains('Created at');
cy.contains('Last updated time');
};

describe('Detectors', () => {
const cypressIndexDns = 'cypress-index-dns';
const cypressIndexWindows = 'cypress-index-windows';
Expand Down Expand Up @@ -86,130 +208,19 @@ describe('Detectors', () => {

cy.get('.euiCallOut')
.should('be.visible')
.contains('The selected log sources contain different log types');
.contains(
'To avoid issues with field mappings, we recommend creating separate detectors for different log types.'
);
});

it('...can be created', () => {
// Locate Create detector button click to start
cy.get('.euiButton').filter(':contains("Create detector")').click({ force: true });

// Check to ensure process started
cy.waitForPageLoad('create-detector', {
contains: 'Define detector',
});

// Enter a name for the detector in the appropriate input
cy.get(`input[placeholder="Enter a name for the detector."]`).focus().realType('test detector');

// Select our pre-seeded data source (check cypressIndexDns)
cy.get(`[data-test-subj="define-detector-select-data-source"]`)
.find('input')
.focus()
.realType(cypressIndexDns);

cy.intercept({
pathname: '/_plugins/_security_analytics/rules/_search',
query: {
prePackaged: 'true',
},
}).as('getSigmaRules');

// Select threat detector type (Windows logs)
cy.get(`input[id="dns"]`).click({ force: true });

cy.wait('@getSigmaRules').then(() => {
// Open Detection rules accordion
cy.get('[data-test-subj="detection-rules-btn"]').click({ force: true, timeout: 5000 });

cy.contains('table tr', 'DNS', {
timeout: 120000,
});

// find search, type USB
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);

// Disable all rules
cy.contains('tr', cypressDNSRule, { timeout: 1000 });
cy.get('table th').within(() => {
cy.get('button').first().click({ force: true });
});

// Enable single rule
cy.contains('table tr', cypressDNSRule).within(() => {
cy.get('button').eq(1).click({ force: true, timeout: 2000 });
});
});

// Select appropriate names to map fields to
for (let field_name in testMappings.properties) {
const mappedTo = testMappings.properties[field_name].path;

cy.contains('tr', field_name).within(() => {
cy.get(`[data-test-subj="detector-field-mappings-select"]`).click().type(mappedTo);
});
}

// Click Next button to continue
cy.get('button').contains('Next').click({ force: true });

// Check that correct page now showing
cy.contains('Set up alerts');

// Type name of new trigger
cy.get(`input[placeholder="Enter a name for the alert condition."]`)
.focus()
.realType('test_trigger');

// Type in (or select) tags for the alert condition
cy.get(`[data-test-subj="alert-tags-combo-box"]`)
.find('input')
.focus()
.realType('attack.defense_evasion')
.realPress('Enter');

// Select applicable severity levels
cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ force: true });
cy.contains('1 (Highest)').click({ force: true });

// Continue to next page
cy.contains('Next').click({ force: true });

// Confirm page is reached
cy.contains('Review and create');

// Confirm field mappings registered
cy.contains('Field mapping');

for (let field in testMappings.properties) {
const mappedTo = testMappings.properties[field].path;

cy.contains(field);
cy.contains(mappedTo);
}

// Confirm entries user has made
cy.contains('Detector details');
cy.contains(detectorName);
cy.contains('dns');
cy.contains(cypressIndexDns);
cy.contains('Alert on test_trigger');

// Create the detector
cy.get('button').contains('Create').click({ force: true });
cy.waitForPageLoad('detector-details', {
contains: detectorName,
});
createDetector(detectorName, cypressIndexDns, false);
cy.contains('Detector created successfully');
});

// Confirm detector active
cy.contains(detectorName);
cy.contains('Active');
cy.contains('Actions');
cy.contains('Detector configuration');
cy.contains('Field mappings');
cy.contains('Alert triggers');
cy.contains('Detector details');
cy.contains('Created at');
cy.contains('Last updated time');
it('...can fail creation', () => {
createDetector(`${detectorName}_fail`, '.kibana_1', true);
cy.contains('Create detector failed.');
});

it('...basic details can be edited', () => {
Expand Down Expand Up @@ -276,7 +287,7 @@ describe('Detectors', () => {
});

// Confirm number of rules before edit
cy.contains('Active rules (1)');
cy.contains('Active rules (13)');

// Click "Edit" button in Detector rules panel
cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true });
Expand All @@ -300,7 +311,7 @@ describe('Detectors', () => {
cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true });

// Confirm 1 rule has been removed from detector
cy.contains('Active rules (0)');
cy.contains('Active rules (12)');

// Click "Edit" button in Detector rules panel
cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true });
Expand All @@ -326,7 +337,7 @@ describe('Detectors', () => {
});

// Confirm 1 rule has been added to detector
cy.contains('Active rules (1)');
cy.contains('Active rules (13)');
});

it('...should update field mappings if data source is changed', () => {
Expand All @@ -347,33 +358,10 @@ describe('Detectors', () => {
cy.get('.reviewFieldMappings').should('not.exist');

// Change input source
cy.get(`[data-test-subj="define-detector-select-data-source"]`)
.find('input')
.ospClear()
.focus()
.realType(cypressIndexWindows)
.realPress('Enter');

cy.get('.reviewFieldMappings').should('be.visible');
cy.get('.reviewFieldMappings').within(($el) => {
cy.get($el).contains('Automatically mapped fields (0)');
});

// Change input source
cy.get(`[data-test-subj="define-detector-select-data-source"]`)
.find('input')
.ospClear()
.focus()
.realType(cypressIndexDns)
.realPress('Enter');

cy.get('.reviewFieldMappings').should('be.visible');
cy.get('.reviewFieldMappings').within(($el) => {
cy.get($el).contains('Automatically mapped fields (1)');
});

// Save changes to detector details
cy.get(`[data-test-subj="save-basic-details-edits"]`).click({ force: true });
cy.get('.euiBadge__iconButton > .euiIcon').click({ force: true });
cy.get(`[data-test-subj="define-detector-select-data-source"]`).type(
`${cypressIndexWindows}{enter}`
);
});

it('...should update field mappings if rule selection is changed', () => {
Expand All @@ -393,61 +381,14 @@ describe('Detectors', () => {

cy.get('.reviewFieldMappings').should('not.exist');

// Search for specific rule
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);

cy.intercept('mappings/view').as('getMappingsView');

// Toggle single search result to unchecked
cy.contains('table tr', cypressDNSRule).within(() => {
// Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case.
cy.wait(1000);
cy.get('button').eq(1).click();
cy.get('table th').within(() => {
cy.get('button').first().click({ force: true });
});

cy.wait('@getMappingsView');
cy.get('.reviewFieldMappings').should('be.visible');
cy.get('.reviewFieldMappings').within(($el) => {
cy.get($el).contains('Automatically mapped fields (0)');
});

//Suspicious DNS Query with B64 Encoded String
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);
cy.contains('table tr', cypressDNSRule).within(() => {
// Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case.
cy.wait(1000);
cy.get('button').eq(1).click();
});

cy.wait('@getMappingsView');
cy.get(`input[placeholder="Search..."]`).ospSearch(
'Suspicious DNS Query with B64 Encoded String'
);
cy.contains('table tr', 'Suspicious DNS Query with B64 Encoded String').within(() => {
// Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case.
cy.wait(1000);
cy.get('button').eq(1).click();
});

cy.wait('@getMappingsView');
cy.get('.reviewFieldMappings').should('be.visible');
cy.get('.reviewFieldMappings').within(($el) => {
cy.get($el).contains('Automatically mapped fields (1)');
});

cy.get(`input[placeholder="Search..."]`).ospSearch('High TXT Records Requests Rate');
cy.contains('table tr', 'High TXT Records Requests Rate').within(() => {
// Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case.
cy.wait(1000);
cy.get('button').eq(1).click();
});

cy.wait('@getMappingsView');
cy.get('.reviewFieldMappings').should('be.visible');
cy.get('.reviewFieldMappings').within(($el) => {
cy.get($el).contains('Automatically mapped fields (1)');
cy.get($el).contains('1 rule fields may need manual mapping');
});
});

it('...can be deleted', () => {
Expand Down
Loading

0 comments on commit 2e0116d

Please sign in to comment.