diff --git a/.rubocop.yml b/.rubocop.yml index 59ac81bb4de..60012c1b96d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -130,6 +130,7 @@ Naming/FileName: - 'qa/spec/**/*' - 'qa/qa/specs/**/*' - 'qa/tasks/**/*.rake' + - '**/*.ru' IgnoreExecutableScripts: true AllowedAcronyms: @@ -151,6 +152,23 @@ Naming/FileName: - CI - CD - OAuth + - CSP + - CSV + - SCA + - SAN + - CIDR + - SPDX + - MR + - SSE + - JWT + - HLL + - VSCode + - GPG + - OTP + - GID + - AR + - RSpec + - Javascript # default ones: - CLI - DSL diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index ceed2249f3d..68a8dbba624 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -8,6 +8,8 @@ import { GlTooltipDirective, GlIntersectionObserver, } from '@gitlab/ui'; +import { once } from 'lodash'; +import api from '~/api'; import { sprintf, s__, __ } from '~/locale'; import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; import { EXTENSION_ICON_CLASS } from '../../constants'; @@ -102,8 +104,15 @@ export default { }); }, methods: { + triggerRedisTracking: once(function triggerRedisTracking() { + if (this.$options.expandEvent) { + api.trackRedisHllUserEvent(this.$options.expandEvent); + } + }), toggleCollapsed() { this.isCollapsed = !this.isCollapsed; + + this.triggerRedisTracking(); }, loadAllData() { if (this.fullData) return; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js index 4ca0b660696..ec6e6ed2620 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js @@ -12,6 +12,7 @@ export const registerExtension = (extension) => { name: extension.name, props: extension.props, i18n: extension.i18n, + expandEvent: extension.expandEvent, computed: { ...Object.keys(extension.computed).reduce( (acc, computedKey) => ({ diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js index 349e9d29355..57117b6ae1f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js @@ -11,6 +11,7 @@ export default { label: 'Issues', loading: 'Loading issues...', }, + expandEvent: 'i_testing_load_performance_widget_total', // Add an array of props // These then get mapped to values stored in the MR Widget store props: ['targetProjectFullPath', 'conflictsDocsPath'], diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 0a18559fc81..ff52d76527e 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -46,6 +46,7 @@ class SearchController < ApplicationController @search_results = @search_service.search_results @search_objects = @search_service.search_objects @search_highlight = @search_service.search_highlight + @aggregations = @search_service.search_aggregations increment_search_counters end diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index 60e37c96f61..5ca360f38da 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -39,14 +39,14 @@ module AppearancesHelper if current_appearance&.header_logo? image_tag current_appearance.header_logo_path, class: 'brand-header-logo' else - render 'shared/logo.svg' + render partial: 'shared/logo', formats: :svg end end # Skip the 'GitLab' type logo when custom brand logo is set def brand_header_logo_type unless current_appearance&.header_logo? - render 'shared/logo_type.svg' + render partial: 'shared/logo_type', formats: :svg end end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index cce7821a226..4ba1b3ade86 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -75,6 +75,10 @@ class SearchService search_results.highlight_map(scope) end + def search_aggregations + search_results.aggregations(scope) + end + private def page diff --git a/app/views/admin/application_settings/_protected_paths.html.haml b/app/views/admin/application_settings/_protected_paths.html.haml index 04b42f42014..d273c81f51d 100644 --- a/app/views/admin/application_settings/_protected_paths.html.haml +++ b/app/views/admin/application_settings/_protected_paths.html.haml @@ -2,30 +2,26 @@ = form_errors(@application_setting) %fieldset - - if omnibus_protected_paths_throttle? - .bs-callout.bs-callout-danger - - relative_url_link = 'https://docs.gitlab.com/ee/user/admin_area/settings/protected_paths.html#migrate-settings-from-gitlab-123-and-earlier' - - relative_url_link_start = ''.html_safe % { url: relative_url_link } - = _("Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}.").html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: ''.html_safe } - .form-group .form-check = f.check_box :throttle_protected_paths_enabled, class: 'form-check-input' = f.label :throttle_protected_paths_enabled, class: 'form-check-label' do - = _('Enable protected paths rate limit') + = _('Enable rate limiting for POST requests to the specified paths') %span.form-text.text-muted - = _('Helps reduce request volume for protected paths') + = _('Helps reduce request volume for protected paths.') .form-group - = f.label :throttle_protected_paths_requests_per_period, 'Max requests per period per user', class: 'label-bold' + = f.label :throttle_protected_paths_requests_per_period, 'Maximum requests per period per user', class: 'label-bold' = f.number_field :throttle_protected_paths_requests_per_period, class: 'form-control gl-form-input' .form-group - = f.label :throttle_protected_paths_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold' + = f.label :throttle_protected_paths_period_in_seconds, 'Rate limit period (in seconds)', class: 'label-bold' = f.number_field :throttle_protected_paths_period_in_seconds, class: 'form-control gl-form-input' .form-group = f.label :protected_paths, class: 'label-bold' do + = _('Paths to protect with rate limiting') + = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control gl-form-input', rows: 10 + %span.form-text.text-muted - relative_url_link = 'https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab' - relative_url_link_start = ''.html_safe % { url: relative_url_link } - = _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: ''.html_safe } - = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control gl-form-input', rows: 10 + = _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: ''.html_safe } = f.submit _('Save changes'), class: 'gl-button btn btn-confirm' diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml index 58e3f3f1136..3a053205725 100644 --- a/app/views/admin/application_settings/network.html.haml +++ b/app/views/admin/application_settings/network.html.haml @@ -87,14 +87,12 @@ %section.settings.as-protected-paths.no-animate#js-protected-paths-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 - = _('Protected Paths') + = _('Protected paths') %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' } = expanded_by_default? ? _('Collapse') : _('Expand') %p - = _('Configure paths to be protected by Rack Attack.') - .help-block - = _('These paths are protected for POST requests.') - = link_to _('More information'), help_page_path('security/rack_attack', anchor: 'protected-paths-throttle'), target: '_blank' + = _('Rate limit access to specified paths.') + = link_to _('Learn more.'), help_page_path('user/admin_area/settings/protected_paths.md'), target: '_blank', rel: 'noopener noreferrer' .settings-content = render 'protected_paths' diff --git a/app/views/issues/_issues_calendar.ics.ruby b/app/views/issues/_issues_calendar.ics.ruby index c21c4dac9f0..4b0be661aa5 100644 --- a/app/views/issues/_issues_calendar.ics.ruby +++ b/app/views/issues/_issues_calendar.ics.ruby @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true cal = Icalendar::Calendar.new @@ -17,3 +18,5 @@ end # rubocop: enable CodeReuse/ActiveRecord cal.to_ical + +# rubocop:enable Naming/FileName diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index 0230a226567..d7bd8207f06 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -87,13 +87,14 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker private def send_email(recipient, project_id, options) - # Generating the body of this email can be expensive, so only do it once - @skip_premailer ||= email.present? - @email ||= Notify.repository_push_email(project_id, options) + @email ||= Notify.repository_push_email(project_id, options).tap do |mail| + Premailer::Rails::Hook.perform(mail) + end - email.to = recipient - email.add_message_id - email.header[:skip_premailer] = true if skip_premailer - email.deliver_now + current_email = email.dup + current_email.to = recipient + current_email.add_message_id + current_email.header[:skip_premailer] = true + current_email.deliver_now end end diff --git a/bin/pngquant b/bin/pngquant index 8434e9d3ec9..a614814a8a3 100755 --- a/bin/pngquant +++ b/bin/pngquant @@ -5,7 +5,7 @@ require 'rails' require 'png_quantizator' require 'parallel' require 'rainbow/ext/string' -require_relative '../tooling/lib/tooling/images' +require_relative '../tooling/lib/tooling/image' return if Rails.env.production? diff --git a/config/feature_flags/ops/product_analytics_tracking.yml b/config/feature_flags/ops/product_analytics_tracking.yml deleted file mode 100644 index 5d392c4e4a7..00000000000 --- a/config/feature_flags/ops/product_analytics_tracking.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: product_analytics_tracking -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46482 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285519 -milestone: '13.7' -type: ops -group: group::product intelligence -default_enabled: false diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt index 8c5eb5758bf..f1caf49e9aa 100644 --- a/doc/.vale/gitlab/spelling-exceptions.txt +++ b/doc/.vale/gitlab/spelling-exceptions.txt @@ -150,6 +150,7 @@ denormalized denormalizes denormalizing denylist +denylisted denylisting denylists deployer diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md index 93b77b07ccb..4f9f08dab28 100644 --- a/doc/administration/instance_limits.md +++ b/doc/administration/instance_limits.md @@ -15,9 +15,7 @@ performance, data, or could even exhaust the allocated resources for the applica Rate limits can be used to improve the security and durability of GitLab. -For example, one script can make thousands of web requests per second. Whether malicious, apathetic, or just a bug, your application and infrastructure may not be able to cope with the load. Rate limits can help to mitigate these types of attacks. - -Read more about [configuring rate limits](../security/rate_limits.md) in the Security documentation. +Read more about [configuring rate limits](../security/rate_limits.md). ### Issue creation @@ -128,16 +126,6 @@ This setting limits the import/export actions for groups and projects. Read more about [import/export rate limits](../user/admin_area/settings/import_export_rate_limits.md). -### Rack attack - -This method of rate limiting is cumbersome, but has some advantages. It allows -throttling of specific paths, and is also integrated into Git and container -registry requests. - -Read more about the [Rack Attack initializer](../security/rack_attack.md) method of setting rate limits. - -- **Default rate limit**: Disabled. - ### Member Invitations Limit the maximum daily member invitations allowed per group hierarchy. diff --git a/doc/administration/logs.md b/doc/administration/logs.md index a9fd698a525..bf74a96a627 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -752,7 +752,6 @@ Depending on your installation method, this file is located at: This log records: -- Information whenever [Rack Attack](../security/rack_attack.md) registers an abusive request. - Requests over the [Rate Limit](../user/admin_area/settings/rate_limits_on_raw_endpoints.md) on raw endpoints. - [Protected paths](../user/admin_area/settings/protected_paths.md) abusive requests. - In GitLab versions [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239) and later, diff --git a/doc/api/settings.md b/doc/api/settings.md index 7b8778973f2..1ac8d8eda5f 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -411,11 +411,11 @@ listed in the descriptions of the relevant settings. | `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. | | `terms` | text | required by: `enforce_terms` | (**Required by:** `enforce_terms`) Markdown content for the ToS. | | `throttle_authenticated_api_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_api_period_in_seconds` and `throttle_authenticated_api_requests_per_period`) Enable authenticated API request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). | -| `throttle_authenticated_api_period_in_seconds` | integer | required by:
`throttle_authenticated_api_enabled` | Rate limit period in seconds. | -| `throttle_authenticated_api_requests_per_period` | integer | required by:
`throttle_authenticated_api_enabled` | Max requests per period per user. | +| `throttle_authenticated_api_period_in_seconds` | integer | required by:
`throttle_authenticated_api_enabled` | Rate limit period (in seconds). | +| `throttle_authenticated_api_requests_per_period` | integer | required by:
`throttle_authenticated_api_enabled` | Maximum requests per period per user. | | `throttle_authenticated_web_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_web_period_in_seconds` and `throttle_authenticated_web_requests_per_period`) Enable authenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). | -| `throttle_authenticated_web_period_in_seconds` | integer | required by:
`throttle_authenticated_web_enabled` | Rate limit period in seconds. | -| `throttle_authenticated_web_requests_per_period` | integer | required by:
`throttle_authenticated_web_enabled` | Max requests per period per user. | +| `throttle_authenticated_web_period_in_seconds` | integer | required by:
`throttle_authenticated_web_enabled` | Rate limit period (in seconds). | +| `throttle_authenticated_web_requests_per_period` | integer | required by:
`throttle_authenticated_web_enabled` | Maximum requests per period per user. | | `throttle_unauthenticated_enabled` | boolean | no | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_enabled` or `throttle_unauthenticated_api_enabled` instead.) (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). | | `throttle_unauthenticated_period_in_seconds` | integer | required by:
`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_period_in_seconds` or `throttle_unauthenticated_api_period_in_seconds` instead.) Rate limit period in seconds. | | `throttle_unauthenticated_requests_per_period` | integer | required by:
`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_requests_per_period` or `throttle_unauthenticated_api_requests_per_period` instead.) Max requests per period per IP. | diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index 72491ab3a33..88f6227b487 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -1026,18 +1026,13 @@ document to ensure it links to the most recent version of the file. When documenting how to navigate through the GitLab UI: - Always use location, then action. - - `From the **Visibility** list,` (location) `select **Public**.` (action) + - From the **Visibility** dropdown list (location), select **Public** (action). - Be brief and specific. For example: - - Avoid: `Select **Save** for the changes to take effect.` - - Use instead: `Select **Save**.` -- When selecting from high-level UI elements, use the word **on**. - - Avoid: `From the left sidebar...` or `In the left sidebar...` - - Use instead: `On the left sidebar...` -- If a step must include a reason, start the step with it. - - Avoid: `Select the link in the merge request to view the changes.` - - Use instead: `To view the changes, select the link in the merge request.` -- If a step is optional, start the step with the word `Optional` followed by a period. - - `1. Optional. Enter a name for the dog.` + - Do: Select **Save**. + - Do not: Select **Save** for the changes to take effect. +- If a step must include a reason, start the step with it. This helps the user scan more quickly. + - Do: To view the changes, in the merge request, select the link. + - Do not: Select the link in the merge request to view the changes. ### Names for menus @@ -1082,6 +1077,42 @@ To select your avatar: 1. On the top bar, in the top right corner, select your avatar. ``` +### Optional steps + +If a step is optional, start the step with the word `Optional` followed by a period. + +For example: + +```markdown +1. Optional. Enter a description for the job. +``` + +### Documenting multiple fields at once + +If the UI text sufficiently explains the fields in a section, do not include a task step for every field. +Instead, summarize multiple fields in a single task step. + +Use the phrase **Complete the fields**. + +For example: + +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > Repository**. +1. Expand **Push rules**. +1. Complete the fields. + +If you are documenting multiple fields and only one field needs explanation, do it in the same step: + +1. Expand **Push rules**. +1. Complete the fields. **Branch name** must be a regular expression. + +To describe multiple fields, use bullets: + +1. Expand **General pipelines**. +1. Complete the fields. + - **Branch name** must be a regular expression. + - **User** must be a user with at least the **Maintainer** role. + ## Images Images, including screenshots, can help a reader better understand a concept. diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index 30d93de5134..2e7ebf4366f 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -259,6 +259,16 @@ Use **box** instead of **field** or **text box**. - Do: In the **Variable name** box, enter `my text`. - Do not: In the **Variable name** field, enter `my text`. +However, you can make an exception when you are writing a task and you need to refer to all +of the fields at once. For example: + +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > CI/CD**. +1. Expand **General pipelines**. +1. Complete the fields. + +Learn more about [documenting multiple fields at once](index.md#documenting-multiple-fields-at-once). + ## foo Do not use **foo** in product documentation. You can use it in our API and contributor documentation, but try to use a clearer and more meaningful example instead. @@ -454,6 +464,13 @@ Do not use **note that** because it's wordy. - Do: You can change the settings. - Do not: Note that you can change the settings. +## on + +When documenting how to select high-level UI elements, use the word **on**. + +- Do: `On the left sidebar...` +- Do not: `From the left sidebar...` or `In the left sidebar...` + ## once The word **once** means **one time**. Don't use it to mean **after** or **when**. diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md index 3b7ea5c1975..f74e9f26362 100644 --- a/doc/install/openshift_and_gitlab/index.md +++ b/doc/install/openshift_and_gitlab/index.md @@ -1,9 +1,45 @@ --- -redirect_to: 'https://docs.gitlab.com/charts/installation/operator.html' -remove_date: '2022-09-22' +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -This file was moved to [another location](https://docs.gitlab.com/charts/installation/operator.html). +# OpenShift support - - +OpenShift - GitLab compatibility can be addressed in three different aspects. This page helps navigating between these aspects and provides introductory information for getting started with OpenShift and GitLab. + +## What is OpenShift + +OpenShift helps you to develop, deploy, and manage container-based applications. It provides you with a self-service platform to create, modify, and deploy applications on demand, thus enabling faster development and release life cycles. + +## Use OpenShift to run GitLab Self-Managed + +Running GitLab within an OpenShift cluster is officially supported using the GitLab Operator. You can learn more on +[setting up GitLab on OpenShift on the GitLab Operator's documentation](https://docs.gitlab.com/charts/installation/operator.html). +Some components (documented on the GitLab Operator doc) are not supported yet. + +## Deploy to and integrate with OpenShift from GitLab + +Deploying custom or COTS applications on top of OpenShift from GitLab is supported using [the GitLab Kubernetes Agent](../../user/clusters/agent/index.md). + +## Use OpenShift to run a GitLab Runner Fleet + +The GitLab Operator does not include the GitLab Runner. To install and manage a GitLab Runner fleet in an OpenShift cluster, use the +[GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator). + +## Unsupported GitLab features + +### Docker-in-Docker + +When using OpenShift to run a GitLab Runner Fleet, we do not support some GitLab features given OpenShift's security model. +Features requiring Docker-in-Docker might not work. + +For Auto DevOps, the following features are not supported yet: + +- Auto Code Quality +- Auto License Compliance +- Auto Browser Performance Testing +- Auto Build + +For Auto Build, there's a [possible workaround using `kaniko`](../../ci/docker/using_kaniko.md). +You can check the progress of the implementation in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/332560). diff --git a/doc/integration/jira/index.md b/doc/integration/jira/index.md index f5f7e8c33fc..e3214ec26fe 100644 --- a/doc/integration/jira/index.md +++ b/doc/integration/jira/index.md @@ -63,7 +63,7 @@ The process for configuring Jira depends on whether you host Jira on your own se how to [set up a user in Jira Server](jira_server_configuration.md). - **Jira on Atlassian cloud** supports authentication through an API token. When connecting to Jira on Atlassian cloud, an email and API token are required. For more information, read - [set up a user in Jira on Atlassian cloud](jira_cloud_configuration.md). + [create an API token for Jira in Atlassian cloud](jira_cloud_configuration.md). ## Privacy considerations diff --git a/doc/integration/jira/jira_cloud_configuration.md b/doc/integration/jira/jira_cloud_configuration.md index 0cfffdb8ba4..08cd34860ff 100644 --- a/doc/integration/jira/jira_cloud_configuration.md +++ b/doc/integration/jira/jira_cloud_configuration.md @@ -4,18 +4,19 @@ group: Integrations info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Create an API token in Jira on Atlassian cloud **(FREE)** +# Create an API token for Jira in Atlassian cloud **(FREE)** You need an API token to [integrate with Jira](index.md) on Atlassian cloud. To create the API token: -1. Sign in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens) - with your email address. Use an account with *write* access to Jira projects. -1. Go to **Settings > Atlassian account settings > Security > Create and manage API tokens**. -1. Select **Create API token** to display a modal window with an API token. +1. Sign in to [Atlassian](https://id.atlassian.com/manage-profile/security/api-tokens) + using an account with *write* access to Jira projects. + + The link opens the API tokens page. Alternatively, to go to this page from your Atlassian + profile, select **Account Settings > Security > Create and manage API tokens**. +1. Select **Create API token**. 1. In the dialog, enter a label for your token and select **Create**. -1. To copy the API token, select **Copy**, then paste the token somewhere safe. You need this value when you - [configure GitLab](configure.md). +1. To copy the API token, select **Copy**, then paste the token somewhere safe. You need the newly created token, and the email address you used when you created it, when you diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md index b0bebc5a956..a8b55007d2e 100644 --- a/doc/security/rack_attack.md +++ b/doc/security/rack_attack.md @@ -1,195 +1,9 @@ --- -stage: Manage -group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: reference, howto +redirect_to: '../user/admin_area/settings/protected_paths.md' +remove_date: '2022-01-14' --- -# Rack Attack initializer **(FREE SELF)** +This document was moved to [another location](../user/admin_area/settings/protected_paths.md). -[Rack Attack](https://github.com/kickstarter/rack-attack), also known as Rack::Attack, is a Ruby gem -that is meant to protect GitLab with the ability to customize throttling and -to block user IP addresses. - -You can prevent brute-force passwords attacks, scrapers, or any other offenders -by throttling requests from IP addresses that are making large volumes of requests. -If you find throttling is not enough to protect you against abusive clients, -Rack Attack offers IP whitelisting, blacklisting, Fail2ban style filtering, and -tracking. - -For more information on how to use these options see the [Rack Attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md). - -NOTE: -See -[User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md) -for simpler limits that are configured in the UI. - -NOTE: -Starting with GitLab 11.2, Rack Attack is disabled by default. If your -instance is not exposed to the public internet, it is recommended that you leave -Rack Attack disabled. - -## Behavior - -If set up as described in the [Settings](#settings) section below, two behaviors -are enabled: - -- Protected paths are throttled. -- Failed authentications for Git and container registry requests trigger a temporary IP ban. - -### Protected paths throttle - -GitLab responds with HTTP status code `429` to POST requests at protected paths -that exceed 10 requests per minute per IP address. - -By default, protected paths are: - -- `/users/password` -- `/users/sign_in` -- `/api/#{API::API.version}/session.json` -- `/api/#{API::API.version}/session` -- `/users` -- `/users/confirmation` -- `/unsubscribes/` -- `/import/github/personal_access_token` -- `/admin/session` - -See [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests. - -For example, the following are limited to a maximum 10 requests per minute: - -- User sign-in -- User sign-up (if enabled) -- User password reset - -After 10 requests, the client must wait a minute before it can -try again. - -### Git and container registry failed authentication ban - -GitLab responds with HTTP status code `403` for 1 hour, if 30 failed -authentication requests were received in a 3-minute period from a single IP address. - -This applies only to Git requests and container registry (`/jwt/auth`) requests -(combined). - -This limit: - -- Is reset by requests that authenticate successfully. For example, 29 - failed authentication requests followed by 1 successful request, followed by 29 - more failed authentication requests would not trigger a ban. -- Does not apply to JWT requests authenticated by `gitlab-ci-token`. - -No response headers are provided. - -## Settings - -**Omnibus GitLab** - -1. Open `/etc/gitlab/gitlab.rb` with your editor -1. Add the following: - - ```ruby - gitlab_rails['rack_attack_git_basic_auth'] = { - 'enabled' => true, - 'ip_whitelist' => ["127.0.0.1"], - 'maxretry' => 10, # Limit the number of Git HTTP authentication attempts per IP - 'findtime' => 60, # Reset the auth attempt counter per IP after 60 seconds - 'bantime' => 3600 # Ban an IP for one hour (3600s) after too many auth attempts - } - ``` - -1. Reconfigure GitLab: - - ```shell - sudo gitlab-ctl reconfigure - ``` - -The following settings can be configured: - -- `enabled`: By default this is set to `false`. Set this to `true` to enable Rack Attack. -- `ip_whitelist`: Whitelist any IPs from being blocked. They must be formatted as strings within a Ruby array. - CIDR notation is supported in GitLab 12.1 and later. - For example, `["127.0.0.1", "127.0.0.2", "127.0.0.3", "192.168.0.1/24"]`. -- `maxretry`: The maximum amount of times a request can be made in the - specified time. -- `findtime`: The maximum amount of time that failed requests can count against an IP - before it's blacklisted (in seconds). -- `bantime`: The total amount of time that a blacklisted IP is blocked (in - seconds). - -**Installations from source** - -These settings can be found in `config/initializers/rack_attack.rb`. If you are -missing `config/initializers/rack_attack.rb`, the following steps need to be -taken in order to enable protection for your GitLab instance: - -1. In `config/application.rb` find and uncomment the following line: - - ```ruby - config.middleware.use Rack::Attack - ``` - -1. Restart GitLab: - - ```shell - sudo service gitlab restart - ``` - -If you want more restrictive/relaxed throttle rules, edit -`config/initializers/rack_attack.rb` and change the `limit` or `period` values. -For example, you can set more relaxed throttle rules with -`limit: 3` and `period: 1.seconds`, allowing 3 requests per second. -You can also add other paths to the protected list by adding to `paths_to_be_protected` -variable. If you change any of these settings you must restart your -GitLab instance. - -## Remove blocked IPs from Rack Attack via Redis - -In case you want to remove a blocked IP, follow these steps: - -1. Find the IPs that have been blocked in the production log: - - ```shell - grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log - ``` - -1. Since the blacklist is stored in Redis, you need to open up `redis-cli`: - - ```shell - /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket - ``` - -1. You can remove the block using the following syntax, replacing `` with - the actual IP that is blacklisted: - - ```plaintext - del cache:gitlab:rack::attack:allow2ban:ban: - ``` - -1. Confirm that the key with the IP no longer shows up: - - ```plaintext - keys *rack::attack* - ``` - -1. Optionally, add the IP to the whitelist to prevent it from being blacklisted - again (see [settings](#settings)). - -## Troubleshooting - -### Rack attack is blacklisting the load balancer - -Rack Attack may block your load balancer if all traffic appears to come from -the load balancer. In that case, you must: - -1. [Configure `nginx[real_ip_trusted_addresses]`](https://docs.gitlab.com/omnibus/settings/nginx.html#configuring-gitlab-trusted_proxies-and-the-nginx-real_ip-module). - This keeps users' IPs from being listed as the load balancer IPs. -1. Whitelist the load balancer's IP address(es) in the Rack Attack [settings](#settings). -1. Reconfigure GitLab: - - ```shell - sudo gitlab-ctl reconfigure - ``` - -1. [Remove the block via Redis.](#remove-blocked-ips-from-rack-attack-via-redis) + + diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md index 4585748ffc2..278be565971 100644 --- a/doc/security/rate_limits.md +++ b/doc/security/rate_limits.md @@ -14,9 +14,13 @@ For GitLab.com, please see Rate limiting is a common technique used to improve the security and durability of a web application. -For example, a simple script can make thousands of web requests per second. -Whether malicious, apathetic, or just a bug, your application and infrastructure -may not be able to cope with the load. For more details, see +For example, a simple script can make thousands of web requests per second. The requests could be: + +- Malicious. +- Apathetic. +- Just a bug. + +Your application and infrastructure may not be able to cope with the load. For more details, see [Denial-of-service attack](https://en.wikipedia.org/wiki/Denial-of-service_attack). Most cases can be mitigated by limiting the rate of requests from a single IP address. @@ -25,7 +29,7 @@ similarly mitigated by a rate limit. ## Admin Area settings -These are rate limits you can set in the Admin Area of your instance: +You can set these rate limits in the Admin Area of your instance: - [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.md) - [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md) @@ -38,14 +42,36 @@ These are rate limits you can set in the Admin Area of your instance: - [Files API rate limits](../user/admin_area/settings/files_api_rate_limits.md) - [Deprecated API rate limits](../user/admin_area/settings/deprecated_api_rate_limits.md) +## Failed authentication ban for Git and container registry + +GitLab returns HTTP status code `403` for 1 hour, if 30 failed authentication requests were received +in a 3-minute period from a single IP address. This applies only to combined: + +- Git requests. +- Container registry (`/jwt/auth`) requests. + +This limit: + +- Is reset by requests that authenticate successfully. For example, 29 failed authentication + requests followed by 1 successful request, followed by 29 more failed authentication requests + would not trigger a ban. +- Does not apply to JWT requests authenticated by `gitlab-ci-token`. +- Is disabled by default. + +No response headers are provided. + +For configuration information, see +[Omnibus GitLab configuration options](https://docs.gitlab.com/omnibus/settings/configuration.html#configure-a-failed-authentication-ban). + ## Non-configurable limits ### Repository archives > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25750) in GitLab 12.9. -There is a rate limit for [downloading repository archives](../api/repositories.md#get-file-archive), -which applies to the project and to the user initiating the download either through the UI or the API. +A rate limit for [downloading repository archives](../api/repositories.md#get-file-archive) is +available. The limit applies to the project and to the user initiating the download either through +the UI or the API. The **rate limit** is 5 requests per minute per user. @@ -57,8 +83,50 @@ There is a rate limit for [testing webhooks](../user/project/integrations/webhoo The **rate limit** is 5 requests per minute per user. -## Rack Attack initializer +## Troubleshooting -This method of rate limiting is cumbersome, but has some advantages. It allows -throttling of specific paths, and is also integrated into Git and container -registry requests. See [Rack Attack initializer](rack_attack.md). +### Rack Attack is denylisting the load balancer + +Rack Attack may block your load balancer if all traffic appears to come from +the load balancer. In that case, you must: + +1. [Configure `nginx[real_ip_trusted_addresses]`](https://docs.gitlab.com/omnibus/settings/nginx.html#configuring-gitlab-trusted_proxies-and-the-nginx-real_ip-module). + This keeps users' IPs from being listed as the load balancer IPs. +1. Allowlist the load balancer's IP addresses. +1. Reconfigure GitLab: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +### Remove blocked IPs from Rack Attack with Redis + +To remove a blocked IP: + +1. Find the IPs that have been blocked in the production log: + + ```shell + grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log + ``` + +1. Since the denylist is stored in Redis, you must open up `redis-cli`: + + ```shell + /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket + ``` + +1. You can remove the block using the following syntax, replacing `` with + the actual IP that is denylisted: + + ```plaintext + del cache:gitlab:rack::attack:allow2ban:ban: + ``` + +1. Confirm that the key with the IP no longer shows up: + + ```plaintext + keys *rack::attack* + ``` + +1. Optionally, add [the IP to the allowlist](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-rack-attack) + to prevent it being denylisted again. diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md index dc328fe8b7c..e686c65fe9a 100644 --- a/doc/user/admin_area/settings/protected_paths.md +++ b/doc/user/admin_area/settings/protected_paths.md @@ -7,28 +7,11 @@ type: reference # Protected paths **(FREE SELF)** -Rate limiting is a common technique used to improve the security and durability -of a web application. For more details, see -[Rate limits](../../../security/rate_limits.md). +Rate limiting is a technique that improves the security and durability of a web +application. For more details, see [Rate limits](../../../security/rate_limits.md). -GitLab rate limits the following paths with Rack Attack by default: - -```plaintext -'/users/password', -'/users/sign_in', -'/api/#{API::API.version}/session.json', -'/api/#{API::API.version}/session', -'/users', -'/users/confirmation', -'/unsubscribes/', -'/import/github/personal_access_token', -'/admin/session' -``` - -GitLab responds with HTTP status code `429` to POST requests at protected paths -that exceed 10 requests per minute per IP address. - -See [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests. +You can rate limit (protect) specified paths. For these paths, GitLab responds with HTTP status +code `429` to POST requests at protected paths that exceed 10 requests per minute per IP address. For example, the following are limited to a maximum 10 requests per minute: @@ -36,10 +19,15 @@ For example, the following are limited to a maximum 10 requests per minute: - User sign-up (if enabled) - User password reset -After 10 requests, the client must wait 60 seconds before it can -try again. +After 10 requests, the client must wait 60 seconds before it can try again. -## Configure using GitLab UI +See also: + +- List of paths [protected by default](../../../administration/instance_limits.md#by-protected-path). +- [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers) + for the headers returned to blocked requests. + +## Configure protected paths > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31246) in GitLab 12.4. diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md index 180833538ed..e49b159515c 100644 --- a/doc/user/application_security/index.md +++ b/doc/user/application_security/index.md @@ -261,10 +261,6 @@ under your project's settings: ``` -## DAST On-Demand Scans - -If you don't want scans running in your normal DevOps process you can use on-demand scans instead. For more details, see [on-demand scans](dast/index.md#on-demand-scans). This feature is only available for DAST. If you run an on-demand scan against the default branch, it is reported as a "successful pipeline" and these results are included in the security dashboard and vulnerability report. - ## Security report validation > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321918) in GitLab 13.11. diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md index 34f4c400265..7bdc8cc8479 100644 --- a/doc/user/application_security/vulnerabilities/index.md +++ b/doc/user/application_security/vulnerabilities/index.md @@ -20,6 +20,9 @@ vulnerability include: - Linked issues - Actions log +In GitLab 14.3 and later, if the scanner determined the vulnerability to be a false positive, an +alert message is included at the top of the vulnerability's page. + On the vulnerability's page, you can: - [Change the vulnerability's status](#change-vulnerability-status). diff --git a/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png b/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png deleted file mode 100644 index 44c689eda3e..00000000000 Binary files a/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png and /dev/null differ diff --git a/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png b/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png new file mode 100644 index 00000000000..ac996fa32db Binary files /dev/null and b/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png differ diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md index 20abb7d1e2f..d13647937a2 100644 --- a/doc/user/application_security/vulnerability_report/index.md +++ b/doc/user/application_security/vulnerability_report/index.md @@ -16,7 +16,16 @@ At all levels, the Vulnerability Report contains: - Filters for common vulnerability attributes. - Details of each vulnerability, presented in tabular layout. -![Vulnerability Report](img/group_vulnerability_report_v14_2.png) +The **Activity** column contains icons to indicate the activity, if any, taken on the vulnerability +in that row: + +- Issues **{issues}**: Links to issues created for the vulnerability. For more details, read + [Create an issue for a vulnerability](../vulnerabilities/index.md#create-an-issue-for-a-vulnerability). +- Wrench **{admin}**: The vulnerability has been remediated. +- False positive **{false-positive}**: The scanner determined this vulnerability to be a false + positive. + +![Example project-level Vulnerability Report](img/project_level_vulnerability_report_v14_5.png) ## Project-level Vulnerability Report diff --git a/doc/user/infrastructure/clusters/index.md b/doc/user/infrastructure/clusters/index.md index 80a1ccb81d1..1337574b8ac 100644 --- a/doc/user/infrastructure/clusters/index.md +++ b/doc/user/infrastructure/clusters/index.md @@ -8,9 +8,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: In GitLab 14.5, the certificate-based method to connect Kubernetes clusters -to GitLab was deprecated, as well as the related [features](#deprecated-features). +to GitLab was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8), +as well as its related [features](#deprecated-features). -This feature is now deprecated. It had the following issues: +Connecting Kubernetes clusters to GitLab through cluster certificates is deprecated. +This method had the following issues: - There were security issues as it required direct access to the Kube API by GitLab. - The configuration options weren't flexible. @@ -54,10 +56,16 @@ the Kubernetes Agent model on the [Agent's blueprint documentation](../../../arc - [Clusters health](manage/clusters_health.md) - [Crossplane integration](../../clusters/crossplane.md) - [Auto Deploy](../../../topics/autodevops/stages.md#auto-deploy) +- [Web terminals](../../../administration/integration/terminal.md) ### Cluster levels -The concept of project-level, group-level, and instance-level clusters becomes +The concept of [project-level](../../project/clusters/index.md), +[group-level](../../group/clusters/index.md), and +[instance-level](../../instance/clusters/index.md) clusters becomes extinct in the new model, although the functionality remains to some extent. -The Agent is always configured in a GitLab project, but you can grant your -cluster's access to a GitLab group through the Agent. + +The Agent is always configured in a GitLab project, but you can: + +- [Grant your cluster's access to GitLab groups through the Agent](../../clusters/agent/repository.md#authorize-groups-to-use-an-agent). +- [Share access to the Agent with other projects and groups through the CI/CD Tunnel](../../clusters/agent/ci_cd_tunnel.md#share-the-cicd-tunnel-provided-by-an-agent-with-other-projects-and-group). diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md index 7d51fb59793..c138dc64d19 100644 --- a/doc/user/project/code_owners.md +++ b/doc/user/project/code_owners.md @@ -84,6 +84,10 @@ so that their members also become eligible Code Owners. If you do not invite **Subgroup Y** to **Project A**, but make them Code Owners, their approval of the merge request becomes optional. +Inviting **Subgroup Y** to a parent group of **Project A** +[is not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/288851). To set **Subgroup Y** as +Code Owners, add this group directly to the project itself. + ### Add a group as a Code Owner To set a group as a Code Owner: diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md index cda018a0c37..0c50fc77e33 100644 --- a/doc/user/project/import/bitbucket.md +++ b/doc/user/project/import/bitbucket.md @@ -52,20 +52,18 @@ namespace that started the import process. ## Import your Bitbucket repositories -1. Sign in to GitLab and go to your dashboard. -1. Click on **New project**. - -1. Click on the "Bitbucket Cloud" button. - - ![Bitbucket](img/import_projects_from_new_project_page.png) - -1. Grant GitLab access to your Bitbucket account +1. Sign in to GitLab. +1. On the top bar, select **New** (**{plus}**). +1. Select **New project/repository**. +1. Select **Import project**. +1. Select **Bitbucket Cloud**. +1. Log in to Bitbucket and grant GitLab access to your Bitbucket account. ![Grant access](img/bitbucket_import_grant_access.png) -1. Click on the projects that you'd like to import or **Import all projects**. - You can also filter projects by name and select the namespace under which - each project will be imported. +1. Select the projects that you'd like to import or import all projects. + You can filter projects by name and select the namespace + each project will be imported for. ![Import projects](img/bitbucket_import_select_project_v12_3.png) diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md index e7ee5742745..6ce8a1e1bdb 100644 --- a/doc/user/project/import/bitbucket_server.md +++ b/doc/user/project/import/bitbucket_server.md @@ -101,22 +101,22 @@ Feature.disable(:bitbucket_server_user_mapping_by_username) ## Import your Bitbucket repositories -1. Sign in to GitLab and go to your dashboard. -1. Click on **New project**. -1. Click on the "Bitbucket Server" button. If the button is not present, enable the importer in - **Admin > Application Settings > Visibility and access controls > Import sources**. +Prerequisite: - ![Bitbucket](img/import_projects_from_new_project_page.png) +- An administrator must have enabled the importer in + **Admin > Application Settings > Visibility and access controls > Import sources**. -1. Enter your Bitbucket Server credentials. +To import your Bitbucket repositories: - ![Grant access](img/bitbucket_server_import_credentials.png) - -1. Click on the projects that you'd like to import or **Import all projects**. - You can also filter projects by name and select the namespace under which each project is - imported. - - ![Import projects](img/bitbucket_server_import_select_project_v12_3.png) +1. Sign in to GitLab. +1. On the top bar, select **New** (**{plus}**). +1. Select **New project/repository**. +1. Select **Import project**. +1. Select **Bitbucket Server**. +1. Log in to Bitbucket and grant GitLab access to your Bitbucket account. +1. Select the projects that you'd like to import or import all projects. + You can filter projects by name and select the namespace + each project will be imported for. ## Troubleshooting diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md index 3bbc70b4337..db55330f806 100644 --- a/doc/user/project/import/gitea.md +++ b/doc/user/project/import/gitea.md @@ -38,8 +38,6 @@ that started the import process. The importer page is visible when you create a new project. -![New project page on GitLab](img/import_projects_from_new_project_page.png) - Select the **Gitea** link to start the import authorization process. ![New Gitea project import](img/import_projects_from_gitea_new_import.png) diff --git a/doc/user/project/import/img/bitbucket_server_import_credentials.png b/doc/user/project/import/img/bitbucket_server_import_credentials.png deleted file mode 100644 index 25bcc3ab6e6..00000000000 Binary files a/doc/user/project/import/img/bitbucket_server_import_credentials.png and /dev/null differ diff --git a/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png b/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png deleted file mode 100644 index 3f94dd83dd6..00000000000 Binary files a/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png and /dev/null differ diff --git a/doc/user/project/import/img/import_projects_from_new_project_page.png b/doc/user/project/import/img/import_projects_from_new_project_page.png deleted file mode 100644 index 7c32d3555d1..00000000000 Binary files a/doc/user/project/import/img/import_projects_from_new_project_page.png and /dev/null differ diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md index 23d7aecc960..6aa32b1b816 100644 --- a/doc/user/project/repository/gpg_signed_commits/index.md +++ b/doc/user/project/repository/gpg_signed_commits/index.md @@ -39,7 +39,10 @@ For a commit to be verified by GitLab: - The committer's public key must have been uploaded to their GitLab account. - One of the emails in the GPG key must match a **verified** email address - used by the committer in GitLab. + used by the committer in GitLab. This address will be part of the public key. + If you want to keep this address private, use the automatically generated + [private commit email address](../../../profile/index.md#use-an-automatically-generated-private-commit-email) + GitLab provides in your profile. - The committer's email address must match the verified email address from the GPG key. diff --git a/lib/api/error_tracking/collector.rb b/lib/api/error_tracking/collector.rb index 22fbd3a1118..142de3d35b0 100644 --- a/lib/api/error_tracking/collector.rb +++ b/lib/api/error_tracking/collector.rb @@ -96,7 +96,10 @@ module API # Collector should never return any information back. # Because DSN and public key are designed for public use, # it is safe only for submission of new events. - no_content! + # + # Some clients sdk require status 200 OK to work correctly. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/343531. + status 200 end desc 'Submit error tracking event to the project' do @@ -129,7 +132,10 @@ module API # Collector should never return any information back. # Because DSN and public key are designed for public use, # it is safe only for submission of new events. - no_content! + # + # Some clients sdk require status 200 OK to work correctly. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/343531. + status 200 end end end diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb index c9bc4ec411d..beb8801096b 100644 --- a/lib/gitlab/ci/pipeline/chain/command.rb +++ b/lib/gitlab/ci/pipeline/chain/command.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -144,3 +145,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb index 54eedec3c7b..a494c357950 100644 --- a/lib/gitlab/database/migrations/observation.rb +++ b/lib/gitlab/database/migrations/observation.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -14,3 +15,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb index b697cb0d027..c1e437831d7 100644 --- a/lib/gitlab/health_checks/metric.rb +++ b/lib/gitlab/health_checks/metric.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -5,3 +6,5 @@ module Gitlab Metric = Struct.new(:name, :value, :labels) end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/health_checks/probes/status.rb b/lib/gitlab/health_checks/probes/status.rb index 192e9366001..1c59f18ff7d 100644 --- a/lib/gitlab/health_checks/probes/status.rb +++ b/lib/gitlab/health_checks/probes/status.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -12,3 +13,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb index 38a36100ec7..cbb847d2af2 100644 --- a/lib/gitlab/health_checks/result.rb +++ b/lib/gitlab/health_checks/result.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -13,3 +14,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb index 0719fb2e8c6..2439e873e0b 100644 --- a/lib/gitlab/middleware/release_env.rb +++ b/lib/gitlab/middleware/release_env.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -14,3 +15,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/redis/hll.rb b/lib/gitlab/redis/hll.rb index 0d04545688b..4d1855e4637 100644 --- a/lib/gitlab/redis/hll.rb +++ b/lib/gitlab/redis/hll.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -51,3 +52,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb index 217a48e740d..37414f9e2b1 100644 --- a/lib/gitlab/search_results.rb +++ b/lib/gitlab/search_results.rb @@ -115,6 +115,11 @@ module Gitlab {} end + # aggregations are only performed by Elasticsearch backed results + def aggregations(scope) + [] + end + private def collection_for(scope) diff --git a/lib/gitlab/slash_commands/result.rb b/lib/gitlab/slash_commands/result.rb index a66a2e0726b..d488606120f 100644 --- a/lib/gitlab/slash_commands/result.rb +++ b/lib/gitlab/slash_commands/result.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -5,3 +6,5 @@ module Gitlab Result = Struct.new(:type, :message) end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/template_parser/ast.rb b/lib/gitlab/template_parser/ast.rb index 89318ee0d68..c6a5f66c377 100644 --- a/lib/gitlab/template_parser/ast.rb +++ b/lib/gitlab/template_parser/ast.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true module Gitlab @@ -155,3 +156,5 @@ module Gitlab end end end + +# rubocop:enable Naming/FileName diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb index f4fbea50515..c9478e13d25 100644 --- a/lib/gitlab/tracking.rb +++ b/lib/gitlab/tracking.rb @@ -13,7 +13,6 @@ module Gitlab contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace, **extra).to_context, *context] snowplow.event(category, action, label: label, property: property, value: value, context: contexts) - product_analytics.event(category, action, label: label, property: property, value: value, context: contexts) rescue StandardError => error Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, snowplow_category: category, snowplow_action: action) end @@ -35,10 +34,6 @@ module Gitlab def snowplow @snowplow ||= Gitlab::Tracking::Destinations::Snowplow.new end - - def product_analytics - @product_analytics ||= Gitlab::Tracking::Destinations::ProductAnalytics.new - end end end end diff --git a/lib/gitlab/tracking/destinations/product_analytics.rb b/lib/gitlab/tracking/destinations/product_analytics.rb deleted file mode 100644 index cacedbc5b83..00000000000 --- a/lib/gitlab/tracking/destinations/product_analytics.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Tracking - module Destinations - class ProductAnalytics < Base - extend ::Gitlab::Utils::Override - include ::Gitlab::Utils::StrongMemoize - - override :event - def event(category, action, label: nil, property: nil, value: nil, context: nil) - return unless event_allowed?(category, action) - return unless enabled? - - tracker.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i) - end - - private - - def event_allowed?(category, action) - category == 'epics' && action == 'promote' - end - - def enabled? - Feature.enabled?(:product_analytics_tracking, type: :ops) && - Gitlab::CurrentSettings.usage_ping_enabled? && - Gitlab::CurrentSettings.self_monitoring_project_id.present? - end - - def tracker - @tracker ||= SnowplowTracker::Tracker.new( - SnowplowTracker::AsyncEmitter.new(::ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol), - SnowplowTracker::Subject.new, - Gitlab::Tracking::SNOWPLOW_NAMESPACE, - Gitlab::CurrentSettings.self_monitoring_project_id.to_s - ) - end - end - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3f5d09ea5c3..331a1742e92 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3334,7 +3334,7 @@ msgstr "" msgid "All merge request dependencies have been merged" msgstr "" -msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}." +msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}." msgstr "" msgid "All projects" @@ -8653,9 +8653,6 @@ msgstr "" msgid "Configure existing installation" msgstr "" -msgid "Configure paths to be protected by Rack Attack." -msgstr "" - msgid "Configure repository mirroring." msgstr "" @@ -12709,7 +12706,7 @@ msgstr "" msgid "Enable or disable version check and Service Ping." msgstr "" -msgid "Enable protected paths rate limit" +msgid "Enable rate limiting for POST requests to the specified paths" msgstr "" msgid "Enable reCAPTCHA" @@ -16847,7 +16844,7 @@ msgstr "" msgid "Helps reduce request volume (for example, from crawlers or abusive bots)" msgstr "" -msgid "Helps reduce request volume for protected paths" +msgid "Helps reduce request volume for protected paths." msgstr "" msgid "Here you will find recent merge request activity" @@ -23640,9 +23637,6 @@ msgstr "" msgid "OmniAuth" msgstr "" -msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}." -msgstr "" - msgid "On" msgstr "" @@ -24775,6 +24769,9 @@ msgstr "" msgid "Paths can contain wildcards, like */welcome" msgstr "" +msgid "Paths to protect with rate limiting" +msgstr "" + msgid "Pause" msgstr "" @@ -27658,9 +27655,6 @@ msgstr "" msgid "Protected Environment" msgstr "" -msgid "Protected Paths" -msgstr "" - msgid "Protected Paths: requests" msgstr "" @@ -27676,6 +27670,9 @@ msgstr "" msgid "Protected environments" msgstr "" +msgid "Protected paths" +msgstr "" + msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported." msgstr "" @@ -28051,6 +28048,9 @@ msgstr "" msgid "Rate limit" msgstr "" +msgid "Rate limit access to specified paths." +msgstr "" + msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)." msgstr "" @@ -34693,9 +34693,6 @@ msgstr "" msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue." msgstr "" -msgid "These paths are protected for POST requests." -msgstr "" - msgid "These runners are shared across projects in this group." msgstr "" diff --git a/rubocop/cop/gitlab/change_timzone.rb b/rubocop/cop/gitlab/change_timezone.rb similarity index 100% rename from rubocop/cop/gitlab/change_timzone.rb rename to rubocop/cop/gitlab/change_timezone.rb diff --git a/rubocop/cop/gitlab/keys-first-and-values-first.rb b/rubocop/cop/gitlab/keys_first_and_values_first.rb similarity index 100% rename from rubocop/cop/gitlab/keys-first-and-values-first.rb rename to rubocop/cop/gitlab/keys_first_and_values_first.rb diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb index c8a573410d8..5a5e76a87e2 100644 --- a/rubocop/rubocop.rb +++ b/rubocop/rubocop.rb @@ -1,4 +1,7 @@ +# rubocop:disable Naming/FileName # frozen_string_literal: true # Auto-require all cops under `rubocop/cop/**/*.rb` Dir[File.join(__dir__, 'cop', '**', '*.rb')].sort.each(&method(:require)) + +# rubocop:enable Naming/FileName diff --git a/scripts/docs_screenshots.rb b/scripts/docs_screenshots.rb index 094e7e87960..a734540eb69 100755 --- a/scripts/docs_screenshots.rb +++ b/scripts/docs_screenshots.rb @@ -5,7 +5,7 @@ require 'png_quantizator' require 'open3' require 'parallel' -require_relative '../tooling/lib/tooling/images' +require_relative '../tooling/lib/tooling/image' generator = ARGV[0] milestone = ARGV[1] diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index 8a99d83237e..19892539a8f 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -6,6 +6,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data'; +import api from '~/api'; import axios from '~/lib/utils/axios_utils'; import { setFaviconOverlay } from '~/lib/utils/favicon'; import notify from '~/lib/utils/notify'; @@ -23,6 +24,8 @@ import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data'; import mockData from './mock_data'; import testExtension from './test_extension'; +jest.mock('~/api.js'); + jest.mock('~/smart_interval'); jest.mock('~/lib/utils/favicon'); @@ -904,6 +907,18 @@ describe('MrWidgetOptions', () => { expect(wrapper.text()).toContain('Test extension summary count: 1'); }); + it('triggers trackRedisHllUserEvent API call', async () => { + await waitForPromises(); + + wrapper + .find('[data-testid="widget-extension"] [data-testid="toggle-button"]') + .trigger('click'); + + await Vue.nextTick(); + + expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_expand_event'); + }); + it('renders full data', async () => { await waitForPromises(); diff --git a/spec/frontend/vue_mr_widget/test_extension.js b/spec/frontend/vue_mr_widget/test_extension.js index a29a4d2fb46..51bc44a7063 100644 --- a/spec/frontend/vue_mr_widget/test_extension.js +++ b/spec/frontend/vue_mr_widget/test_extension.js @@ -3,6 +3,7 @@ import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants'; export default { name: 'WidgetTestExtension', props: ['targetProjectFullPath'], + expandEvent: 'test_expand_event', computed: { summary({ count, targetProjectFullPath }) { return `Test extension summary count: ${count} & ${targetProjectFullPath}`; diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb index 27d65e14347..a38073e7c51 100644 --- a/spec/lib/gitlab/search_results_spec.rb +++ b/spec/lib/gitlab/search_results_spec.rb @@ -96,6 +96,18 @@ RSpec.describe Gitlab::SearchResults do end end + describe '#aggregations' do + where(:scope) do + %w(projects issues merge_requests blobs commits wiki_blobs epics milestones users unknown) + end + + with_them do + it 'returns an empty array' do + expect(results.aggregations(scope)).to match_array([]) + end + end + end + context "when count_limit is lower than total amount" do before do allow(results).to receive(:count_limit).and_return(1) diff --git a/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb b/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb deleted file mode 100644 index 63e2e930acd..00000000000 --- a/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Tracking::Destinations::ProductAnalytics do - let(:emitter) { SnowplowTracker::Emitter.new('localhost', buffer_size: 1) } - let(:tracker) { SnowplowTracker::Tracker.new(emitter, SnowplowTracker::Subject.new, 'namespace', 'app_id') } - - describe '#event' do - shared_examples 'does not send an event' do - it 'does not send an event' do - expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event) - - subject.event(allowed_category, allowed_action) - end - end - - let(:allowed_category) { 'epics' } - let(:allowed_action) { 'promote' } - let(:self_monitoring_project) { create(:project) } - - before do - stub_feature_flags(product_analytics_tracking: true) - stub_application_setting(self_monitoring_project_id: self_monitoring_project.id) - stub_application_setting(usage_ping_enabled: true) - end - - context 'with allowed event' do - it 'sends an event to Product Analytics snowplow collector' do - expect(SnowplowTracker::AsyncEmitter) - .to receive(:new) - .with(ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol) - .and_return(emitter) - - expect(SnowplowTracker::Tracker) - .to receive(:new) - .with(emitter, an_instance_of(SnowplowTracker::Subject), Gitlab::Tracking::SNOWPLOW_NAMESPACE, self_monitoring_project.id.to_s) - .and_return(tracker) - - freeze_time do - expect(tracker) - .to receive(:track_struct_event) - .with(allowed_category, allowed_action, 'label', 'property', 1.5, nil, (Time.now.to_f * 1000).to_i) - - subject.event(allowed_category, allowed_action, label: 'label', property: 'property', value: 1.5) - end - end - end - - context 'with non-allowed event' do - it 'does not send an event' do - expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event) - - subject.event('category', 'action') - subject.event(allowed_category, 'action') - subject.event('category', allowed_action) - end - end - - context 'when self-monitoring project does not exist' do - before do - stub_application_setting(self_monitoring_project_id: nil) - end - - include_examples 'does not send an event' - end - - context 'when product_analytics_tracking FF is disabled' do - before do - stub_feature_flags(product_analytics_tracking: false) - end - - include_examples 'does not send an event' - end - - context 'when usage ping is disabled' do - before do - stub_application_setting(usage_ping_enabled: false) - end - - include_examples 'does not send an event' - end - end -end diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb index dacaae55676..b9902ab42e5 100644 --- a/spec/lib/gitlab/tracking_spec.rb +++ b/spec/lib/gitlab/tracking_spec.rb @@ -41,7 +41,6 @@ RSpec.describe Gitlab::Tracking do shared_examples 'delegates to destination' do |klass| before do allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow).to receive(:event) - allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event) end it "delegates to #{klass} destination" do @@ -73,7 +72,6 @@ RSpec.describe Gitlab::Tracking do end it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow - it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::ProductAnalytics it 'tracks errors' do expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with( diff --git a/spec/requests/api/error_tracking/collector_spec.rb b/spec/requests/api/error_tracking/collector_spec.rb index 7acadeb1287..cb1b255d30f 100644 --- a/spec/requests/api/error_tracking/collector_spec.rb +++ b/spec/requests/api/error_tracking/collector_spec.rb @@ -24,10 +24,10 @@ RSpec.describe API::ErrorTracking::Collector do end RSpec.shared_examples 'successful request' do - it 'writes to the database and returns no content' do + it 'writes to the database and returns OK' do expect { subject }.to change { ErrorTracking::ErrorEvent.count }.by(1) - expect(response).to have_gitlab_http_status(:no_content) + expect(response).to have_gitlab_http_status(:ok) end end @@ -89,10 +89,10 @@ RSpec.describe API::ErrorTracking::Collector do context 'transaction request type' do let(:params) { fixture_file('error_tracking/transaction.txt') } - it 'does nothing and returns no content' do + it 'does nothing and returns ok' do expect { subject }.not_to change { ErrorTracking::ErrorEvent.count } - expect(response).to have_gitlab_http_status(:no_content) + expect(response).to have_gitlab_http_status(:ok) end end diff --git a/spec/rubocop/cop/gitlab/change_timezone_spec.rb b/spec/rubocop/cop/gitlab/change_timezone_spec.rb index f3c07e44cc7..ff6365aa0f7 100644 --- a/spec/rubocop/cop/gitlab/change_timezone_spec.rb +++ b/spec/rubocop/cop/gitlab/change_timezone_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'fast_spec_helper' -require_relative '../../../../rubocop/cop/gitlab/change_timzone' +require_relative '../../../../rubocop/cop/gitlab/change_timezone' RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone do subject(:cop) { described_class.new } diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb index 1c71715d922..33b01b77c3a 100644 --- a/spec/services/members/create_service_spec.rb +++ b/spec/services/members/create_service_spec.rb @@ -216,8 +216,7 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_ expect(source.issues).to all have_attributes( project: source, - author: user, - assignees: array_including(member) + author: user ) end diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb index 7799e49d4c1..0c5bf09f6b7 100644 --- a/spec/support/helpers/migrations_helpers.rb +++ b/spec/support/helpers/migrations_helpers.rb @@ -2,7 +2,7 @@ module MigrationsHelpers def active_record_base - ActiveRecord::Base + Gitlab::Database.database_base_models.fetch(self.class.metadata[:database] || :main) end def table(name) @@ -34,7 +34,7 @@ module MigrationsHelpers end def migrations_paths - ActiveRecord::Migrator.migrations_paths + active_record_base.connection.migrations_paths end def migration_context @@ -52,7 +52,7 @@ module MigrationsHelpers end def foreign_key_exists?(source, target = nil, column: nil) - ActiveRecord::Base.connection.foreign_keys(source).any? do |key| + active_record_base.connection.foreign_keys(source).any? do |key| if column key.options[:column].to_s == column.to_s else diff --git a/spec/support/stub_snowplow.rb b/spec/support/stub_snowplow.rb index a21ce2399d7..c6e3b40972f 100644 --- a/spec/support/stub_snowplow.rb +++ b/spec/support/stub_snowplow.rb @@ -8,8 +8,6 @@ module StubSnowplow host = 'localhost' # rubocop:disable RSpec/AnyInstanceOf - allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event) - allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow) .to receive(:emitter) .and_return(SnowplowTracker::Emitter.new(host, buffer_size: buffer_size)) diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 6c37c422aed..1993edb804f 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -139,6 +139,43 @@ RSpec.describe EmailsOnPushWorker, :mailer do perform end + + context 'when SMIME signing is enabled' do + include SmimeHelper + + before :context do + @root_ca = generate_root + @cert = generate_cert(signer_ca: @root_ca) + end + + let(:root_certificate) do + Gitlab::X509::Certificate.new(@root_ca[:key], @root_ca[:cert]) + end + + let(:certificate) do + Gitlab::X509::Certificate.new(@cert[:key], @cert[:cert]) + end + + before do + allow(Gitlab::X509::Certificate).to receive_messages(from_files: certificate) + + Mail.register_interceptor(Gitlab::Email::Hook::SmimeSignatureInterceptor) + end + + after do + Mail.unregister_interceptor(Gitlab::Email::Hook::SmimeSignatureInterceptor) + end + + it 'does not sign the email multiple times' do + perform + + ActionMailer::Base.deliveries.each do |mail| + expect(mail.header['Content-Type'].value).to match('multipart/signed').and match('protocol="application/x-pkcs7-signature"') + + expect(mail.to_s.scan(/Content-Disposition: attachment;\r\n filename=smime.p7s/).size).to eq(1) + end + end + end end context "when recipients are invalid" do diff --git a/tooling/lib/tooling/images.rb b/tooling/lib/tooling/image.rb similarity index 100% rename from tooling/lib/tooling/images.rb rename to tooling/lib/tooling/image.rb