Skip to content
Snippets Groups Projects
Commit 4cb5e501 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 0301a0ca
No related branches found
No related tags found
No related merge requests found
Showing
with 224 additions and 63 deletions
app/assets/images/cluster_app_logos/modsecurity.png

6.09 KiB

Loading
Loading
@@ -256,6 +256,7 @@ export default class Clusters {
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data));
eventHub.$on('resetIngressModSecurityEnabled', id => this.resetIngressModSecurityEnabled(id));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
Loading
Loading
@@ -270,6 +271,7 @@ export default class Clusters {
eventHub.$off('setCrossplaneProviderStack');
eventHub.$off('uninstallApplication');
eventHub.$off('setIngressModSecurityEnabled');
eventHub.$off('resetIngressModSecurityEnabled');
}
 
initPolling(method, successCallback, errorCallback) {
Loading
Loading
@@ -523,6 +525,10 @@ export default class Clusters {
this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled);
}
 
resetIngressModSecurityEnabled(id) {
this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', false);
}
destroy() {
this.destroyed = true;
 
Loading
Loading
Loading
Loading
@@ -119,9 +119,6 @@ export default {
ingressInstalled() {
return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED;
},
ingressEnableModsecurity() {
return this.applications.ingress.modsecurity_enabled;
},
ingressExternalEndpoint() {
return this.applications.ingress.externalIp || this.applications.ingress.externalHostname;
},
Loading
Loading
<script>
import _ from 'lodash';
import { __ } from '../../locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import { GlAlert, GlSprintf, GlLink, GlToggle, GlButton } from '@gitlab/ui';
import eventHub from '~/clusters/event_hub';
import modSecurityLogo from 'images/cluster_app_logos/modsecurity.png';
 
const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
 
export default {
title: 'ModSecurity Web Application Firewall',
modsecurityUrl: 'https://modsecurity.org/about.html',
components: {
LoadingButton,
GlAlert,
GlSprintf,
GlLink,
GlToggle,
GlButton,
},
props: {
ingress: {
Loading
Loading
@@ -26,6 +29,10 @@ export default {
default: '',
},
},
data: () => ({
modSecurityLogo,
hasValueChanged: false,
}),
computed: {
modSecurityEnabled: {
get() {
Loading
Loading
@@ -36,6 +43,11 @@ export default {
id: INGRESS,
modSecurityEnabled: isEnabled,
});
if (this.hasValueChanged) {
this.resetStatus();
} else {
this.hasValueChanged = true;
}
},
},
ingressModSecurityDescription() {
Loading
Loading
@@ -45,13 +57,21 @@ export default {
return [UPDATING].includes(this.ingress.status);
},
saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.ingress.status);
return [UNINSTALLING, UPDATING, INSTALLING].includes(this.ingress.status);
},
saveButtonLabel() {
return this.saving ? __('Saving') : __('Save changes');
},
ingressInstalled() {
return this.ingress.installed;
/**
* 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.hasValueChanged && [INSTALLED, UPDATED].includes(this.ingress.status))
);
},
},
methods: {
Loading
Loading
@@ -60,6 +80,11 @@ export default {
id: INGRESS,
params: { modsecurity_enabled: this.ingress.modsecurity_enabled },
});
this.resetStatus();
},
resetStatus() {
eventHub.$emit('resetIngressModSecurityEnabled', INGRESS);
this.hasValueChanged = false;
},
},
};
Loading
Loading
@@ -75,42 +100,65 @@ export default {
@dismiss="alert = null"
>
{{
s__('ClusterIntegration|Something went wrong while updating the Web Application Firewall.')
s__(
'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.',
)
}}
</gl-alert>
<div class="form-group">
<div class="form-check form-check-inline">
<input
v-model="modSecurityEnabled"
type="checkbox"
autocomplete="off"
class="form-check-input"
<div class="gl-responsive-table-row-layout" role="row">
<div class="table-section append-right-8 section-align-top" role="gridcell">
<img
:src="modSecurityLogo"
:alt="`${$options.title} logo`"
class="cluster-application-logo avatar s40"
/>
<label class="form-check-label label-bold" for="ingress-enable-modsecurity">
{{ s__('ClusterIntegration|Enable Web Application Firewall') }}
</label>
</div>
<p class="form-text text-muted">
<div class="table-section section-wrap" role="gridcell">
<strong>
<gl-sprintf
:message="s__('ClusterIntegration|Learn more about %{linkStart}ModSecurity%{linkEnd}')"
>
<template #link="{ content }">
<gl-link :href="ingressModSecurityDescription" target="_blank"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
<gl-link :href="$options.modsecurityUrl" target="_blank">{{ $options.title }} </gl-link>
</strong>
</p>
<loading-button
v-if="ingressInstalled"
class="btn-success mt-1"
:loading="saving"
:disabled="saveButtonDisabled"
:label="saveButtonLabel"
@click="updateApplication"
/>
<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"
:label-on="__('Enabled')"
:label-off="__('Disabled')"
:disabled="saveButtonDisabled"
label-position="right"
/>
</div>
<div v-if="showButtons">
<gl-button
class="btn-success inline mr-1"
:loading="saving"
:disabled="saveButtonDisabled"
@click="updateApplication"
>
{{ saveButtonLabel }}
</gl-button>
<gl-button :disabled="saveButtonDisabled" @click="resetStatus">
{{ __('Cancel') }}
</gl-button>
</div>
</div>
</div>
</div>
</div>
</template>
Loading
Loading
@@ -211,9 +211,7 @@ export default class ClusterStore {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
if (!this.state.applications.ingress.isEditingModSecurityEnabled) {
this.state.applications.ingress.modsecurity_enabled =
serverAppEntry.modsecurity_enabled ||
this.state.applications.ingress.modsecurity_enabled;
this.state.applications.ingress.modsecurity_enabled = serverAppEntry.modsecurity_enabled;
}
} else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email =
Loading
Loading
Loading
Loading
@@ -77,6 +77,9 @@ export default {
v-gl-tooltip
title="Jump to next unresolved thread"
class="btn btn-default discussion-next-btn"
data-track-event="click_button"
data-track-label="mr_next_unresolved_thread"
data-track-property="click_next_unresolved_thread_top"
@click="jumpToNextDiscussion"
>
<icon name="comment-next" />
Loading
Loading
Loading
Loading
@@ -28,6 +28,9 @@ export default {
v-gl-tooltip
class="btn btn-default discussion-next-btn"
:title="s__('MergeRequests|Jump to next unresolved thread')"
data-track-event="click_button"
data-track-label="mr_next_unresolved_thread"
data-track-property="click_next_unresolved_thread"
@click="jumpToNextRelativeDiscussion(fromDiscussionId)"
>
<icon name="comment-next" />
Loading
Loading
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
integrationSettingsForm.init();
if (prometheusSettingsWrapper) {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
Loading
Loading
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
snippetEmbed();
} else {
initSnippetsApp();
initNotes();
}
});
Loading
Loading
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
snippetEmbed();
} else {
initSnippetsApp();
initNotes();
}
});
Loading
Loading
@@ -64,7 +64,7 @@ export default {
:deployment="deployment"
:computed-deployment-status="computedDeploymentStatus"
:show-visual-review-app="showVisualReviewApp"
:visual-review-app-metadata="visualReviewAppMeta"
:visual-review-app-meta="visualReviewAppMeta"
/>
</div>
</div>
Loading
Loading
Loading
Loading
@@ -173,7 +173,7 @@ export default {
:app-button-text="appButtonText"
:deployment="deployment"
:show-visual-review-app="showVisualReviewApp"
:visual-review-app-metadata="visualReviewAppMeta"
:visual-review-app-meta="visualReviewAppMeta"
/>
<deployment-action-button
v-if="stopUrl"
Loading
Loading
Loading
Loading
@@ -93,8 +93,10 @@ export default {
/>
<visual-review-app-link
v-if="showVisualReviewApp"
:view-app-display="appButtonText"
:link="deploymentExternalUrl"
:app-metadata="visualReviewAppMeta"
:changes="deployment.changes"
/>
</span>
</template>
Loading
Loading
@@ -118,6 +118,14 @@
}
}
 
.ssh-keys-list {
.last-used-at,
.expires,
.key-created-at {
line-height: 32px;
}
}
.key-created-at {
line-height: 42px;
}
Loading
Loading
# frozen_string_literal: true
class Admin::IntegrationsController < Admin::ApplicationController
include ServiceParams
before_action :not_found, unless: :instance_level_integrations_enabled?
before_action :service, only: [:edit, :update, :test]
def edit
end
def update
@service.attributes = service_params[:service]
if @service.save(context: :manual_change)
redirect_to edit_admin_application_settings_integration_path(@service), notice: success_message
else
render :edit
end
end
def test
if @service.can_test?
render json: service_test_response, status: :ok
else
render json: {}, status: :not_found
end
end
private
def instance_level_integrations_enabled?
Feature.enabled?(:instance_level_integrations)
end
def project
# TODO: Change to something more meaningful
Project.first
end
def service
@service ||= project.find_or_initialize_service(params[:id])
end
def success_message
message = @service.active? ? _('activated') : _('settings saved, but not activated')
_('%{service_title} %{message}.') % { service_title: @service.title, message: message }
end
def service_test_response
unless @service.update(service_params[:service])
return { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
end
data = @service.test_data(project, current_user)
outcome = @service.test(data)
unless outcome[:success]
return { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
end
{}
rescue Gitlab::HTTP::BlockedUrlError => e
{ error: true, message: _('Test failed.'), service_response: e.message, test_failed: true }
end
end
Loading
Loading
@@ -55,6 +55,6 @@ class Profiles::KeysController < Profiles::ApplicationController
private
 
def key_params
params.require(:key).permit(:title, :key)
params.require(:key).permit(:title, :key, :expires_at)
end
end
Loading
Loading
@@ -52,28 +52,26 @@ class Projects::ServicesController < Projects::ApplicationController
private
 
def service_test_response
if @service.update(service_params[:service])
data = @service.test_data(project, current_user)
outcome = @service.test(data)
if outcome[:success]
{}
else
{ error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
end
else
{ error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
unless @service.update(service_params[:service])
return { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
end
data = @service.test_data(project, current_user)
outcome = @service.test(data)
unless outcome[:success]
return { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
end
{}
rescue Gitlab::HTTP::BlockedUrlError => e
{ error: true, message: _('Test failed.'), service_response: e.message, test_failed: true }
end
 
def success_message
if @service.active?
_("%{service_title} activated.") % { service_title: @service.title }
else
_("%{service_title} settings saved, but not activated.") % { service_title: @service.title }
end
message = @service.active? ? _('activated') : _('settings saved, but not activated')
_('%{service_title} %{message}.') % { service_title: @service.title, message: message }
end
 
def service
Loading
Loading
Loading
Loading
@@ -16,7 +16,7 @@ module Clusters
include AfterCommitQueue
 
default_value_for :ingress_type, :nginx
default_value_for :modsecurity_enabled, false
default_value_for :modsecurity_enabled, true
default_value_for :version, VERSION
 
enum ingress_type: {
Loading
Loading
Loading
Loading
@@ -6,6 +6,7 @@ class Key < ApplicationRecord
include AfterCommitQueue
include Sortable
include Sha256Attribute
include Expirable
 
sha256_attribute :fingerprint_sha256
 
Loading
Loading
%h3.page-title
= @service.title
%p= @service.description
= form_for @service, as: :service, url: admin_application_settings_integration_path, method: :put, html: { class: 'gl-show-field-errors fieldset-form integration-settings-form js-integration-settings-form', data: { 'can-test' => @service.can_test?, 'test-url' => test_admin_application_settings_integration_path(@service) } } do |form|
= render 'shared/service_settings', form: form, service: @service
- if @service.editable?
.footer-block.row-content-block
= service_save_button(@service)
= link_to _('Cancel'), admin_application_settings_integration_path, class: 'btn btn-cancel'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment