Skip to content

Commit

Permalink
Merge branch 'main' into fix-errorResponse
Browse files Browse the repository at this point in the history
Signed-off-by: Riya <[email protected]>
  • Loading branch information
riysaxen-amzn authored Mar 27, 2024
2 parents 2743992 + 890c486 commit 0aa1251
Show file tree
Hide file tree
Showing 137 changed files with 3,236 additions and 3,461 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @amsiglan @AWSHurneyt @getsaurabh02 @lezzago @praveensameneni @sbcd90 @eirsep
* @amsiglan @AWSHurneyt @getsaurabh02 @lezzago @praveensameneni @sbcd90 @eirsep @riysaxen-amzn
19 changes: 1 addition & 18 deletions .github/workflows/cypress-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ env:
OPENSEARCH_VERSION: '3.0.0-SNAPSHOT'
SECURITY_ANALYTICS_BRANCH: 'main'
GRADLE_VERSION: '7.6.1'

# If this variable is not empty, the package.json, opensearch_dashboards.json, and yarn.lock files will be replaced
# with those files from the 'opensearch-project/security-analytics-dashboards-plugin' branch or commit specified.
OVERRIDE_REFERENCE: 'main'
jobs:
tests:
name: Run Cypress E2E tests
Expand Down Expand Up @@ -74,19 +70,6 @@ jobs:
with:
path: OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin

# This job replaces the package.json, opensearch_dashboards.json, and yarn.lock files from the
# 'opensearch-project/security-analytics-dashboards-plugin' branch or commit specified in env variable.
# This is most useful on the 'main' branch as it will enable us to specify which version to use for the build when
# one of this package's dependencies is not building reliably without having to adjust the actual version of this package.
- name: Override Package Version
if: ${{ env.OVERRIDE_REFERENCE != '' }}
run: |
cd OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin
git fetch --all
git checkout origin/${{ env.OVERRIDE_REFERENCE }} opensearch_dashboards.json
git checkout origin/${{ env.OVERRIDE_REFERENCE }} package.json
git checkout origin/${{ env.OVERRIDE_REFERENCE }} yarn.lock
- name: Setup Node
uses: actions/setup-node@v3
with:
Expand All @@ -106,7 +89,7 @@ jobs:
- name: Bootstrap plugin/OpenSearch-Dashboards
run: |
cd OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin
yarn osd bootstrap
yarn osd bootstrap --single-version=loose
- name: Run OpenSearch-Dashboards server
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unit-tests-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
cd ./OpenSearch-Dashboards/
su `id -un 1000` -c "source $NVM_DIR/nvm.sh && nvm use && node -v && yarn -v &&
cd ./plugins/security-analytics-dashboards-plugin &&
whoami && yarn osd bootstrap && yarn run test:jest --coverage"
whoami && yarn osd bootstrap --single-version=loose && yarn run test:jest --coverage"
- name: Uploads coverage
if: ${{ matrix.os == 'ubuntu-latest' }}
Expand Down Expand Up @@ -89,7 +89,7 @@ jobs:
- name: Bootstrap plugin/OpenSearch-Dashboards
run: |
cd OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin
yarn osd bootstrap
yarn osd bootstrap --single-version=loose
- name: Run tests
run: |
cd OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/verify-binary-installation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: 'Install Dashboards with Plugin via Binary'

on: [push, pull_request]
env:
OPENSEARCH_VERSION: '3.0.0'
CI: 1
# avoid warnings like "tput: No value for $TERM and no -T specified"
TERM: xterm

jobs:
verify-binary-installation:
name: Run binary installation
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
# TODO: add windows support when OSD core is stable on windows
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Branch
uses: actions/checkout@v3

- name: Set env
run: |
opensearch_version=$(node -p "require('./opensearch_dashboards.json').opensearchDashboardsVersion")
plugin_version=$(node -p "require('./opensearch_dashboards.json').version")
echo "OPENSEARCH_VERSION=$opensearch_version" >> $GITHUB_ENV
echo "PLUGIN_VERSION=$plugin_version" >> $GITHUB_ENV
shell: bash

- name: Run Opensearch
uses: derek-ho/start-opensearch@v2
with:
opensearch-version: ${{ env.OPENSEARCH_VERSION }}
security-enabled: false

- name: Run Dashboard
id: setup-dashboards
uses: derek-ho/setup-opensearch-dashboards@v1
with:
plugin_name: security-analytics-dashboards-plugin
built_plugin_name: security-analytics-dashboards
install_zip: true

- name: Start the binary
run: |
nohup ./bin/opensearch-dashboards &
working-directory: ${{ steps.setup-dashboards.outputs.dashboards-binary-directory }}
shell: bash

- name: Health check
run: |
timeout 300 bash -c 'while [[ "$(curl http://localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done'
shell: bash

5 changes: 3 additions & 2 deletions .opensearch_dashboards-plugin-helpers.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"tsconfig.json",
"yarn.lock",
".yarnrc",
"{lib,public,server,webpackShims,translations,utils,models,test}/**/*",
"!__tests__"
"{lib,public,server,webpackShims,translations,utils,models,test,common,types}/**/*",
"!__tests__",
"config.ts"
]
}
1 change: 1 addition & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ This document contains a list of maintainers in this repo. See [opensearch-proje
| Praveen Sameneni | [praveensameneni](https://github.com/praveensameneni) | Amazon |
| Amardeepsingh Siglani | [amsiglan](https://github.com/amsiglan) | Amazon |
| Saurabh Singh | [getsaurabh02](https://github.com/getsaurabh02) | Amazon |
| Riya Saxena | [riysaxen-amzn](https://github.com/riysaxen-amzn) | Amazon |
6 changes: 6 additions & 0 deletions common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const DEFAULT_RULE_UUID = '25b9c01c-350d-4b95-bed1-836d04a4f324';
45 changes: 45 additions & 0 deletions common/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import _ from 'lodash';
import { DEFAULT_METRICS_COUNTER } from '../server/utils/constants';
import { MetricsCounter, PartialMetricsCounter } from '../types';
import { SecurityAnalyticsPluginConfigType } from '../config';

export function aggregateMetrics(
metrics: PartialMetricsCounter,
currentMetricsCounter: PartialMetricsCounter
): MetricsCounter {
const partialMetrics: PartialMetricsCounter = {
...currentMetricsCounter,
};
Object.keys(metrics).forEach((w) => {
const workflow = w as keyof MetricsCounter;
const workFlowMetrics = metrics[workflow];

if (workFlowMetrics) {
const counterToUpdate: any =
partialMetrics[workflow] || _.cloneDeep(DEFAULT_METRICS_COUNTER[workflow]);
Object.entries(workFlowMetrics).forEach(([metric, count]) => {
if (!counterToUpdate[metric]) {
counterToUpdate[metric] = 0;
}
counterToUpdate[metric] += count;
});

partialMetrics[workflow] = counterToUpdate;
}
});

return partialMetrics as MetricsCounter;
}

let securityAnalyticsPluginConfig: SecurityAnalyticsPluginConfigType;
export const setSecurityAnalyticsPluginConfig = (config: SecurityAnalyticsPluginConfigType) => {
securityAnalyticsPluginConfig = config;
};

export const getSecurityAnalyticsPluginConfig = (): SecurityAnalyticsPluginConfigType | undefined =>
securityAnalyticsPluginConfig;
15 changes: 15 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { schema, TypeOf } from '@osd/config-schema';

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
// Interval in minutes at which the browser should emit the metrics to the Kibana server
// Setting this to "0" will disable the metrics
uxTelemetryInterval: schema.number({ defaultValue: 2 }),
});

export type SecurityAnalyticsPluginConfigType = TypeOf<typeof configSchema>;
26 changes: 26 additions & 0 deletions cypress/fixtures/sample_aws_s3_rule_to_import.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
title: Moriya Rootkit
id: 25b9c01c-350d-4b95-bed1-836d04a4f324
description: Detects the use of Moriya rootkit as described in the securelist Operation TunnelSnake report
status: experimental
author: Bhabesh Raj
date: 2021/05/06
modified: 2021/11/30
references:
- https://securelist.com/operation-tunnelsnake-and-moriya-rootkit/101831
tags:
- attack.persistence
- attack.privilege_escalation
- attack.t1543.003
logsource:
product: d3
category: s3
service: azure
detection:
selection:
Provider_Name: 'Service Control Manager'
EventID: 2100
ServiceName: ZzNetSvc
condition: selection
level: critical
falsepositives:
- Unknown
81 changes: 58 additions & 23 deletions cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import dns_type_rule_data from '../fixtures/integration_tests/rule/create_dns_ru
import _ from 'lodash';
import { getMappingFields } from '../../public/pages/Detectors/utils/helpers';
import { getLogTypeLabel } from '../../public/pages/LogTypes/utils/helpers';
import { setupIntercept } from '../support/helpers';
import { descriptionErrorString } from '../../public/utils/validation';

const cypressIndexDns = 'cypress-index-dns';
const cypressIndexWindows = 'cypress-index-windows';
Expand Down Expand Up @@ -113,9 +115,15 @@ const validatePendingFieldMappingsPanel = (mappings) => {
});
};

const fillDetailsForm = (detectorName, dataSource) => {
const fillDetailsForm = (detectorName, dataSource, isCustomDataSource = false) => {
getNameField().type(detectorName);
getDataSourceField().selectComboboxItem(dataSource);
if (isCustomDataSource) {
getDataSourceField()
.focus()
.type(dataSource + '{enter}');
} else {
getDataSourceField().selectComboboxItem(dataSource);
}
getDataSourceField().focus().blur();
getLogTypeField().selectComboboxItem(getLogTypeLabel(cypressLogTypeDns));
getLogTypeField().focus().blur();
Expand All @@ -124,7 +132,7 @@ const fillDetailsForm = (detectorName, dataSource) => {
const createDetector = (detectorName, dataSource, expectFailure) => {
getCreateDetectorButton().click({ force: true });

fillDetailsForm(detectorName, dataSource);
fillDetailsForm(detectorName, dataSource, expectFailure);

cy.getElementByText('.euiAccordion .euiTitle', 'Selected detection rules (14)')
.click({ force: true, timeout: 5000 })
Expand All @@ -151,8 +159,8 @@ const createDetector = (detectorName, dataSource, expectFailure) => {
.focus()
.blur();

cy.intercept('POST', '/_plugins/_security_analytics/mappings').as('createMappingsRequest');
cy.intercept('POST', '/_plugins/_security_analytics/detectors').as('createDetectorRequest');
setupIntercept(cy, '/_plugins/_security_analytics/mappings', 'createMappingsRequest');
setupIntercept(cy, '/_plugins/_security_analytics/detectors', 'createDetectorRequest');

// create the detector
cy.getElementByText('button', 'Create').click({ force: true });
Expand Down Expand Up @@ -218,7 +226,7 @@ describe('Detectors', () => {

describe('...should validate form fields', () => {
beforeEach(() => {
cy.intercept('/_plugins/_security_analytics/detectors/_search').as('detectorsSearch');
setupIntercept(cy, '/_plugins/_security_analytics/detectors/_search', 'detectorsSearch');

// Visit Detectors page before any test
cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`);
Expand Down Expand Up @@ -272,9 +280,7 @@ describe('Detectors', () => {
getDescriptionField()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.contains(
'Description should only consist of upper and lowercase letters, numbers 0-9, commas, hyphens, periods, spaces, and underscores. Max limit of 500 characters.'
);
.contains(descriptionErrorString);

getDescriptionField()
.type('{selectall}')
Expand Down Expand Up @@ -352,7 +358,7 @@ describe('Detectors', () => {

describe('...validate create detector flow', () => {
beforeEach(() => {
cy.intercept('/_plugins/_security_analytics/detectors/_search').as('detectorsSearch');
setupIntercept(cy, '/_plugins/_security_analytics/detectors/_search', 'detectorsSearch');

// Visit Detectors page before any test
cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`);
Expand All @@ -370,7 +376,7 @@ describe('Detectors', () => {
});

it('...basic details can be edited', () => {
cy.intercept('GET', '/_plugins/_security_analytics/indices').as('getIndices');
setupIntercept(cy, '/_plugins/_security_analytics/indices', 'getIndices', 'GET');
openDetectorDetails(detectorName);

editDetectorDetails(detectorName, 'Detector details');
Expand Down Expand Up @@ -422,8 +428,8 @@ describe('Detectors', () => {
});

it('...should update field mappings if data source is changed', () => {
cy.intercept('mappings/view').as('getMappingsView');
cy.intercept('GET', '/indices').as('getIndices');
setupIntercept(cy, 'mappings/view', 'getMappingsView', 'GET');
setupIntercept(cy, '/indices', 'getIndices', 'GET');
openDetectorDetails(detectorName);

editDetectorDetails(detectorName, 'Detector details');
Expand All @@ -445,7 +451,7 @@ describe('Detectors', () => {
});

it('...should show field mappings if rule selection is changed', () => {
cy.intercept('mappings/view').as('getMappingsView');
setupIntercept(cy, 'mappings/view', 'getMappingsView', 'GET');

openDetectorDetails(detectorName);

Expand All @@ -467,23 +473,52 @@ describe('Detectors', () => {
validateFieldMappingsTable('rules are changed');
});

it('...can be stopped and started back from detectors list action menu', () => {
cy.wait(1000);
cy.get('tbody > tr')
.first()
.within(() => {
cy.get('[class="euiCheckbox__input"]').click({ force: true });
});

// Waiting for Actions menu button to be enabled
cy.wait(1000);

setupIntercept(cy, '/_plugins/_security_analytics/detectors/_search', 'detectorsSearch');

cy.get('[data-test-subj="detectorsActionsButton').click({ force: true });
cy.get('[data-test-subj="toggleDetectorButton').contains('Stop');
cy.get('[data-test-subj="toggleDetectorButton').click({ force: true });

cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete');
// Need this extra wait time for the Actions button to become enabled again
cy.wait(1000);

setupIntercept(cy, '/_plugins/_security_analytics/detectors/_search', 'detectorsSearch');
cy.get('[data-test-subj="detectorsActionsButton').click({ force: true });
cy.get('[data-test-subj="toggleDetectorButton').contains('Start');
cy.get('[data-test-subj="toggleDetectorButton').click({ force: true });

cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete');
// Need this extra wait time for the Actions button to become enabled again
cy.wait(1000);

cy.get('[data-test-subj="detectorsActionsButton').click({ force: true });
cy.get('[data-test-subj="toggleDetectorButton').contains('Stop');
});

it('...can be deleted', () => {
cy.intercept('/_plugins/_security_analytics/rules/_search?prePackaged=true').as(
'getSigmaRules'
);
cy.intercept('/_plugins/_security_analytics/rules/_search?prePackaged=false').as(
'getCustomRules'
);
setupIntercept(cy, '/rules/_search', 'getRules');

openDetectorDetails(detectorName);

cy.wait('@detectorsSearch');
cy.wait('@getCustomRules');
cy.wait('@getSigmaRules');
cy.wait('@getRules');

cy.getButtonByText('Actions')
.click({ force: true })
.then(() => {
cy.intercept('/detectors').as('detectors');
setupIntercept(cy, '/detectors', 'detectors');
cy.getElementByText('.euiContextMenuItem', 'Delete').click({ force: true });
cy.wait('@detectors').then(() => {
cy.contains('There are no existing detectors');
Expand Down
Loading

0 comments on commit 0aa1251

Please sign in to comment.