Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e440c86979
commit
05f1d5d981
|
@ -10,7 +10,6 @@ stages:
|
||||||
- review
|
- review
|
||||||
- qa
|
- qa
|
||||||
- post-qa
|
- post-qa
|
||||||
- notification
|
|
||||||
- pages
|
- pages
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
|
@ -36,7 +35,6 @@ include:
|
||||||
- local: .gitlab/ci/frontend.gitlab-ci.yml
|
- local: .gitlab/ci/frontend.gitlab-ci.yml
|
||||||
- local: .gitlab/ci/global.gitlab-ci.yml
|
- local: .gitlab/ci/global.gitlab-ci.yml
|
||||||
- local: .gitlab/ci/memory.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/pages.gitlab-ci.yml
|
||||||
- local: .gitlab/ci/qa.gitlab-ci.yml
|
- local: .gitlab/ci/qa.gitlab-ci.yml
|
||||||
- local: .gitlab/ci/reports.gitlab-ci.yml
|
- local: .gitlab/ci/reports.gitlab-ci.yml
|
||||||
|
|
|
@ -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
|
|
|
@ -1 +1 @@
|
||||||
1.78.0
|
1.79.0
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default class Clusters {
|
||||||
helpPath,
|
helpPath,
|
||||||
ingressHelpPath,
|
ingressHelpPath,
|
||||||
ingressDnsHelpPath,
|
ingressDnsHelpPath,
|
||||||
|
ingressModSecurityHelpPath,
|
||||||
environmentsHelpPath,
|
environmentsHelpPath,
|
||||||
clustersHelpPath,
|
clustersHelpPath,
|
||||||
deployBoardsHelpPath,
|
deployBoardsHelpPath,
|
||||||
|
@ -69,6 +70,7 @@ export default class Clusters {
|
||||||
helpPath,
|
helpPath,
|
||||||
ingressHelpPath,
|
ingressHelpPath,
|
||||||
ingressDnsHelpPath,
|
ingressDnsHelpPath,
|
||||||
|
ingressModSecurityHelpPath,
|
||||||
environmentsHelpPath,
|
environmentsHelpPath,
|
||||||
clustersHelpPath,
|
clustersHelpPath,
|
||||||
deployBoardsHelpPath,
|
deployBoardsHelpPath,
|
||||||
|
@ -169,6 +171,7 @@ export default class Clusters {
|
||||||
ingressHelpPath: this.state.ingressHelpPath,
|
ingressHelpPath: this.state.ingressHelpPath,
|
||||||
managePrometheusPath: this.state.managePrometheusPath,
|
managePrometheusPath: this.state.managePrometheusPath,
|
||||||
ingressDnsHelpPath: this.state.ingressDnsHelpPath,
|
ingressDnsHelpPath: this.state.ingressDnsHelpPath,
|
||||||
|
ingressModSecurityHelpPath: this.state.ingressModSecurityHelpPath,
|
||||||
cloudRunHelpPath: this.state.cloudRunHelpPath,
|
cloudRunHelpPath: this.state.cloudRunHelpPath,
|
||||||
providerType: this.state.providerType,
|
providerType: this.state.providerType,
|
||||||
preInstalledKnative: this.state.preInstalledKnative,
|
preInstalledKnative: this.state.preInstalledKnative,
|
||||||
|
|
|
@ -56,6 +56,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
ingressModSecurityHelpPath: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
cloudRunHelpPath: {
|
cloudRunHelpPath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -112,6 +117,9 @@ 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;
|
||||||
},
|
},
|
||||||
|
@ -127,6 +135,18 @@ export default {
|
||||||
enableClusterApplicationElasticStack() {
|
enableClusterApplicationElasticStack() {
|
||||||
return gon.features && gon.features.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() {
|
ingressDescription() {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
_.escape(
|
_.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">
|
target="_blank" rel="noopener noreferrer">
|
||||||
${_.escape(s__('ClusterIntegration|pricing'))}</a></strong>`,
|
${_.escape(s__('ClusterIntegration|pricing'))}</a>`,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
@ -311,6 +331,9 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
|
||||||
:request-reason="applications.ingress.requestReason"
|
:request-reason="applications.ingress.requestReason"
|
||||||
:installed="applications.ingress.installed"
|
:installed="applications.ingress.installed"
|
||||||
:install-failed="applications.ingress.installFailed"
|
:install-failed="applications.ingress.installFailed"
|
||||||
|
:install-application-request-params="{
|
||||||
|
modsecurity_enabled: applications.ingress.modsecurity_enabled,
|
||||||
|
}"
|
||||||
:uninstallable="applications.ingress.uninstallable"
|
:uninstallable="applications.ingress.uninstallable"
|
||||||
:uninstall-successful="applications.ingress.uninstallSuccessful"
|
:uninstall-successful="applications.ingress.uninstallSuccessful"
|
||||||
:uninstall-failed="applications.ingress.uninstallFailed"
|
:uninstall-failed="applications.ingress.uninstallFailed"
|
||||||
|
@ -326,6 +349,26 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
|
||||||
}}
|
}}
|
||||||
</p>
|
</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">
|
<template v-if="ingressInstalled">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
|
<label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
|
||||||
|
@ -375,7 +418,9 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="!ingressInstalled">
|
<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>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</application-row>
|
</application-row>
|
||||||
|
|
|
@ -52,6 +52,7 @@ export default class ClusterStore {
|
||||||
ingress: {
|
ingress: {
|
||||||
...applicationInitialState,
|
...applicationInitialState,
|
||||||
title: s__('ClusterIntegration|Ingress'),
|
title: s__('ClusterIntegration|Ingress'),
|
||||||
|
modsecurity_enabled: false,
|
||||||
externalIp: null,
|
externalIp: null,
|
||||||
externalHostname: null,
|
externalHostname: null,
|
||||||
},
|
},
|
||||||
|
@ -108,6 +109,7 @@ export default class ClusterStore {
|
||||||
helpPath,
|
helpPath,
|
||||||
ingressHelpPath,
|
ingressHelpPath,
|
||||||
ingressDnsHelpPath,
|
ingressDnsHelpPath,
|
||||||
|
ingressModSecurityHelpPath,
|
||||||
environmentsHelpPath,
|
environmentsHelpPath,
|
||||||
clustersHelpPath,
|
clustersHelpPath,
|
||||||
deployBoardsHelpPath,
|
deployBoardsHelpPath,
|
||||||
|
@ -116,6 +118,7 @@ export default class ClusterStore {
|
||||||
this.state.helpPath = helpPath;
|
this.state.helpPath = helpPath;
|
||||||
this.state.ingressHelpPath = ingressHelpPath;
|
this.state.ingressHelpPath = ingressHelpPath;
|
||||||
this.state.ingressDnsHelpPath = ingressDnsHelpPath;
|
this.state.ingressDnsHelpPath = ingressDnsHelpPath;
|
||||||
|
this.state.ingressModSecurityHelpPath = ingressModSecurityHelpPath;
|
||||||
this.state.environmentsHelpPath = environmentsHelpPath;
|
this.state.environmentsHelpPath = environmentsHelpPath;
|
||||||
this.state.clustersHelpPath = clustersHelpPath;
|
this.state.clustersHelpPath = clustersHelpPath;
|
||||||
this.state.deployBoardsHelpPath = deployBoardsHelpPath;
|
this.state.deployBoardsHelpPath = deployBoardsHelpPath;
|
||||||
|
@ -207,6 +210,8 @@ export default class ClusterStore {
|
||||||
if (appId === INGRESS) {
|
if (appId === INGRESS) {
|
||||||
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;
|
||||||
|
this.state.applications.ingress.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 =
|
||||||
this.state.applications.cert_manager.email || serverAppEntry.email;
|
this.state.applications.cert_manager.email || serverAppEntry.email;
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def cluster_application_params
|
def cluster_application_params
|
||||||
params.permit(:application, :hostname, :kibana_hostname, :email, :stack)
|
params.permit(:application, :hostname, :kibana_hostname, :email, :stack, :modsecurity_enabled)
|
||||||
end
|
end
|
||||||
|
|
||||||
def cluster_application_destroy_params
|
def cluster_application_destroy_params
|
||||||
|
|
|
@ -14,6 +14,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 :version, VERSION
|
default_value_for :version, VERSION
|
||||||
|
|
||||||
enum ingress_type: {
|
enum ingress_type: {
|
||||||
|
@ -73,7 +74,7 @@ module Clusters
|
||||||
private
|
private
|
||||||
|
|
||||||
def specification
|
def specification
|
||||||
return {} unless Feature.enabled?(:ingress_modsecurity)
|
return {} unless modsecurity_enabled
|
||||||
|
|
||||||
{
|
{
|
||||||
"controller" => {
|
"controller" => {
|
||||||
|
|
|
@ -11,6 +11,7 @@ class ClusterApplicationEntity < Grape::Entity
|
||||||
expose :kibana_hostname, if: -> (e, _) { e.respond_to?(:kibana_hostname) }
|
expose :kibana_hostname, if: -> (e, _) { e.respond_to?(:kibana_hostname) }
|
||||||
expose :email, if: -> (e, _) { e.respond_to?(:email) }
|
expose :email, if: -> (e, _) { e.respond_to?(:email) }
|
||||||
expose :stack, if: -> (e, _) { e.respond_to?(:stack) }
|
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 :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
|
||||||
expose :can_uninstall?, as: :can_uninstall
|
expose :can_uninstall?, as: :can_uninstall
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,10 @@ module Clusters
|
||||||
application.stack = params[:stack]
|
application.stack = params[:stack]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if application.has_attribute?(:modsecurity_enabled)
|
||||||
|
application.modsecurity_enabled = params[:modsecurity_enabled] || false
|
||||||
|
end
|
||||||
|
|
||||||
if application.respond_to?(:oauth_application)
|
if application.respond_to?(:oauth_application)
|
||||||
application.oauth_application = create_oauth_application(application, request)
|
application.oauth_application = create_oauth_application(application, request)
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
|
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_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_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'),
|
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'),
|
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'),
|
deploy_boards_help_path: help_page_path('user/project/deploy_boards.html', anchor: 'enabling-deploy-boards'),
|
||||||
|
|
|
@ -187,3 +187,4 @@
|
||||||
- project_daily_statistics
|
- project_daily_statistics
|
||||||
- create_evidence
|
- create_evidence
|
||||||
- group_export
|
- group_export
|
||||||
|
- self_monitoring_project_create
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add enable_modsecurity setting to managed ingress
|
||||||
|
merge_request: 21966
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Upgrade to Gitaly v1.79.0
|
||||||
|
merge_request: 22515
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -99,6 +99,7 @@
|
||||||
- [chaos, 2]
|
- [chaos, 2]
|
||||||
- [create_evidence, 2]
|
- [create_evidence, 2]
|
||||||
- [group_export, 1]
|
- [group_export, 1]
|
||||||
|
- [self_monitoring_project_create, 2]
|
||||||
|
|
||||||
# EE-specific queues
|
# EE-specific queues
|
||||||
- [analytics, 1]
|
- [analytics, 1]
|
||||||
|
|
|
@ -264,10 +264,6 @@ subgraph "`qa` stage"
|
||||||
dast -.-> |needs and depends on| G;
|
dast -.-> |needs and depends on| G;
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph "`notification` stage"
|
|
||||||
NOTIFICATION2["package-and-qa:notify-failure<br>(manual)"] -.-> |needs| Q;
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "`post-test` stage"
|
subgraph "`post-test` stage"
|
||||||
M
|
M
|
||||||
end
|
end
|
||||||
|
|
|
@ -248,10 +248,10 @@ use an A record. If your external endpoint is a hostname, use a CNAME record.
|
||||||
|
|
||||||
#### Web Application Firewall (ModSecurity)
|
#### 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
|
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,
|
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,
|
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
|
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
|
To enable ModSecurity, check the **Enable Web Application Firewall** checkbox
|
||||||
considered significant for your application, you can either:
|
when installing your [Ingress application](#ingress).
|
||||||
|
|
||||||
- Disable ModSecurity's rule engine for your deployed application by setting
|
There is a small performance overhead by enabling ModSecurity. If this is
|
||||||
[the deployment variable](../../topics/autodevops/index.md)
|
considered significant for your application, you can disable ModSecurity's
|
||||||
`AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity from
|
rule engine for your deployed application by setting
|
||||||
processing any requests for the given application or environment.
|
[the deployment variable](../../topics/autodevops/index.md)
|
||||||
- Toggle the feature flag to false by running the following command within your
|
`AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity
|
||||||
instance's Rails console:
|
from processing any requests for the given application or environment.
|
||||||
|
|
||||||
```ruby
|
To permanently disable it, you must [uninstall](#uninstalling-applications) and
|
||||||
Feature.disable(:ingress_modsecurity)
|
reinstall your Ingress application for the changes to take effect.
|
||||||
```
|
|
||||||
|
|
||||||
Once disabled, you must [uninstall](#uninstalling-applications) and reinstall your Ingress
|
|
||||||
application for the changes to take effect.
|
|
||||||
|
|
||||||
### JupyterHub
|
### JupyterHub
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -6,38 +6,26 @@ module Gitlab
|
||||||
module Project
|
module Project
|
||||||
class CreateService < ::BaseService
|
class CreateService < ::BaseService
|
||||||
include Stepable
|
include Stepable
|
||||||
|
include SelfMonitoring::Helpers
|
||||||
STEPS_ALLOWED_TO_FAIL = [
|
|
||||||
:validate_application_settings, :validate_project_created, :validate_admins
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
|
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
|
||||||
PROJECT_NAME = 'GitLab Instance Administration'
|
PROJECT_NAME = 'GitLab Instance Administration'
|
||||||
|
|
||||||
steps :validate_application_settings,
|
steps :validate_application_settings,
|
||||||
:validate_project_created,
|
|
||||||
:validate_admins,
|
:validate_admins,
|
||||||
:create_group,
|
:create_group,
|
||||||
:create_project,
|
:create_project,
|
||||||
:save_project_id,
|
:save_project_id,
|
||||||
:add_group_members,
|
:add_group_members,
|
||||||
:add_prometheus_manual_configuration
|
:add_prometheus_manual_configuration,
|
||||||
|
:track_event
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super(nil)
|
super(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute!
|
def execute
|
||||||
result = execute_steps
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -49,13 +37,6 @@ module Gitlab
|
||||||
error(_('No application_settings found'))
|
error(_('No application_settings found'))
|
||||||
end
|
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)
|
def validate_admins(result)
|
||||||
unless instance_admins.any?
|
unless instance_admins.any?
|
||||||
log_error('No active admin user found')
|
log_error('No active admin user found')
|
||||||
|
@ -68,7 +49,7 @@ module Gitlab
|
||||||
def create_group(result)
|
def create_group(result)
|
||||||
if project_created?
|
if project_created?
|
||||||
log_info(_('Instance administrators group already exists'))
|
log_info(_('Instance administrators group already exists'))
|
||||||
result[:group] = application_settings.instance_administration_project.owner
|
result[:group] = self_monitoring_project.owner
|
||||||
return success(result)
|
return success(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -84,7 +65,7 @@ module Gitlab
|
||||||
def create_project(result)
|
def create_project(result)
|
||||||
if project_created?
|
if project_created?
|
||||||
log_info('Instance administration project already exists')
|
log_info('Instance administration project already exists')
|
||||||
result[:project] = application_settings.instance_administration_project
|
result[:project] = self_monitoring_project
|
||||||
return success(result)
|
return success(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,7 +80,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_project_id(result)
|
def save_project_id(result)
|
||||||
return success if project_created?
|
return success(result) if project_created?
|
||||||
|
|
||||||
response = application_settings.update(
|
response = application_settings.update(
|
||||||
instance_administration_project_id: result[:project].id
|
instance_administration_project_id: result[:project].id
|
||||||
|
@ -140,12 +121,10 @@ module Gitlab
|
||||||
success(result)
|
success(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
def application_settings
|
def track_event(result)
|
||||||
@application_settings ||= ApplicationSetting.current_without_cache
|
::Gitlab::Tracking.event("self_monitoring", "project_created")
|
||||||
end
|
|
||||||
|
|
||||||
def project_created?
|
success(result)
|
||||||
application_settings.instance_administration_project.present?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_url(uri_string)
|
def parse_url(uri_string)
|
||||||
|
|
|
@ -2567,6 +2567,9 @@ msgstr ""
|
||||||
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
|
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Batch operations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BatchComments|Delete all pending comments"
|
msgid "BatchComments|Delete all pending comments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3848,6 +3851,9 @@ msgstr ""
|
||||||
msgid "ClusterIntegration|Enable Cloud Run on GKE (beta)"
|
msgid "ClusterIntegration|Enable Cloud Run on GKE (beta)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ClusterIntegration|Enable Web Application Firewall"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
|
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4034,6 +4040,9 @@ msgstr ""
|
||||||
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
|
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ClusterIntegration|Learn more about %{startLink}ModSecurity%{endLink}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ClusterIntegration|Learn more about %{startLink}Regions %{externalLinkIcon}%{endLink}."
|
msgid "ClusterIntegration|Learn more about %{startLink}Regions %{externalLinkIcon}%{endLink}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -13827,9 +13836,6 @@ msgstr ""
|
||||||
msgid "Project access must be granted explicitly to each user."
|
msgid "Project access must be granted explicitly to each user."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Project already created"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Project already deleted"
|
msgid "Project already deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -15434,6 +15440,12 @@ msgstr ""
|
||||||
msgid "Resume replication"
|
msgid "Resume replication"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Resync"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Resync all designs"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Retry"
|
msgid "Retry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -18332,6 +18344,9 @@ msgstr ""
|
||||||
msgid "There was an error subscribing to this label."
|
msgid "There was an error subscribing to this label."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "There was an error syncing the Design Repositories."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "There was an error trying to validate your query"
|
msgid "There was an error trying to validate your query"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -71,6 +71,7 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :clusters_applications_ingress, class: Clusters::Applications::Ingress do
|
factory :clusters_applications_ingress, class: Clusters::Applications::Ingress do
|
||||||
|
modsecurity_enabled { false }
|
||||||
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
|
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
"kibana_hostname": { "type": ["string", "null"] },
|
"kibana_hostname": { "type": ["string", "null"] },
|
||||||
"email": { "type": ["string", "null"] },
|
"email": { "type": ["string", "null"] },
|
||||||
"stack": { "type": ["string", "null"] },
|
"stack": { "type": ["string", "null"] },
|
||||||
|
"modsecurity_enabled": { "type": ["boolean", "null"] },
|
||||||
"update_available": { "type": ["boolean", "null"] },
|
"update_available": { "type": ["boolean", "null"] },
|
||||||
"can_uninstall": { "type": "boolean" }
|
"can_uninstall": { "type": "boolean" }
|
||||||
},
|
},
|
||||||
|
|
|
@ -190,6 +190,7 @@ describe('Applications', () => {
|
||||||
title: 'Ingress',
|
title: 'Ingress',
|
||||||
status: 'installed',
|
status: 'installed',
|
||||||
externalHostname: 'localhost.localdomain',
|
externalHostname: 'localhost.localdomain',
|
||||||
|
modsecurity_enabled: false,
|
||||||
},
|
},
|
||||||
helm: { title: 'Helm Tiller' },
|
helm: { title: 'Helm Tiller' },
|
||||||
cert_manager: { title: 'Cert-Manager' },
|
cert_manager: { title: 'Cert-Manager' },
|
||||||
|
@ -473,7 +474,12 @@ describe('Applications', () => {
|
||||||
vm = mountComponent(Applications, {
|
vm = mountComponent(Applications, {
|
||||||
applications: {
|
applications: {
|
||||||
...APPLICATIONS_MOCK_STATE,
|
...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: '' },
|
elastic_stack: { title: 'Elastic Stack', status: 'installed', kibana_hostname: '' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -150,7 +150,7 @@ const DEFAULT_APPLICATION_STATE = {
|
||||||
|
|
||||||
const APPLICATIONS_MOCK_STATE = {
|
const APPLICATIONS_MOCK_STATE = {
|
||||||
helm: { title: 'Helm Tiller', status: 'installable' },
|
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: '' },
|
crossplane: { title: 'Crossplane', status: 'installable', stack: '' },
|
||||||
cert_manager: { title: 'Cert-Manager', status: 'installable' },
|
cert_manager: { title: 'Cert-Manager', status: 'installable' },
|
||||||
runner: { title: 'GitLab Runner' },
|
runner: { title: 'GitLab Runner' },
|
||||||
|
|
|
@ -86,6 +86,7 @@ describe('Clusters Store', () => {
|
||||||
uninstallSuccessful: false,
|
uninstallSuccessful: false,
|
||||||
uninstallFailed: false,
|
uninstallFailed: false,
|
||||||
validationError: null,
|
validationError: null,
|
||||||
|
modsecurity_enabled: false,
|
||||||
},
|
},
|
||||||
runner: {
|
runner: {
|
||||||
title: 'GitLab Runner',
|
title: 'GitLab Runner',
|
||||||
|
|
|
@ -69,15 +69,17 @@ describe('Sentry Error Stack Trace', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Stack trace', () => {
|
describe('Stack trace', () => {
|
||||||
it('should show stacktrace', () => {
|
beforeEach(() => {
|
||||||
store.state.details.loadingStacktrace = false;
|
store.state.details.loadingStacktrace = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show stacktrace', () => {
|
||||||
mountComponent({ stubs: {} });
|
mountComponent({ stubs: {} });
|
||||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
||||||
expect(wrapper.find(Stacktrace).exists()).toBe(true);
|
expect(wrapper.find(Stacktrace).exists()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show stacktrace if it does not exist', () => {
|
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(GlLoadingIcon).exists()).toBe(false);
|
||||||
expect(wrapper.find(Stacktrace).exists()).toBe(false);
|
expect(wrapper.find(Stacktrace).exists()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
||||||
describe '#execute' do
|
describe '#execute' do
|
||||||
let(:result) { subject.execute! }
|
let(:result) { subject.execute }
|
||||||
|
|
||||||
let(:prometheus_settings) do
|
let(:prometheus_settings) do
|
||||||
{
|
{
|
||||||
|
@ -18,10 +18,12 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without application_settings' do
|
context 'without application_settings' do
|
||||||
it 'does not fail' do
|
it 'returns error' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
expect(subject).to receive(:log_error).and_call_original
|
||||||
expect(result).to eq(
|
expect(result).to eq(
|
||||||
status: :success
|
status: :error,
|
||||||
|
message: 'No application_settings found',
|
||||||
|
last_step: :validate_application_settings
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(Project.count).to eq(0)
|
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 }
|
allow(ApplicationSetting).to receive(:current_without_cache) { application_setting }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not fail' do
|
it 'returns error' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
expect(subject).to receive(:log_error).and_call_original
|
||||||
expect(result).to eq(
|
expect(result).to eq(
|
||||||
status: :success
|
status: :error,
|
||||||
|
message: 'No active admin user found',
|
||||||
|
last_step: :validate_admins
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(Project.count).to eq(0)
|
expect(Project.count).to eq(0)
|
||||||
|
@ -47,7 +51,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with admin users' do
|
context 'with application settings and admin users' do
|
||||||
let(:project) { result[:project] }
|
let(:project) { result[:project] }
|
||||||
let(:group) { result[:group] }
|
let(:group) { result[:group] }
|
||||||
let(:application_setting) { Gitlab::CurrentSettings.current_application_settings }
|
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_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
|
it 'creates group' do
|
||||||
expect(result[:status]).to eq(:success)
|
expect(result[:status]).to eq(:success)
|
||||||
expect(group).to be_persisted
|
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
|
it 'returns error when saving project ID fails' do
|
||||||
allow(application_setting).to receive(:save) { false }
|
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
|
end
|
||||||
|
|
||||||
context 'when project already exists' do
|
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
|
application_setting.instance_administration_project_id = existing_project.id
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not fail' do
|
it 'returns success' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
expect(result).to include(status: :success)
|
||||||
expect(result[:status]).to eq(:success)
|
|
||||||
|
|
||||||
expect(Project.count).to eq(1)
|
expect(Project.count).to eq(1)
|
||||||
expect(Group.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
|
it 'returns error' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -261,7 +279,11 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
||||||
|
|
||||||
it 'returns error' do
|
it 'returns error' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -275,15 +297,13 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
|
||||||
|
|
||||||
it 'returns error' do
|
it 'returns error' do
|
||||||
expect(subject).to receive(:log_error).and_call_original
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "tracks successful install" do
|
|
||||||
expect(Gitlab::Tracking).to receive(:event).with("self_monitoring", "project_created")
|
|
||||||
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -142,11 +142,11 @@ describe Clusters::Applications::Ingress do
|
||||||
let(:project) { build(:project) }
|
let(:project) { build(:project) }
|
||||||
let(:cluster) { build(:cluster, projects: [project]) }
|
let(:cluster) { build(:cluster, projects: [project]) }
|
||||||
|
|
||||||
context 'when ingress_modsecurity is enabled' do
|
context 'when modsecurity_enabled is enabled' do
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(ingress_modsecurity: true)
|
|
||||||
|
|
||||||
allow(subject).to receive(:cluster).and_return(cluster)
|
allow(subject).to receive(:cluster).and_return(cluster)
|
||||||
|
|
||||||
|
allow(subject).to receive(:modsecurity_enabled).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes modsecurity module enablement' do
|
it 'includes modsecurity module enablement' do
|
||||||
|
@ -173,10 +173,8 @@ describe Clusters::Applications::Ingress do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when ingress_modsecurity is disabled' do
|
context 'when modsecurity_enabled is disabled' do
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(ingress_modsecurity: false)
|
|
||||||
|
|
||||||
allow(subject).to receive(:cluster).and_return(cluster)
|
allow(subject).to receive(:cluster).and_return(cluster)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,33 @@ describe Clusters::Applications::CreateService do
|
||||||
create(:clusters_applications_helm, :installed, cluster: cluster)
|
create(:clusters_applications_helm, :installed, cluster: cluster)
|
||||||
end
|
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
|
context 'cert manager application' do
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue