summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/notifications.gitlab-ci.yml27
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js3
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue51
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js5
-rw-r--r--app/controllers/clusters/applications_controller.rb2
-rw-r--r--app/models/clusters/applications/ingress.rb3
-rw-r--r--app/serializers/cluster_application_entity.rb1
-rw-r--r--app/services/clusters/applications/base_service.rb4
-rw-r--r--app/views/clusters/clusters/show.html.haml1
-rw-r--r--app/workers/all_queues.yml1
-rw-r--r--app/workers/self_monitoring_project_create_worker.rb40
-rw-r--r--changelogs/unreleased/39140-toggle-modsecurity-enabled-for-managed-ingress.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.79.0.yml5
-rw-r--r--config/sidekiq_queues.yml1
-rw-r--r--doc/development/pipelines.md4
-rw-r--r--doc/user/clusters/applications.md28
-rw-r--r--lib/gitlab/database_importers/self_monitoring/helpers.rb25
-rw-r--r--lib/gitlab/database_importers/self_monitoring/project/create_service.rb43
-rw-r--r--locale/gitlab.pot21
-rwxr-xr-xscripts/notifications.sh27
-rw-r--r--spec/factories/clusters/applications/helm.rb1
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json1
-rw-r--r--spec/frontend/clusters/components/applications_spec.js8
-rw-r--r--spec/frontend/clusters/services/mock_data.js2
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js1
-rw-r--r--spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js6
-rw-r--r--spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb58
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb10
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb27
-rw-r--r--spec/workers/self_monitoring_project_create_worker_spec.rb28
32 files changed, 297 insertions, 146 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ba0bc3b8c3e..5f0aa51a805 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,7 +10,6 @@ stages:
- review
- qa
- post-qa
- - notification
- pages
variables:
@@ -36,7 +35,6 @@ include:
- local: .gitlab/ci/frontend.gitlab-ci.yml
- local: .gitlab/ci/global.gitlab-ci.yml
- local: .gitlab/ci/memory.gitlab-ci.yml
- - local: .gitlab/ci/notifications.gitlab-ci.yml
- local: .gitlab/ci/pages.gitlab-ci.yml
- local: .gitlab/ci/qa.gitlab-ci.yml
- local: .gitlab/ci/reports.gitlab-ci.yml
diff --git a/.gitlab/ci/notifications.gitlab-ci.yml b/.gitlab/ci/notifications.gitlab-ci.yml
deleted file mode 100644
index 1ec61acdfca..00000000000
--- a/.gitlab/ci/notifications.gitlab-ci.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Make sure to update all the similar conditions in other CI config files if you modify these conditions
-.if-canonical-gitlab-schedule: &if-canonical-gitlab-schedule
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/)/ && $CI_PIPELINE_SOURCE == "schedule"'
-
-.notify:
- image: ruby:2.6-alpine
- stage: notification
- dependencies: []
- cache: {}
- before_script:
- - apk update && apk add git curl bash
- - source scripts/utils.sh
- - source scripts/notifications.sh
- - install_gitlab_gem
- variables:
- COMMIT_NOTES_URL: "https://${CI_SERVER_HOST}/${CI_PROJECT_PATH}/commit/${CI_COMMIT_SHA}#notes-list"
-
-package-and-qa:notify-failure:
- extends: .notify
- rules:
- - <<: *if-canonical-gitlab-schedule
- when: manual # TODO: remove notify job if not necessary
- script:
- - 'export NOTIFICATION_MESSAGE=":skull_and_crossbones: Scheduled QA against master failed! :skull_and_crossbones: See ${CI_PIPELINE_URL}. For downstream pipelines, see ${COMMIT_NOTES_URL}"'
- - 'notify_on_job_failure package-and-qa qa-master "${NOTIFICATION_MESSAGE}" ci_failing'
- needs: ["package-and-qa"]
- allow_failure: true
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 54227249d1f..b3a8c61e6a8 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1.78.0
+1.79.0
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index d990d2677a8..b764348eb3c 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -53,6 +53,7 @@ export default class Clusters {
helpPath,
ingressHelpPath,
ingressDnsHelpPath,
+ ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
@@ -69,6 +70,7 @@ export default class Clusters {
helpPath,
ingressHelpPath,
ingressDnsHelpPath,
+ ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
@@ -169,6 +171,7 @@ 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,
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 99844a356c8..af50ca7361d 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -56,6 +56,11 @@ export default {
required: false,
default: '',
},
+ ingressModSecurityHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
cloudRunHelpPath: {
type: String,
required: false,
@@ -112,6 +117,9 @@ 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;
},
@@ -127,6 +135,18 @@ export default {
enableClusterApplicationElasticStack() {
return gon.features && gon.features.enableClusterApplicationElasticStack;
},
+ ingressModSecurityDescription() {
+ const escapedUrl = _.escape(this.ingressModSecurityHelpPath);
+
+ return sprintf(
+ s__('ClusterIntegration|Learn more about %{startLink}ModSecurity%{endLink}'),
+ {
+ startLink: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`,
+ endLink: '</a>',
+ },
+ false,
+ );
+ },
ingressDescription() {
return sprintf(
_.escape(
@@ -135,9 +155,9 @@ export default {
),
),
{
- pricingLink: `<strong><a href="https://cloud.google.com/compute/pricing#lb"
+ pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb"
target="_blank" rel="noopener noreferrer">
- ${_.escape(s__('ClusterIntegration|pricing'))}</a></strong>`,
+ ${_.escape(s__('ClusterIntegration|pricing'))}</a>`,
},
false,
);
@@ -311,6 +331,9 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
:request-reason="applications.ingress.requestReason"
:installed="applications.ingress.installed"
:install-failed="applications.ingress.installFailed"
+ :install-application-request-params="{
+ modsecurity_enabled: applications.ingress.modsecurity_enabled,
+ }"
:uninstallable="applications.ingress.uninstallable"
:uninstall-successful="applications.ingress.uninstallSuccessful"
:uninstall-failed="applications.ingress.uninstallFailed"
@@ -326,6 +349,26 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
}}
</p>
+ <template>
+ <div class="form-group">
+ <div class="form-check form-check-inline">
+ <input
+ v-model="applications.ingress.modsecurity_enabled"
+ :disabled="ingressInstalled"
+ type="checkbox"
+ autocomplete="off"
+ class="form-check-input"
+ />
+ <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">
+ <strong v-html="ingressModSecurityDescription"></strong>
+ </p>
+ </div>
+ </template>
+
<template v-if="ingressInstalled">
<div class="form-group">
<label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
@@ -375,7 +418,9 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
</p>
</template>
<template v-if="!ingressInstalled">
- <div class="bs-callout bs-callout-info" v-html="ingressDescription"></div>
+ <div class="bs-callout bs-callout-info">
+ <strong v-html="ingressDescription"></strong>
+ </div>
</template>
</div>
</application-row>
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 35dbf951551..9c8563e8f77 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -52,6 +52,7 @@ export default class ClusterStore {
ingress: {
...applicationInitialState,
title: s__('ClusterIntegration|Ingress'),
+ modsecurity_enabled: false,
externalIp: null,
externalHostname: null,
},
@@ -108,6 +109,7 @@ export default class ClusterStore {
helpPath,
ingressHelpPath,
ingressDnsHelpPath,
+ ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
@@ -116,6 +118,7 @@ export default class ClusterStore {
this.state.helpPath = helpPath;
this.state.ingressHelpPath = ingressHelpPath;
this.state.ingressDnsHelpPath = ingressDnsHelpPath;
+ this.state.ingressModSecurityHelpPath = ingressModSecurityHelpPath;
this.state.environmentsHelpPath = environmentsHelpPath;
this.state.clustersHelpPath = clustersHelpPath;
this.state.deployBoardsHelpPath = deployBoardsHelpPath;
@@ -207,6 +210,8 @@ export default class ClusterStore {
if (appId === INGRESS) {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
+ this.state.applications.ingress.modsecurity_enabled =
+ serverAppEntry.modsecurity_enabled || this.state.applications.ingress.modsecurity_enabled;
} else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email =
this.state.applications.cert_manager.email || serverAppEntry.email;
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
index be68d0d0a1d..788ebb14fec 100644
--- a/app/controllers/clusters/applications_controller.rb
+++ b/app/controllers/clusters/applications_controller.rb
@@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
end
def cluster_application_params
- params.permit(:application, :hostname, :kibana_hostname, :email, :stack)
+ params.permit(:application, :hostname, :kibana_hostname, :email, :stack, :modsecurity_enabled)
end
def cluster_application_destroy_params
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index d140649af3c..d41fc72ae68 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -14,6 +14,7 @@ module Clusters
include AfterCommitQueue
default_value_for :ingress_type, :nginx
+ default_value_for :modsecurity_enabled, false
default_value_for :version, VERSION
enum ingress_type: {
@@ -73,7 +74,7 @@ module Clusters
private
def specification
- return {} unless Feature.enabled?(:ingress_modsecurity)
+ return {} unless modsecurity_enabled
{
"controller" => {
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index 218bdd21e37..e7e4f5767e9 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -11,6 +11,7 @@ class ClusterApplicationEntity < Grape::Entity
expose :kibana_hostname, if: -> (e, _) { e.respond_to?(:kibana_hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
expose :stack, if: -> (e, _) { e.respond_to?(:stack) }
+ expose :modsecurity_enabled, if: -> (e, _) { e.respond_to?(:modsecurity_enabled) }
expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
expose :can_uninstall?, as: :can_uninstall
end
diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb
index c9f7917938f..4b6c937fd5d 100644
--- a/app/services/clusters/applications/base_service.rb
+++ b/app/services/clusters/applications/base_service.rb
@@ -31,6 +31,10 @@ module Clusters
application.stack = params[:stack]
end
+ if application.has_attribute?(:modsecurity_enabled)
+ application.modsecurity_enabled = params[:modsecurity_enabled] || false
+ end
+
if application.respond_to?(:oauth_application)
application.oauth_application = create_oauth_application(application, request)
end
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 5beeaf7259a..4b295cd022d 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -30,6 +30,7 @@
help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-endpoint'),
ingress_dns_help_path: help_page_path('user/project/clusters/index.md', anchor: 'manually-determining-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', anchor: 'defining-environments'),
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.html', anchor: 'enabling-deploy-boards'),
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 96d75b2fd33..ca050887e0f 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -187,3 +187,4 @@
- project_daily_statistics
- create_evidence
- group_export
+- self_monitoring_project_create
diff --git a/app/workers/self_monitoring_project_create_worker.rb b/app/workers/self_monitoring_project_create_worker.rb
new file mode 100644
index 00000000000..69bc5431ff7
--- /dev/null
+++ b/app/workers/self_monitoring_project_create_worker.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class SelfMonitoringProjectCreateWorker
+ include ApplicationWorker
+ include ExclusiveLeaseGuard
+
+ # This worker falls under Self-monitoring with Monitor::APM group. However,
+ # self-monitoring is not classified as a feature category but rather as
+ # Other Functionality. Metrics seems to be the closest feature_category for
+ # this worker.
+ feature_category :metrics
+
+ LEASE_TIMEOUT = 15.minutes.to_i
+
+ EXCLUSIVE_LEASE_KEY = 'self_monitoring_service_creation_deletion'
+
+ def perform
+ try_obtain_lease do
+ Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute
+ end
+ end
+
+ # @param job_id [String]
+ # Job ID that is used to construct the cache keys.
+ # @return [Hash]
+ # Returns true if the job is enqueued or in progress and false otherwise.
+ def self.in_progress?(job_id)
+ Gitlab::SidekiqStatus.job_status(Array.wrap(job_id)).first
+ end
+
+ private
+
+ def lease_key
+ EXCLUSIVE_LEASE_KEY
+ end
+
+ def lease_timeout
+ LEASE_TIMEOUT
+ end
+end
diff --git a/changelogs/unreleased/39140-toggle-modsecurity-enabled-for-managed-ingress.yml b/changelogs/unreleased/39140-toggle-modsecurity-enabled-for-managed-ingress.yml
new file mode 100644
index 00000000000..3d4d5ca23f3
--- /dev/null
+++ b/changelogs/unreleased/39140-toggle-modsecurity-enabled-for-managed-ingress.yml
@@ -0,0 +1,5 @@
+---
+title: Add enable_modsecurity setting to managed ingress
+merge_request: 21966
+author:
+type: added
diff --git a/changelogs/unreleased/gitaly-version-v1.79.0.yml b/changelogs/unreleased/gitaly-version-v1.79.0.yml
new file mode 100644
index 00000000000..7741f6b74ee
--- /dev/null
+++ b/changelogs/unreleased/gitaly-version-v1.79.0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade to Gitaly v1.79.0
+merge_request: 22515
+author:
+type: changed
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 68ad819d48b..e0885bc5ca5 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -99,6 +99,7 @@
- [chaos, 2]
- [create_evidence, 2]
- [group_export, 1]
+ - [self_monitoring_project_create, 2]
# EE-specific queues
- [analytics, 1]
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 1269087c38d..ba50b013c9f 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -264,10 +264,6 @@ subgraph "`qa` stage"
dast -.-> |needs and depends on| G;
end
-subgraph "`notification` stage"
- NOTIFICATION2["package-and-qa:notify-failure<br>(manual)"] -.-> |needs| Q;
- end
-
subgraph "`post-test` stage"
M
end
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index a7753e3f3a4..0b889a29674 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -248,10 +248,10 @@ use an A record. If your external endpoint is a hostname, use a CNAME record.
#### Web Application Firewall (ModSecurity)
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/65192) in GitLab 12.3 (enabled using `ingress_modsecurity` [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development)).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/21966) in GitLab 12.7.
Out of the box, GitLab provides you real-time security monitoring with
-[`modsecurity`](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#modsecurity)
+[ModSecurity](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#modsecurity).
Modsecurity is a toolkit for real-time web application monitoring, logging,
and access control. With GitLab's offering, the [OWASP's Core Rule Set](https://www.modsecurity.org/CRS/Documentation/), which provides generic attack detection capabilities,
@@ -267,22 +267,18 @@ This feature:
kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- tail -f /var/log/modsec/audit.log
```
-There is a small performance overhead by enabling `modsecurity`. If this is
-considered significant for your application, you can either:
+To enable ModSecurity, check the **Enable Web Application Firewall** checkbox
+when installing your [Ingress application](#ingress).
-- Disable ModSecurity's rule engine for your deployed application by setting
- [the deployment variable](../../topics/autodevops/index.md)
- `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity from
- processing any requests for the given application or environment.
-- Toggle the feature flag to false by running the following command within your
- instance's Rails console:
+There is a small performance overhead by enabling ModSecurity. If this is
+considered significant for your application, you can disable ModSecurity's
+rule engine for your deployed application by setting
+[the deployment variable](../../topics/autodevops/index.md)
+`AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity
+from processing any requests for the given application or environment.
- ```ruby
- Feature.disable(:ingress_modsecurity)
- ```
-
-Once disabled, you must [uninstall](#uninstalling-applications) and reinstall your Ingress
-application for the changes to take effect.
+To permanently disable it, you must [uninstall](#uninstalling-applications) and
+reinstall your Ingress application for the changes to take effect.
### JupyterHub
diff --git a/lib/gitlab/database_importers/self_monitoring/helpers.rb b/lib/gitlab/database_importers/self_monitoring/helpers.rb
new file mode 100644
index 00000000000..d7e90967e89
--- /dev/null
+++ b/lib/gitlab/database_importers/self_monitoring/helpers.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DatabaseImporters
+ module SelfMonitoring
+ module Helpers
+ def application_settings
+ @application_settings ||= ApplicationSetting.current_without_cache
+ end
+
+ def project_created?
+ self_monitoring_project.present?
+ end
+
+ def self_monitoring_project
+ application_settings.instance_administration_project
+ end
+
+ def self_monitoring_project_id
+ application_settings.instance_administration_project_id
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
index fbf252b7ec3..92a2e504a11 100644
--- a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
+++ b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
@@ -6,38 +6,26 @@ module Gitlab
module Project
class CreateService < ::BaseService
include Stepable
-
- STEPS_ALLOWED_TO_FAIL = [
- :validate_application_settings, :validate_project_created, :validate_admins
- ].freeze
+ include SelfMonitoring::Helpers
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
PROJECT_NAME = 'GitLab Instance Administration'
steps :validate_application_settings,
- :validate_project_created,
:validate_admins,
:create_group,
:create_project,
:save_project_id,
:add_group_members,
- :add_prometheus_manual_configuration
+ :add_prometheus_manual_configuration,
+ :track_event
def initialize
super(nil)
end
- def execute!
- result = execute_steps
- if result[:status] == :success
- ::Gitlab::Tracking.event("self_monitoring", "project_created")
- result
- elsif STEPS_ALLOWED_TO_FAIL.include?(result[:last_step])
- ::Gitlab::Tracking.event("self_monitoring", "project_created")
- success
- else
- raise StandardError, result[:message]
- end
+ def execute
+ execute_steps
end
private
@@ -49,13 +37,6 @@ module Gitlab
error(_('No application_settings found'))
end
- def validate_project_created(result)
- return success(result) unless project_created?
-
- log_error('Project already created')
- error(_('Project already created'))
- end
-
def validate_admins(result)
unless instance_admins.any?
log_error('No active admin user found')
@@ -68,7 +49,7 @@ module Gitlab
def create_group(result)
if project_created?
log_info(_('Instance administrators group already exists'))
- result[:group] = application_settings.instance_administration_project.owner
+ result[:group] = self_monitoring_project.owner
return success(result)
end
@@ -84,7 +65,7 @@ module Gitlab
def create_project(result)
if project_created?
log_info('Instance administration project already exists')
- result[:project] = application_settings.instance_administration_project
+ result[:project] = self_monitoring_project
return success(result)
end
@@ -99,7 +80,7 @@ module Gitlab
end
def save_project_id(result)
- return success if project_created?
+ return success(result) if project_created?
response = application_settings.update(
instance_administration_project_id: result[:project].id
@@ -140,12 +121,10 @@ module Gitlab
success(result)
end
- def application_settings
- @application_settings ||= ApplicationSetting.current_without_cache
- end
+ def track_event(result)
+ ::Gitlab::Tracking.event("self_monitoring", "project_created")
- def project_created?
- application_settings.instance_administration_project.present?
+ success(result)
end
def parse_url(uri_string)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e110ccf8544..8967ce8b994 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2567,6 +2567,9 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Batch operations"
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -3848,6 +3851,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run on GKE (beta)"
msgstr ""
+msgid "ClusterIntegration|Enable Web Application Firewall"
+msgstr ""
+
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr ""
@@ -4034,6 +4040,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
+msgid "ClusterIntegration|Learn more about %{startLink}ModSecurity%{endLink}"
+msgstr ""
+
msgid "ClusterIntegration|Learn more about %{startLink}Regions %{externalLinkIcon}%{endLink}."
msgstr ""
@@ -13827,9 +13836,6 @@ msgstr ""
msgid "Project access must be granted explicitly to each user."
msgstr ""
-msgid "Project already created"
-msgstr ""
-
msgid "Project already deleted"
msgstr ""
@@ -15434,6 +15440,12 @@ msgstr ""
msgid "Resume replication"
msgstr ""
+msgid "Resync"
+msgstr ""
+
+msgid "Resync all designs"
+msgstr ""
+
msgid "Retry"
msgstr ""
@@ -18332,6 +18344,9 @@ msgstr ""
msgid "There was an error subscribing to this label."
msgstr ""
+msgid "There was an error syncing the Design Repositories."
+msgstr ""
+
msgid "There was an error trying to validate your query"
msgstr ""
diff --git a/scripts/notifications.sh b/scripts/notifications.sh
deleted file mode 100755
index d1b11d44e88..00000000000
--- a/scripts/notifications.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-# Sends Slack notification MSG to CI_SLACK_WEBHOOK_URL (which needs to be set).
-# ICON_EMOJI needs to be set to an icon emoji name (without the `:` around it).
-function notify_slack() {
- CHANNEL=$1
- MSG=$2
- ICON_EMOJI=$3
-
- if [ -z "$CHANNEL" ] || [ -z "$CI_SLACK_WEBHOOK_URL" ] || [ -z "$MSG" ] || [ -z "$ICON_EMOJI" ]; then
- echo "Missing argument(s) - Use: $0 channel message icon_emoji"
- echo "and set CI_SLACK_WEBHOOK_URL environment variable."
- else
- curl -X POST --data-urlencode 'payload={"channel": "#'"${CHANNEL}"'", "username": "GitLab QA Bot", "text": "'"${MSG}"'", "icon_emoji": "'":${ICON_EMOJI}:"'"}' "${CI_SLACK_WEBHOOK_URL}"
- fi
-}
-
-function notify_on_job_failure() {
- JOB_NAME=$1
- CHANNEL=$2
- MSG=$3
- ICON_EMOJI=$4
-
- local job_id
- job_id=$(scripts/get-job-id "$CI_PROJECT_ID" "$CI_PIPELINE_ID" "$JOB_NAME" -s failed)
- if [ -n "${job_id}" ]; then
- notify_slack "${CHANNEL}" "${MSG}" "${ICON_EMOJI}"
- fi
-}
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 0e59f8cb9ec..8858675c2b8 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -71,6 +71,7 @@ FactoryBot.define do
end
factory :clusters_applications_ingress, class: Clusters::Applications::Ingress do
+ modsecurity_enabled { false }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index f978baa2026..fcb4f2b94cd 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -38,6 +38,7 @@
"kibana_hostname": { "type": ["string", "null"] },
"email": { "type": ["string", "null"] },
"stack": { "type": ["string", "null"] },
+ "modsecurity_enabled": { "type": ["boolean", "null"] },
"update_available": { "type": ["boolean", "null"] },
"can_uninstall": { "type": "boolean" }
},
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index 2d7958a6b65..e8c5a2bd242 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -190,6 +190,7 @@ describe('Applications', () => {
title: 'Ingress',
status: 'installed',
externalHostname: 'localhost.localdomain',
+ modsecurity_enabled: false,
},
helm: { title: 'Helm Tiller' },
cert_manager: { title: 'Cert-Manager' },
@@ -473,7 +474,12 @@ describe('Applications', () => {
vm = mountComponent(Applications, {
applications: {
...APPLICATIONS_MOCK_STATE,
- ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
+ ingress: {
+ title: 'Ingress',
+ status: 'installed',
+ externalIp: '1.1.1.1',
+ modsecurity_enabled: false,
+ },
elastic_stack: { title: 'Elastic Stack', status: 'installed', kibana_hostname: '' },
},
});
diff --git a/spec/frontend/clusters/services/mock_data.js b/spec/frontend/clusters/services/mock_data.js
index 016f5a259b5..98fa0ec3b07 100644
--- a/spec/frontend/clusters/services/mock_data.js
+++ b/spec/frontend/clusters/services/mock_data.js
@@ -150,7 +150,7 @@ const DEFAULT_APPLICATION_STATE = {
const APPLICATIONS_MOCK_STATE = {
helm: { title: 'Helm Tiller', status: 'installable' },
- ingress: { title: 'Ingress', status: 'installable' },
+ ingress: { title: 'Ingress', status: 'installable', modsecurity_enabled: false },
crossplane: { title: 'Crossplane', status: 'installable', stack: '' },
cert_manager: { title: 'Cert-Manager', status: 'installable' },
runner: { title: 'GitLab Runner' },
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index 71d4daceb75..c7ec4ddc464 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -86,6 +86,7 @@ describe('Clusters Store', () => {
uninstallSuccessful: false,
uninstallFailed: false,
validationError: null,
+ modsecurity_enabled: false,
},
runner: {
title: 'GitLab Runner',
diff --git a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
index fb50b31a3da..e5f83b6fa49 100644
--- a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
+++ b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
@@ -69,15 +69,17 @@ describe('Sentry Error Stack Trace', () => {
});
describe('Stack trace', () => {
- it('should show stacktrace', () => {
+ beforeEach(() => {
store.state.details.loadingStacktrace = false;
+ });
+
+ it('should show stacktrace', () => {
mountComponent({ stubs: {} });
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
});
it('should not show stacktrace if it does not exist', () => {
- store.state.details.loadingStacktrace = false;
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
});
diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
index ee3c99afdf1..082485f5ddd 100644
--- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
+++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
describe '#execute' do
- let(:result) { subject.execute! }
+ let(:result) { subject.execute }
let(:prometheus_settings) do
{
@@ -18,10 +18,12 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
end
context 'without application_settings' do
- it 'does not fail' do
+ it 'returns error' do
expect(subject).to receive(:log_error).and_call_original
expect(result).to eq(
- status: :success
+ status: :error,
+ message: 'No application_settings found',
+ last_step: :validate_application_settings
)
expect(Project.count).to eq(0)
@@ -36,10 +38,12 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
allow(ApplicationSetting).to receive(:current_without_cache) { application_setting }
end
- it 'does not fail' do
+ it 'returns error' do
expect(subject).to receive(:log_error).and_call_original
expect(result).to eq(
- status: :success
+ status: :error,
+ message: 'No active admin user found',
+ last_step: :validate_admins
)
expect(Project.count).to eq(0)
@@ -47,7 +51,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
end
end
- context 'with admin users' do
+ context 'with application settings and admin users' do
let(:project) { result[:project] }
let(:group) { result[:group] }
let(:application_setting) { Gitlab::CurrentSettings.current_application_settings }
@@ -73,6 +77,13 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it_behaves_like 'has prometheus service', 'http://localhost:9090'
+ it "tracks successful install" do
+ expect(::Gitlab::Tracking).to receive(:event)
+ expect(::Gitlab::Tracking).to receive(:event).with("self_monitoring", "project_created")
+
+ result
+ end
+
it 'creates group' do
expect(result[:status]).to eq(:success)
expect(group).to be_persisted
@@ -132,7 +143,11 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it 'returns error when saving project ID fails' do
allow(application_setting).to receive(:save) { false }
- expect { result }.to raise_error(StandardError, 'Could not save project ID')
+ expect(result).to eq(
+ status: :error,
+ message: 'Could not save project ID',
+ last_step: :save_project_id
+ )
end
context 'when project already exists' do
@@ -149,9 +164,8 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
application_setting.instance_administration_project_id = existing_project.id
end
- it 'does not fail' do
- expect(subject).to receive(:log_error).and_call_original
- expect(result[:status]).to eq(:success)
+ it 'returns success' do
+ expect(result).to include(status: :success)
expect(Project.count).to eq(1)
expect(Group.count).to eq(1)
@@ -250,7 +264,11 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it 'returns error' do
expect(subject).to receive(:log_error).and_call_original
- expect { result }.to raise_error(StandardError, 'Could not create project')
+ expect(result).to eq(
+ status: :error,
+ message: 'Could not create project',
+ last_step: :create_project
+ )
end
end
@@ -261,7 +279,11 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it 'returns error' do
expect(subject).to receive(:log_error).and_call_original
- expect { result }.to raise_error(StandardError, 'Could not add admins as members')
+ expect(result).to eq(
+ status: :error,
+ message: 'Could not add admins as members',
+ last_step: :add_group_members
+ )
end
end
@@ -275,15 +297,13 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it 'returns error' do
expect(subject).to receive(:log_error).and_call_original
- expect { result }.to raise_error(StandardError, 'Could not save prometheus manual configuration')
+ expect(result).to eq(
+ status: :error,
+ message: 'Could not save prometheus manual configuration',
+ last_step: :add_prometheus_manual_configuration
+ )
end
end
end
-
- it "tracks successful install" do
- expect(Gitlab::Tracking).to receive(:event).with("self_monitoring", "project_created")
-
- result
- end
end
end
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index d7ad7867e1a..c1158698601 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -142,11 +142,11 @@ describe Clusters::Applications::Ingress do
let(:project) { build(:project) }
let(:cluster) { build(:cluster, projects: [project]) }
- context 'when ingress_modsecurity is enabled' do
+ context 'when modsecurity_enabled is enabled' do
before do
- stub_feature_flags(ingress_modsecurity: true)
-
allow(subject).to receive(:cluster).and_return(cluster)
+
+ allow(subject).to receive(:modsecurity_enabled).and_return(true)
end
it 'includes modsecurity module enablement' do
@@ -173,10 +173,8 @@ describe Clusters::Applications::Ingress do
end
end
- context 'when ingress_modsecurity is disabled' do
+ context 'when modsecurity_enabled is disabled' do
before do
- stub_feature_flags(ingress_modsecurity: false)
-
allow(subject).to receive(:cluster).and_return(cluster)
end
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
index bdacb9ce071..d5ad03a94ac 100644
--- a/spec/services/clusters/applications/create_service_spec.rb
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -47,6 +47,33 @@ describe Clusters::Applications::CreateService do
create(:clusters_applications_helm, :installed, cluster: cluster)
end
+ context 'ingress application' do
+ let(:params) do
+ {
+ application: 'ingress',
+ modsecurity_enabled: true
+ }
+ end
+
+ before do
+ expect_any_instance_of(Clusters::Applications::Ingress)
+ .to receive(:make_scheduled!)
+ .and_call_original
+ end
+
+ it 'creates the application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_ingress)
+ end
+
+ it 'sets modsecurity_enabled' do
+ expect(subject.modsecurity_enabled).to eq(true)
+ end
+ end
+
context 'cert manager application' do
let(:params) do
{
diff --git a/spec/workers/self_monitoring_project_create_worker_spec.rb b/spec/workers/self_monitoring_project_create_worker_spec.rb
new file mode 100644
index 00000000000..75c4f5d49d1
--- /dev/null
+++ b/spec/workers/self_monitoring_project_create_worker_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe SelfMonitoringProjectCreateWorker do
+ describe '#perform' do
+ let(:service_class) { Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService }
+ let(:service) { instance_double(service_class) }
+
+ before do
+ allow(service_class).to receive(:new) { service }
+ end
+
+ it 'runs the SelfMonitoring::Project::CreateService' do
+ expect(service).to receive(:execute)
+
+ subject.perform
+ end
+ end
+
+ describe '.in_progress?', :clean_gitlab_redis_shared_state do
+ it 'returns in_progress when job is enqueued' do
+ jid = described_class.perform_async
+
+ expect(described_class.in_progress?(jid)).to eq(true)
+ end
+ end
+end