{{ s__('SecurityOrchestration|Configuration type') }}
-
- {{ s__('SecurityOrchestration|Template') }}
-
-
- {{ s__('SecurityOrchestration|Custom') }}
-
+
diff --git a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js
index c124bf73758947d9d73f86e9291b4c6f5a7f9852..e8d6bceba5c97385f3a72dfba75acdf1e5336d70 100644
--- a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js
+++ b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js
@@ -22,34 +22,11 @@ export const optimizedConfiguration = ` rules:
skip_ci:
allowed: true`;
-export const DEFAULT_SCAN_EXECUTION_POLICY_OPTIMIZED = `scan_execution_policy:
- - name: ''
- description: ''
- enabled: true
-${optimizedConfiguration}`;
-
-export const DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_OPTIMIZED = `scan_execution_policy:
- - name: ''
- description: ''
- enabled: true
- policy_scope:
- projects:
- excluding: []
-${optimizedConfiguration}`;
-
export const DEFAULT_SCAN_EXECUTION_POLICY = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- skip_ci:
- allowed: true
-`;
+${optimizedConfiguration}`;
export const DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE = `scan_execution_policy:
- name: ''
@@ -58,44 +35,9 @@ export const DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE = `scan_execution_policy:
policy_scope:
projects:
excluding: []
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- skip_ci:
- allowed: true
-`;
-
-export const DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES = `scan_execution_policy:
- - name: ''
- description: ''
- enabled: true
- policy_scope:
- projects:
- excluding: []
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
-`;
+${optimizedConfiguration}`;
export const getPolicyYaml = ({ isGroup }) => {
- const { flexibleScanExecutionPolicy } = window.gon?.features || {};
-
- if (flexibleScanExecutionPolicy) {
- return isGroup
- ? DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_OPTIMIZED
- : DEFAULT_SCAN_EXECUTION_POLICY_OPTIMIZED;
- }
-
return isGroup ? DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE : DEFAULT_SCAN_EXECUTION_POLICY;
};
diff --git a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component.vue b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component.vue
index c73089815234d9254d6d62530389fec303e0915e..4f98e78e4327919e1a7dd572a48a6c1d415d9966 100644
--- a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component.vue
+++ b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component.vue
@@ -87,9 +87,6 @@ export default {
pipelineSources() {
return this.initRule.pipeline_sources || {};
},
- hasFlexibleScanExecutionPolicyFeatureFlag() {
- return this.glFeatures.flexibleScanExecutionPolicy;
- },
rulesListBoxItems() {
return Object.entries(this.$options.SCAN_EXECUTION_RULES_LABELS).map(([value, text]) => ({
value,
@@ -118,18 +115,9 @@ export default {
);
}
- // Handle flexible scan execution policy with target branches
- const hasFlexiblePolicy = this.hasFlexibleScanExecutionPolicyFeatureFlag;
-
- if (hasFlexiblePolicy) {
- return s__(
- 'ScanExecutionPolicy|%{rules} every time a pipeline runs that %{scopes} %{branches} using %{sources} %{branchExceptions} %{agents} %{namespaces}',
- );
- }
-
// Default pipeline rule
return s__(
- 'ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces}',
+ 'ScanExecutionPolicy|%{rules} every time a pipeline runs that %{scopes} %{branches} using %{sources} %{branchExceptions} %{agents} %{namespaces}',
);
},
showAllPipelineSources() {
diff --git a/ee/app/controllers/groups/security/policies_controller.rb b/ee/app/controllers/groups/security/policies_controller.rb
index 42bdb7feed30d686c9e922e3dcd533fd84cccbba..af5af1d557b665b23eb6b5641c7c5b08645a4127 100644
--- a/ee/app/controllers/groups/security/policies_controller.rb
+++ b/ee/app/controllers/groups/security/policies_controller.rb
@@ -15,7 +15,6 @@ class PoliciesController < Groups::ApplicationController
push_frontend_feature_flag(:security_policies_split_view, group)
push_frontend_feature_flag(:security_policy_approval_warn_mode, group)
push_frontend_feature_flag(:scheduled_pipeline_execution_policies, group)
- push_frontend_feature_flag(:flexible_scan_execution_policy, group)
push_frontend_feature_flag(:security_policies_combined_list, group)
push_frontend_feature_flag(:security_policies_kev_filter, group)
end
diff --git a/ee/app/controllers/projects/security/policies_controller.rb b/ee/app/controllers/projects/security/policies_controller.rb
index 1b0ae8eeb13ee1aa80f9f5a5f35c1e2acdd5a6b0..e83544079f59b06056f322bcedfcaa025b86d66d 100644
--- a/ee/app/controllers/projects/security/policies_controller.rb
+++ b/ee/app/controllers/projects/security/policies_controller.rb
@@ -15,7 +15,6 @@ class PoliciesController < Projects::ApplicationController
push_frontend_feature_flag(:scheduled_pipeline_execution_policies, project)
push_frontend_feature_flag(:security_policies_split_view, project.group)
push_frontend_feature_flag(:security_policy_approval_warn_mode, project.group)
- push_frontend_feature_flag(:flexible_scan_execution_policy, project.group)
push_frontend_feature_flag(:security_policies_combined_list, project)
push_frontend_feature_flag(:security_policies_kev_filter, project.group)
end
diff --git a/ee/config/feature_flags/beta/flexible_scan_execution_policy.yml b/ee/config/feature_flags/beta/flexible_scan_execution_policy.yml
deleted file mode 100644
index 9efe1b1203f82dcb2cd66f4124025ab8bafa3d6a..0000000000000000000000000000000000000000
--- a/ee/config/feature_flags/beta/flexible_scan_execution_policy.yml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: flexible_scan_execution_policy
-description:
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/541370
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/191015
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/541689
-milestone: '18.0'
-group: group::security policies
-type: beta
-default_enabled: true
diff --git a/ee/spec/features/groups/security/user_creates_scan_execution_policy_spec.rb b/ee/spec/features/groups/security/user_creates_scan_execution_policy_spec.rb
index f9cf08d966ca490f0493c68910926b74165a6603..ced36b03f95834b476b2e2b74b0038c0461d2c3e 100644
--- a/ee/spec/features/groups/security/user_creates_scan_execution_policy_spec.rb
+++ b/ee/spec/features/groups/security/user_creates_scan_execution_policy_spec.rb
@@ -22,7 +22,6 @@
before do
sign_in(owner)
stub_feature_flags(security_policies_split_view: false)
- stub_feature_flags(flexible_scan_execution_policy: false)
end
it_behaves_like 'creating scan execution policy with valid properties'
diff --git a/ee/spec/features/projects/security/user_creates_scan_execution_policy_spec.rb b/ee/spec/features/projects/security/user_creates_scan_execution_policy_spec.rb
index ae296453e7f60abf8a1c31b18a6bd0f1b4bd48f1..dd0017a80cb2bb9c7451865aff4b33fc620bc24a 100644
--- a/ee/spec/features/projects/security/user_creates_scan_execution_policy_spec.rb
+++ b/ee/spec/features/projects/security/user_creates_scan_execution_policy_spec.rb
@@ -18,7 +18,6 @@
before do
sign_in(owner)
stub_feature_flags(security_policies_split_view: false)
- stub_feature_flags(flexible_scan_execution_policy: false)
end
it_behaves_like 'creating scan execution policy with valid properties'
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/constants_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/constants_spec.js
index 1bef8388e7b2871264a1f489e29382f9a6339400..2d56f05d004dacb7c09b73e93bdeff5113435c3f 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/constants_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/constants_spec.js
@@ -12,96 +12,56 @@ import {
} from 'ee/security_orchestration/components/policy_editor/constants';
describe('SCAN_EXECUTION_BRANCH_TYPE_OPTIONS', () => {
- afterEach(() => {
- window.gon = { features: {} };
+ it('returns extended options for group namespace', () => {
+ expect(
+ SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({
+ namespaceType: NAMESPACE_TYPES.GROUP,
+ includeTargetTypes: true,
+ }),
+ ).toEqual([
+ ALL_BRANCHES,
+ GROUP_DEFAULT_BRANCHES,
+ ALL_PROTECTED_BRANCHES,
+ SPECIFIC_BRANCHES,
+ TARGET_PROTECTED_BRANCHES,
+ GROUP_TARGET_DEFAULT_BRANCHES,
+ ]);
});
- describe('with feature flag disabled', () => {
- beforeEach(() => {
- window.gon = { features: { flexibleScanExecutionPolicy: false } };
- });
-
- it('returns base options for group namespace', () => {
- expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ namespaceType: NAMESPACE_TYPES.GROUP })).toEqual([
- ALL_BRANCHES,
- GROUP_DEFAULT_BRANCHES,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- ]);
- });
-
- it('returns base options for project namespace', () => {
- expect(
- SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ namespaceType: NAMESPACE_TYPES.PROJECT }),
- ).toEqual([ALL_BRANCHES, PROJECT_DEFAULT_BRANCH, ALL_PROTECTED_BRANCHES, SPECIFIC_BRANCHES]);
- });
-
- it('uses group namespace by default when namespace type is not provided', () => {
- expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({})).toEqual([
- ALL_BRANCHES,
- GROUP_DEFAULT_BRANCHES,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- ]);
- });
+ it('returns extended options for project namespace', () => {
+ expect(
+ SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({
+ namespaceType: NAMESPACE_TYPES.PROJECT,
+ includeTargetTypes: true,
+ }),
+ ).toEqual([
+ ALL_BRANCHES,
+ PROJECT_DEFAULT_BRANCH,
+ ALL_PROTECTED_BRANCHES,
+ SPECIFIC_BRANCHES,
+ TARGET_PROTECTED_BRANCHES,
+ PROJECT_TARGET_DEFAULT_BRANCH,
+ ]);
});
- describe('with feature flag enabled', () => {
- beforeEach(() => {
- window.gon = { features: { flexibleScanExecutionPolicy: true } };
- });
-
- it('returns extended options for group namespace', () => {
- expect(
- SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({
- namespaceType: NAMESPACE_TYPES.GROUP,
- includeTargetTypes: true,
- }),
- ).toEqual([
- ALL_BRANCHES,
- GROUP_DEFAULT_BRANCHES,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- TARGET_PROTECTED_BRANCHES,
- GROUP_TARGET_DEFAULT_BRANCHES,
- ]);
- });
-
- it('returns extended options for project namespace', () => {
- expect(
- SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({
- namespaceType: NAMESPACE_TYPES.PROJECT,
- includeTargetTypes: true,
- }),
- ).toEqual([
- ALL_BRANCHES,
- PROJECT_DEFAULT_BRANCH,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- TARGET_PROTECTED_BRANCHES,
- PROJECT_TARGET_DEFAULT_BRANCH,
- ]);
- });
-
- it('uses group namespace by default when namespace type is not provided', () => {
- expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ includeTargetTypes: true })).toEqual([
- ALL_BRANCHES,
- GROUP_DEFAULT_BRANCHES,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- TARGET_PROTECTED_BRANCHES,
- GROUP_TARGET_DEFAULT_BRANCHES,
- ]);
- });
+ it('uses group namespace by default when namespace type is not provided', () => {
+ expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ includeTargetTypes: true })).toEqual([
+ ALL_BRANCHES,
+ GROUP_DEFAULT_BRANCHES,
+ ALL_PROTECTED_BRANCHES,
+ SPECIFIC_BRANCHES,
+ TARGET_PROTECTED_BRANCHES,
+ GROUP_TARGET_DEFAULT_BRANCHES,
+ ]);
+ });
- it('does not return target types if not specified', () => {
- expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ namespaceType: NAMESPACE_TYPES.GROUP })).toEqual([
- ALL_BRANCHES,
- GROUP_DEFAULT_BRANCHES,
- ALL_PROTECTED_BRANCHES,
- SPECIFIC_BRANCHES,
- ]);
- });
+ it('does not return target types if not specified', () => {
+ expect(SCAN_EXECUTION_BRANCH_TYPE_OPTIONS({ namespaceType: NAMESPACE_TYPES.GROUP })).toEqual([
+ ALL_BRANCHES,
+ GROUP_DEFAULT_BRANCHES,
+ ALL_PROTECTED_BRANCHES,
+ SPECIFIC_BRANCHES,
+ ]);
});
it('uses empty feature flags object by default when not provided', () => {
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/editor_component_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/editor_component_spec.js
index e977b1dffb2e93f870cf2935b1cafe3c7cbb612d..dc137306ca32c619a87c1156f9437b4f52089ae4 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/editor_component_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/editor_component_spec.js
@@ -1,6 +1,6 @@
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { GlEmptyState, GlToggle } from '@gitlab/ui';
+import { GlEmptyState, GlFormRadioGroup, GlToggle } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import EditorComponent from 'ee/security_orchestration/components/policy_editor/scan_execution/editor_component.vue';
import RuleSection from 'ee/security_orchestration/components/policy_editor/scan_execution/rule/rule_section.vue';
@@ -18,29 +18,26 @@ import {
ASSIGNED_POLICY_PROJECT,
} from 'ee_jest/security_orchestration/mocks/mock_data';
import {
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE,
buildScannerAction,
buildDefaultScheduleRule,
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES,
} from 'ee/security_orchestration/components/policy_editor/scan_execution/lib';
-import {
- DEFAULT_ASSIGNED_POLICY_PROJECT,
- NAMESPACE_TYPES,
-} from 'ee/security_orchestration/constants';
+
+import { NAMESPACE_TYPES } from 'ee/security_orchestration/constants';
import {
mockDastScanExecutionManifest,
mockDastScanExecutionObject,
mockInvalidActionScanExecutionObject,
mockInvalidRuleScanExecutionObject,
mockScheduledTemplateScanExecutionObject,
+ mockScanExecutionWithDefaultVariablesManifest,
+ mockCustomScanExecutionWithDefaultVariablesManifest,
+ mockCustomScanExecutionObject,
} from 'ee_jest/security_orchestration/mocks/mock_scan_execution_policy_data';
import {
ACTION_SECTION_DISABLE_ERROR,
CONDITION_SECTION_DISABLE_ERROR,
SECURITY_POLICY_ACTIONS,
- EDITOR_MODE_RULE,
- EDITOR_MODE_YAML,
} from 'ee/security_orchestration/components/policy_editor/constants';
import {
DEFAULT_CONDITION_STRATEGY,
@@ -50,6 +47,7 @@ import {
POLICY_ACTION_BUILDER_DAST_PROFILES_ERROR_KEY,
RUNNER_TAGS_PARSING_ERROR,
DAST_SCANNERS_PARSING_ERROR,
+ SELECTION_CONFIG_CUSTOM,
} from 'ee/security_orchestration/components/policy_editor/scan_execution/constants';
import { RULE_KEY_MAP } from 'ee/security_orchestration/components/policy_editor/scan_execution/lib/rules';
import {
@@ -92,7 +90,6 @@ describe('EditorComponent', () => {
wrapper = shallowMountExtended(EditorComponent, {
apolloProvider: createMockApolloProvider(handler),
propsData: {
- assignedPolicyProject: DEFAULT_ASSIGNED_POLICY_PROJECT,
selectedPolicyType: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
errorSources: [],
isCreating: false,
@@ -139,49 +136,73 @@ describe('EditorComponent', () => {
const findDisabledAction = () => wrapper.findByTestId('disabled-action');
const findDisabledRule = () => wrapper.findByTestId('disabled-rule');
const findSkipCiSelector = () => wrapper.findComponent(SkipCiSelector);
- const findActionBuilderDefaultConfig = () => wrapper.findByTestId('default-action-config');
- const findActionBuilderDefaultConfigRadioButton = () =>
- wrapper.findByTestId('default-action-config-radio-button');
- const findActionBuilderCustomConfig = () => wrapper.findByTestId('custom-action-config');
- const findActionBuilderCustomConfigRadioButton = () =>
- wrapper.findByTestId('default-action-config-radio-button');
const findOptimizedScanSelector = () => wrapper.findComponent(OptimizedScanSelector);
const findRuleStrategySelector = () => wrapper.findComponent(RuleStrategySelector);
const findConfigurationSelection = () => wrapper.findByTestId('configuration-selection');
+ const findRadioFormGroup = () => wrapper.findComponent(GlFormRadioGroup);
+ const findActionBuilderCustomConfig = () => wrapper.findByTestId('custom-action-config');
+ const findActionBuilderDefaultConfig = () => wrapper.findByTestId('default-action-config');
+ const findActionBuilderDefaultConfigRadioButton = () => findRadioFormGroup().props('options')[0];
const selectScheduleRule = async () => {
await findRuleSection().vm.$emit('changed', buildDefaultScheduleRule());
};
+ const navigateToCustomMode = async () => {
+ await findRadioFormGroup().vm.$emit('input', SELECTION_CONFIG_CUSTOM);
+ };
+
beforeEach(() => {
- uniqueId.mockImplementation(jest.fn((prefix) => `${prefix}0`));
+ uniqueId
+ .mockImplementationOnce(jest.fn((prefix) => `${prefix}0`))
+ .mockImplementationOnce(jest.fn((prefix) => `${prefix}1`))
+ .mockImplementationOnce(jest.fn((prefix) => `${prefix}2`));
});
describe('default', () => {
- beforeEach(() => {
- factory();
- });
describe('scope', () => {
it.each`
- namespaceType | manifest
+ namespaceType | expected
${NAMESPACE_TYPES.GROUP} | ${SCAN_EXECUTION_DEFAULT_POLICY_WITH_SCOPE}
${NAMESPACE_TYPES.PROJECT} | ${SCAN_EXECUTION_DEFAULT_POLICY}
- `('should render default policy for a $namespaceType', ({ namespaceType, manifest }) => {
+ `('renders default policy for a $namespaceType', ({ namespaceType, expected }) => {
factory({ provide: { namespaceType } });
- expect(findPolicyEditorLayout().props('policy')).toEqual(manifest);
+ expect(findPolicyEditorLayout().props('policy')).toEqual(expected);
expect(findSkipCiSelector().exists()).toBe(true);
});
});
- it('should render correctly', () => {
- expect(findDisabledAction().props()).toEqual({
- disabled: false,
- error: ACTION_SECTION_DISABLE_ERROR,
+ describe('policy', () => {
+ it('renders default and custom selections', () => {
+ factory();
+ expect(findConfigurationSelection().exists()).toBe(true);
});
- expect(findDisabledRule().props()).toEqual({
- disabled: false,
- error: CONDITION_SECTION_DISABLE_ERROR,
+
+ it('renders optimized scanner by default', () => {
+ factory();
+ expect(findRadioFormGroup().attributes('checked')).toBe('default');
+ expect(findActionBuilderDefaultConfigRadioButton().disabled).toBe(false);
+ });
+
+ it('does not show custom configuration section', () => {
+ factory();
+ expect(findActionBuilderDefaultConfig().exists()).toBe(true);
+ expect(findActionBuilderCustomConfig().exists()).toBe(false);
+ });
+
+ it('disables default configuration when the policy is incompatible', async () => {
+ factory();
+ await navigateToCustomMode();
+
+ // Add a DAST scan action, but there are many reasons the policy may be invalid for
+ // optimized scans. See the getConfiguration method in
+ // ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js
+ // for more info
+ const dastAction = { scan: 'dast' };
+ await findActionBuilder().vm.$emit('changed', dastAction);
+
+ expect(findRadioFormGroup().props('options')[0].disabled).toBe(true);
});
});
});
@@ -189,7 +210,7 @@ describe('EditorComponent', () => {
describe('modifying a policy', () => {
it.each`
status | action | event | factoryFn | yamlEditorValue
- ${'creating a new policy'} | ${undefined} | ${'save-policy'} | ${factory} | ${policyBodyToYaml(fromYaml({ manifest: DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES, type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter }))}
+ ${'creating a new policy'} | ${undefined} | ${'save-policy'} | ${factory} | ${policyBodyToYaml(fromYaml({ manifest: mockScanExecutionWithDefaultVariablesManifest, type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter }))}
${'updating an existing policy'} | ${undefined} | ${'save-policy'} | ${factoryWithExistingPolicy} | ${mockDastScanExecutionManifest}
${'deleting an existing policy'} | ${SECURITY_POLICY_ACTIONS.REMOVE} | ${'remove-policy'} | ${factoryWithExistingPolicy} | ${mockDastScanExecutionManifest}
`('emits "save" when $status', async ({ action, event, factoryFn, yamlEditorValue }) => {
@@ -201,9 +222,8 @@ describe('EditorComponent', () => {
});
describe('when a user is not an owner of the project', () => {
- it('displays the empty state with the appropriate properties', async () => {
+ it('displays the empty state with the appropriate properties', () => {
factory({ provide: { disableScanPolicyUpdate: true } });
- await nextTick();
const emptyState = findEmptyState();
expect(emptyState.props('primaryButtonLink')).toMatch(scanPolicyDocumentationPath);
@@ -215,20 +235,18 @@ describe('EditorComponent', () => {
describe('yaml mode', () => {
beforeEach(factory);
+ it('renders yaml mode properties correctly', () => {
+ expect(findPolicyEditorLayout().props()).toMatchObject({
+ parsingError: '',
+ yamlEditorValue: mockScanExecutionWithDefaultVariablesManifest,
+ });
+ });
+
it('updates the yaml and policy object when "update-yaml" is emitted', async () => {
const newManifest = `name: test
enabled: true`;
+ await findPolicyEditorLayout().vm.$emit('update-yaml', newManifest);
- expect(findPolicyEditorLayout().props()).toMatchObject({
- parsingError: '',
- policy: fromYaml({
- manifest: DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE,
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }),
- yamlEditorValue: DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES,
- });
- findPolicyEditorLayout().vm.$emit('update-yaml', newManifest);
- await nextTick();
expect(findPolicyEditorLayout().props()).toMatchObject({
parsingError: '',
policy: expect.objectContaining({ enabled: true }),
@@ -248,8 +266,7 @@ enabled: true`;
`${component}: ${oldValue}`,
);
- findPolicyEditorLayout().vm.$emit('update-property', component, newValue);
- await nextTick();
+ await findPolicyEditorLayout().vm.$emit('update-property', component, newValue);
expect(findPolicyEditorLayout().props('policy')[component]).toBe(newValue);
expect(findPolicyEditorLayout().props('yamlEditorValue')).toMatch(
@@ -281,140 +298,11 @@ enabled: true`;
uniqueId.mockRestore();
});
- it('should add new rule', async () => {
- factory();
-
- const initialValue = [RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE]()];
- expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual(initialValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toStrictEqual(initialValue);
- expect(findAllRuleSections()).toHaveLength(1);
-
- findAddRuleButton().vm.$emit('click');
- await nextTick();
-
- const finalValue = [
- RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE](),
- RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE](),
- ];
- expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual(finalValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toStrictEqual(finalValue);
- expect(findAllRuleSections()).toHaveLength(2);
- });
-
- it('should add a new rule if the rule property does not exist', async () => {
- factory({ propsData: { existingPolicy: { name: 'test' }, isEditing: true } });
- expect(findAllRuleSections()).toHaveLength(0);
- findAddRuleButton().vm.$emit('click');
- await nextTick();
- expect(findAllRuleSections()).toHaveLength(1);
- });
-
- it('should update rule', async () => {
- factory();
- const initialValue = [RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE]()];
- expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual(initialValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toStrictEqual(initialValue);
-
- const finalValue = [{ ...RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE](), branches: ['main'] }];
- findRuleSection().vm.$emit('changed', finalValue[0]);
- await nextTick();
-
- expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual(finalValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toStrictEqual(finalValue);
- });
-
- it('should remove rule', async () => {
- factory();
- findAddRuleButton().vm.$emit('click');
- await nextTick();
-
- expect(findAllRuleSections()).toHaveLength(2);
- expect(findPolicyEditorLayout().props('policy').rules).toHaveLength(2);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toHaveLength(2);
-
- findRuleSection().vm.$emit('remove', 1);
- await nextTick();
-
- expect(findAllRuleSections()).toHaveLength(1);
- expect(findPolicyEditorLayout().props('policy').rules).toHaveLength(1);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).rules,
- ).toHaveLength(1);
- });
- });
-
- describe('action builder', () => {
- const glFeatures = { flexibleScanExecutionPolicy: true };
-
- beforeEach(() => {
- uniqueId.mockRestore();
- window.gon = { features: glFeatures };
- });
-
- afterAll(() => {
- window.gon = { features: {} };
- });
-
- describe('default', () => {
- it('shows default and custom selections', () => {
- factory({
- provide: { glFeatures },
- });
- expect(findConfigurationSelection().exists()).toBe(true);
- });
-
- it('checks optimized scanner by default', () => {
- factory({
- provide: { glFeatures },
- });
- expect(findActionBuilderDefaultConfigRadioButton().props('checked')).toBe('default');
- expect(findActionBuilderDefaultConfigRadioButton().attributes().disabled).toBe(undefined);
- });
- });
-
describe('default configuration', () => {
- it('does not show custom configuration section', () => {
- factory({
- provide: { glFeatures },
- });
- expect(findActionBuilderDefaultConfig().exists()).toBe(true);
- expect(findActionBuilderCustomConfig().exists()).toBe(false);
- });
-
describe('rule strategy selector', () => {
it('updates the rules when a change is emitted', async () => {
const rules = [{ branch_type: 'all' }];
- factory({
- provide: { glFeatures },
- });
+ factory();
expect(findRuleStrategySelector().props('strategy')).toBe(DEFAULT_CONDITION_STRATEGY);
await findRuleStrategySelector().vm.$emit('changed', {
strategy: 'any',
@@ -425,19 +313,95 @@ enabled: true`;
});
it('selects the pre-defined strategy for an existing policy', () => {
- factoryWithExistingPolicy({
- provide: { glFeatures },
- policy: mockScheduledTemplateScanExecutionObject,
- });
+ factoryWithExistingPolicy({ policy: mockScheduledTemplateScanExecutionObject });
expect(findRuleStrategySelector().props('strategy')).toBe('scheduled');
});
});
+ });
+
+ describe('custom configuration', () => {
+ it('should add new rule', async () => {
+ factory();
+ await navigateToCustomMode();
+ await findAddRuleButton().vm.$emit('click');
+
+ expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual([
+ { branch_type: 'default', id: undefined, type: 'pipeline' },
+ {
+ branch_type: 'target_default',
+ id: undefined,
+ pipeline_sources: { including: ['merge_request_event'] },
+ type: 'pipeline',
+ },
+ { branches: ['*'], id: undefined, type: 'pipeline' },
+ ]);
+ expect(findAllRuleSections()).toHaveLength(3);
+ });
+
+ it('should add a new rule if there are zero rules', async () => {
+ await factory({
+ propsData: { existingPolicy: { name: 'test', rules: [] }, isEditing: true },
+ });
+ expect(findAllRuleSections()).toHaveLength(0);
+ await findAddRuleButton().vm.$emit('click');
+ expect(findAllRuleSections()).toHaveLength(1);
+ });
+
+ it('should update rule', async () => {
+ factory();
+ await navigateToCustomMode();
+ await findRuleSection().vm.$emit('changed', {
+ ...RULE_KEY_MAP[SCAN_EXECUTION_PIPELINE_RULE](),
+ branches: ['main'],
+ });
+ expect(findPolicyEditorLayout().props('policy').rules).toStrictEqual([
+ { branches: ['main'], id: undefined, type: 'pipeline' },
+ {
+ branch_type: 'target_default',
+ id: undefined,
+ pipeline_sources: { including: ['merge_request_event'] },
+ type: 'pipeline',
+ },
+ ]);
+ });
+ it('should remove rule', async () => {
+ factory();
+ await navigateToCustomMode();
+ await findAddRuleButton().vm.$emit('click');
+
+ expect(findAllRuleSections()).toHaveLength(3);
+ expect(findPolicyEditorLayout().props('policy').rules).toHaveLength(3);
+ expect(
+ fromYaml({
+ manifest: findPolicyEditorLayout().props('yamlEditorValue'),
+ type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
+ }).rules,
+ ).toHaveLength(3);
+
+ await findRuleSection().vm.$emit('remove', 1);
+
+ expect(findAllRuleSections()).toHaveLength(2);
+ expect(findPolicyEditorLayout().props('policy').rules).toHaveLength(2);
+ expect(
+ fromYaml({
+ manifest: findPolicyEditorLayout().props('yamlEditorValue'),
+ type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
+ }).rules,
+ ).toHaveLength(2);
+ });
+ });
+ });
+
+ describe('action builder', () => {
+ beforeEach(() => {
+ uniqueId.mockRestore();
+ });
+
+ describe('default configuration', () => {
describe('optimized scan selector', () => {
it('renders optimized scan selector', () => {
- factory({
- provide: { glFeatures },
- });
+ factory();
expect(findOptimizedScanSelector().exists()).toBe(true);
expect(findOptimizedScanSelector().props()).toEqual({
disabled: false,
@@ -446,9 +410,7 @@ enabled: true`;
});
it('adds new action when selected', async () => {
- factory({
- provide: { glFeatures },
- });
+ factory();
await findOptimizedScanSelector().vm.$emit('change', {
scanner: 'sast',
enabled: true,
@@ -471,9 +433,7 @@ enabled: true`;
});
it('removes action when deselected', async () => {
- factory({
- provide: { glFeatures },
- });
+ factory();
await findOptimizedScanSelector().vm.$emit('change', {
scanner: 'secret_detection',
enabled: false,
@@ -486,29 +446,6 @@ enabled: true`;
}).actions,
).toStrictEqual([]);
});
-
- it('is disabled when the policy is incompatible', async () => {
- factory({
- provide: { glFeatures },
- });
-
- // Switch to custom config first
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
-
- // Add a DAST scan action, but there are many reasons the policy may be invalid for
- // optimized scans. See the getConfiguration method in
- // ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/lib/index.js
- // for more info
- const dastAction = { scan: 'dast' };
- findActionBuilder().vm.$emit('changed', dastAction);
- await nextTick();
-
- // Switch to YAML mode and back to rule mode to trigger recalculation
- await findPolicyEditorLayout().vm.$emit('editor-mode-changed', EDITOR_MODE_YAML);
- await findPolicyEditorLayout().vm.$emit('editor-mode-changed', EDITOR_MODE_RULE);
-
- expect(findActionBuilderDefaultConfigRadioButton().attributes().disabled).toBe('true');
- });
});
});
@@ -521,17 +458,15 @@ enabled: true`;
},
];
it('does not show default configuration section', async () => {
- factory({
- provide: { glFeatures },
- });
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
+ factory();
+ await navigateToCustomMode();
expect(findActionBuilderDefaultConfig().exists()).toBe(false);
expect(findActionBuilderCustomConfig().exists()).toBe(true);
});
it('adds new action', async () => {
- factory({ provide: { glFeatures } });
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
+ factory();
+ await navigateToCustomMode();
expect(findPolicyEditorLayout().props('policy').actions).toEqual(
expect.objectContaining(newActions),
@@ -543,8 +478,7 @@ enabled: true`;
}).actions,
).toEqual(expect.objectContaining(newActions));
- findAddActionButton().vm.$emit('click');
- await nextTick();
+ await findAddActionButton().vm.$emit('click');
const finalValue = [
buildScannerAction({
@@ -567,22 +501,20 @@ enabled: true`;
it('adds a new action if the action property does not exist', async () => {
factory({
propsData: { existingPolicy: { name: 'test' }, isEditing: true },
- provide: { glFeatures },
});
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
+ await navigateToCustomMode();
expect(findAllActionBuilders()).toHaveLength(0);
- findAddActionButton().vm.$emit('click');
- await nextTick();
+ await findAddActionButton().vm.$emit('click');
expect(findAddActionButtonWrapper().attributes('title')).toBe('');
expect(findAllActionBuilders()).toHaveLength(1);
});
it('updates action', async () => {
- factory({ provide: { glFeatures } });
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
+ factory();
+ await navigateToCustomMode();
const initialValue = [
buildScannerAction({
@@ -604,8 +536,7 @@ enabled: true`;
).toEqual(expect.objectContaining(newActions));
const finalValue = [buildScannerAction({ scanner: 'sast', withDefaultVariables: true })];
- findActionBuilder().vm.$emit('changed', finalValue[0]);
- await nextTick();
+ await findActionBuilder().vm.$emit('changed', finalValue[0]);
expect(findPolicyEditorLayout().props('policy').actions).toStrictEqual(finalValue);
expect(
@@ -617,10 +548,9 @@ enabled: true`;
});
it('removes action', async () => {
- factory({ provide: { glFeatures } });
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
- findAddActionButton().vm.$emit('click');
- await nextTick();
+ factory();
+ await navigateToCustomMode();
+ await findAddActionButton().vm.$emit('click');
expect(findAllActionBuilders()).toHaveLength(2);
expect(findPolicyEditorLayout().props('policy').actions).toHaveLength(2);
@@ -631,8 +561,7 @@ enabled: true`;
}).actions,
).toHaveLength(2);
- findActionBuilder().vm.$emit('remove', 1);
- await nextTick();
+ await findActionBuilder().vm.$emit('remove', 1);
expect(findAllActionBuilders()).toHaveLength(1);
expect(findPolicyEditorLayout().props('policy').actions).toHaveLength(1);
@@ -646,13 +575,8 @@ enabled: true`;
it('limits number of actions', async () => {
const MAX_ACTIONS = 3;
- factory({
- provide: {
- maxScanExecutionPolicyActions: MAX_ACTIONS,
- glFeatures,
- },
- });
- await findActionBuilderCustomConfigRadioButton().vm.$emit('input');
+ factory({ provide: { maxScanExecutionPolicyActions: MAX_ACTIONS } });
+ await navigateToCustomMode();
expect(findAddActionButton().attributes().disabled).toBeUndefined();
expect(findAllActionBuilders()).toHaveLength(1);
@@ -670,130 +594,6 @@ enabled: true`;
});
});
- describe('action builder without flexibleScanExecutionPolicy feature flag', () => {
- beforeEach(() => {
- uniqueId.mockRestore();
- });
-
- it('does not show configuration selection', () => {
- factory();
- expect(findConfigurationSelection().exists()).toBe(false);
- });
-
- it('should add new action', async () => {
- factory();
- const initialValue = [
- buildScannerAction({ scanner: DEFAULT_SCANNER, withDefaultVariables: true }),
- ];
- expect(findPolicyEditorLayout().props('policy').actions).toStrictEqual(initialValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toStrictEqual(initialValue);
-
- findAddActionButton().vm.$emit('click');
- await nextTick();
-
- const finalValue = [
- buildScannerAction({ scanner: DEFAULT_SCANNER, withDefaultVariables: true }),
- buildScannerAction({ scanner: DEFAULT_SCANNER, withDefaultVariables: true }),
- ];
-
- expect(findPolicyEditorLayout().props('policy').actions).toStrictEqual(finalValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toStrictEqual(finalValue);
- });
-
- it('should add a new action if the action property does not exist', async () => {
- factory({ propsData: { existingPolicy: { name: 'test' }, isEditing: true } });
- expect(findAllActionBuilders()).toHaveLength(0);
- findAddActionButton().vm.$emit('click');
- await nextTick();
- expect(findAddActionButtonWrapper().attributes('title')).toBe('');
- expect(findAllActionBuilders()).toHaveLength(1);
- });
-
- it('should update action', async () => {
- factory();
- const initialValue = [
- buildScannerAction({ scanner: DEFAULT_SCANNER, withDefaultVariables: true }),
- ];
- expect(findPolicyEditorLayout().props('policy').actions).toStrictEqual(initialValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toStrictEqual(initialValue);
-
- const finalValue = [buildScannerAction({ scanner: 'sast', withDefaultVariables: true })];
- findActionBuilder().vm.$emit('changed', finalValue[0]);
- await nextTick();
-
- expect(findPolicyEditorLayout().props('policy').actions).toStrictEqual(finalValue);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toStrictEqual(finalValue);
- });
-
- it('should remove action', async () => {
- factory();
- findAddActionButton().vm.$emit('click');
- await nextTick();
-
- expect(findAllActionBuilders()).toHaveLength(2);
- expect(findPolicyEditorLayout().props('policy').actions).toHaveLength(2);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toHaveLength(2);
-
- findActionBuilder().vm.$emit('remove', 1);
- await nextTick();
-
- expect(findAllActionBuilders()).toHaveLength(1);
- expect(findPolicyEditorLayout().props('policy').actions).toHaveLength(1);
- expect(
- fromYaml({
- manifest: findPolicyEditorLayout().props('yamlEditorValue'),
- type: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.urlParameter,
- }).actions,
- ).toHaveLength(1);
- });
-
- it('should limit number of actions', async () => {
- factory({
- provide: {
- maxScanExecutionPolicyActions: 3,
- },
- });
-
- expect(findAddActionButton().attributes().disabled).toBeUndefined();
- expect(findAllActionBuilders()).toHaveLength(1);
-
- await findAddActionButton().vm.$emit('click');
- await findAddActionButton().vm.$emit('click');
- await findAddActionButton().vm.$emit('click');
-
- expect(findAddActionButton().attributes().disabled).toBe('true');
- expect(findAddActionButtonWrapper().attributes('title')).toBe(
- 'Policy has reached the maximum of 3 actions',
- );
- expect(findAllActionBuilders()).toHaveLength(3);
- });
- });
-
describe('parsing errors', () => {
it.each`
name | errorKey | error
@@ -801,8 +601,8 @@ enabled: true`;
${'DAST profiles'} | ${POLICY_ACTION_BUILDER_DAST_PROFILES_ERROR_KEY} | ${DAST_SCANNERS_PARSING_ERROR}
`('disables action section when parsing of $name fails', async ({ errorKey, error }) => {
factory();
- findActionBuilder().vm.$emit('parsing-error', errorKey);
- await nextTick();
+ await navigateToCustomMode();
+ await findActionBuilder().vm.$emit('parsing-error', errorKey);
expect(findDisabledAction().props()).toEqual({ disabled: true, error });
expect(findDisabledRule().props()).toEqual({
disabled: false,
@@ -832,8 +632,7 @@ enabled: true`;
disabled: true,
error: CONDITION_SECTION_DISABLE_ERROR,
});
- findActionBuilder().vm.$emit('parsing-error', POLICY_ACTION_BUILDER_TAGS_ERROR_KEY);
- await nextTick();
+ await findActionBuilder().vm.$emit('parsing-error', POLICY_ACTION_BUILDER_TAGS_ERROR_KEY);
expect(findDisabledRule().props()).toEqual({
disabled: true,
error: CONDITION_SECTION_DISABLE_ERROR,
@@ -844,8 +643,9 @@ enabled: true`;
describe('performance warning modal', () => {
describe('group', () => {
describe('performance threshold not reached', () => {
- beforeEach(() => {
+ beforeEach(async () => {
factory();
+ await navigateToCustomMode();
});
it('saves policy when performance threshold is not reached', async () => {
@@ -887,6 +687,7 @@ enabled: true`;
});
await waitForPromises();
+ await navigateToCustomMode();
});
it('shows the warning when performance threshold is reached but schedule rules were selected', async () => {
@@ -993,6 +794,7 @@ enabled: true`;
});
await waitForPromises();
+ await navigateToCustomMode();
});
it('does not show the warning when performance threshold is reached but schedule rules were selected for a project', async () => {
@@ -1036,33 +838,24 @@ enabled: true`;
});
it('renders existing default skip ci configuration when it is removed from yaml', async () => {
- factoryWithExistingPolicy({
- policy: {
- skip_ci: skipCi,
- },
- });
+ factoryWithExistingPolicy({ policy: { skip_ci: skipCi } });
expect(findSkipCiSelector().props('skipCiConfiguration')).toEqual(skipCi);
await findPolicyEditorLayout().vm.$emit('update-yaml', mockDastScanExecutionManifest);
-
- expect(findSkipCiSelector().findComponent(GlToggle).props('value')).toBe(
- !DEFAULT_SKIP_SI_CONFIGURATION.allowed,
- );
+ expect(findSkipCiSelector().props('skipCiConfiguration')).toBe(undefined);
});
});
describe('new yaml format with type as a wrapper', () => {
- beforeEach(() => {
- factory();
- });
-
it('renders default yaml in new format', () => {
+ factoryWithExistingPolicy({ policy: mockCustomScanExecutionObject });
expect(findPolicyEditorLayout().props('yamlEditorValue')).toBe(
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES,
+ mockCustomScanExecutionWithDefaultVariablesManifest,
);
});
it('converts new policy format to old policy format when saved', async () => {
+ factory();
findPolicyEditorLayout().vm.$emit('save-policy');
await waitForPromises();
@@ -1078,10 +871,15 @@ policy_scope:
excluding: []
rules:
- type: pipeline
- branches:
- - '*'
+ branch_type: default
+ - type: pipeline
+ branch_type: target_default
+ pipeline_sources:
+ including:
+ - merge_request_event
actions:
- scan: secret_detection
+ template: latest
variables:
SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
skip_ci:
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/actions_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/actions_spec.js
index b6b56b5e1879b22fbb17715a62776fa67520618a..858e58063487ab06d4ac0b75fdc4314535fbc2c5 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/actions_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/actions_spec.js
@@ -14,9 +14,9 @@ import {
REPORT_TYPE_API_FUZZING,
} from '~/vue_shared/security_reports/constants';
import {
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE,
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES,
-} from 'ee/security_orchestration/components/policy_editor/scan_execution/lib';
+ mockCustomScanExecutionManifest,
+ mockCustomScanExecutionWithDefaultVariablesManifest,
+} from 'ee_jest/security_orchestration/mocks/mock_scan_execution_policy_data';
const actionId = 'action_0';
jest.mock('lodash/uniqueId', () => jest.fn().mockReturnValue(actionId));
@@ -93,8 +93,10 @@ describe('addDefaultVariablesToPolicy', () => {
describe('addDefaultVariablesToManifest', () => {
it('adds default variable to a policy manifest with specific scanners', () => {
expect(
- addDefaultVariablesToManifest({ manifest: DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE }),
- ).toBe(DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_WITH_DEFAULT_VARIABLES);
+ addDefaultVariablesToManifest({
+ manifest: mockCustomScanExecutionManifest,
+ }),
+ ).toBe(mockCustomScanExecutionWithDefaultVariablesManifest);
});
});
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/index_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/index_spec.js
index 1d81c96a34046388cf15c1079c2e3395f6093462..5715d31c7e3c3a2457032840bc66881247ec60ce 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/index_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/lib/index_spec.js
@@ -2,8 +2,6 @@ import { REPORT_TYPE_DAST } from '~/vue_shared/security_reports/constants';
import {
DEFAULT_SCAN_EXECUTION_POLICY,
DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE,
- DEFAULT_SCAN_EXECUTION_POLICY_OPTIMIZED,
- DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_OPTIMIZED,
STRATEGIES_RULE_MAP,
getPolicyYaml,
getConfiguration,
@@ -17,43 +15,12 @@ import {
} from 'ee/security_orchestration/components/policy_editor/scan_execution/constants';
describe('getPolicyYaml', () => {
- let originalGon;
-
- beforeEach(() => {
- originalGon = window.gon;
- window.gon = { features: {} };
- });
-
- afterEach(() => {
- window.gon = originalGon;
- });
-
- describe('with feature flag disabled', () => {
- beforeEach(() => {
- window.gon.features = { flexibleScanExecutionPolicy: false };
- });
-
- it.each`
- namespaceType | expected
- ${NAMESPACE_TYPES.PROJECT} | ${DEFAULT_SCAN_EXECUTION_POLICY}
- ${NAMESPACE_TYPES.GROUP} | ${DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE}
- `('returns the standard yaml for $namespaceType namespace', ({ namespaceType, expected }) => {
- expect(getPolicyYaml({ isGroup: isGroup(namespaceType) })).toEqual(expected);
- });
- });
-
- describe('with feature flag enabled', () => {
- beforeEach(() => {
- window.gon.features = { flexibleScanExecutionPolicy: true };
- });
-
- it.each`
- namespaceType | expected
- ${NAMESPACE_TYPES.PROJECT} | ${DEFAULT_SCAN_EXECUTION_POLICY_OPTIMIZED}
- ${NAMESPACE_TYPES.GROUP} | ${DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE_OPTIMIZED}
- `('returns the optimized yaml for $namespaceType namespace', ({ namespaceType, expected }) => {
- expect(getPolicyYaml({ isGroup: isGroup(namespaceType) })).toEqual(expected);
- });
+ it.each`
+ namespaceType | expected
+ ${NAMESPACE_TYPES.PROJECT} | ${DEFAULT_SCAN_EXECUTION_POLICY}
+ ${NAMESPACE_TYPES.GROUP} | ${DEFAULT_SCAN_EXECUTION_POLICY_WITH_SCOPE}
+ `('returns the optimized yaml for $namespaceType namespace', ({ namespaceType, expected }) => {
+ expect(getPolicyYaml({ isGroup: isGroup(namespaceType) })).toEqual(expected);
});
});
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component_spec.js
index 263f608395d73d49ce8fe38b46198ae41067056e..72bef7a4ec0cb65376fa6e141699a5efefb01659 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component_spec.js
@@ -294,7 +294,6 @@ describe('BaseRuleComponent', () => {
branch_type: ALL_PROTECTED_BRANCHES,
},
},
- provide: { glFeatures: { flexibleScanExecutionPolicy: true } },
});
expect(findPipelineSourceSelector().exists()).toBe(true);
@@ -312,7 +311,6 @@ describe('BaseRuleComponent', () => {
branch_type: TARGET_DEFAULT,
},
},
- provide: { glFeatures: { flexibleScanExecutionPolicy: true } },
});
expect(findPipelineSourceSelector().exists()).toBe(true);
@@ -332,7 +330,6 @@ describe('BaseRuleComponent', () => {
branch_type: TARGET_DEFAULT,
},
},
- provide: { glFeatures: { flexibleScanExecutionPolicy: true } },
});
const pipelineSources = { pipeline_sources: { including: ['web', 'api'] } };
await findPipelineSourceSelector().vm.$emit('select', pipelineSources);
@@ -350,27 +347,10 @@ describe('BaseRuleComponent', () => {
props: {
initRule: { ...pipelineRule, pipeline_sources: { including: ['api'] } },
},
- provide: { glFeatures: { flexibleScanExecutionPolicy: true } },
});
findPipelineSourceSelector().vm.$emit('remove');
expect(wrapper.emitted('changed')).toEqual([[{ ...pipelineRule }]]);
});
});
-
- describe('with feature flag disabled', () => {
- it('does not show when feature flag is disabled', () => {
- createComponent({
- props: {
- initRule: {
- type: SCAN_EXECUTION_RULES_PIPELINE_KEY,
- branch_type: TARGET_DEFAULT,
- },
- },
- provide: { glFeatures: { flexibleScanExecutionPolicy: false } },
- });
-
- expect(findPipelineSourceSelector().exists()).toBe(false);
- });
- });
});
});
diff --git a/ee/spec/frontend/security_orchestration/components/utils_spec.js b/ee/spec/frontend/security_orchestration/components/utils_spec.js
index c380ab3a388586fc20a029bebdc5485189546950..373f8a3bb815f6c3319ac94937ad9586105d8412 100644
--- a/ee/spec/frontend/security_orchestration/components/utils_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/utils_spec.js
@@ -312,11 +312,18 @@ describe('checkForPerformanceRisk', () => {
describe('extractPolicyContent', () => {
const defaultPayload = {};
const extractedPolicyContent = {
- actions: [{ scan: 'secret_detection' }],
+ actions: [{ scan: 'secret_detection', template: 'latest' }],
description: '',
enabled: true,
name: '',
- rules: [{ branches: ['*'], type: 'pipeline' }],
+ rules: [
+ { branch_type: 'default', type: 'pipeline' },
+ {
+ branch_type: 'target_default',
+ pipeline_sources: { including: ['merge_request_event'] },
+ type: 'pipeline',
+ },
+ ],
skip_ci: {
allowed: true,
},
diff --git a/ee/spec/frontend/security_orchestration/mocks/mock_data.js b/ee/spec/frontend/security_orchestration/mocks/mock_data.js
index f6f0571ef7e3abb95164404af3f6a4241e1bdb25..83e7ada49e9108fd5fa3c4fab67371ad28836116 100644
--- a/ee/spec/frontend/security_orchestration/mocks/mock_data.js
+++ b/ee/spec/frontend/security_orchestration/mocks/mock_data.js
@@ -95,14 +95,23 @@ export const SCAN_EXECUTION_DEFAULT_POLICY = {
name: '',
description: '',
enabled: true,
- rules: [{ type: 'pipeline', branches: ['*'], id: 'rule_0' }],
actions: [
{
- scan: 'secret_detection',
id: 'action_0',
+ scan: 'secret_detection',
+ template: 'latest',
variables: { SECURE_ENABLE_LOCAL_CONFIGURATION: 'false' },
},
],
+ rules: [
+ { type: 'pipeline', branch_type: 'default', id: 'rule_1' },
+ {
+ id: 'rule_2',
+ type: 'pipeline',
+ branch_type: 'target_default',
+ pipeline_sources: { including: ['merge_request_event'] },
+ },
+ ],
skip_ci: DEFAULT_SKIP_SI_CONFIGURATION,
};
diff --git a/ee/spec/frontend/security_orchestration/mocks/mock_scan_execution_policy_data.js b/ee/spec/frontend/security_orchestration/mocks/mock_scan_execution_policy_data.js
index 69b53058d51675ef4a8b1c1a22eb36026da5813f..c10fd7b5fda8a9dfa7358e1d22f10e12c54d084e 100644
--- a/ee/spec/frontend/security_orchestration/mocks/mock_scan_execution_policy_data.js
+++ b/ee/spec/frontend/security_orchestration/mocks/mock_scan_execution_policy_data.js
@@ -57,6 +57,70 @@ export const mockScanExecutionWithConfigurationManifest = `scan_execution_policy
allowed: true
`;
+export const mockCustomScanExecutionManifest = `scan_execution_policy:
+ - name: ''
+ description: ''
+ enabled: true
+ rules:
+ - type: pipeline
+ branches:
+ - '*'
+ actions:
+ - scan: secret_detection
+ skip_ci:
+ allowed: true
+`;
+
+export const mockCustomScanExecutionObject = {
+ type: 'scan_execution_policy',
+ name: '',
+ description: '',
+ enabled: true,
+ rules: [{ type: 'pipeline', branches: ['*'] }],
+ actions: [{ scan: 'secret_detection' }],
+ skip_ci: { allowed: true },
+};
+
+export const mockCustomScanExecutionWithDefaultVariablesManifest = `scan_execution_policy:
+ - name: ''
+ description: ''
+ enabled: true
+ rules:
+ - type: pipeline
+ branches:
+ - '*'
+ actions:
+ - scan: secret_detection
+ variables:
+ SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
+ skip_ci:
+ allowed: true
+`;
+
+export const mockScanExecutionWithDefaultVariablesManifest = `scan_execution_policy:
+ - name: ''
+ description: ''
+ enabled: true
+ policy_scope:
+ projects:
+ excluding: []
+ rules:
+ - type: pipeline
+ branch_type: default
+ - type: pipeline
+ branch_type: target_default
+ pipeline_sources:
+ including:
+ - merge_request_event
+ actions:
+ - scan: secret_detection
+ template: latest
+ variables:
+ SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
+ skip_ci:
+ allowed: true
+`;
+
export const mockScheduleScanExecutionManifest = defaultMockScanExecutionManifest.concat(`
rules:
- type: schedule
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/mocks/mocks.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/mocks/mocks.js
index 269b9ae9a32e24ea19b84ecd1a25dcee4c3b810a..2ffb15a58168ef5c97c94d6f90d17ae75a6a95e1 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/mocks/mocks.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/mocks/mocks.js
@@ -35,3 +35,23 @@ export const DEFAULT_PROVIDE = {
export const SCAN_EXECUTION_POLICY = 'scan_execution_policy';
export const PIPELINE_EXECUTION_POLICY = 'pipeline_execution_policy';
export const APPROVAL_POLICY = 'approval_policy';
+
+export const SCAN_EXECUTION_DEFAULT = {
+ rules: ` rules:
+ - type: pipeline
+ branch_type: default
+ - type: pipeline
+ branch_type: target_default
+ pipeline_sources:
+ including:
+ - merge_request_event`,
+
+ actions: ` actions:
+ - scan: secret_detection
+ template: latest
+ variables:
+ SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'`,
+
+ skip: ` skip_ci:
+ allowed: true`,
+};
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/policy_scope/mocks.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/policy_scope/mocks.js
index 5eb80844275ca2e141ba8e43e1d1f8254ccbcdb7..307bd16ec24af6714d76e76c4ee7e3ac98ed845a 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/policy_scope/mocks.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/policy_scope/mocks.js
@@ -1,3 +1,5 @@
+import { SCAN_EXECUTION_DEFAULT } from '../mocks/mocks';
+
export const mockScanExecutionActionManifest = `scan_execution_policy:
- name: ''
description: ''
@@ -6,32 +8,18 @@ export const mockScanExecutionActionManifest = `scan_execution_policy:
compliance_frameworks:
- id: 1
- id: 2
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`;
export const mockScanExecutionActionProjectManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
policy_scope:
compliance_frameworks:
- id: 1
@@ -120,16 +108,9 @@ export const EXCLUDING_PROJECTS_MOCKS = {
excluding:
- id: 1
- id: 2
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`,
PIPELINE_EXECUTION: `name: ''
description: ''
@@ -179,16 +160,9 @@ export const EXCLUDING_PROJECTS_PROJECTS_LEVEL_MOCKS = {
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
policy_scope:
projects:
excluding:
@@ -268,16 +242,9 @@ export const INCLUDING_GROUPS_WITH_EXCEPTIONS_MOCKS = {
- id: 2
projects:
excluding: []
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`,
PIPELINE_EXECUTION: `pipeline_execution_policy:
- name: ''
@@ -343,16 +310,9 @@ export const INCLUDING_GROUPS_MOCKS = {
- id: 2
projects:
excluding: []
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`,
PIPELINE_EXECUTION: `pipeline_execution_policy:
- name: ''
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/actions_spec.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/actions_spec.js
index 016905b69d81465f6074b6fceed1c33a0a5f3344..65c15af2a17e06237c0a70ca77a610469423043a 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/actions_spec.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/actions_spec.js
@@ -1,5 +1,5 @@
-import { mountExtended } from 'helpers/vue_test_utils_helper';
import * as urlUtils from '~/lib/utils/url_utility';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import App from 'ee/security_orchestration/components/policy_editor/app.vue';
import GroupDastProfileSelector from 'ee/security_orchestration/components/policy_editor/scan_execution/action/scan_filters/group_dast_profile_selector.vue';
import ProjectDastProfileSelector from 'ee/security_orchestration/components/policy_editor/scan_execution/action/scan_filters/project_dast_profile_selector.vue';
@@ -16,7 +16,7 @@ import {
REPORT_TYPE_SECRET_DETECTION,
} from '~/vue_shared/security_reports/constants';
import { DEFAULT_PROVIDE } from '../mocks/mocks';
-import { verify } from '../utils';
+import { navigateToCustomMode, verify } from '../utils';
import {
createScanActionScanExecutionManifest,
mockDastActionScanExecutionManifest,
@@ -53,36 +53,17 @@ describe('Scan execution policy actions', () => {
});
const findCiVariablesSelectors = () => wrapper.findComponent(CiVariablesSelectors);
- const findScanTypeSelector = () => wrapper.findByTestId('scan-type-selector');
+ const findDisabledActionSection = () => wrapper.findByTestId('disabled-action');
const findGroupDastProfileSelector = () => wrapper.findComponent(GroupDastProfileSelector);
const findProjectDastProfileSelector = () => wrapper.findComponent(ProjectDastProfileSelector);
const findRunnerTagsList = () => wrapper.findComponent(RunnerTagsList);
const findScanFilterButton = () => wrapper.findByTestId('add-variable-button');
- const findDisabledActionSection = () => wrapper.findByTestId('disabled-action');
-
- describe('secret detection', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('selects secret detection scan as action', async () => {
- const verifyRuleMode = () => {
- expect(findScanTypeSelector().exists()).toBe(true);
- expect(findRunnerTagsList().exists()).toBe(true);
- expect(findDisabledActionSection().props('disabled')).toBe(false);
- };
-
- await verify({
- manifest: createScanActionScanExecutionManifest(REPORT_TYPE_SECRET_DETECTION),
- verifyRuleMode,
- wrapper,
- });
- });
- });
+ const findScanTypeSelector = () => wrapper.findByTestId('scan-type-selector');
- describe('non dast scanners', () => {
- beforeEach(() => {
- createWrapper();
+ describe('non-dast scanners', () => {
+ beforeEach(async () => {
+ await createWrapper();
+ await navigateToCustomMode(wrapper);
});
it.each`
@@ -115,7 +96,8 @@ describe('Scan execution policy actions', () => {
`(
'selects secret detection dast as action',
async ({ namespaceType, findDastSelector, manifest }) => {
- createWrapper({ provide: { namespaceType } });
+ await createWrapper({ provide: { namespaceType } });
+ await navigateToCustomMode(wrapper);
const verifyRuleMode = () => {
expect(findScanTypeSelector().exists()).toBe(true);
@@ -132,8 +114,9 @@ describe('Scan execution policy actions', () => {
});
describe('actions filters', () => {
- beforeEach(() => {
- createWrapper();
+ beforeEach(async () => {
+ await createWrapper();
+ await navigateToCustomMode(wrapper);
});
it('selects variables filter', async () => {
@@ -144,7 +127,9 @@ describe('Scan execution policy actions', () => {
expect(findDisabledActionSection().props('disabled')).toBe(false);
};
+ await findScanTypeSelector().vm.$emit('select', REPORT_TYPE_SECRET_DETECTION);
await findScanFilterButton().vm.$emit('click');
+ await findCiVariablesSelectors().vm.$emit('input', { variables: { a: 'b' } });
await verify({
manifest: mockActionsVariablesScanExecutionManifest,
verifyRuleMode,
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/mocks.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/mocks.js
index b952cd27403488d9040f389f25dd83728a55a537..596db278be4c4d1755a772787fa97348882565fc 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/mocks.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/mocks.js
@@ -1,52 +1,42 @@
import { POLICY_TYPE_COMPONENT_OPTIONS } from 'ee/security_orchestration/components/constants';
import { fromYaml } from 'ee/security_orchestration/components/utils';
+import { SCAN_EXECUTION_DEFAULT } from '../mocks/mocks';
export const mockScanExecutionManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`;
-const mockScanExecutionManifestParsed = `scan_execution_policy:
+export const mockAllBranchesScanExecutionManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
rules:
- type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+ branch_type: all
+ - type: pipeline
+ branch_type: target_default
+ pipeline_sources:
+ including:
+ - merge_request_event
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`;
export const mockDastActionScanExecutionManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
+${SCAN_EXECUTION_DEFAULT.rules}
actions:
- scan: dast
site_profile: ''
scanner_profile: ''
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.skip}
`;
export const mockGroupDastActionScanExecutionManifest = `scan_execution_policy:
@@ -56,38 +46,31 @@ export const mockGroupDastActionScanExecutionManifest = `scan_execution_policy:
policy_scope:
projects:
excluding: []
- rules:
- - type: pipeline
- branches:
- - '*'
+${SCAN_EXECUTION_DEFAULT.rules}
actions:
- scan: dast
site_profile: ''
scanner_profile: ''
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.skip}
`;
export const mockActionsVariablesScanExecutionManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
+${SCAN_EXECUTION_DEFAULT.rules}
actions:
- scan: secret_detection
variables:
+ a: b
SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- '': ''
- skip_ci:
- allowed: true
+${SCAN_EXECUTION_DEFAULT.skip}
`;
-export const createScanActionScanExecutionManifest = (scanType, parsed = false) => {
- const parser = parsed ? mockScanExecutionManifestParsed : mockScanExecutionManifest;
- return parser.replace('scan: secret_detection', `scan: ${scanType}`);
+export const createScanActionScanExecutionManifest = (scanType) => {
+ return mockScanExecutionManifest
+ .replace('scan: secret_detection', `scan: ${scanType}`)
+ .replace('\n template: latest', '');
};
export const mockScheduleScanExecutionManifest = `scan_execution_policy:
@@ -98,26 +81,21 @@ export const mockScheduleScanExecutionManifest = `scan_execution_policy:
- type: schedule
branches: []
cadence: 0 0 * * *
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
- skip_ci:
- allowed: true
+ - type: pipeline
+ branch_type: target_default
+ pipeline_sources:
+ including:
+ - merge_request_event
+${SCAN_EXECUTION_DEFAULT.actions}
+${SCAN_EXECUTION_DEFAULT.skip}
`;
export const mockSkipCiScanExecutionManifest = `scan_execution_policy:
- name: ''
description: ''
enabled: true
- rules:
- - type: pipeline
- branches:
- - '*'
- actions:
- - scan: secret_detection
- variables:
- SECURE_ENABLE_LOCAL_CONFIGURATION: 'false'
+${SCAN_EXECUTION_DEFAULT.rules}
+${SCAN_EXECUTION_DEFAULT.actions}
skip_ci:
allowed: false
`;
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/rules_spec.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/rules_spec.js
index fc35b1c295b56d483af769309c13d7360c791d51..f74b4ee35410d9384e1d9102647e793fbe01512a 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/rules_spec.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/rules_spec.js
@@ -5,9 +5,10 @@ import { DEFAULT_ASSIGNED_POLICY_PROJECT } from 'ee/security_orchestration/const
import BaseRuleComponent from 'ee/security_orchestration/components/policy_editor/scan_execution/rule/base_rule_component.vue';
import ScheduleRuleComponent from 'ee/security_orchestration/components/policy_editor/scan_execution/rule/schedule_rule_component.vue';
import { SCAN_EXECUTION_SCHEDULE_RULE } from 'ee/security_orchestration/components/policy_editor/scan_execution/constants';
+import BranchTypeSelector from 'ee/security_orchestration/components/policy_editor/scan_execution/rule/branch_type_selector.vue';
import { DEFAULT_PROVIDE } from '../mocks/mocks';
-import { verify } from '../utils';
-import { mockScheduleScanExecutionManifest, mockScanExecutionManifest } from './mocks';
+import { navigateToCustomMode, verify } from '../utils';
+import { mockScheduleScanExecutionManifest, mockAllBranchesScanExecutionManifest } from './mocks';
describe('Scan execution policy rules', () => {
let wrapper;
@@ -39,12 +40,14 @@ describe('Scan execution policy rules', () => {
});
const findBaseRuleComponent = () => wrapper.findComponent(BaseRuleComponent);
+ const findBranchTypeSelector = () => wrapper.findComponent(BranchTypeSelector);
const findScheduleRuleComponent = () => wrapper.findComponent(ScheduleRuleComponent);
const findDisabledRuleSection = () => wrapper.findByTestId('disabled-rule');
describe('pipeline', () => {
- beforeEach(() => {
- createWrapper();
+ beforeEach(async () => {
+ await createWrapper();
+ await navigateToCustomMode(wrapper);
});
it('parses pipeline rule', async () => {
@@ -54,8 +57,9 @@ describe('Scan execution policy rules', () => {
expect(findDisabledRuleSection().props('disabled')).toBe(false);
};
+ await findBranchTypeSelector().vm.$emit('set-branch-type', 'all');
await verify({
- manifest: mockScanExecutionManifest,
+ manifest: mockAllBranchesScanExecutionManifest,
verifyRuleMode,
wrapper,
});
@@ -63,8 +67,9 @@ describe('Scan execution policy rules', () => {
});
describe('schedule rule', () => {
- beforeEach(() => {
- createWrapper();
+ beforeEach(async () => {
+ await createWrapper();
+ await navigateToCustomMode(wrapper);
});
it('parses schedule rule', async () => {
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/split_view_layout_spec.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/split_view_layout_spec.js
index a8aff10252d5c349a4fb4bb0a425fc82cf90c743..9ff97c30d4cd740ac7b26337dfdcc029c4f05371 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/split_view_layout_spec.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/scan_execution/split_view_layout_spec.js
@@ -7,6 +7,7 @@ import { DEFAULT_ASSIGNED_POLICY_PROJECT } from 'ee/security_orchestration/const
import { POLICY_TYPE_COMPONENT_OPTIONS } from 'ee/security_orchestration/components/constants';
import { REPORT_TYPE_DAST } from '~/vue_shared/security_reports/constants';
import EditorLayout from 'ee/security_orchestration/components/policy_editor/editor_layout.vue';
+import { navigateToCustomMode } from '../utils';
import { DEFAULT_PROVIDE } from '../mocks/mocks';
import { mockDastActionScanExecutionManifest } from './mocks';
@@ -39,14 +40,15 @@ describe('Split View', () => {
describe('rendering', () => {
let createPolicyObjectMock;
- beforeEach(() => {
- createWrapper({
+ beforeEach(async () => {
+ await createWrapper({
provide: {
glFeatures: { securityPoliciesSplitView: true },
policyEditorEnabled: true,
namespaceType: 'group',
},
});
+ await navigateToCustomMode(wrapper);
findAdvancedEditorToggle().vm.$emit('enable-advanced-editor', true);
diff --git a/ee/spec/frontend_integration/security_orchestration/policy_editor/utils.js b/ee/spec/frontend_integration/security_orchestration/policy_editor/utils.js
index a7fca0715bf067218b58c9434740018365af758a..6c56f411afb7d4f3f4903b9168ba4589282d0d6c 100644
--- a/ee/spec/frontend_integration/security_orchestration/policy_editor/utils.js
+++ b/ee/spec/frontend_integration/security_orchestration/policy_editor/utils.js
@@ -5,6 +5,7 @@ import {
EDITOR_MODE_YAML,
} from 'ee/security_orchestration/components/policy_editor/constants';
import YamlEditor from 'ee/security_orchestration/components/yaml_editor.vue';
+import { SELECTION_CONFIG_CUSTOM } from 'ee/security_orchestration/components/policy_editor/scan_execution/constants';
export const switchRuleMode = async (wrapper, mode, awaitPromise = true) => {
await wrapper.findComponent(GlSegmentedControl).vm.$emit('input', mode);
@@ -55,3 +56,7 @@ export const createSppSubscriptionHandler = () =>
export const removeGroupSetting = (yaml) =>
yaml.replace(' block_group_branch_modification: true\n', '');
+
+export const navigateToCustomMode = async (wrapper) => {
+ await wrapper.findByTestId('enforcement-selection').vm.$emit('input', SELECTION_CONFIG_CUSTOM);
+};
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index aa2db6b47eb7d1410dddadf804d30063bfbba0c6..cbc0725b9faf0a04e0bf5a065c7e6348aaaab42e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -57026,9 +57026,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{rules} actions for %{scopes} %{branches} %{agents} %{branchExceptions} %{namespaces} %{period}"
msgstr ""
-msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces}"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs that %{scopes} %{branches} using %{sources} %{branchExceptions} %{agents} %{namespaces}"
msgstr ""
diff --git a/spec/support/shared_examples/security/creating_scan_execution_policy_shared_examples.rb b/spec/support/shared_examples/security/creating_scan_execution_policy_shared_examples.rb
index 96c0d7d06092d48c9f4a10ae880fb3d2bca1be23..e637e595690b17bfe5ca7770423d090c5fc4acab 100644
--- a/spec/support/shared_examples/security/creating_scan_execution_policy_shared_examples.rb
+++ b/spec/support/shared_examples/security/creating_scan_execution_policy_shared_examples.rb
@@ -48,7 +48,10 @@
it "fails to create a policy without branch information for schedules" do
fill_in _('Name'), with: 'Missing branch information'
- select_from_listbox 'Schedules:', from: 'Triggers:'
+ page.find('span', text: 'Custom').click
+ within_testid('rule-0') do
+ select_from_listbox 'Schedules:', from: 'Triggers:'
+ end
click_button _('Configure with a merge request')
expect(page).to have_content('Policy cannot be enabled without branch information')
expect(page).to have_current_path(path_to_scan_execution_policy_editor)
@@ -56,7 +59,11 @@
it "fails to create a policy without branch information" do
fill_in _('Name'), with: 'Scan execution policy'
- fill_in _('Select branches'), with: ''
+ page.find('span', text: 'Custom').click
+ within_testid('rule-0') do
+ select_from_listbox 'specific protected branches', from: 'default branch'
+ fill_in _('Select branches'), with: ''
+ end
click_button _('Configure with a merge request')
expect(page).to have_content('Policy cannot be enabled without branch information')
expect(page).to have_current_path(path_to_scan_execution_policy_editor)