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
@@ -256,6 +256,7 @@ export default class Clusters {
Loading
@@ -256,6 +256,7 @@ export default class Clusters {
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data)); eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data)); eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data)); eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data));
eventHub.$on('resetIngressModSecurityEnabled', id => this.resetIngressModSecurityEnabled(id));
// Add event listener to all the banner close buttons // Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable'); this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure'); this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
Loading
@@ -270,6 +271,7 @@ export default class Clusters {
Loading
@@ -270,6 +271,7 @@ export default class Clusters {
eventHub.$off('setCrossplaneProviderStack'); eventHub.$off('setCrossplaneProviderStack');
eventHub.$off('uninstallApplication'); eventHub.$off('uninstallApplication');
eventHub.$off('setIngressModSecurityEnabled'); eventHub.$off('setIngressModSecurityEnabled');
eventHub.$off('resetIngressModSecurityEnabled');
} }
   
initPolling(method, successCallback, errorCallback) { initPolling(method, successCallback, errorCallback) {
Loading
@@ -523,6 +525,10 @@ export default class Clusters {
Loading
@@ -523,6 +525,10 @@ export default class Clusters {
this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled); this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled);
} }
   
resetIngressModSecurityEnabled(id) {
this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', false);
}
destroy() { destroy() {
this.destroyed = true; this.destroyed = true;
   
Loading
Loading
Loading
@@ -119,9 +119,6 @@ export default {
Loading
@@ -119,9 +119,6 @@ export default {
ingressInstalled() { ingressInstalled() {
return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED; return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED;
}, },
ingressEnableModsecurity() {
return this.applications.ingress.modsecurity_enabled;
},
ingressExternalEndpoint() { ingressExternalEndpoint() {
return this.applications.ingress.externalIp || this.applications.ingress.externalHostname; return this.applications.ingress.externalIp || this.applications.ingress.externalHostname;
}, },
Loading
Loading
<script> <script>
import _ from 'lodash'; import _ from 'lodash';
import { __ } from '../../locale'; import { __ } from '../../locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants'; 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 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 { export default {
title: 'ModSecurity Web Application Firewall',
modsecurityUrl: 'https://modsecurity.org/about.html',
components: { components: {
LoadingButton,
GlAlert, GlAlert,
GlSprintf, GlSprintf,
GlLink, GlLink,
GlToggle,
GlButton,
}, },
props: { props: {
ingress: { ingress: {
Loading
@@ -26,6 +29,10 @@ export default {
Loading
@@ -26,6 +29,10 @@ export default {
default: '', default: '',
}, },
}, },
data: () => ({
modSecurityLogo,
hasValueChanged: false,
}),
computed: { computed: {
modSecurityEnabled: { modSecurityEnabled: {
get() { get() {
Loading
@@ -36,6 +43,11 @@ export default {
Loading
@@ -36,6 +43,11 @@ export default {
id: INGRESS, id: INGRESS,
modSecurityEnabled: isEnabled, modSecurityEnabled: isEnabled,
}); });
if (this.hasValueChanged) {
this.resetStatus();
} else {
this.hasValueChanged = true;
}
}, },
}, },
ingressModSecurityDescription() { ingressModSecurityDescription() {
Loading
@@ -45,13 +57,21 @@ export default {
Loading
@@ -45,13 +57,21 @@ export default {
return [UPDATING].includes(this.ingress.status); return [UPDATING].includes(this.ingress.status);
}, },
saveButtonDisabled() { saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.ingress.status); return [UNINSTALLING, UPDATING, INSTALLING].includes(this.ingress.status);
}, },
saveButtonLabel() { saveButtonLabel() {
return this.saving ? __('Saving') : __('Save changes'); 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: { methods: {
Loading
@@ -60,6 +80,11 @@ export default {
Loading
@@ -60,6 +80,11 @@ export default {
id: INGRESS, id: INGRESS,
params: { modsecurity_enabled: this.ingress.modsecurity_enabled }, params: { modsecurity_enabled: this.ingress.modsecurity_enabled },
}); });
this.resetStatus();
},
resetStatus() {
eventHub.$emit('resetIngressModSecurityEnabled', INGRESS);
this.hasValueChanged = false;
}, },
}, },
}; };
Loading
@@ -75,42 +100,65 @@ export default {
Loading
@@ -75,42 +100,65 @@ export default {
@dismiss="alert = null" @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> </gl-alert>
<div class="form-group"> <div class="gl-responsive-table-row-layout" role="row">
<div class="form-check form-check-inline"> <div class="table-section append-right-8 section-align-top" role="gridcell">
<input <img
v-model="modSecurityEnabled" :src="modSecurityLogo"
type="checkbox" :alt="`${$options.title} logo`"
autocomplete="off" class="cluster-application-logo avatar s40"
class="form-check-input"
/> />
<label class="form-check-label label-bold" for="ingress-enable-modsecurity">
{{ s__('ClusterIntegration|Enable Web Application Firewall') }}
</label>
</div> </div>
<p class="form-text text-muted"> <div class="table-section section-wrap" role="gridcell">
<strong> <strong>
<gl-sprintf <gl-link :href="$options.modsecurityUrl" target="_blank">{{ $options.title }} </gl-link>
:message="s__('ClusterIntegration|Learn more about %{linkStart}ModSecurity%{linkEnd}')"
>
<template #link="{ content }">
<gl-link :href="ingressModSecurityDescription" target="_blank"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
</strong> </strong>
</p> <div class="form-group">
<loading-button <p class="form-text text-muted">
v-if="ingressInstalled" <strong>
class="btn-success mt-1" <gl-sprintf
:loading="saving" :message="
:disabled="saveButtonDisabled" s__(
:label="saveButtonLabel" 'ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}',
@click="updateApplication" )
/> "
>
<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>
</div> </div>
</template> </template>
Loading
@@ -211,9 +211,7 @@ export default class ClusterStore {
Loading
@@ -211,9 +211,7 @@ export default class ClusterStore {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip; this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname; this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
if (!this.state.applications.ingress.isEditingModSecurityEnabled) { if (!this.state.applications.ingress.isEditingModSecurityEnabled) {
this.state.applications.ingress.modsecurity_enabled = this.state.applications.ingress.modsecurity_enabled = serverAppEntry.modsecurity_enabled;
serverAppEntry.modsecurity_enabled ||
this.state.applications.ingress.modsecurity_enabled;
} }
} else if (appId === CERT_MANAGER) { } else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email = this.state.applications.cert_manager.email =
Loading
Loading
Loading
@@ -77,6 +77,9 @@ export default {
Loading
@@ -77,6 +77,9 @@ export default {
v-gl-tooltip v-gl-tooltip
title="Jump to next unresolved thread" title="Jump to next unresolved thread"
class="btn btn-default discussion-next-btn" 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" @click="jumpToNextDiscussion"
> >
<icon name="comment-next" /> <icon name="comment-next" />
Loading
Loading
Loading
@@ -28,6 +28,9 @@ export default {
Loading
@@ -28,6 +28,9 @@ export default {
v-gl-tooltip v-gl-tooltip
class="btn btn-default discussion-next-btn" class="btn btn-default discussion-next-btn"
:title="s__('MergeRequests|Jump to next unresolved thread')" :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)" @click="jumpToNextRelativeDiscussion(fromDiscussionId)"
> >
<icon name="comment-next" /> <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
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
Loading
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
snippetEmbed(); snippetEmbed();
} else { } else {
initSnippetsApp(); initSnippetsApp();
initNotes();
} }
}); });
Loading
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
Loading
@@ -14,5 +14,6 @@ document.addEventListener('DOMContentLoaded', () => {
snippetEmbed(); snippetEmbed();
} else { } else {
initSnippetsApp(); initSnippetsApp();
initNotes();
} }
}); });
Loading
@@ -64,7 +64,7 @@ export default {
Loading
@@ -64,7 +64,7 @@ export default {
:deployment="deployment" :deployment="deployment"
:computed-deployment-status="computedDeploymentStatus" :computed-deployment-status="computedDeploymentStatus"
:show-visual-review-app="showVisualReviewApp" :show-visual-review-app="showVisualReviewApp"
:visual-review-app-metadata="visualReviewAppMeta" :visual-review-app-meta="visualReviewAppMeta"
/> />
</div> </div>
</div> </div>
Loading
Loading
Loading
@@ -173,7 +173,7 @@ export default {
Loading
@@ -173,7 +173,7 @@ export default {
:app-button-text="appButtonText" :app-button-text="appButtonText"
:deployment="deployment" :deployment="deployment"
:show-visual-review-app="showVisualReviewApp" :show-visual-review-app="showVisualReviewApp"
:visual-review-app-metadata="visualReviewAppMeta" :visual-review-app-meta="visualReviewAppMeta"
/> />
<deployment-action-button <deployment-action-button
v-if="stopUrl" v-if="stopUrl"
Loading
Loading
Loading
@@ -93,8 +93,10 @@ export default {
Loading
@@ -93,8 +93,10 @@ export default {
/> />
<visual-review-app-link <visual-review-app-link
v-if="showVisualReviewApp" v-if="showVisualReviewApp"
:view-app-display="appButtonText"
:link="deploymentExternalUrl" :link="deploymentExternalUrl"
:app-metadata="visualReviewAppMeta" :app-metadata="visualReviewAppMeta"
:changes="deployment.changes"
/> />
</span> </span>
</template> </template>
Loading
@@ -118,6 +118,14 @@
Loading
@@ -118,6 +118,14 @@
} }
} }
   
.ssh-keys-list {
.last-used-at,
.expires,
.key-created-at {
line-height: 32px;
}
}
.key-created-at { .key-created-at {
line-height: 42px; 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
@@ -55,6 +55,6 @@ class Profiles::KeysController < Profiles::ApplicationController
Loading
@@ -55,6 +55,6 @@ class Profiles::KeysController < Profiles::ApplicationController
private private
   
def key_params def key_params
params.require(:key).permit(:title, :key) params.require(:key).permit(:title, :key, :expires_at)
end end
end end
Loading
@@ -52,28 +52,26 @@ class Projects::ServicesController < Projects::ApplicationController
Loading
@@ -52,28 +52,26 @@ class Projects::ServicesController < Projects::ApplicationController
private private
   
def service_test_response def service_test_response
if @service.update(service_params[:service]) unless @service.update(service_params[:service])
data = @service.test_data(project, current_user) return { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
outcome = @service.test(data) end
if outcome[:success] data = @service.test_data(project, current_user)
{} outcome = @service.test(data)
else
{ error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true } unless outcome[:success]
end return { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
else
{ error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
end end
{}
rescue Gitlab::HTTP::BlockedUrlError => e rescue Gitlab::HTTP::BlockedUrlError => e
{ error: true, message: _('Test failed.'), service_response: e.message, test_failed: true } { error: true, message: _('Test failed.'), service_response: e.message, test_failed: true }
end end
   
def success_message def success_message
if @service.active? message = @service.active? ? _('activated') : _('settings saved, but not activated')
_("%{service_title} activated.") % { service_title: @service.title }
else _('%{service_title} %{message}.') % { service_title: @service.title, message: message }
_("%{service_title} settings saved, but not activated.") % { service_title: @service.title }
end
end end
   
def service def service
Loading
Loading
Loading
@@ -16,7 +16,7 @@ module Clusters
Loading
@@ -16,7 +16,7 @@ module Clusters
include AfterCommitQueue include AfterCommitQueue
   
default_value_for :ingress_type, :nginx default_value_for :ingress_type, :nginx
default_value_for :modsecurity_enabled, false default_value_for :modsecurity_enabled, true
default_value_for :version, VERSION default_value_for :version, VERSION
   
enum ingress_type: { enum ingress_type: {
Loading
Loading
Loading
@@ -6,6 +6,7 @@ class Key < ApplicationRecord
Loading
@@ -6,6 +6,7 @@ class Key < ApplicationRecord
include AfterCommitQueue include AfterCommitQueue
include Sortable include Sortable
include Sha256Attribute include Sha256Attribute
include Expirable
   
sha256_attribute :fingerprint_sha256 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