Commit 835d06e9 authored by Simon Knox's avatar Simon Knox

Merge branch '338521-non-cilium-policy' into 'master'

Add support for non-cilium network policies

See merge request gitlab-org/gitlab!68497
parents 340e73c1 6810b91a
...@@ -28,7 +28,10 @@ export const POLICY_TYPE_COMPONENT_OPTIONS = { ...@@ -28,7 +28,10 @@ export const POLICY_TYPE_COMPONENT_OPTIONS = {
text: s__('SecurityOrchestration|Network'), text: s__('SecurityOrchestration|Network'),
urlParameter: 'container_policy', urlParameter: 'container_policy',
value: 'container', value: 'container',
yamlIndicator: 'CiliumNetworkPolicy', yamlIndicator: {
cilium: 'CiliumNetworkPolicy',
network: 'NetworkPolicy',
},
}, },
scanExecution: { scanExecution: {
component: 'scan-execution-policy-editor', component: 'scan-execution-policy-editor',
......
...@@ -152,15 +152,19 @@ export default { ...@@ -152,15 +152,19 @@ export default {
return Boolean(this.networkPolicies?.some((policy) => policy.fromAutoDevops)); return Boolean(this.networkPolicies?.some((policy) => policy.fromAutoDevops));
}, },
editPolicyPath() { editPolicyPath() {
return this.hasSelectedPolicy if (this.hasSelectedPolicy) {
? mergeUrlParams( const parameters = {
{
environment_id: this.currentEnvironmentId, environment_id: this.currentEnvironmentId,
type: POLICY_TYPE_COMPONENT_OPTIONS[this.policyType]?.urlParameter, type: POLICY_TYPE_COMPONENT_OPTIONS[this.policyType]?.urlParameter,
}, ...(this.selectedPolicy.kind && { kind: this.selectedPolicy.kind }),
};
return mergeUrlParams(
parameters,
this.newPolicyPath.replace('new', `${this.selectedPolicy.name}/edit`), this.newPolicyPath.replace('new', `${this.selectedPolicy.name}/edit`),
) );
: ''; }
return '';
}, },
policyType() { policyType() {
return this.selectedPolicy ? getPolicyType(this.selectedPolicy.yaml) : 'container'; return this.selectedPolicy ? getPolicyType(this.selectedPolicy.yaml) : 'container';
......
...@@ -48,7 +48,7 @@ export default function toYaml(policy) { ...@@ -48,7 +48,7 @@ export default function toYaml(policy) {
const policySpec = { const policySpec = {
apiVersion: 'cilium.io/v2', apiVersion: 'cilium.io/v2',
kind: POLICY_TYPE_COMPONENT_OPTIONS.container.yamlIndicator, kind: POLICY_TYPE_COMPONENT_OPTIONS.container.yamlIndicator.cilium,
}; };
if (description?.length > 0) { if (description?.length > 0) {
......
import createGqClient from '~/lib/graphql'; import createGqClient from '~/lib/graphql';
import { POLICY_TYPE_COMPONENT_OPTIONS } from './components/constants'; import { POLICY_TYPE_COMPONENT_OPTIONS } from './components/constants';
/**
* Determines if the yaml passed in is of the type `container`
* @param {String} yaml the policy in yaml form
* @returns {Boolean}
*/
const isContainerPolicyYaml = (yaml) => {
const containerYamlIndicator = Object.values(
POLICY_TYPE_COMPONENT_OPTIONS.container.yamlIndicator,
);
return containerYamlIndicator.some((str) => yaml?.includes(str));
};
/** /**
* Get the height of the wrapper page element * Get the height of the wrapper page element
* This height can be used to determine where the highest element goes in a page * This height can be used to determine where the highest element goes in a page
...@@ -19,7 +31,7 @@ export const getContentWrapperHeight = (contentWrapperClass) => { ...@@ -19,7 +31,7 @@ export const getContentWrapperHeight = (contentWrapperClass) => {
* @returns {String|null} policy type if available * @returns {String|null} policy type if available
*/ */
export const getPolicyType = (yaml = '') => { export const getPolicyType = (yaml = '') => {
if (yaml?.includes(POLICY_TYPE_COMPONENT_OPTIONS.container.yamlIndicator)) { if (isContainerPolicyYaml(yaml)) {
return POLICY_TYPE_COMPONENT_OPTIONS.container.value; return POLICY_TYPE_COMPONENT_OPTIONS.container.value;
} }
if (yaml?.includes(POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.yamlIndicator)) { if (yaml?.includes(POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.yamlIndicator)) {
......
...@@ -27,6 +27,10 @@ const environments = [ ...@@ -27,6 +27,10 @@ const environments = [
id: 2, id: 2,
global_id: 'gid://gitlab/Environment/2', global_id: 'gid://gitlab/Environment/2',
}, },
{
id: 3,
global_id: 'gid://gitlab/Environment/3',
},
]; ];
const scanExecutionPoliciesSpy = scanExecutionPolicies(mockScanExecutionPoliciesResponse); const scanExecutionPoliciesSpy = scanExecutionPolicies(mockScanExecutionPoliciesResponse);
const defaultRequestHandlers = { const defaultRequestHandlers = {
...@@ -47,6 +51,7 @@ describe('PoliciesList component', () => { ...@@ -47,6 +51,7 @@ describe('PoliciesList component', () => {
...state, ...state,
}); });
store.state.threatMonitoring.environments = environments; store.state.threatMonitoring.environments = environments;
store.state.threatMonitoring.currentEnvironmentId = environments[0].id;
requestHandlers = { requestHandlers = {
...defaultRequestHandlers, ...defaultRequestHandlers,
...handlers, ...handlers,
...@@ -125,6 +130,7 @@ describe('PoliciesList component', () => { ...@@ -125,6 +130,7 @@ describe('PoliciesList component', () => {
it('fetches policies', () => { it('fetches policies', () => {
expect(requestHandlers.networkPolicies).toHaveBeenCalledWith({ expect(requestHandlers.networkPolicies).toHaveBeenCalledWith({
environmentId: environments[0].global_id,
fullPath, fullPath,
}); });
expect(requestHandlers.scanExecutionPolicies).toHaveBeenCalledWith({ expect(requestHandlers.scanExecutionPolicies).toHaveBeenCalledWith({
...@@ -148,11 +154,11 @@ describe('PoliciesList component', () => { ...@@ -148,11 +154,11 @@ describe('PoliciesList component', () => {
it('fetches network policies on environment change', async () => { it('fetches network policies on environment change', async () => {
store.dispatch.mockReset(); store.dispatch.mockReset();
await store.commit('threatMonitoring/SET_CURRENT_ENVIRONMENT_ID', 2); await store.commit('threatMonitoring/SET_CURRENT_ENVIRONMENT_ID', 3);
expect(requestHandlers.networkPolicies).toHaveBeenCalledTimes(2); expect(requestHandlers.networkPolicies).toHaveBeenCalledTimes(2);
expect(requestHandlers.networkPolicies.mock.calls[1][0]).toEqual({ expect(requestHandlers.networkPolicies.mock.calls[1][0]).toEqual({
fullPath: 'project/path', fullPath: 'project/path',
environmentId: environments[0].global_id, environmentId: environments[1].global_id,
}); });
}); });
...@@ -259,10 +265,11 @@ describe('PoliciesList component', () => { ...@@ -259,10 +265,11 @@ describe('PoliciesList component', () => {
}); });
describe.each` describe.each`
description | policy | policyType description | policy | policyType | editPolicyPath
${'container'} | ${mockNetworkPoliciesResponse[1]} | ${'container'} ${'network'} | ${mockNetworkPoliciesResponse[0]} | ${'container'} | ${'path/to/policy?environment_id=2&type=container_policy&kind=NetworkPolicy'}
${'scan execution'} | ${mockScanExecutionPoliciesResponse[0]} | ${'scanExecution'} ${'container'} | ${mockNetworkPoliciesResponse[1]} | ${'container'} | ${'path/to/policy?environment_id=2&type=container_policy&kind=CiliumNetworkPolicy'}
`('given there is a $description policy selected', ({ policy, policyType }) => { ${'scan execution'} | ${mockScanExecutionPoliciesResponse[0]} | ${'scanExecution'} | ${'path/to/policy?environment_id=2&type=scan_execution_policy'}
`('given there is a $description policy selected', ({ policy, policyType, editPolicyPath }) => {
beforeEach(() => { beforeEach(() => {
mountShallowWrapper(); mountShallowWrapper();
findPoliciesTable().vm.$emit('row-selected', [policy]); findPoliciesTable().vm.$emit('row-selected', [policy]);
...@@ -272,6 +279,7 @@ describe('PoliciesList component', () => { ...@@ -272,6 +279,7 @@ describe('PoliciesList component', () => {
const editorDrawer = findPolicyDrawer(); const editorDrawer = findPolicyDrawer();
expect(editorDrawer.exists()).toBe(true); expect(editorDrawer.exists()).toBe(true);
expect(editorDrawer.props()).toMatchObject({ expect(editorDrawer.props()).toMatchObject({
editPolicyPath,
open: true, open: true,
policy, policy,
policyType, policyType,
......
...@@ -115,9 +115,9 @@ describe('NetworkPolicyEditor component', () => { ...@@ -115,9 +115,9 @@ describe('NetworkPolicyEditor component', () => {
findPolicyEditorLayout().vm.$emit('update-yaml', mockL3Manifest); findPolicyEditorLayout().vm.$emit('update-yaml', mockL3Manifest);
expect(wrapper.vm.policy).toMatchObject({ expect(wrapper.vm.policy).toMatchObject({
name: 'test-policy', name: 'test-policy-02',
description: 'test description', description: 'test description',
isEnabled: false, isEnabled: true,
endpointMatchMode: EndpointMatchModeLabel, endpointMatchMode: EndpointMatchModeLabel,
endpointLabels: 'foo:bar', endpointLabels: 'foo:bar',
rules: [ rules: [
......
...@@ -15,27 +15,115 @@ export const mockEnvironmentsResponse = { ...@@ -15,27 +15,115 @@ export const mockEnvironmentsResponse = {
stopped_count: 5, stopped_count: 5,
}; };
export const mockNetworkPoliciesResponse = [ export const mockDastScanExecutionManifest = `type: scan_execution_policy
name: Test Dast
description: This policy enforces pipeline configuration to have a job with DAST scan
enabled: false
rules:
- type: pipeline
branches:
- main
actions:
- scan: dast
site_profile: required_site_profile
scanner_profile: required_scanner_profile
`;
export const mockDastScanExecutionObject = {
type: 'scan_execution_policy',
name: 'Test Dast',
description: 'This policy enforces pipeline configuration to have a job with DAST scan',
enabled: false,
rules: [{ type: 'pipeline', branches: ['main'] }],
actions: [
{ {
name: 'policy', scan: 'dast',
kind: 'NetworkPolicy', site_profile: 'required_site_profile',
yaml: `--- scanner_profile: 'required_scanner_profile',
apiVersion: networking.k8s.io/v1 },
kind: NetworkPolicy ],
};
export const mockNetworkManifest = `kind: CiliumNetworkPolicy
metadata:
name: test-policy-01
namespace: network-policy-demo-cluster-management-5000174-production
labels:
app.gitlab.com/proj: '5000174'
spec:
endpointSelector:
matchLabels:
network-policy.gitlab.com/disabled_by: gitlab
ingress:
- fromCIDR:
- 192.168.2.3/5
description: this is the
`;
export const mockCiliumManifest = `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata: metadata:
name: example-name name: test-policy-03
namespace: example-namespace namespace: network-policy-demo-cluster-management-5000174-production
labels:
app.gitlab.com/proj: '5000174'
resourceVersion: '655210'
spec: spec:
podSelector: endpointSelector:
matchLabels: matchLabels:
role: db network-policy.gitlab.com/disabled_by: gitlab
policyTypes:
- Ingress
ingress: ingress:
- from: - fromCIDR:
- namespaceSelector: - 10.101.12.14/5
description: 03-desc`;
export const mockL3Manifest = `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
description: test description
metadata:
name: test-policy-02
labels:
app.gitlab.com/proj: '21'
spec:
endpointSelector:
matchLabels: matchLabels:
project: myproject`, foo: bar
ingress:
- fromEndpoints:
- matchLabels:
foo: bar`;
export const mockL7Manifest = `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: limit-inbound-ip
spec:
endpointSelector: {}
ingress:
- toPorts:
- ports:
- port: '80'
protocol: TCP
- port: '443'
protocol: TCP
rules:
http:
- headers:
- 'X-Forwarded-For: 192.168.1.1'
fromEntities:
- cluster`;
export const mockCiliumPolicy = {
name: 'test-policy-03',
updatedAt: new Date('2021-06-07T00:00:00.000Z'),
yaml: mockCiliumManifest,
};
export const mockNetworkPoliciesResponse = [
{
name: 'policy',
kind: 'NetworkPolicy',
yaml: mockNetworkManifest,
updatedAt: '2020-04-14T00:08:30Z', updatedAt: '2020-04-14T00:08:30Z',
enabled: true, enabled: true,
fromAutoDevops: false, fromAutoDevops: false,
...@@ -44,23 +132,9 @@ spec: ...@@ -44,23 +132,9 @@ spec:
}, },
}, },
{ {
name: 'test-policy-01', name: 'test-policy-02',
kind: 'CiliumNetworkPolicy', kind: 'CiliumNetworkPolicy',
yaml: `--- yaml: mockL3Manifest,
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: test-policy-01
namespace: network-policy-demo-cluster-management-5000174-production
labels:
app.gitlab.com/proj: '5000174'
resourceVersion: '630685'
spec:
endpointSelector: {}
ingress:
- fromCIDR:
- 192.168.2.3/5
description: this is the first`,
enabled: true, enabled: true,
fromAutoDevops: false, fromAutoDevops: false,
updatedAt: '2021-06-08T04:01:11Z', updatedAt: '2021-06-08T04:01:11Z',
...@@ -70,33 +144,10 @@ description: this is the first`, ...@@ -70,33 +144,10 @@ description: this is the first`,
}, },
]; ];
export const mockCiliumPolicy = {
name: 'policy',
updatedAt: new Date('2021-06-07T00:00:00.000Z'),
yaml: `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: policy
spec:
endpointSelector: {}`,
};
export const mockScanExecutionPolicy = { export const mockScanExecutionPolicy = {
name: 'Scheduled DAST scan', name: 'Scheduled DAST scan',
updatedAt: new Date('2021-06-07T00:00:00.000Z'), updatedAt: new Date('2021-06-07T00:00:00.000Z'),
yaml: `--- yaml: mockDastScanExecutionManifest,
name: Enforce DAST in every pipeline
description: This policy enforces pipeline configuration to have a job with DAST scan
enabled: true
rules:
- type: pipeline
branches:
- master
actions:
- scan: dast
scanner_profile: Scanner Profile
site_profile: Site Profile
`,
enabled: true, enabled: true,
}; };
...@@ -219,69 +270,3 @@ export const mockAlertDetails = { ...@@ -219,69 +270,3 @@ export const mockAlertDetails = {
todos: { nodes: [{ id: 'gid://gitlab/Todo/5984130' }] }, todos: { nodes: [{ id: 'gid://gitlab/Todo/5984130' }] },
notes: { nodes: [] }, notes: { nodes: [] },
}; };
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 mockDastScanExecutionObject = {
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:
name: limit-inbound-ip
spec:
endpointSelector: {}
ingress:
- toPorts:
- ports:
- port: '80'
protocol: TCP
- port: '443'
protocol: TCP
rules:
http:
- headers:
- 'X-Forwarded-For: 192.168.1.1'
fromEntities:
- cluster`;
export const mockL3Manifest = `apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
description: test description
metadata:
name: test-policy
labels:
app.gitlab.com/proj: '21'
spec:
endpointSelector:
matchLabels:
network-policy.gitlab.com/disabled_by: gitlab
foo: bar
ingress:
- fromEndpoints:
- matchLabels:
foo: bar`;
...@@ -5,7 +5,11 @@ import { ...@@ -5,7 +5,11 @@ import {
removeUnnecessaryDashes, removeUnnecessaryDashes,
} from 'ee/threat_monitoring/utils'; } from 'ee/threat_monitoring/utils';
import { setHTMLFixture } from 'helpers/fixtures'; import { setHTMLFixture } from 'helpers/fixtures';
import { mockL3Manifest, mockDastScanExecutionManifest } from './mocks/mock_data'; import {
mockDastScanExecutionManifest,
mockCiliumManifest,
mockNetworkManifest,
} from './mocks/mock_data';
describe('Threat Monitoring Utils', () => { describe('Threat Monitoring Utils', () => {
describe('getContentWrapperHeight', () => { describe('getContentWrapperHeight', () => {
...@@ -34,8 +38,9 @@ describe('Threat Monitoring Utils', () => { ...@@ -34,8 +38,9 @@ describe('Threat Monitoring Utils', () => {
it.each` it.each`
input | output input | output
${''} | ${null} ${''} | ${null}
${'ciliumNetworkPolicy'} | ${null} ${'random string'} | ${null}
${mockL3Manifest} | ${POLICY_TYPE_COMPONENT_OPTIONS.container.value} ${mockNetworkManifest} | ${POLICY_TYPE_COMPONENT_OPTIONS.container.value}
${mockCiliumManifest} | ${POLICY_TYPE_COMPONENT_OPTIONS.container.value}
${mockDastScanExecutionManifest} | ${POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.value} ${mockDastScanExecutionManifest} | ${POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.value}
`('returns $output when used on $input', ({ input, output }) => { `('returns $output when used on $input', ({ input, output }) => {
expect(getPolicyType(input)).toBe(output); expect(getPolicyType(input)).toBe(output);
......
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