Skip to content

Commit

Permalink
UI polish for correlations and custom log types (opensearch-project#683
Browse files Browse the repository at this point in the history
…) (opensearch-project#685)

* fixed abbreviations

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* fixed log type name validation

Signed-off-by: Amardeepsingh Siglani <[email protected]>

---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>
(cherry picked from commit b54bb36)

Co-authored-by: Amardeepsingh Siglani <[email protected]>
Signed-off-by: AWSHurneyt <[email protected]>
  • Loading branch information
2 people authored and AWSHurneyt committed Oct 12, 2023
1 parent ad46288 commit 1da4d30
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 69 deletions.
53 changes: 12 additions & 41 deletions public/pages/Correlations/components/FindingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ import {
EuiToolTip,
EuiDescriptionList,
} from '@elastic/eui';
import {
getAbbrFromLogType,
getSeverityLabel,
getSeverityColor,
getLabelFromLogType,
} from '../utils/constants';
import { getSeverityLabel, getSeverityColor, getLabelFromLogType } from '../utils/constants';
import { DataStore } from '../../../store/DataStore';
import { CorrelationFinding } from '../../../../types';

Expand All @@ -31,7 +26,6 @@ export interface FindingCardProps {
timestamp: string;
detectionRule: { name: string; severity: string };
correlationData?: {
// ruleName: string;
score: string;
onInspect: (findingId: string, logType: string) => void;
};
Expand Down Expand Up @@ -90,43 +84,20 @@ export const FindingCard: React.FC<FindingCardProps> = ({
return (
<EuiPanel>
{correlationHeader}
<EuiFlexGroup justifyContent="flexStart" alignItems="center">
<EuiFlexItem grow={1} style={{ maxWidth: 120 }}>
<div style={{ position: 'relative' }}>
<div
style={{
width: '35px',
height: '35px',
border: '1px solid',
borderRadius: '50%',
position: 'relative',
fontSize: 10,
lineHeight: '35px',
textAlign: 'center',
borderColor: '#98A2B3',
color: '#98A2B3',
}}
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" gutterSize="s">
<EuiFlexItem grow={false}>
<div>
<EuiBadge
color={getSeverityColor(detectionRule.severity).background}
style={{ padding: '3px 10px' }}
>
{getAbbrFromLogType(logType)}
</div>
{getSeverityLabel(detectionRule.severity) ? (
<EuiBadge
style={{
position: 'absolute',
transform: 'translateY(-100%)',
left: '33px',
color: getSeverityColor(detectionRule.severity).text,
}}
color={getSeverityColor(detectionRule.severity).background}
>
{getSeverityLabel(detectionRule.severity)}
</EuiBadge>
) : null}
{getSeverityLabel(detectionRule.severity)}
</EuiBadge>
<EuiBadge color="hollow" style={{ padding: '3px 10px' }}>
{getLabelFromLogType(logType)}
</EuiBadge>
</div>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<strong>{getLabelFromLogType(logType)}</strong>
</EuiFlexItem>
{!correlationData && (
<EuiFlexItem grow={false}>
<EuiToolTip content={'View finding details'}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
getDefaultLogTypeFilterItemOptions,
defaultSeverityFilterItemOptions,
emptyGraphData,
getAbbrFromLogType,
getLabelFromLogType,
getSeverityColor,
getSeverityLabel,
Expand Down Expand Up @@ -255,12 +254,9 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation

nodes.push({
id: finding.id,
label: `<b>${getAbbrFromLogType(
finding.logType
)}</b>\n<code>${finding.detectionRule.severity.slice(0, 4)}</code>`,
title: this.createNodeTooltip(finding),
color: {
background: 'white',
background: borderColor,
border: borderColor,
highlight: {
background: '#e7f5ff',
Expand All @@ -272,7 +268,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
},
},
widthConstraint: {
minimum: 50,
minimum: 40,
},
borderWidth: 2,
font: {
Expand All @@ -291,6 +287,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
chosen: false,
color: '#98A2B3', //ouiColorMediumShade,
label: f1.correlationScore || f2.correlationScore || '',
width: 2,
});
}

Expand Down
6 changes: 1 addition & 5 deletions public/pages/Correlations/utils/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,8 @@ export const emptyGraphData: CorrelationGraphData = {
events: {},
};

export const getAbbrFromLogType = (logType: string) => {
return ruleTypes.find((ruleType) => ruleType.value === logType)?.abbr || '-';
};

export const getLabelFromLogType = (logType: string) => {
return ruleTypes.find((ruleType) => ruleType.value === logType)?.label || '-';
return ruleTypes.find((ruleType) => ruleType.value === logType)?.label || logType;
};

export const getSeverityLabel = (sev: string) => {
Expand Down
2 changes: 2 additions & 0 deletions public/pages/LogTypes/components/LogTypeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { LogTypeItem } from '../../../../types';
import { DataStore } from '../../../store/DataStore';
import { LogTypeForm } from './LogTypeForm';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { successNotificationToast } from '../../../utils/helpers';

export interface LogTypeDetailsProps {
initialLogTypeDetails: LogTypeItem;
Expand All @@ -31,6 +32,7 @@ export const LogTypeDetails: React.FC<LogTypeDetailsProps> = ({
const onUpdateLogType = async () => {
const success = await DataStore.logTypes.updateLogType(logTypeDetails);
if (success) {
successNotificationToast(notifications, 'updated', `log type ${logTypeDetails.name}`);
setIsEditMode(false);
}
};
Expand Down
25 changes: 23 additions & 2 deletions public/pages/LogTypes/components/LogTypeDetectionRules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React from 'react';
import { RulesTable } from '../../Rules/components/RulesTable/RulesTable';
import { RuleTableItem } from '../../Rules/utils/helpers';
import { ContentPanel } from '../../../components/ContentPanel';
import { EuiButton } from '@elastic/eui';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';

export interface LogTypeDetectionRulesProps {
rules: RuleTableItem[];
Expand All @@ -26,7 +26,28 @@ export const LogTypeDetectionRules: React.FC<LogTypeDetectionRulesProps> = ({
hideHeaderBorder={true}
actions={[<EuiButton onClick={refreshRules}>Refresh</EuiButton>]}
>
<RulesTable loading={loadingRules} ruleItems={rules} showRuleDetails={() => {}} />
{rules.length === 0 ? (
<EuiFlexGroup justifyContent="center" alignItems="center" direction="column">
<EuiFlexItem grow={false}>
<EuiText color="subdued">
<p>There are no detection rules associated with this log type. </p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
href={`opensearch_security_analytics_dashboards#/create-rule`}
target="_blank"
>
Create detection rule&nbsp;
<EuiIcon type={'popout'} />
</EuiButton>
<EuiSpacer size="xl" />
</EuiFlexItem>
</EuiFlexGroup>
) : (
<RulesTable loading={loadingRules} ruleItems={rules} showRuleDetails={() => {}} />
)}
</ContentPanel>
);
};
6 changes: 3 additions & 3 deletions public/pages/LogTypes/components/LogTypeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '@elastic/eui';
import { LogTypeItem } from '../../../../types';
import React from 'react';
import { validateName } from '../../../utils/validation';
import { LOG_TYPE_NAME_REGEX, validateName } from '../../../utils/validation';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { useState } from 'react';

Expand All @@ -42,7 +42,7 @@ export const LogTypeForm: React.FC<LogTypeFormProps> = ({
const [nameError, setNameError] = useState('');

const updateErrors = (details = logTypeDetails) => {
const nameInvalid = !validateName(details.name);
const nameInvalid = !validateName(details.name, LOG_TYPE_NAME_REGEX, false /* shouldTrim */);
setNameError(nameInvalid ? 'Invalid name' : '');

return { nameInvalid };
Expand All @@ -68,7 +68,7 @@ export const LogTypeForm: React.FC<LogTypeFormProps> = ({
label="Name"
helpText={
isEditMode &&
'Must contain 5-50 characters. Valid characters are a-z, A-Zm 0-9, hyphens, spaces, and underscores'
'Must contain 2-50 characters. Valid characters are a-z, 0-9, hyphens, and underscores'
}
isInvalid={!!nameError}
error={nameError}
Expand Down
8 changes: 1 addition & 7 deletions public/pages/LogTypes/containers/CreateLogType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiLink } from '@elastic/eui';
import { ContentPanel } from '../../../components/ContentPanel';
import React, { useContext, useState } from 'react';
import { LogTypeForm } from '../components/LogTypeForm';
Expand Down Expand Up @@ -38,12 +37,7 @@ export const CreateLogType: React.FC<CreateLogTypeProps> = ({ history, notificat
<ContentPanel
title={'Create log type'}
subTitleText={
<p>
Create log type to categorize and identify detection rules for your data sources. &nbsp;{' '}
<EuiLink href={'#'} target="_blank">
Learn more
</EuiLink>
</p>
<p>Create log type to categorize and identify detection rules for your data sources.</p>
}
hideHeaderBorder={true}
>
Expand Down
2 changes: 1 addition & 1 deletion public/pages/Rules/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { euiPaletteForStatus } from '@elastic/eui';

export const ruleTypes: { label: string; value: string; abbr: string }[] = [];
export const ruleTypes: { label: string; value: string; id: string }[] = [];

const paletteColors = euiPaletteForStatus(5);

Expand Down
4 changes: 2 additions & 2 deletions public/store/LogTypeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export class LogTypeStore {
ruleTypes.length,
...logTypes.map((logType) => ({
label: logType.name,
value: logType.id,
abbr: '',
value: logType.name,
id: logType.id,
}))
);

Expand Down
11 changes: 9 additions & 2 deletions public/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const MAX_NAME_CHARACTERS = 50;
// numbers 0-9, hyphens, spaces, and underscores.
export const NAME_REGEX = new RegExp(/^[a-zA-Z0-9 _-]{5,50}$/);

export const LOG_TYPE_NAME_REGEX = new RegExp(/^[a-z0-9_-]{2,50}$/);

// This regex pattern support MIN to MAX character limit, capital and lowercase letters,
// numbers 0-9, hyphens, dot, and underscores.
export const DETECTION_NAME_REGEX = new RegExp(/^[a-zA-Z0-9_.-]{5,50}$/);
Expand All @@ -28,8 +30,13 @@ export const AUTHOR_REGEX = new RegExp(/^[a-zA-Z0-9 _,-.]{5,50}$/);
* @param regex
* @return TRUE if valid; else FALSE.
*/
export function validateName(name: string, regex: RegExp = NAME_REGEX): boolean {
return name.trim().match(regex) !== null;
export function validateName(
name: string,
regex: RegExp = NAME_REGEX,
shouldTrimName: boolean = true
): boolean {
const toValidate = shouldTrimName ? name.trim() : name;
return toValidate.match(regex) !== null;
}

export function validateDetectionFieldName(
Expand Down

0 comments on commit 1da4d30

Please sign in to comment.