Commit 537bcb16 authored by ap4y's avatar ap4y

Add Policies tab to the Threat Management page

This commit introduces new 'networkPolicyManagement' feature flag and
adds a new Policies tab to the Threat Management page behind this
feature flag.
parent ea9ff9a4
<script>
import { mapActions } from 'vuex';
import { GlAlert, GlEmptyState, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import { GlAlert, GlEmptyState, GlIcon, GlLink, GlPopover, GlTabs, GlTab } from '@gitlab/ui';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ThreatMonitoringFilters from './threat_monitoring_filters.vue';
import ThreatMonitoringSection from './threat_monitoring_section.vue';
import NetworkPolicyList from './network_policy_list.vue';
export default {
name: 'ThreatMonitoring',
......@@ -15,8 +16,11 @@ export default {
GlIcon,
GlLink,
GlPopover,
GlTabs,
GlTab,
ThreatMonitoringFilters,
ThreatMonitoringSection,
NetworkPolicyList,
},
mixins: [glFeatureFlagsMixin()],
props: {
......@@ -154,38 +158,49 @@ export default {
</h2>
</header>
<threat-monitoring-filters />
<gl-tabs>
<gl-tab :title="s__('ThreatMonitoring|Overview')">
<threat-monitoring-filters />
<threat-monitoring-section
ref="wafSection"
store-namespace="threatMonitoringWaf"
:title="s__('ThreatMonitoring|Web Application Firewall')"
:subtitle="s__('ThreatMonitoring|Requests')"
:anomalous-title="s__('ThreatMonitoring|Anomalous Requests')"
:nominal-title="s__('ThreatMonitoring|Total Requests')"
:y-legend="s__('ThreatMonitoring|Requests')"
:chart-empty-state-title="s__('ThreatMonitoring|Application firewall not detected')"
:chart-empty-state-text="$options.wafChartEmptyStateDescription"
:chart-empty-state-svg-path="wafNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="web-application-firewall"
/>
<threat-monitoring-section
ref="wafSection"
store-namespace="threatMonitoringWaf"
:title="s__('ThreatMonitoring|Web Application Firewall')"
:subtitle="s__('ThreatMonitoring|Requests')"
:anomalous-title="s__('ThreatMonitoring|Anomalous Requests')"
:nominal-title="s__('ThreatMonitoring|Total Requests')"
:y-legend="s__('ThreatMonitoring|Requests')"
:chart-empty-state-title="s__('ThreatMonitoring|Application firewall not detected')"
:chart-empty-state-text="$options.wafChartEmptyStateDescription"
:chart-empty-state-svg-path="wafNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="web-application-firewall"
/>
<hr />
<hr />
<threat-monitoring-section
ref="networkPolicySection"
store-namespace="threatMonitoringNetworkPolicy"
:title="s__('ThreatMonitoring|Container Network Policy')"
:subtitle="s__('ThreatMonitoring|Packet Activity')"
:anomalous-title="s__('ThreatMonitoring|Dropped Packets')"
:nominal-title="s__('ThreatMonitoring|Total Packets')"
:y-legend="s__('ThreatMonitoring|Operations Per Second')"
:chart-empty-state-title="s__('ThreatMonitoring|Container NetworkPolicies not detected')"
:chart-empty-state-text="$options.networkPolicyChartEmptyStateDescription"
:chart-empty-state-svg-path="networkPolicyNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="container-network-policy"
/>
<threat-monitoring-section
ref="networkPolicySection"
store-namespace="threatMonitoringNetworkPolicy"
:title="s__('ThreatMonitoring|Container Network Policy')"
:subtitle="s__('ThreatMonitoring|Packet Activity')"
:anomalous-title="s__('ThreatMonitoring|Dropped Packets')"
:nominal-title="s__('ThreatMonitoring|Total Packets')"
:y-legend="s__('ThreatMonitoring|Operations Per Second')"
:chart-empty-state-title="s__('ThreatMonitoring|Container NetworkPolicies not detected')"
:chart-empty-state-text="$options.networkPolicyChartEmptyStateDescription"
:chart-empty-state-svg-path="networkPolicyNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="container-network-policy"
/>
</gl-tab>
<gl-tab
v-if="glFeatures.networkPolicyManagement"
ref="networkPolicyTab"
:title="s__('ThreatMonitoring|Policies')"
>
<network-policy-list :documentation-path="documentationPath" />
</gl-tab>
</gl-tabs>
</section>
</template>
......@@ -9,6 +9,7 @@ export default () => {
wafStatisticsEndpoint,
networkPolicyStatisticsEndpoint,
environmentsEndpoint,
networkPoliciesEndpoint,
chartEmptyStateSvgPath,
emptyStateSvgPath,
wafNoDataSvgPath,
......@@ -26,6 +27,9 @@ export default () => {
networkPolicyStatisticsEndpoint,
environmentsEndpoint,
});
store.dispatch('networkPolicies/setEndpoints', {
networkPoliciesEndpoint,
});
return new Vue({
el,
......
......@@ -58,6 +58,9 @@ export const setCurrentEnvironmentId = ({ commit, dispatch }, environmentId) =>
commit(types.SET_CURRENT_ENVIRONMENT_ID, environmentId);
dispatch(`threatMonitoringWaf/fetchStatistics`, null, { root: true });
dispatch(`threatMonitoringNetworkPolicy/fetchStatistics`, null, { root: true });
if (window.gon.features?.networkPolicyManagement) {
dispatch(`networkPolicies/fetchPolicies`, environmentId, { root: true });
}
};
export const setCurrentTimeWindow = ({ commit, dispatch }, timeWindow) => {
......
......@@ -3,5 +3,8 @@
module Projects
class ThreatMonitoringController < Projects::ApplicationController
before_action :authorize_read_threat_monitoring!
before_action only: [:show] do
push_frontend_feature_flag(:network_policy_management)
end
end
end
......@@ -11,6 +11,7 @@
waf_statistics_endpoint: summary_project_security_waf_anomalies_path(@project, format: :json),
network_policy_statistics_endpoint: summary_project_security_network_policies_path(@project, format: :json),
environments_endpoint: project_environments_path(@project),
network_policies_endpoint: project_security_network_policies_path(@project),
default_environment_id: default_environment_id,
user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::THREAT_MONITORING_INFO,
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ThreatMonitoringApp component given there is a default environment with data given the networkPolicyManagement feature flag is enabled renders the network policy tab 1`] = `
<gl-tab-stub
title="Policies"
>
<network-policy-list-stub
documentationpath="/docs"
/>
</gl-tab-stub>
`;
exports[`ThreatMonitoringApp component given there is a default environment with data renders the network policy section 1`] = `
<threat-monitoring-section-stub
anomaloustitle="Dropped Packets"
......
......@@ -57,9 +57,11 @@ describe('ThreatMonitoringApp component', () => {
const findWafSection = () => wrapper.find({ ref: 'wafSection' });
const findNetworkPolicySection = () => wrapper.find({ ref: 'networkPolicySection' });
const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
const findNetworkPolicyTab = () => wrapper.find({ ref: 'networkPolicyTab' });
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe.each([-1, NaN, Math.PI])(
......@@ -116,6 +118,28 @@ describe('ThreatMonitoringApp component', () => {
expect(findNetworkPolicySection().element).toMatchSnapshot();
});
it('does not render the network policy tab', () => {
expect(findNetworkPolicyTab().exists()).toBe(false);
});
describe('given the networkPolicyManagement feature flag is enabled', () => {
beforeEach(() => {
factory({
options: {
provide: {
glFeatures: {
networkPolicyManagement: true,
},
},
},
});
});
it('renders the network policy tab', () => {
expect(findNetworkPolicyTab().element).toMatchSnapshot();
});
});
describe('dismissing the alert', () => {
let mockAxios;
......
......@@ -26,6 +26,7 @@ describe('EnvironmentPicker component', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('the environments dropdown', () => {
......
......@@ -36,6 +36,7 @@ describe('NetworkPolicyList component', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('renders EnvironmentPicker', () => {
......
......@@ -16,6 +16,16 @@ const environmentsEndpoint = 'environmentsEndpoint';
const wafStatisticsEndpoint = 'wafStatisticsEndpoint';
const networkPolicyStatisticsEndpoint = 'networkPolicyStatisticsEndpoint';
const stubFeatureFlags = features => {
beforeEach(() => {
window.gon.features = features;
});
afterEach(() => {
delete window.gon.features;
});
};
describe('Threat Monitoring actions', () => {
let state;
......@@ -209,6 +219,23 @@ describe('Threat Monitoring actions', () => {
{ type: 'threatMonitoringNetworkPolicy/fetchStatistics', payload: null },
],
));
describe('given the networkPolicyManagement feature flag is enabled', () => {
stubFeatureFlags({ networkPolicyManagement: true });
it('commits the SET_CURRENT_ENVIRONMENT_ID mutation and dispatches WAF, Network Policy statistics fetch actions and policy fetch action', () =>
testAction(
actions.setCurrentEnvironmentId,
environmentId,
state,
[{ type: types.SET_CURRENT_ENVIRONMENT_ID, payload: environmentId }],
[
{ type: 'threatMonitoringWaf/fetchStatistics', payload: null },
{ type: 'threatMonitoringNetworkPolicy/fetchStatistics', payload: null },
{ type: 'networkPolicies/fetchPolicies', payload: environmentId },
],
));
});
});
describe('setCurrentTimeWindow', () => {
......
......@@ -14065,6 +14065,9 @@ msgstr ""
msgid "Network"
msgstr ""
msgid "NetworkPolicies|Enabled"
msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
......@@ -14074,6 +14077,18 @@ msgstr ""
msgid "NetworkPolicies|Kubernetes error: %{error}"
msgstr ""
msgid "NetworkPolicies|Last modified"
msgstr ""
msgid "NetworkPolicies|Name"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other network endpoints."
msgstr ""
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr ""
......@@ -14083,6 +14098,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
msgid "Never"
msgstr ""
......@@ -22329,9 +22347,15 @@ msgstr ""
msgid "ThreatMonitoring|Operations Per Second"
msgstr ""
msgid "ThreatMonitoring|Overview"
msgstr ""
msgid "ThreatMonitoring|Packet Activity"
msgstr ""
msgid "ThreatMonitoring|Policies"
msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
......
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