Skip to content

Commit

Permalink
[D4C] fix to targetFilePath/processExecutable regex, and null check (e…
Browse files Browse the repository at this point in the history
…lastic#157771)

## Summary

Fixes the path regex to allow /* and /** values, also fixed a null
pointer in yaml editor.

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
mitodrummer authored May 15, 2023
1 parent fd6e3b8 commit 92600a4
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 23 deletions.
13 changes: 10 additions & 3 deletions x-pack/plugins/cloud_defend/public/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,22 @@ export function validateMaxSelectorsAndResponses(selectors: Selector[], response
return errors;
}

export function validateStringValuesForCondition(condition: SelectorCondition, values: string[]) {
export function validateStringValuesForCondition(condition: SelectorCondition, values?: string[]) {
const errors: string[] = [];
const maxValueBytes =
SelectorConditionsMap[condition].maxValueBytes || MAX_CONDITION_VALUE_LENGTH_BYTES;

const { pattern, patternError } = SelectorConditionsMap[condition];

values.forEach((value) => {
if (pattern && !new RegExp(pattern).test(value)) {
values?.forEach((value) => {
if (value?.length === 0) {
errors.push(
i18n.translate('xpack.cloudDefend.errorGenericEmptyValue', {
defaultMessage: '"{condition}" values cannot be empty',
values: { condition },
})
);
} else if (pattern && !new RegExp(pattern).test(value)) {
if (patternError) {
errors.push(patternError);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,22 +300,27 @@ describe('<ControlGeneralViewSelector />', () => {
}

updatedSelector = onChange.mock.calls[1][0];
expect(updatedSelector.hasErrors).toBeFalsy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});

userEvent.type(el, '/*{enter}');
updatedSelector = onChange.mock.calls[2][0];
expect(updatedSelector.hasErrors).toBeFalsy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});

userEvent.type(el, 'badpath{enter}');
updatedSelector = onChange.mock.calls[3][0];

expect(updatedSelector.hasErrors).toBeTruthy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(getByText(errorStr)).toBeTruthy();

userEvent.type(el, ' {enter}');
updatedSelector = onChange.mock.calls[4][0];
expect(updatedSelector.hasErrors).toBeTruthy();
rerender(<WrappedComponent selector={updatedSelector} />);
expect(getByText('"targetFilePath" values cannot be empty')).toBeTruthy();
});

it('validates processExecutable conditions values', async () => {
Expand All @@ -336,7 +341,7 @@ describe('<ControlGeneralViewSelector />', () => {
'input'
);

const errorStr = i18n.errorInvalidProcessExecutable;
const regexError = i18n.errorInvalidProcessExecutable;

if (el) {
userEvent.type(el, '/usr/bin/**{enter}');
Expand All @@ -345,28 +350,33 @@ describe('<ControlGeneralViewSelector />', () => {
}

updatedSelector = onChange.mock.calls[1][0];
expect(updatedSelector.hasErrors).toBeFalsy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});
expect(findByText(regexError)).toMatchObject({});

userEvent.type(el, '/*{enter}');
updatedSelector = onChange.mock.calls[2][0];
expect(updatedSelector.hasErrors).toBeFalsy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});
expect(findByText(regexError)).toMatchObject({});

userEvent.type(el, '/usr/bin/ls{enter}');
updatedSelector = onChange.mock.calls[3][0];
expect(updatedSelector.hasErrors).toBeFalsy();
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});
expect(findByText(regexError)).toMatchObject({});

userEvent.type(el, 'badpath{enter}');
updatedSelector = onChange.mock.calls[4][0];

expect(updatedSelector.hasErrors).toBeTruthy();
rerender(<WrappedComponent selector={updatedSelector} />);
expect(getByText(regexError)).toBeTruthy();

expect(getByText(errorStr)).toBeTruthy();
userEvent.type(el, ' {enter}');
updatedSelector = onChange.mock.calls[4][0];
expect(updatedSelector.hasErrors).toBeTruthy();
rerender(<WrappedComponent selector={updatedSelector} />);
expect(getByText('"processExecutable" values cannot be empty')).toBeTruthy();
});

it('validates containerImageFullName conditions values', async () => {
Expand All @@ -385,7 +395,7 @@ describe('<ControlGeneralViewSelector />', () => {
'input'
);

const errorStr = i18n.errorInvalidFullContainerImageName;
const regexError = i18n.errorInvalidFullContainerImageName;

if (el) {
userEvent.type(el, 'docker.io/nginx{enter}');
Expand All @@ -396,13 +406,13 @@ describe('<ControlGeneralViewSelector />', () => {
updatedSelector = onChange.mock.calls[1][0];
rerender(<WrappedComponent selector={updatedSelector} />);

expect(findByText(errorStr)).toMatchObject({});
expect(findByText(regexError)).toMatchObject({});

userEvent.type(el, 'nginx{enter}');
updatedSelector = onChange.mock.calls[2][0];
rerender(<WrappedComponent selector={updatedSelector} />);

expect(getByText(errorStr)).toBeTruthy();
expect(getByText(regexError)).toBeTruthy();
});

it('validates kubernetesPodLabel conditions values', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@
"minItems": 1,
"items": {
"type": "string",
"pattern": "^(?:\\/[^\\/\\*]+)+(?:\\/\\*|\\/\\*\\*)?$"
"pattern": "^(?:\\/[^\\/\\*]+)*(?:\\/\\*|\\/\\*\\*)?$",
"minLength": 1
}
},
"ignoreVolumeMounts": {
Expand Down Expand Up @@ -319,7 +320,8 @@
"minItems": 1,
"items": {
"type": "string",
"pattern": "^(?:\\/[^\\/\\*]+)+(?:\\/\\*|\\/\\*\\*)?$"
"pattern": "^(?:\\/[^\\/\\*]+)*(?:\\/\\*|\\/\\*\\*)?$",
"minLength": 1
}
},
"processName": {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/cloud_defend/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export const SelectorConditionsMap: SelectorConditionsMapProps = {
selectorType: 'file',
type: 'stringArray',
maxValueBytes: 255,
pattern: '^(?:\\/[^\\/\\*]+)+(?:\\/\\*|\\/\\*\\*)?$',
pattern: '^(?:\\/[^\\/\\*]+)*(?:\\/\\*|\\/\\*\\*)?$',
patternError: i18n.errorInvalidTargetFilePath,
},
ignoreVolumeFiles: { selectorType: 'file', type: 'flag', not: ['ignoreVolumeMounts'] },
Expand All @@ -143,7 +143,7 @@ export const SelectorConditionsMap: SelectorConditionsMapProps = {
selectorType: 'process',
type: 'stringArray',
not: ['processName'],
pattern: '^(?:\\/[^\\/\\*]+)+(?:\\/\\*|\\/\\*\\*)?$',
pattern: '^(?:\\/[^\\/\\*]+)*(?:\\/\\*|\\/\\*\\*)?$',
patternError: i18n.errorInvalidProcessExecutable,
},
processName: {
Expand Down

0 comments on commit 92600a4

Please sign in to comment.