257 lines
7.6 KiB
Vue
257 lines
7.6 KiB
Vue
<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 {
|
|
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: () => ({
|
|
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" />
|
|
</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>
|