Commit cb9cf4ab authored by Thong Kuah's avatar Thong Kuah

Merge branch '326975-remove-fe-for-waf' into 'master'

Remove frontend code for WAF feature [RUN-AS-IF-FOSS]

See merge request gitlab-org/gitlab!61489
parents 924ec18e 2e2382d1
......@@ -55,7 +55,6 @@ export default class Clusters {
helmHelpPath,
ingressHelpPath,
ingressDnsHelpPath,
ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
......@@ -74,7 +73,6 @@ export default class Clusters {
helmHelpPath,
ingressHelpPath,
ingressDnsHelpPath,
ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
......@@ -168,7 +166,6 @@ export default class Clusters {
ingressHelpPath: this.state.ingressHelpPath,
managePrometheusPath: this.state.managePrometheusPath,
ingressDnsHelpPath: this.state.ingressDnsHelpPath,
ingressModSecurityHelpPath: this.state.ingressModSecurityHelpPath,
cloudRunHelpPath: this.state.cloudRunHelpPath,
providerType: this.state.providerType,
preInstalledKnative: this.state.preInstalledKnative,
......@@ -253,9 +250,6 @@ export default class Clusters {
eventHub.$on('setKnativeDomain', (data) => this.setKnativeDomain(data));
eventHub.$on('uninstallApplication', (data) => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', (data) => this.setCrossplaneProviderStack(data));
eventHub.$on('setIngressModSecurityEnabled', (data) => this.setIngressModSecurityEnabled(data));
eventHub.$on('setIngressModSecurityMode', (data) => this.setIngressModSecurityMode(data));
eventHub.$on('resetIngressModSecurityChanges', (id) => this.resetIngressModSecurityChanges(id));
eventHub.$on('setFluentdSettings', (data) => this.setFluentdSettings(data));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
......@@ -274,12 +268,6 @@ export default class Clusters {
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('uninstallApplication');
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('setIngressModSecurityEnabled');
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('setIngressModSecurityMode');
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('resetIngressModSecurityChanges');
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('setFluentdSettings');
}
......@@ -519,21 +507,6 @@ export default class Clusters {
this.store.updateAppProperty(appId, 'validationError', null);
}
setIngressModSecurityEnabled({ id, modSecurityEnabled }) {
this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', true);
this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled);
}
setIngressModSecurityMode({ id, modSecurityMode }) {
this.store.updateAppProperty(id, 'isEditingModSecurityMode', true);
this.store.updateAppProperty(id, 'modsecurity_mode', modSecurityMode);
}
resetIngressModSecurityChanges(id) {
this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', false);
this.store.updateAppProperty(id, 'isEditingModSecurityMode', false);
}
destroy() {
this.destroyed = true;
......
......@@ -16,7 +16,6 @@ import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../con
import applicationRow from './application_row.vue';
import CrossplaneProviderStack from './crossplane_provider_stack.vue';
import FluentdOutputSettings from './fluentd_output_settings.vue';
import IngressModsecuritySettings from './ingress_modsecurity_settings.vue';
import KnativeDomainEditor from './knative_domain_editor.vue';
export default {
......@@ -28,7 +27,6 @@ export default {
GlLink,
KnativeDomainEditor,
CrossplaneProviderStack,
IngressModsecuritySettings,
FluentdOutputSettings,
GlAlert,
},
......@@ -63,11 +61,7 @@ export default {
required: false,
default: '',
},
ingressModSecurityHelpPath: {
type: String,
required: false,
default: '',
},
cloudRunHelpPath: {
type: String,
required: false,
......@@ -219,10 +213,6 @@ export default {
:request-reason="applications.ingress.requestReason"
:installed="applications.ingress.installed"
:install-failed="applications.ingress.installFailed"
:install-application-request-params="{
modsecurity_enabled: applications.ingress.modsecurity_enabled,
modsecurity_mode: applications.ingress.modsecurity_mode,
}"
:uninstallable="applications.ingress.uninstallable"
:uninstall-successful="applications.ingress.uninstallSuccessful"
:uninstall-failed="applications.ingress.uninstallFailed"
......@@ -238,11 +228,6 @@ export default {
}}
</p>
<ingress-modsecurity-settings
:ingress="ingress"
:ingress-mod-security-help-path="ingressModSecurityHelpPath"
/>
<template v-if="ingressInstalled">
<div class="form-group">
<label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
......@@ -658,7 +643,6 @@ export default {
host: applications.fluentd.host,
port: applications.fluentd.port,
protocol: applications.fluentd.protocol,
waf_log_enabled: applications.fluentd.wafLogEnabled,
cilium_log_enabled: applications.fluentd.ciliumLogEnabled,
}"
:uninstallable="applications.fluentd.uninstallable"
......@@ -680,7 +664,6 @@ export default {
:port="applications.fluentd.port"
:protocol="applications.fluentd.protocol"
:host="applications.fluentd.host"
:waf-log-enabled="applications.fluentd.wafLogEnabled"
:cilium-log-enabled="applications.fluentd.ciliumLogEnabled"
:status="applications.fluentd.status"
:update-failed="applications.fluentd.updateFailed"
......
......@@ -45,10 +45,6 @@ export default {
required: false,
default: '',
},
wafLogEnabled: {
type: Boolean,
required: false,
},
ciliumLogEnabled: {
type: Boolean,
required: false,
......@@ -60,7 +56,6 @@ export default {
host: null,
port: null,
protocol: null,
wafLogEnabled: null,
ciliumLogEnabled: null,
},
};
......@@ -109,7 +104,6 @@ export default {
port: this.port,
protocol: this.protocol,
host: this.host,
waf_log_enabled: this.wafLogEnabled,
cilium_log_enabled: this.ciliumLogEnabled,
},
});
......@@ -151,9 +145,6 @@ export default {
portChanged(port) {
this.setFluentdSettings({ port: Number(port) });
},
wafLogChanged(wafLogEnabled) {
this.setFluentdSettings({ wafLogEnabled });
},
ciliumLogChanged(ciliumLogEnabled) {
this.setFluentdSettings({ ciliumLogEnabled });
},
......@@ -210,9 +201,6 @@ export default {
</gl-dropdown>
</div>
<div class="form-group flex flex-wrap">
<gl-form-checkbox :checked="wafLogEnabled" @input="wafLogChanged">
<strong>{{ s__('ClusterIntegration|Send Web Application Firewall Logs') }}</strong>
</gl-form-checkbox>
<gl-form-checkbox :checked="ciliumLogEnabled" @input="ciliumLogChanged">
<strong>{{ s__('ClusterIntegration|Send Container Network Policies Logs') }}</strong>
</gl-form-checkbox>
......
<script>
import {
GlAlert,
GlSprintf,
GlLink,
GlToggle,
GlButton,
GlDropdown,
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
import { escape } from 'lodash';
import modSecurityLogo from 'images/cluster_app_logos/gitlab.png';
import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
import { s__, __ } from '../../locale';
const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
export default {
i18n: {
modSecurityEnabled: s__('ClusterIntegration|ModSecurity enabled'),
},
title: __('Web Application Firewall'),
modsecurityUrl: 'https://modsecurity.org/about.html',
components: {
GlAlert,
GlSprintf,
GlLink,
GlToggle,
GlButton,
GlDropdown,
GlDropdownItem,
GlIcon,
},
props: {
ingress: {
type: Object,
required: true,
},
ingressModSecurityHelpPath: {
type: String,
required: false,
default: '',
},
modes: {
type: Object,
required: false,
default: () => ({
[LOGGING_MODE]: {
name: s__('ClusterIntegration|Logging mode'),
},
[BLOCKING_MODE]: {
name: s__('ClusterIntegration|Blocking mode'),
},
}),
},
},
data() {
return {
modSecurityLogo,
initialValue: null,
initialMode: null,
};
},
computed: {
modSecurityEnabled: {
get() {
return this.ingress.modsecurity_enabled;
},
set(isEnabled) {
if (this.initialValue === null) {
this.initialValue = this.ingress.modsecurity_enabled;
}
eventHub.$emit('setIngressModSecurityEnabled', {
id: INGRESS,
modSecurityEnabled: isEnabled,
});
},
},
hasValueChanged() {
return this.modSecurityEnabledChanged || this.modSecurityModeChanged;
},
modSecurityEnabledChanged() {
return this.initialValue !== null && this.initialValue !== this.ingress.modsecurity_enabled;
},
modSecurityModeChanged() {
return (
this.ingress.modsecurity_enabled &&
this.initialMode !== null &&
this.initialMode !== this.ingress.modsecurity_mode
);
},
ingressModSecurityDescription() {
return escape(this.ingressModSecurityHelpPath);
},
saving() {
return [UPDATING].includes(this.ingress.status);
},
saveButtonDisabled() {
return (
[UNINSTALLING, UPDATING, INSTALLING].includes(this.ingress.status) ||
this.ingress.updateAvailable
);
},
saveButtonLabel() {
return this.saving ? __('Saving') : __('Save changes');
},
/**
* Returns true either when:
* - The application is getting updated.
* - The user has changed some of the settings for an application which is
* neither getting installed nor updated.
*/
showButtons() {
return this.saving || this.valuesChangedByUser;
},
modSecurityModeName() {
return this.modes[this.ingress.modsecurity_mode].name;
},
valuesChangedByUser() {
return this.hasValueChanged && [INSTALLED, UPDATED].includes(this.ingress.status);
},
},
methods: {
updateApplication() {
eventHub.$emit('updateApplication', {
id: INGRESS,
params: {
modsecurity_enabled: this.ingress.modsecurity_enabled,
modsecurity_mode: this.ingress.modsecurity_mode,
},
});
this.resetStatus();
},
resetStatus() {
if (this.initialMode !== null) {
// eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_mode = this.initialMode;
}
if (this.initialValue !== null) {
// eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_enabled = this.initialValue;
}
this.initialValue = null;
this.initialMode = null;
eventHub.$emit('resetIngressModSecurityChanges', INGRESS);
},
selectMode(modeKey) {
if (this.initialMode === null) {
this.initialMode = this.ingress.modsecurity_mode;
}
eventHub.$emit('setIngressModSecurityMode', {
id: INGRESS,
modSecurityMode: modeKey,
});
},
},
};
</script>
<template>
<div>
<gl-alert
v-if="ingress.updateFailed"
class="mb-3"
variant="danger"
:dismissible="false"
@dismiss="alert = null"
>
{{
s__(
'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.',
)
}}
</gl-alert>
<div class="gl-responsive-table-row-layout" role="row">
<div class="table-section gl-mr-3 section-align-top" role="gridcell">
<img
:src="modSecurityLogo"
:alt="`${$options.title} logo`"
class="cluster-application-logo avatar s40"
/>
</div>
<div class="table-section section-wrap" role="gridcell">
<strong>
<gl-link :href="$options.modsecurityUrl" target="_blank">{{ $options.title }} </gl-link>
</strong>
<div class="form-group">
<p class="form-text text-muted">
<strong>
<gl-sprintf
:message="
s__(
'ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}',
)
"
>
<template #link="{ content }">
<gl-link :href="ingressModSecurityDescription" target="_blank"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
</strong>
</p>
<div class="form-check form-check-inline mt-3">
<gl-toggle
v-model="modSecurityEnabled"
:disabled="saveButtonDisabled"
:label="$options.i18n.modSecurityEnabled"
label-position="hidden"
/>
</div>
<div
v-if="ingress.modsecurity_enabled"
class="gl-responsive-table-row-layout mt-3"
role="row"
>
<div class="table-section section-wrap" role="gridcell">
<strong>
{{ s__('ClusterIntegration|Global default') }}
<gl-icon name="earth" class="align-text-bottom" />
</strong>
<div class="form-group">
<p class="form-text text-muted">
<strong>
{{
s__(
'ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level.',
)
}}
</strong>
</p>
</div>
<gl-dropdown :text="modSecurityModeName" :disabled="saveButtonDisabled">
<gl-dropdown-item v-for="(mode, key) in modes" :key="key" @click="selectMode(key)">
{{ mode.name }}
</gl-dropdown-item>
</gl-dropdown>
</div>
</div>
<div v-if="showButtons" class="gl-mt-5 gl-display-flex">
<gl-button
variant="success"
category="primary"
data-qa-selector="save_ingress_modsecurity_settings"
:loading="saving"
:disabled="saveButtonDisabled"
@click="updateApplication"
>
{{ saveButtonLabel }}
</gl-button>
<gl-button
data-qa-selector="cancel_ingress_modsecurity_settings"
:disabled="saveButtonDisabled"
@click="resetStatus"
>
{{ __('Cancel') }}
</gl-button>
</div>
</div>
</div>
</div>
</div>
</template>
......@@ -55,12 +55,8 @@ export default class ClusterStore {
ingress: {
...applicationInitialState,
title: s__('ClusterIntegration|Ingress'),
modsecurity_enabled: false,
modsecurity_mode: null,
externalIp: null,
externalHostname: null,
isEditingModSecurityEnabled: false,
isEditingModSecurityMode: false,
updateFailed: false,
updateAvailable: false,
},
......@@ -112,7 +108,6 @@ export default class ClusterStore {
host: null,
port: null,
protocol: null,
wafLogEnabled: null,
ciliumLogEnabled: null,
isEditingSettings: false,
},
......@@ -219,12 +214,6 @@ export default class ClusterStore {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
this.state.applications.ingress.updateAvailable = updateAvailable;
if (!this.state.applications.ingress.isEditingModSecurityEnabled) {
this.state.applications.ingress.modsecurity_enabled = serverAppEntry.modsecurity_enabled;
}
if (!this.state.applications.ingress.isEditingModSecurityMode) {
this.state.applications.ingress.modsecurity_mode = serverAppEntry.modsecurity_mode;
}
} else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email =
this.state.applications.cert_manager.email || serverAppEntry.email;
......@@ -262,7 +251,6 @@ export default class ClusterStore {
this.state.applications.fluentd.port = serverAppEntry.port;
this.state.applications.fluentd.host = serverAppEntry.host;
this.state.applications.fluentd.protocol = serverAppEntry.protocol;
this.state.applications.fluentd.wafLogEnabled = serverAppEntry.waf_log_enabled;
this.state.applications.fluentd.ciliumLogEnabled = serverAppEntry.cilium_log_enabled;
}
}
......
......@@ -16,6 +16,7 @@ module Clusters
default_value_for :version, VERSION
default_value_for :port, 514
default_value_for :protocol, :tcp
default_value_for :waf_log_enabled, false
enum protocol: { tcp: 0, udp: 1 }
......
......@@ -5,7 +5,7 @@ module Clusters
class BaseService
InvalidApplicationError = Class.new(StandardError)
FLUENTD_KNOWN_ATTRS = %i[host protocol port waf_log_enabled cilium_log_enabled].freeze
FLUENTD_KNOWN_ATTRS = %i[host protocol port cilium_log_enabled].freeze
attr_reader :cluster, :current_user, :params
......
......@@ -30,7 +30,6 @@
helm_help_path: help_page_path('user/clusters/applications.md', anchor: 'helm'),
ingress_help_path: help_page_path('user/clusters/applications.md', anchor: 'determining-the-external-endpoint-automatically'),
ingress_dns_help_path: help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint'),
ingress_mod_security_help_path: help_page_path('user/clusters/applications.md', anchor: 'web-application-firewall-modsecurity'),
environments_help_path: help_page_path('ci/environments/index.md', anchor: 'create-a-static-environment'),
clusters_help_path: help_page_path('user/project/clusters/index.md', anchor: 'deploying-to-a-kubernetes-cluster'),
deploy_boards_help_path: help_page_path('user/project/deploy_boards.md', anchor: 'enabling-deploy-boards'),
......
......@@ -28,10 +28,6 @@ export default {
type: Number,
required: true,
},
wafNoDataSvgPath: {
type: String,
required: true,
},
networkPolicyNoDataSvgPath: {
type: String,
required: true,
......@@ -62,15 +58,6 @@ export default {
return Number.isInteger(id) && id >= 0;
},
},
chartEmptyStateDescription: s__(
`ThreatMonitoring|While it's rare to have no traffic coming to your
application, it can happen. In any event, we ask that you double check your
settings to make sure you've set up the WAF correctly.`,
),
wafChartEmptyStateDescription: s__(
`ThreatMonitoring|The firewall is not installed or has been disabled. To view
this data, ensure the web application firewall is installed and enabled for your cluster.`,
),
networkPolicyChartEmptyStateDescription: s__(
`ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view
this data, ensure your Network Policies are installed and enabled for your cluster.`,
......@@ -118,23 +105,6 @@ export default {
<template v-else>
<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"
/>
<hr />
<threat-monitoring-section
ref="networkPolicySection"
store-namespace="threatMonitoringNetworkPolicy"
......
......@@ -27,12 +27,10 @@ const apolloProvider = new VueApollo({
export default () => {
const el = document.querySelector('#js-threat-monitoring-app');
const {
wafStatisticsEndpoint,
networkPolicyStatisticsEndpoint,
environmentsEndpoint,
networkPoliciesEndpoint,
emptyStateSvgPath,
wafNoDataSvgPath,
networkPolicyNoDataSvgPath,
newPolicyPath,
documentationPath,
......@@ -42,7 +40,6 @@ export default () => {
const store = createStore();
store.dispatch('threatMonitoring/setEndpoints', {
wafStatisticsEndpoint,
networkPolicyStatisticsEndpoint,
environmentsEndpoint,
});
......@@ -62,7 +59,6 @@ export default () => {
render(createElement) {
return createElement(ThreatMonitoringApp, {
props: {
wafNoDataSvgPath,
networkPolicyNoDataSvgPath,
defaultEnvironmentId: parseInt(defaultEnvironmentId, 10),
newPolicyPath,
......
......@@ -11,10 +11,6 @@ export default () =>
new Vuex.Store({
modules: {
threatMonitoring: threatMonitoring(),
threatMonitoringWaf: threatMonitoringStatistics((payload) => {
const { totalTraffic, anomalousTraffic, history } = convertObjectPropsToCamelCase(payload);
return { total: totalTraffic, anomalous: anomalousTraffic, history };
}),
threatMonitoringNetworkPolicy: threatMonitoringStatistics((payload) => {
const {
opsRate,
......
......@@ -5,9 +5,6 @@ import * as types from './mutation_types';
export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINT, endpoints.environmentsEndpoint);
commit(`threatMonitoringWaf/${types.SET_ENDPOINT}`, endpoints.wafStatisticsEndpoint, {
root: true,
});
commit(
`threatMonitoringNetworkPolicy/${types.SET_ENDPOINT}`,
endpoints.networkPolicyStatisticsEndpoint,
......
......@@ -7,11 +7,6 @@ export const currentEnvironmentName = ({ currentEnvironmentId, environments }) =
export const canChangeEnvironment = ({
isLoadingEnvironments,
isLoadingWafStatistics,
isLoadingNetworkPolicyStatistics,
environments,
}) =>
!isLoadingEnvironments &&
!isLoadingWafStatistics &&
!isLoadingNetworkPolicyStatistics &&
environments.length > 0;
}) => !isLoadingEnvironments && !isLoadingNetworkPolicyStatistics && environments.length > 0;
......@@ -27,19 +27,3 @@ exports[`ThreatMonitoringApp component given there is a default environment with
/>
</gl-tab-stub>
`;
exports[`ThreatMonitoringApp component given there is a default environment with data renders the waf section 1`] = `
<threat-monitoring-section-stub
anomaloustitle="Anomalous Requests"
chartemptystatesvgpath="/waf-no-data-svg"
chartemptystatetext="The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
chartemptystatetitle="Application firewall not detected"
documentationanchor="web-application-firewall"
documentationpath="/docs"
nominaltitle="Total Requests"
storenamespace="threatMonitoringWaf"
subtitle="Requests"
title="Web Application Firewall"
ylegend="Requests"
/>
`;
......@@ -12,10 +12,8 @@ const defaultEnvironmentId = 3;
const documentationPath = '/docs';
const newPolicyPath = '/policy/new';
const emptyStateSvgPath = '/svgs';
const wafNoDataSvgPath = '/waf-no-data-svg';
const networkPolicyNoDataSvgPath = '/network-policy-no-data-svg';
const environmentsEndpoint = `${TEST_HOST}/environments`;
const wafStatisticsEndpoint = `${TEST_HOST}/waf`;
const networkPolicyStatisticsEndpoint = `${TEST_HOST}/network_policy`;
describe('ThreatMonitoringApp component', () => {
......@@ -26,7 +24,6 @@ describe('ThreatMonitoringApp component', () => {
store = createStore();
Object.assign(store.state.threatMonitoring, {
environmentsEndpoint,
wafStatisticsEndpoint,
networkPolicyStatisticsEndpoint,
...state,
});
......@@ -38,7 +35,6 @@ describe('ThreatMonitoringApp component', () => {
propsData: {
defaultEnvironmentId,
emptyStateSvgPath,
wafNoDataSvgPath,
networkPolicyNoDataSvgPath,
newPolicyPath,
...propsData,
......@@ -56,7 +52,6 @@ describe('ThreatMonitoringApp component', () => {
const findAlertsView = () => wrapper.find(ThreatMonitoringAlerts);
const findNetworkPolicyList = () => wrapper.find(NetworkPolicyList);
const findFilters = () => wrapper.find(ThreatMonitoringFilters);
const findWafSection = () => wrapper.find({ ref: 'wafSection' });
const findNetworkPolicySection = () => wrapper.find({ ref: 'networkPolicySection' });
const findNoEnvironmentEmptyStates = () => wrapper.findAll(NoEnvironmentEmptyState);
const findNetworkPolicyTab = () => wrapper.find({ ref: 'networkPolicyTab' });
......@@ -119,10 +114,6 @@ describe('ThreatMonitoringApp component', () => {
expect(findFilters().exists()).toBe(true);
});
it('renders the waf section', () => {
expect(findWafSection().element).toMatchSnapshot();
});
it('renders the network policy section', () => {
expect(findNetworkPolicySection().element).toMatchSnapshot();
});
......
......@@ -99,24 +99,17 @@ describe('EnvironmentPicker component', () => {
});
describe.each`
context | isLoadingEnvironments | isLoadingWafStatistics | isLoadingNetworkPolicyStatistics | environments
${'environments are loading'} | ${true} | ${false} | ${false} | ${mockEnvironments}
${'WAF statistics are loading'} | ${false} | ${true} | ${false} | ${mockEnvironments}
${'NetPol statistics are loading'} | ${false} | ${false} | ${true} | ${mockEnvironments}
${'there are no environments'} | ${false} | ${false} | ${false} | ${[]}
context | isLoadingEnvironments | isLoadingNetworkPolicyStatistics | environments
${'environments are loading'} | ${true} | ${false} | ${mockEnvironments}
${'NetPol statistics are loading'} | ${false} | ${true} | ${mockEnvironments}
${'there are no environments'} | ${false} | ${false} | ${[]}
`(
'given $context',
({
isLoadingEnvironments,
isLoadingWafStatistics,
isLoadingNetworkPolicyStatistics,
environments,
}) => {
({ isLoadingEnvironments, isLoadingNetworkPolicyStatistics, environments }) => {
beforeEach(() => {
factory({
environments,
isLoadingEnvironments,
isLoadingWafStatistics,
isLoadingNetworkPolicyStatistics,
});
......
......@@ -66,24 +66,17 @@ describe('ThreatMonitoringFilters component', () => {
});
describe.each`
context | isLoadingEnvironments | isLoadingWafStatistics | isLoadingNetworkPolicyStatistics | environments
${'environments are loading'} | ${true} | ${false} | ${false} | ${mockEnvironments}
${'WAF statistics are loading'} | ${false} | ${true} | ${false} | ${mockEnvironments}
${'NetPol statistics are loading'} | ${false} | ${false} | ${true} | ${mockEnvironments}
${'there are no environments'} | ${false} | ${false} | ${false} | ${[]}
context | isLoadingEnvironments | isLoadingNetworkPolicyStatistics | environments
${'environments are loading'} | ${true} | ${false} | ${mockEnvironments}
${'NetPol statistics are loading'} | ${false} | ${true} | ${mockEnvironments}
${'there are no environments'} | ${false} | ${false} | ${[]}
`(
'given $context',
({
isLoadingEnvironments,
isLoadingWafStatistics,
isLoadingNetworkPolicyStatistics,
environments,
}) => {
({ isLoadingEnvironments, isLoadingNetworkPolicyStatistics, environments }) => {
beforeEach(() => {
factory({
environments,
isLoadingEnvironments,
isLoadingWafStatistics,
isLoadingNetworkPolicyStatistics,
});
......
......@@ -18,7 +18,7 @@ describe('ThreatMonitoringSection component', () => {
const factory = ({ propsData, state } = {}) => {
store = createStore();
Object.assign(store.state.threatMonitoringWaf, {
Object.assign(store.state.threatMonitoringNetworkPolicy, {
isLoadingStatistics: false,
statistics: {
total: 100,
......@@ -36,7 +36,7 @@ describe('ThreatMonitoringSection component', () => {
wrapper = shallowMount(ThreatMonitoringSection, {
propsData: {
storeNamespace: 'threatMonitoringWaf',
storeNamespace: 'threatMonitoringNetworkPolicy',
title: 'Web Application Firewall',
subtitle: 'Requests',
nominalTitle: 'Total Requests',
......@@ -113,21 +113,21 @@ describe('ThreatMonitoringSection component', () => {
});
it('fetches statistics', () => {
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringWaf/fetchStatistics');
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringNetworkPolicy/fetchStatistics');
});
it('fetches statistics on environment change', async () => {
store.dispatch.mockReset();
await store.commit('threatMonitoring/SET_CURRENT_ENVIRONMENT_ID', 2);
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringWaf/fetchStatistics');
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringNetworkPolicy/fetchStatistics');
});
it('fetches statistics on time window change', async () => {
store.dispatch.mockReset();
await store.commit('threatMonitoring/SET_CURRENT_TIME_WINDOW', 'hour');
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringWaf/fetchStatistics');
expect(store.dispatch).toHaveBeenCalledWith('threatMonitoringNetworkPolicy/fetchStatistics');
});
describe('given the statistics are loading', () => {
......
......@@ -7,7 +7,7 @@ export const mockEnvironmentsResponse = {
},
{
id: 1156094,
name: 'review/enable-blocking-waf',
name: 'review/enable-network-policies',
state: 'available',
},
],
......@@ -51,15 +51,6 @@ export const mockAnomalousHistory = [
['2019-12-05T00:00:00.000Z', 83],
];
export const mockWafStatisticsResponse = {
total_traffic: 2703,
anomalous_traffic: 0.03,
history: {
nominal: mockNominalHistory,
anomalous: mockAnomalousHistory,
},
};
export const mockNetworkPolicyStatisticsResponse = {
ops_total: {
total: 2703,
......
......@@ -13,7 +13,6 @@ import { mockEnvironmentsResponse } from '../../../mocks/mock_data';
jest.mock('~/flash');
const environmentsEndpoint = 'environmentsEndpoint';
const wafStatisticsEndpoint = 'wafStatisticsEndpoint';
const networkPolicyStatisticsEndpoint = 'networkPolicyStatisticsEndpoint';
describe('Threat Monitoring actions', () => {
......@@ -33,7 +32,6 @@ describe('Threat Monitoring actions', () => {
actions.setEndpoints,
{
environmentsEndpoint,
wafStatisticsEndpoint,
networkPolicyStatisticsEndpoint,
},
state,
......@@ -42,10 +40,6 @@ describe('Threat Monitoring actions', () => {
type: types.SET_ENDPOINT,
payload: environmentsEndpoint,
},
{
type: `threatMonitoringWaf/${types.SET_ENDPOINT}`,
payload: wafStatisticsEndpoint,
},
{
type: `threatMonitoringNetworkPolicy/${types.SET_ENDPOINT}`,
payload: networkPolicyStatisticsEndpoint,
......
......@@ -8,7 +8,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import { mockWafStatisticsResponse } from '../../../mocks/mock_data';
import { mockNetworkPolicyStatisticsResponse } from '../../../mocks/mock_data';
jest.mock('~/flash');
......@@ -51,12 +51,12 @@ describe('threatMonitoringStatistics actions', () => {
it('commits the RECEIVE_STATISTICS_SUCCESS mutation', () =>
testAction(
actions.receiveStatisticsSuccess,
mockWafStatisticsResponse,
mockNetworkPolicyStatisticsResponse,
state,
[
{
type: types.RECEIVE_STATISTICS_SUCCESS,
payload: mockWafStatisticsResponse,
payload: mockNetworkPolicyStatisticsResponse,
},
],
[],
......@@ -105,7 +105,7 @@ describe('threatMonitoringStatistics actions', () => {
...timeRange,
},
})
.replyOnce(httpStatus.OK, mockWafStatisticsResponse);
.replyOnce(httpStatus.OK, mockNetworkPolicyStatisticsResponse);
});
it('should dispatch the request and success actions', () =>
......@@ -121,7 +121,7 @@ describe('threatMonitoringStatistics actions', () => {
},
{
type: 'receiveStatisticsSuccess',
payload: mockWafStatisticsResponse,
payload: mockNetworkPolicyStatisticsResponse,
},
],
));
......
import * as types from 'ee/threat_monitoring/store/modules/threat_monitoring_statistics/mutation_types';
import mutationsFactory from 'ee/threat_monitoring/store/modules/threat_monitoring_statistics/mutations';
import { mockWafStatisticsResponse } from '../../../mocks/mock_data';
import { mockNetworkPolicyStatisticsResponse } from '../../../mocks/mock_data';
describe('threatMonitoringStatistics mutations', () => {
let state;
......@@ -39,11 +39,11 @@ describe('threatMonitoringStatistics mutations', () => {
describe(types.RECEIVE_STATISTICS_SUCCESS, () => {
beforeEach(() => {
mutations[types.RECEIVE_STATISTICS_SUCCESS](state, mockWafStatisticsResponse);
mutations[types.RECEIVE_STATISTICS_SUCCESS](state, mockNetworkPolicyStatisticsResponse);
});
it('sets statistics according to the payload', () => {
expect(state.statistics).toEqual(mockWafStatisticsResponse);
expect(state.statistics).toEqual(mockNetworkPolicyStatisticsResponse);
});
it('sets isLoadingStatistics to false', () => {
......
......@@ -7027,9 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
msgid "ClusterIntegration|Blocking mode"
msgstr ""
msgid "ClusterIntegration|CA Certificate"
msgstr ""
......@@ -7279,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
msgid "ClusterIntegration|Global default"
msgstr ""
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
......@@ -7438,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
msgid "ClusterIntegration|Logging mode"
msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr ""
......@@ -7453,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
msgid "ClusterIntegration|ModSecurity enabled"
msgstr ""
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
......@@ -7552,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
......@@ -7693,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
msgid "ClusterIntegration|Send Web Application Firewall Logs"
msgstr ""
msgid "ClusterIntegration|Service Token"
msgstr ""
......@@ -7708,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
......@@ -33723,9 +33702,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
msgid "ThreatMonitoring|Application firewall not detected"
msgstr ""
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
......@@ -33804,9 +33780,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
......@@ -33837,12 +33810,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
msgid "ThreatMonitoring|Web Application Firewall"
msgstr ""
msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
msgstr ""
msgid "Throughput"
msgstr ""
......@@ -36559,9 +36526,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
msgid "Web Application Firewall"
msgstr ""
msgid "Web IDE"
msgstr ""
......
......@@ -3,7 +3,6 @@ import ApplicationRow from '~/clusters/components/application_row.vue';
import Applications from '~/clusters/components/applications.vue';
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
import FluentdOutputSettings from '~/clusters/components/fluentd_output_settings.vue';
import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
import { CLUSTER_TYPE, PROVIDER_TYPE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
......@@ -185,24 +184,6 @@ describe('Applications', () => {
expect(findByTestId('ingressCostWarning').element).toMatchSnapshot();
});
describe('with nested component', () => {
const propsData = {
applications: {
ingress: {
title: 'Ingress',
status: 'installed',
},
},
};
beforeEach(() => createShallowComponent(propsData));
it('renders IngressModsecuritySettings', () => {
const modsecuritySettings = wrapper.find(IngressModsecuritySettings);
expect(modsecuritySettings.exists()).toBe(true);
});
});
describe('when installed', () => {
describe('with ip address', () => {
it('renders ip address with a clipboard button', () => {
......@@ -231,7 +212,6 @@ describe('Applications', () => {
title: 'Ingress',
status: 'installed',
externalHostname: 'localhost.localdomain',
modsecurity_enabled: false,
},
cert_manager: { title: 'Cert-Manager' },
crossplane: { title: 'Crossplane', stack: '' },
......
......@@ -13,7 +13,6 @@ describe('FluentdOutputSettings', () => {
protocol: 'tcp',
host: '127.0.0.1',
port: 514,
wafLogEnabled: true,
ciliumLogEnabled: false,
};
const defaultProps = {
......@@ -52,9 +51,8 @@ describe('FluentdOutputSettings', () => {
const changePort = (val) => changeInput(findPort(), val);
const changeHost = (val) => changeInput(findHost(), val);
const changeProtocol = (idx) => findProtocolDropdown().vm.$children[idx].$emit('click');
const toApplicationSettings = ({ wafLogEnabled, ciliumLogEnabled, ...settings }) => ({
const toApplicationSettings = ({ ciliumLogEnabled, ...settings }) => ({
...settings,
waf_log_enabled: wafLogEnabled,
cilium_log_enabled: ciliumLogEnabled,
});
......@@ -74,7 +72,6 @@ describe('FluentdOutputSettings', () => {
${'when protocol dropdown is triggered'} | ${() => changeProtocol(1)} | ${'protocol'} | ${'udp'}
${'when host is changed'} | ${() => changeHost('test-host')} | ${'host'} | ${'test-host'}
${'when port is changed'} | ${() => changePort(123)} | ${'port'} | ${123}
${'when wafLogEnabled changes'} | ${() => changeCheckbox(findCheckbox('Send Web Application Firewall Logs'))} | ${'wafLogEnabled'} | ${!defaultSettings.wafLogEnabled}
${'when ciliumLogEnabled changes'} | ${() => changeCheckbox(findCheckbox('Send Container Network Policies Logs'))} | ${'ciliumLogEnabled'} | ${!defaultSettings.ciliumLogEnabled}
`('$desc', ({ changeFn, key, value }) => {
beforeEach(() => {
......
import { GlAlert, GlToggle, GlDropdown } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
const { UPDATING } = APPLICATION_STATUS;
describe('IngressModsecuritySettings', () => {
let wrapper;
const defaultProps = {
modsecurity_enabled: false,
status: 'installable',
installed: false,
modsecurity_mode: 'logging',
updateAvailable: false,
};
const createComponent = (props = defaultProps) => {
wrapper = shallowMount(IngressModsecuritySettings, {
propsData: {
ingress: {
...defaultProps,
...props,
},
},
});
};
const findSaveButton = () =>
wrapper.find('[data-qa-selector="save_ingress_modsecurity_settings"]');
const findCancelButton = () =>
wrapper.find('[data-qa-selector="cancel_ingress_modsecurity_settings"]');
const findModSecurityToggle = () => wrapper.find(GlToggle);
const findModSecurityDropdown = () => wrapper.find(GlDropdown);
describe('when ingress is installed', () => {
beforeEach(() => {
createComponent({ installed: true, status: 'installed' });
jest.spyOn(eventHub, '$emit');
});
it('does not render save and cancel buttons', () => {
expect(findSaveButton().exists()).toBe(false);
expect(findCancelButton().exists()).toBe(false);
});
describe('with toggle changed by the user', () => {
beforeEach(() => {
findModSecurityToggle().vm.$emit('change');
wrapper.setProps({
ingress: {
...defaultProps,
installed: true,
status: 'installed',
modsecurity_enabled: true,
},
});
});
it('renders toggle with label', () => {
expect(findModSecurityToggle().props('label')).toBe(
IngressModsecuritySettings.i18n.modSecurityEnabled,
);
});
it('renders save and cancel buttons', () => {
expect(findSaveButton().exists()).toBe(true);
expect(findCancelButton().exists()).toBe(true);
});
it('enables related toggle and buttons', () => {
expect(findSaveButton().attributes().disabled).toBeUndefined();
expect(findCancelButton().attributes().disabled).toBeUndefined();
});
describe('with dropdown changed by the user', () => {
beforeEach(() => {
findModSecurityDropdown().vm.$children[1].$emit('click');
wrapper.setProps({
ingress: {
...defaultProps,
installed: true,
status: 'installed',
modsecurity_enabled: true,
modsecurity_mode: 'blocking',
},
});
});
it('renders both save and cancel buttons', () => {
expect(findSaveButton().exists()).toBe(true);
expect(findCancelButton().exists()).toBe(true);
});
describe('and the save changes button is clicked', () => {
beforeEach(() => {
findSaveButton().vm.$emit('click');
});
it('triggers save event and pass current modsecurity value', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('updateApplication', {
id: INGRESS,
params: { modsecurity_enabled: true, modsecurity_mode: 'blocking' },
});
});
});
});
describe('and the cancel button is clicked', () => {
beforeEach(() => {
findCancelButton().vm.$emit('click');
});
it('triggers reset event and hides both cancel and save changes button', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('resetIngressModSecurityChanges', INGRESS);
expect(findSaveButton().exists()).toBe(false);
expect(findCancelButton().exists()).toBe(false);
});
});
describe('with a new version available', () => {
beforeEach(() => {
wrapper.setProps({
ingress: {
...defaultProps,
installed: true,
status: 'installed',
modsecurity_enabled: true,
updateAvailable: true,
},
});
});
it('disables related toggle and buttons', () => {
expect(findSaveButton().attributes().disabled).toBe('true');
expect(findCancelButton().attributes().disabled).toBe('true');
});
});
});
it('triggers set event to be propagated with the current modsecurity value', () => {
wrapper.setData({ modSecurityEnabled: true });
return wrapper.vm.$nextTick().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('setIngressModSecurityEnabled', {
id: INGRESS,
modSecurityEnabled: true,
});
});
});
describe(`when ingress status is ${UPDATING}`, () => {
beforeEach(() => {
createComponent({ installed: true, status: UPDATING });
});
it('renders loading spinner in save button', () => {
expect(findSaveButton().props('loading')).toBe(true);
});
it('renders disabled save button', () => {
expect(findSaveButton().props('disabled')).toBe(true);
});
it('renders save button with "Saving" label', () => {
expect(findSaveButton().text()).toBe('Saving');
});
});
describe('when ingress fails to update', () => {
beforeEach(() => {
createComponent({ updateFailed: true });
});
it('displays a error message', () => {
expect(wrapper.find(GlAlert).exists()).toBe(true);
});
});
});
describe('when ingress is not installed', () => {
beforeEach(() => {
createComponent();
});
it('does not render the save button', () => {
expect(findSaveButton().exists()).toBe(false);
expect(findModSecurityToggle().props('value')).toBe(false);
});
});
});
......@@ -20,7 +20,6 @@ const CLUSTERS_MOCK_DATA = {
external_ip: null,
external_hostname: null,
can_uninstall: false,
modsecurity_enabled: false,
},
{
name: 'runner',
......@@ -154,7 +153,6 @@ const APPLICATIONS_MOCK_STATE = {
ingress: {
title: 'Ingress',
status: 'installable',
modsecurity_enabled: false,
},
crossplane: { title: 'Crossplane', status: 'installable', stack: '' },
cert_manager: { title: 'Cert-Manager', status: 'installable' },
......
......@@ -84,16 +84,12 @@ describe('Clusters Store', () => {
externalHostname: null,
installable: true,
installed: false,
isEditingModSecurityEnabled: false,
isEditingModSecurityMode: false,
installFailed: true,
uninstallable: false,
updateFailed: false,
uninstallSuccessful: false,
uninstallFailed: false,
validationError: null,
modsecurity_enabled: false,
modsecurity_mode: undefined,
},
runner: {
title: 'GitLab Runner',
......@@ -143,7 +139,6 @@ describe('Clusters Store', () => {
uninstallSuccessful: false,
uninstallFailed: false,
validationError: null,
wafLogEnabled: null,
},
jupyter: {
title: 'JupyterHub',
......
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