Commit aad07ccb authored by Alexander Turinske's avatar Alexander Turinske

Prevent changing of an existing policy's type

- users should not be able to switch an existing
  policy's type
- they should instead delete the policy and
  create a new one
- abstract out code
- add tests
parent 034d36ae
......@@ -20,3 +20,8 @@ export const COLORS = {
// otherwise they could get out of sync.
// See https://gitlab.com/gitlab-org/gitlab-ui/issues/554.
export { dateFormats as DATE_FORMATS } from 'ee/analytics/shared/constants';
export const POLICY_KINDS = {
ciliumNetwork: 'CiliumNetworkPolicy',
scanExecution: 'scanner_profile',
};
......@@ -37,7 +37,7 @@ export default {
<template>
<base-policy :policy="policy">
<template #type>{{ s__('NetworkPolicies|Network policy') }}</template>
<template #type>{{ s__('NetworkPolicies|Network') }}</template>
<template #default="{ enforcementStatusLabel }">
<div v-if="policy">
......
<script>
import { GlButton, GlDrawer } from '@gitlab/ui';
import { getContentWrapperHeight } from '../../utils';
import {
CiliumNetworkPolicyKind,
ScanExecutionPolicyKind,
} from '../policy_editor/network_policy/lib';
import { getContentWrapperHeight, getPolicyKind } from '../../utils';
import { POLICY_KINDS } from '../constants';
import CiliumNetworkPolicy from './cilium_network_policy.vue';
import ScanExecutionPolicy from './scan_execution_policy.vue';
const policyComponent = {
[CiliumNetworkPolicyKind]: CiliumNetworkPolicy,
[ScanExecutionPolicyKind]: ScanExecutionPolicy,
[POLICY_KINDS.ciliumNetwork]: CiliumNetworkPolicy,
[POLICY_KINDS.scanExecution]: ScanExecutionPolicy,
};
export default {
......@@ -36,13 +33,7 @@ export default {
},
computed: {
policyKind() {
if (this.policy?.manifest?.includes(CiliumNetworkPolicyKind)) {
return CiliumNetworkPolicyKind;
}
if (this.policy?.manifest?.includes(ScanExecutionPolicyKind)) {
return ScanExecutionPolicyKind;
}
return null;
return getPolicyKind(this.policy);
},
policyComponent() {
return policyComponent[this.policyKind] || null;
......
......@@ -12,10 +12,10 @@ export const EDITOR_MODES = [
{ value: EDITOR_MODE_YAML, text: s__('NetworkPolicies|.yaml mode') },
];
export const POLICY_TYPES = {
networkPolicy: {
value: 'networkPolicy',
text: s__('NetworkPolicies|Network Policy'),
export const POLICY_KIND_OPTIONS = {
network: {
value: 'network',
text: s__('NetworkPolicies|Network'),
component: 'network-policy-editor',
shouldShowEnvironmentPicker: true,
},
......@@ -23,7 +23,6 @@ export const POLICY_TYPES = {
value: 'scanExecution',
text: s__('NetworkPolicies|Scan Execution'),
component: 'scan-execution-policy-editor',
shouldShowMergeRequestButton: true,
},
};
......
......@@ -13,9 +13,6 @@ export const RuleTypeEntity = 'NetworkPolicyRuleEntity';
export const RuleTypeCIDR = 'NetworkPolicyRuleCIDR';
export const RuleTypeFQDN = 'NetworkPolicyRuleFQDN';
export const CiliumNetworkPolicyKind = 'CiliumNetworkPolicy';
export const ScanExecutionPolicyKind = 'scanner_profile';
export const EntityTypes = {
ALL: 'all',
HOST: 'host',
......
import { safeDump } from 'js-yaml';
import { EndpointMatchModeAny, DisabledByLabel, CiliumNetworkPolicyKind } from './constants';
import { POLICY_KINDS } from 'ee/threat_monitoring/components/constants';
import { EndpointMatchModeAny, DisabledByLabel } from './constants';
import { ruleSpec } from './rules';
import { labelSelector } from './utils';
......@@ -47,7 +48,7 @@ export default function toYaml(policy) {
const policySpec = {
apiVersion: 'cilium.io/v2',
kind: CiliumNetworkPolicyKind,
kind: POLICY_KINDS.ciliumNetwork,
};
if (description?.length > 0) {
......
......@@ -3,7 +3,7 @@ import { GlFormGroup, GlFormSelect } from '@gitlab/ui';
import { mapActions } from 'vuex';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import EnvironmentPicker from '../environment_picker.vue';
import { POLICY_TYPES } from './constants';
import { POLICY_KIND_OPTIONS } from './constants';
import NetworkPolicyEditor from './network_policy/network_policy_editor.vue';
import ScanExecutionPolicyEditor from './scan_execution_policy/scan_execution_policy_editor.vue';
......@@ -25,18 +25,18 @@ export default {
},
data() {
return {
policyType: POLICY_TYPES.networkPolicy.value,
policyType: POLICY_KIND_OPTIONS.network.value,
};
},
computed: {
policyComponent() {
return POLICY_TYPES[this.policyType].component;
return POLICY_KIND_OPTIONS[this.policyType].component;
},
shouldAllowPolicyTypeSelection() {
return this.glFeatures.scanExecutionPolicyUi;
return !this.existingPolicy && this.glFeatures.scanExecutionPolicyUi;
},
shouldShowEnvironmentPicker() {
return POLICY_TYPES[this.policyType].shouldShowEnvironmentPicker;
return POLICY_KIND_OPTIONS[this.policyType].shouldShowEnvironmentPicker;
},
},
created() {
......@@ -48,7 +48,7 @@ export default {
this.policyType = type;
},
},
policyTypes: Object.values(POLICY_TYPES),
policyTypes: Object.values(POLICY_KIND_OPTIONS),
};
</script>
......
......@@ -23,16 +23,12 @@ export default {
},
},
data() {
const policy = this.existingPolicy
? fromYaml(this.existingPolicy.manifest)
: fromYaml(DEFAULT_SCAN_EXECUTION_POLICY);
const yamlEditorValue = this.existingPolicy
? removeUnnecessaryDashes(this.existingPolicy.manifest)
: DEFAULT_SCAN_EXECUTION_POLICY;
return {
policy,
policy: fromYaml(yamlEditorValue),
yamlEditorValue,
};
},
......
import { POLICY_KINDS } from './components/constants';
/**
* Get the height of the wrapper page element
* This height can be used to determine where the highest element goes in a page
......@@ -10,6 +12,21 @@ export const getContentWrapperHeight = (contentWrapperClass) => {
return wrapperEl ? `${wrapperEl.offsetTop}px` : '';
};
/**
* Get a policy's type
* @param {Object} policy policy information including a manifest in yaml
* @returns {String|null} policy type if available
*/
export const getPolicyKind = (policy) => {
if (policy?.manifest?.includes(POLICY_KINDS.ciliumNetwork)) {
return POLICY_KINDS.ciliumNetwork;
}
if (policy?.manifest?.includes(POLICY_KINDS.scanExecution)) {
return POLICY_KINDS.scanExecution;
}
return null;
};
/**
* Removes inital line dashes from a policy YAML that is received from the API, which
* is not required for the user.
......
......@@ -11,7 +11,7 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview tab
<p
data-testid="policy-type"
>
Network policy
Network
</p>
<div>
......@@ -58,7 +58,7 @@ exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview t
<p
data-testid="policy-type"
>
Network policy
Network
</p>
<!---->
......
import { GlFormSelect } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import EnvironmentPicker from 'ee/threat_monitoring/components/environment_picker.vue';
import { POLICY_TYPES } from 'ee/threat_monitoring/components/policy_editor/constants';
import { POLICY_KIND_OPTIONS } from 'ee/threat_monitoring/components/policy_editor/constants';
import NetworkPolicyEditor from 'ee/threat_monitoring/components/policy_editor/network_policy/network_policy_editor.vue';
import PolicyEditor from 'ee/threat_monitoring/components/policy_editor/policy_editor.vue';
import createStore from 'ee/threat_monitoring/store';
import { mockL3Manifest } from '../../mocks/mock_data';
describe('PolicyEditor component', () => {
let store;
......@@ -20,11 +21,7 @@ describe('PolicyEditor component', () => {
jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve());
wrapper = shallowMount(PolicyEditor, {
propsData: {
threatMonitoringPath: '/threat-monitoring',
projectId: '21',
...propsData,
},
propsData,
provide,
store,
stubs: { GlFormSelect },
......@@ -42,10 +39,10 @@ describe('PolicyEditor component', () => {
expect(findEnvironmentPicker().exists()).toBe(true);
});
it('renders the form select', () => {
it('renders the disabled form select', () => {
const formSelect = findFormSelect();
expect(formSelect.exists()).toBe(true);
expect(formSelect.attributes('value')).toBe(POLICY_TYPES.networkPolicy.value);
expect(formSelect.attributes('value')).toBe(POLICY_KIND_OPTIONS.network.value);
expect(formSelect.attributes('disabled')).toBe('true');
});
......@@ -54,6 +51,19 @@ describe('PolicyEditor component', () => {
});
});
describe('when an existing policy is present', () => {
beforeEach(() => {
factory({ propsData: { existingPolicy: { manifest: mockL3Manifest } } });
});
it('renders the disabled form select', () => {
const formSelect = findFormSelect();
expect(formSelect.exists()).toBe(true);
expect(formSelect.attributes('value')).toBe(POLICY_KIND_OPTIONS.network.value);
expect(formSelect.attributes('disabled')).toBe('true');
});
});
describe('with "scanExecutionPolicyUi" feature flag enabled', () => {
beforeEach(() => {
factory({ provide: { glFeatures: { scanExecutionPolicyUi: true } } });
......
......@@ -182,6 +182,20 @@ export const mockAlertDetails = {
monitorTool: 'Cilium',
};
export const mockDastScanExecutionManifest = `type: scan_execution_policy
name: 'Test Dast'
description: 'This is a good test'
enabled: false
rules:
- type: pipeline
branches:
- main
actions:
- scan: dast
site_profile: 'required_site_profile'
scanner_profile: 'required_scanner_profile'
`;
export const mockL7Manifest = `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
......
import { getContentWrapperHeight, removeUnnecessaryDashes } from 'ee/threat_monitoring/utils';
import { POLICY_KINDS } from 'ee/threat_monitoring/components/constants';
import {
getContentWrapperHeight,
getPolicyKind,
removeUnnecessaryDashes,
} from 'ee/threat_monitoring/utils';
import { setHTMLFixture } from 'helpers/fixtures';
import { mockL3Manifest, mockDastScanExecutionManifest } from './mocks/mock_data';
describe('Threat Monitoring Utils', () => {
describe('getContentWrapperHeight', () => {
......@@ -24,6 +30,19 @@ describe('Threat Monitoring Utils', () => {
});
});
describe('getPolicyKind', () => {
it.each`
input | output
${{}} | ${null}
${{ manifest: '' }} | ${null}
${{ manifest: 'ciliumNetworkPolicy' }} | ${null}
${{ manifest: mockL3Manifest }} | ${POLICY_KINDS.ciliumNetwork}
${{ manifest: mockDastScanExecutionManifest }} | ${POLICY_KINDS.scanExecution}
`('returns $output when used on $input', ({ input, output }) => {
expect(getPolicyKind(input)).toBe(output);
});
});
describe('removeUnnecessaryDashes', () => {
it.each`
input | output
......
......@@ -21758,10 +21758,7 @@ msgstr ""
msgid "NetworkPolicies|Namespace"
msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
msgid "NetworkPolicies|Network policy"
msgid "NetworkPolicies|Network"
msgstr ""
msgid "NetworkPolicies|Network traffic"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment