From db5097a28b061ef273a058aa64845c79635ea4e7 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 8 Sep 2022 09:10:45 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- app/models/member.rb | 9 + .../ops/increase_branch_cache_expiry.yml | 8 + doc/api/graphql/reference/index.md | 2 + doc/integration/jira/development_panel.md | 9 +- doc/topics/autodevops/index.md | 84 +-- doc/topics/autodevops/stages.md | 2 +- .../configuration/index.md | 2 +- doc/user/application_security/index.md | 2 +- .../secret_detection/index.md | 603 +++++++++--------- .../group/saml_sso/example_saml_config.md | 15 +- .../group/saml_sso/img/scim_token_v13_3.png | Bin 56821 -> 0 bytes doc/user/group/saml_sso/index.md | 8 +- doc/user/group/saml_sso/scim_setup.md | 171 ++--- .../project/integrations/hangouts_chat.md | 34 +- lib/api/branches.rb | 8 +- .../usage_data_counters/hll_redis_counter.rb | 2 +- .../known_events/ecosystem.yml | 8 - locale/gitlab.pot | 3 + package.json | 4 +- scripts/trigger-build.rb | 40 -- spec/models/member_spec.rb | 9 + spec/requests/api/branches_spec.rb | 62 ++ spec/scripts/trigger-build_spec.rb | 150 ----- yarn.lock | 16 +- 24 files changed, 567 insertions(+), 684 deletions(-) create mode 100644 config/feature_flags/ops/increase_branch_cache_expiry.yml delete mode 100644 doc/user/group/saml_sso/img/scim_token_v13_3.png diff --git a/app/models/member.rb b/app/models/member.rb index 0cd1e022617..893109a71d9 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -60,6 +60,7 @@ class Member < ApplicationRecord if: :project_bot? validate :access_level_inclusion validate :validate_member_role_access_level + validate :validate_access_level_locked_for_member_role, on: :update scope :with_invited_user_state, -> do joins('LEFT JOIN users as invited_user ON invited_user.email = members.invite_email') @@ -438,6 +439,14 @@ class Member < ApplicationRecord end end + def validate_access_level_locked_for_member_role + return unless member_role_id + + if access_level_changed? + errors.add(:access_level, _("cannot be changed since member is associated with a custom role")) + end + end + def send_invite # override in subclass end diff --git a/config/feature_flags/ops/increase_branch_cache_expiry.yml b/config/feature_flags/ops/increase_branch_cache_expiry.yml new file mode 100644 index 00000000000..61b9d5b9c42 --- /dev/null +++ b/config/feature_flags/ops/increase_branch_cache_expiry.yml @@ -0,0 +1,8 @@ +--- +name: increase_branch_cache_expiry +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96739 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372331 +milestone: '15.4' +type: ops +group: group::code review +default_enabled: false diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 7693d364745..bcfd6d44cc1 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -6093,6 +6093,7 @@ The connection type for [`BoardEpic`](#boardepic). | Name | Type | Description | | ---- | ---- | ----------- | +| `count` | [`Int!`](#int) | Total count of collection. | | `edges` | [`[BoardEpicEdge]`](#boardepicedge) | A list of edges. | | `nodes` | [`[BoardEpic]`](#boardepic) | A list of nodes. | | `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. | @@ -7265,6 +7266,7 @@ The connection type for [`Epic`](#epic). | Name | Type | Description | | ---- | ---- | ----------- | +| `count` | [`Int!`](#int) | Total count of collection. | | `edges` | [`[EpicEdge]`](#epicedge) | A list of edges. | | `nodes` | [`[Epic]`](#epic) | A list of nodes. | | `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. | diff --git a/doc/integration/jira/development_panel.md b/doc/integration/jira/development_panel.md index 4d5a9f92257..d52d86c5658 100644 --- a/doc/integration/jira/development_panel.md +++ b/doc/integration/jira/development_panel.md @@ -38,7 +38,7 @@ After the integration is [set up on GitLab and Jira](#configure-the-integration) - Refer to any Jira issue by its ID (in uppercase) in GitLab branch names, commit messages, and merge request titles. - See the linked branches, commits, and merge requests in Jira issues. -- Create GitLab branches from Jira Cloud issues ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2). +- Create GitLab branches from Jira Cloud issues ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2 for the GitLab for Jira app). At this time, merge requests are called "pull requests" in Jira issues. This name may change in a future Jira release. @@ -85,9 +85,10 @@ documentation for [central administration of project integrations](../../user/ad ## Limitations -This integration is not supported on GitLab instances under a -[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab). -For example, `http://example.com/gitlab`. +- This integration is not supported on GitLab instances under a +[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configure-a-relative-url-for-gitlab) +(for example, `http://example.com/gitlab`). +- [Creating a branch](https://gitlab.com/gitlab-org/gitlab/-/issues/2647) is only supported by the GitLab for Jira app and is not available within the DVCS integration. See [officially supported DVCS features](https://confluence.atlassian.com/adminjiraserver/integrating-with-development-tools-938846890.html) for more information. ## Troubleshoot the development panel diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index dc58f42f30e..5cec7347578 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -12,15 +12,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w GitLab Auto DevOps is a collection of pre-configured features and integrations that work together to support your software delivery process. -Auto DevOps features and integrations: +Auto DevOps detects your programming language and uses [CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) +to create and run default pipelines to build and test your application. Then, you can [configure deployments](requirements.md) to deploy your apps to staging +and production, and set up [Review Apps](stages.md#auto-review-apps) +to preview your changes per branch. -- Detect your code's language. -- Build and test your application. -- Measure code quality. -- Scan for vulnerabilities and security flaws. -- Check for licensing issues. -- Monitor in real time. -- Deploy your application. +You can use default settings to quickly ship your apps, and iterate and [customize](customize.md) later. + +You can also [manage Auto DevOps with APIs](customize.md#extend-auto-devops-with-the-api). For an introduction to Auto DevOps, watch [Auto DevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4). @@ -58,33 +57,6 @@ Based on the DevOps [stages](stages.md), use Auto DevOps to: - [Auto Static Application Security Testing (SAST)](stages.md#auto-sast) - [Auto Secret Detection](stages.md#auto-secret-detection) -### How it works - -Auto DevOps detects your code language and uses [CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) -to create and run default pipelines. All you need to kick it off is to -[enable](#enable-or-disable-auto-devops) it. - -Auto DevOps starts by building and testing your application. Then, based on your -[predefined deployment configuration](requirements.md), -creates the necessary jobs to deploy your apps to staging -and/or production. It also sets up [Review Apps](stages.md#auto-review-apps) -so that you can preview your changes in a per-branch basis. - -Note that you don't need to set up the deployment upfront. Auto DevOps -still builds and tests your application. You can define the deployment later. - -Auto DevOps avoids the hassle of having to create entire pipelines manually. -Keep it simple and facilitate an iterative approach: ship your app first, -then explore the [customizations](customize.md) later. -You can also [manage Auto DevOps with APIs](customize.md#extend-auto-devops-with-the-api). - -Some of the benefits of using Auto DevOps as part of your workflow are: - -- Consistency: always start from default templates. -- Simplicity: create your pipeline with the default settings first, iterate later. -- Productivity: deploy multiple apps in a short period of time. -- Efficiency: get things done fast. - ### Comparison to application platforms and PaaS Auto DevOps provides features often included in an application @@ -146,11 +118,11 @@ you can enable it for a [group](#at-the-group-level) or an [instance](#at-the-instance-level). This can save you the time of enabling it one by one. -Only project Maintainers can enable or disable Auto DevOps at the project level. +Prerequisites: -Before enabling Auto DevOps, ensure that your project does not have a -`.gitlab-ci.yml` present. If present, your CI/CD configuration takes -precedence over the Auto DevOps pipeline. +- You must have at least the Maintainer role for the project. +- Ensure your project does not have a `.gitlab-ci.yml` present. If present, your CI/CD configuration takes + precedence over the Auto DevOps pipeline. To enable Auto DevOps for a project: @@ -178,8 +150,9 @@ rather than enabling individually for each subgroup or project. When enabled for a group, you can still disable Auto DevOps for the subgroups and projects where you don't want to use it. -Only GitLab administrators and group owners can enable or disable Auto DevOps -at the group level. +Prerequisites: + +- You must have at least the Owner role for the group. To enable Auto DevOps for a group: @@ -193,7 +166,7 @@ To disable Auto DevOps on the group level, follow the same process and clear the **Default to Auto DevOps pipeline** checkbox. After enabling Auto DevOps at the group level, you can trigger the -Auto DevOps pipeline for any project that belongs to that group. To do so: +Auto DevOps pipeline for any project that belongs to that group: 1. On the top bar, select **Menu > Projects** and find your project. 1. Make sure the project doesn't contain a `.gitlab-ci.yml` file. @@ -207,12 +180,13 @@ instance become enabled. This is convenient when you want to run Auto DevOps by default for all projects. You can still disable Auto DevOps individually for the groups and projects where you don't want to run it. -Only GitLab administrators can enable or disable Auto DevOps at the instance -level. - -Even when disabled for an instance, group owners and project maintainers +Even when disabled for an instance, group Owners and project Maintainers can still enable Auto DevOps at the group and project levels. +Prerequisites: + +- You must be an administrator for the instance. + To enable Auto DevOps for your instance: 1. On the top bar, select **Menu > Admin**. @@ -232,6 +206,13 @@ it remains unchanged and Auto DevOps doesn't affect it. To disable Auto DevOps in the instance level, follow the same process and clear the **Default to Auto DevOps pipeline** checkbox. +### Private registry support + +There is no guarantee that you can use a private container registry with Auto DevOps. + +Instead, use the [GitLab Container Registry](../../user/packages/container_registry/index.md) with Auto DevOps to +simplify configuration and prevent any unforeseen issues. + ### Quick start - [Use Auto DevOps to deploy to a Kubernetes cluster on Google Kubernetes Engine (GKE)](cloud_deployments/auto_devops_with_gke.md) @@ -252,16 +233,7 @@ match your new GitLab version: - Environment variables. - [Upgrading PostgreSQL](upgrading_postgresql.md). -## Limitations - -### Private registry support - -We cannot guarantee that you can use a private container registry with Auto DevOps. - -We strongly advise you to use GitLab Container Registry with Auto DevOps to -simplify configuration and prevent any unforeseen issues. - -### Install applications behind a proxy +## Install applications behind a proxy The GitLab integration with Helm does not support installing applications when behind a proxy. diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md index 4e8d0e08eff..62356807854 100644 --- a/doc/topics/autodevops/stages.md +++ b/doc/topics/autodevops/stages.md @@ -199,7 +199,7 @@ see the documentation. ## Auto Secret Detection > - Introduced in GitLab 13.1. -> - Select functionality [made available](../../user/application_security/secret_detection/index.md#making-secret-detection-available-to-all-gitlab-tiers) in all tiers in GitLab 13.3 +> - Select functionality [made available](../../user/application_security/secret_detection/index.md#features-per-tier) in all tiers in GitLab 13.3 Secret Detection uses the [Secret Detection Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) to run Secret Detection on the current code, and checks for leaked secrets. Auto Secret Detection requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above. diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md index 9ca1a6f125f..56580f9ca83 100644 --- a/doc/user/application_security/configuration/index.md +++ b/doc/user/application_security/configuration/index.md @@ -56,7 +56,7 @@ You can configure the following security controls: - Can be configured by adding a configuration block to your agent configuration. For more details, read [Operational Container Scanning](../../clusters/agent/vulnerabilities.md#enable-operational-container-scanning). - [Secret Detection](../secret_detection/index.md) - Select **Configure with a merge request** to create a merge request with the changes required to - enable Secret Detection. For more details, read [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request). + enable Secret Detection. For more details, read [Enable Secret Detection using a merge request](../secret_detection/index.md#enable-secret-detection-using-a-merge-request). - [API Fuzzing](../api_fuzzing/index.md) - Select **Enable API Fuzzing** to use API Fuzzing for the current project. For more details, read [API Fuzzing](../../../user/application_security/api_fuzzing/index.md#enable-web-api-fuzzing). - [Coverage Fuzzing](../coverage_fuzzing/index.md) diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md index 57acd5b8150..fbd617351da 100644 --- a/doc/user/application_security/index.md +++ b/doc/user/application_security/index.md @@ -361,7 +361,7 @@ Learn more on overriding security jobs: - [Overriding SAST jobs](sast/index.md#overriding-sast-jobs). - [Overriding Dependency Scanning jobs](dependency_scanning/index.md#overriding-dependency-scanning-jobs). - [Overriding Container Scanning jobs](container_scanning/index.md#overriding-the-container-scanning-template). -- [Overriding Secret Detection jobs](secret_detection/index.md#customizing-settings). +- [Overriding Secret Detection jobs](secret_detection/index.md#configure-scan-settings). - [Overriding DAST jobs](dast/index.md#customize-dast-settings). - [Overriding License Compliance jobs](../compliance/license_compliance/index.md#overriding-the-template). diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md index 950a18b95fd..8e91015976c 100644 --- a/doc/user/application_security/secret_detection/index.md +++ b/doc/user/application_security/secret_detection/index.md @@ -6,16 +6,35 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Secret Detection **(FREE)** -> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) from GitLab Ultimate to GitLab Free in 13.3. +> - In GitLab 13.1, Secret Detection was split from the [SAST configuration](../sast/index.md#configuration) +> into its own CI/CD template. If you're using GitLab 13.0 or earlier and SAST is enabled, then +> Secret Detection is already enabled. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) from GitLab Ultimate to GitLab +> Free in 13.3. +> - [In GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/297269), Secret Detection jobs +> `secret_detection_default_branch` and `secret_detection` were consolidated into one job, +> `secret_detection`. -A recurring problem when developing applications is that people may accidentally commit secrets to -their remote Git repositories. Secrets include keys, passwords, API tokens, and other sensitive +People may accidentally commit secrets to +remote Git repositories. Secrets include keys, passwords, API tokens, and other sensitive information. Anyone with access to the repository could use the secrets for malicious purposes. -Secrets exposed in this way must be treated as compromised, and be replaced, which can be costly. -It's important to prevent secrets from being committed to a Git repository. +Exposed secrets are compromised and must be replaced, which can be costly. -Secret Detection uses the [Gitleaks](https://github.com/zricethezav/gitleaks) tool to scan the -repository for secrets. All identified secrets are reported in the: +To help prevent secrets from being committed to a Git repository, you can use Secret Detection +to scan your repository for secrets. Scanning is language +and framework agnostic, but does not support scanning binary files. + +Secret Detection uses a specific analyzer containing the +[Gitleaks](https://github.com/zricethezav/gitleaks) tool to scan the repository for secrets, in a +`secret-detection` job. The results are saved as a +[Secret Detection report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportssecret_detection) +that you can later download and analyze. Due to implementation limitations, we always take the +latest Secret Detection artifact available. + +GitLab SaaS supports post-processing hooks, so you can take action when a secret is found. For +more information, see [Post-processing and revocation](post_processing.md). + +All identified secrets are reported in the: - Merge request widget - Pipelines' **Security** tab @@ -23,9 +42,6 @@ repository for secrets. All identified secrets are reported in the: ![Secret Detection in merge request widget](img/secret_detection_v13_2.png) -WARNING: -Secret Detection does not support scanning binary files. - ## Detected secrets Secret Detection uses a [default ruleset](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/master/gitleaks.toml) @@ -34,92 +50,136 @@ patterns using [custom rulesets](#custom-rulesets). If you want to contribute ru "well-identifiable" secrets, follow the steps detailed in the [community contributions guidelines](https://gitlab.com/gitlab-org/gitlab/-/issues/345453). -## Requirements +## Features per tier -To run Secret Detection jobs, by default, you need GitLab Runner with the -[`docker`](https://docs.gitlab.com/runner/executors/docker.html) or -[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor. -If you're using the shared runners on GitLab.com, this is enabled by default. +Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/). -WARNING: -Our Secret Detection jobs expect a Linux/amd64 container type. Windows containers are not supported. +| Capability | In Free & Premium | In Ultimate | +|:---------------------------------------------------------------- |:-----------------------|:-----------------------| +| [Configure Secret Detection scanner](#enable-secret-detection) | **{check-circle}** Yes | **{check-circle}** Yes | +| [Customize Secret Detection settings](#configure-scan-settings) | **{check-circle}** Yes | **{check-circle}** Yes | +| Download [JSON Report](../sast/index.md#reports-json-format) | **{check-circle}** Yes | **{check-circle}** Yes | +| See new findings in the merge request widget | **{dotted-circle}** No | **{check-circle}** Yes | +| View identified secrets in the pipelines' **Security** tab | **{dotted-circle}** No | **{check-circle}** Yes | +| [Manage vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** No | **{check-circle}** Yes | +| [Access the Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** No | **{check-circle}** Yes | +| [Customize Secret Detection rulesets](#custom-rulesets) | **{dotted-circle}** No | **{check-circle}** Yes | -WARNING: -If you use your own runners, make sure the Docker version installed -is **not** `19.03.0`. See [troubleshooting information](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details. +## Enable Secret Detection -### Making Secret Detection available to all GitLab tiers +Prerequisites: -To make Secret Detection available to as many customers as possible, we have enabled it for all GitLab tiers. -However not all features are available on every tier. See the breakdown below for more details. +- GitLab Runner with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html) or +[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor. If you're using the +shared runners on GitLab.com, this is enabled by default. +- If you use your own runners, make sure the Docker version installed is **not** `19.03.0`. See + [troubleshooting information](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) + for details. +- Linux/amd64 container type. Windows containers are not supported. +- GitLab CI/CD configuration (`.gitlab-ci.yml`) must include the `test` stage. -#### Summary of features per tier +To enable Secret Detection, either: -Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/), -as shown in the following table: +- Enable [Auto DevOps](../../../topics/autodevops/index.md), which includes [Auto Secret Detection](../../../topics/autodevops/stages.md#auto-secret-detection). -| Capability | In Free & Premium | In Ultimate | -|:----------------------------------------------------------------|:--------------------|:-------------------| -| [Configure Secret Detection scanner](#configuration) | **{check-circle}** | **{check-circle}** | -| [Customize Secret Detection settings](#customizing-settings) | **{check-circle}** | **{check-circle}** | -| Download [JSON Report](../sast/index.md#reports-json-format) | **{check-circle}** | **{check-circle}** | -| See new findings in the merge request widget | **{dotted-circle}** | **{check-circle}** | -| View identified secrets in the pipelines' **Security** tab | **{dotted-circle}** | **{check-circle}** | -| [Manage vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** | -| [Access the Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** | -| [Customize Secret Detection rulesets](#custom-rulesets) | **{dotted-circle}** | **{check-circle}** | +- [Enable Secret Detection by including the template](#enable-secret-detection-by-including-the-template). -## Configuration +- [Enable Secret Detection using a merge request](#enable-secret-detection-using-a-merge-request). -> - In GitLab 13.1, Secret Detection was split from the [SAST configuration](../sast#configuration) into its own CI/CD template. If you're using GitLab 13.0 or earlier and SAST is enabled, then Secret Detection is already enabled. -> - [In GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/297269), Secret Detection jobs `secret_detection_default_branch` and `secret_detection` were consolidated into one job, `secret_detection`. +### Enable Secret Detection by including the template -Secret Detection is performed by a [specific analyzer](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) -during the `secret-detection` job. It runs regardless of your app's programming language. +We recommend this method if you have an existing GitLab CI/CD configuration file. -The Secret Detection analyzer includes [Gitleaks](https://github.com/zricethezav/gitleaks) checks. - -Note that the Secret Detection analyzer ignores Password-in-URL vulnerabilities if the password -begins with a dollar sign (`$`), as this likely indicates the password is an environment variable. -For example, `https://username:$password@example.com/path/to/repo` isn't detected, while -`https://username:password@example.com/path/to/repo` is. - -NOTE: -You don't have to configure Secret Detection manually as shown in this section if you're using -[Auto Secret Detection](../../../topics/autodevops/stages.md#auto-secret-detection), -provided by [Auto DevOps](../../../topics/autodevops/index.md). - -To enable Secret Detection for GitLab 13.1 and later, you must include the -`Secret-Detection.gitlab-ci.yml` template that's provided as a part of your GitLab installation. For -GitLab versions earlier than 11.9, you can copy and use the job as defined in that template. - -Ensure your `.gitlab-ci.yml` file has a `stage` called `test`, and add the following to your `.gitlab-ci.yml` file: +Add the following extract to your `.gitlab-ci.yml` file: ```yaml include: - template: Security/Secret-Detection.gitlab-ci.yml ``` -The included template creates Secret Detection jobs in your CI/CD pipeline and scans -your project's source code for secrets. +Pipelines now include a Secret Detection job, and the results are included in the merge request +widget. -The results are saved as a -[Secret Detection report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportssecret_detection) -that you can later download and analyze. Due to implementation limitations, we -always take the latest Secret Detection artifact available. +### Enable Secret Detection using a merge request -### Supported distributions +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, deployed behind a feature flag, enabled by default. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/329886) in GitLab 14.1. -The default scanner images are build off a base Alpine image for size and maintainability. +NOTE: +This method works best with no existing `.gitlab-ci.yml` file, or with a minimal configuration +file. If you have a complex GitLab configuration file it may not be parsed successfully, and an +error may occur. -#### FIPS-enabled images +To enable Secret Detection using a merge request: + +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Security & Compliance > Configuration**. +1. In the **Secret Detection** row, select **Configure with a merge request**. +1. Review and merge the merge request. + +Pipelines now include a Secret Detection job, and the results are included in the merge request +widget. + +## Configure scan settings + +The Secret Detection scan settings can be changed through [CI/CD variables](#available-cicd-variables) +by using the [`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`. + +WARNING: +All configuration of GitLab security scanning tools should be tested in a merge request before +merging these changes to the default branch. Failure to do so can give unexpected results, +including a large number of false positives. + +To override a job definition, (for example, change properties like `variables` or `dependencies`), +declare a job with the same name as the secret detection job to override. Place this new job after +the template inclusion and specify any additional keys under it. + +In the following example _extract_ of a `.gitlab-ci.yml` file: + +- The Secret Detection template is [included](../../../ci/yaml/index.md#include). +- In the `secret_detection` job, the CI/CD variable `SECRET_DETECTION_HISTORIC_SCAN` is set to + `true`. Because the template is evaluated before the pipeline configuration, the last mention of + the variable takes precedence. + +```yaml +include: + - template: Security/Secret-Detection.gitlab-ci.yml + +secret_detection: + variables: + SECRET_DETECTION_HISTORIC_SCAN: "true" +``` + +### Available CI/CD variables + +Secret Detection can be customized by defining available CI/CD variables: + +| CI/CD variable | Default value | Description | +|-----------------------------------|---------------|-------------| +| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. | +| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. | +| `SECRET_DETECTION_IMAGE_SUFFIX` | "" | Suffix added to the image name. If set to `-fips`, `FIPS-enabled` images are used for scan. See [Use FIPS-enabled images](#use-fips-enabled-images) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355519) in GitLab 14.10. | +| `SECRET_DETECTION_LOG_OPTIONS` | "" | [`git log`](https://git-scm.com/docs/git-log) options used to define commit ranges. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350660) in GitLab 15.1.| + +In previous GitLab versions, the following variables were also available: + +| CI/CD variable | Default value | Description | +|-----------------------------------|---------------|-------------| +| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. | +| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. | +| `SECRET_DETECTION_COMMITS` | - | The list of commits that Gitleaks should scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/352565) in GitLab 15.0. | + +#### Use FIPS-enabled images > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6479) in GitLab 14.10. -GitLab offers [Red Hat UBI](https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image) -versions of the images that are FIPS-enabled. To use the FIPS-enabled images, you can either: +The default scanner images are built off a base Alpine image for size and maintainability. GitLab +offers [Red Hat UBI](https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image) +versions of the images that are FIPS-enabled. -- Set the `SAST_IMAGE_SUFFIX` to `-fips`. +To use the FIPS-enabled images, either: + +- Set the `SECRET_DETECTION_IMAGE_SUFFIX` CI/CD variable to `-fips`. - Add the `-fips` extension to the default image name. For example: @@ -132,124 +192,54 @@ include: - template: Security/Secret-Detection.gitlab-ci.yml ``` -### Enable Secret Detection via an automatic merge request +## Full history Secret Detection -> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, deployed behind a feature flag, enabled by default. -> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/329886) in GitLab 14.1. +By default, Secret Detection scans only the current state of the Git repository. Any secrets +contained in the repository's history are not detected. To address this, Secret Detection can +scan the Git repository's full history. -NOTE: -This method works best with no existing `.gitlab-ci.yml` file, or with a minimal configuration -file. If you have a complex GitLab configuration file it may not be parsed successfully, and an -error may occur. +We recommend you do a full history scan only once, after enabling Secret Detection. A full history +can take a long time, especially for larger repositories with lengthy Git histories. After +completing an initial full history scan, use only standard Secret Detection as part of your +pipeline. -To enable Secret Detection in a project, you can create a merge request: +### Enable full history Secret Detection -1. On the top bar, select **Menu > Projects** and find your project. -1. On the left sidebar, select **Security & Compliance > Configuration**. -1. In the **Secret Detection** row, select **Configure with a merge request**. -1. Review and merge the merge request to enable Secret Detection. +To enable full history Secret Detection, set the variable `SECRET_DETECTION_HISTORIC_SCAN` to `true` in your `.gitlab-ci.yml` file. -Pipelines now include a Secret Detection job. - -### Customizing settings - -The Secret Detection scan settings can be changed through [CI/CD variables](#available-cicd-variables) -by using the -[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`. - -WARNING: -All customization of GitLab security scanning tools should be tested in a merge request before -merging these changes to the default branch. Failure to do so can give unexpected results, -including a large number of false positives. - -To override a job definition, (for example, change properties like `variables` or `dependencies`), -declare a job with the same name as the secret detection job to override. Place this new job after the template -inclusion and specify any additional keys under it. - -WARNING: -Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/index.md#only--except) -is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/index.md#rules) instead. - -#### `GIT_DEPTH` variable - -The [`GIT_DEPTH` CI/CD variable](../../../ci/runners/configure_runners.md#shallow-cloning) affects Secret Detection. -The Secret Detection analyzer relies on generating patches between commits to scan content for -secrets. If you override the default, ensure the value is greater than 1. If the number of commits -in an MR is greater than the `GIT_DEPTH` value, Secret Detection will [fail to detect secrets](#error-couldnt-run-the-gitleaks-command-exit-status-2). - -#### Custom settings example - -In the following example, we include the Secret Detection template and at the same time we -override the `secret_detection` job with the `SECRET_DETECTION_HISTORIC_SCAN` CI/CD variable to `true`: - -```yaml -include: - - template: Security/Secret-Detection.gitlab-ci.yml - -secret_detection: - variables: - SECRET_DETECTION_HISTORIC_SCAN: "true" -``` - -Because the template is [evaluated before](../../../ci/yaml/index.md#include) -the pipeline configuration, the last mention of the variable takes precedence. - -#### Available CI/CD variables - -Secret Detection can be customized by defining available CI/CD variables: - -| CI/CD variable | Default value | Description | -|-----------------------------------|---------------|-------------| -| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. | -| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. | -| `SECRET_DETECTION_IMAGE_SUFFIX` | "" | Suffix added to the image name. If set to `-fips`, `FIPS-enabled` images are used for scan. See [FIPS-enabled images](#fips-enabled-images) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355519) in GitLab 14.10. | -| `SECRET_DETECTION_LOG_OPTIONS` | "" | [`git log`](https://git-scm.com/docs/git-log) options used to define commit ranges. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350660) in GitLab 15.1.| - -In previous GitLab versions, the following variables were also available: - -| CI/CD variable | Default value | Description | -|-----------------------------------|---------------|-------------| -| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. | -| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. | -| `SECRET_DETECTION_COMMITS` | - | The list of commits that Gitleaks should scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/352565) in GitLab 15.0. | - -### Custom rulesets **(ULTIMATE)** +## Custom rulesets **(ULTIMATE)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5. -> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for -> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6. -> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8. +> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for passthrough chains. +> Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6. +> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in +> GitLab 14.8. -You can customize the default secret detection rules provided with GitLab. -Ruleset customization supports the following capabilities that can be used -simultaneously: +You can customize the default Secret Detection rules provided with GitLab. -- [Disabling predefined rules](#disable-predefined-analyzer-rules). -- [Overriding predefined rules](#override-predefined-analyzer-rules). -- Modifying the default behavior of the Secret Detection analyzer by [synthesizing and passing a custom configuration](#synthesize-a-custom-configuration). +The following customization options can be used separately, or in combination: -Customization allows replacing the default secret detection rules with rules that you define. +- [Disable predefined rules](#disable-predefined-analyzer-rules). +- [Override predefined rules](#override-predefined-analyzer-rules). +- [Synthesize a custom configuration](#synthesize-a-custom-configuration). -To create a custom ruleset: +### Disable predefined analyzer rules -1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist. -1. Create a custom ruleset file named `secret-detection-ruleset.toml` in the `.gitlab` directory. - -#### Disable predefined analyzer rules +If there are specific Secret Detection rules that you don't want active, you can disable them. To disable analyzer rules: +1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist. +1. Create a custom ruleset file named `secret-detection-ruleset.toml` in the `.gitlab` directory, if + one doesn't already exist. 1. Set the `disabled` flag to `true` in the context of a `ruleset` section. +1. In one or more `ruleset.identifier` subsections, list the rules to disable. Every + `ruleset.identifier` section has: + - A `type` field for the predefined rule identifier. + - A `value` field for the rule name. -1. In one or more `ruleset.identifier` subsections, list the rules that you want disabled. Every `ruleset.identifier` section has: - - - a `type` field, to name the predefined rule identifier. - - a `value` field, to name the rule to be disabled. - -##### Example: Disable predefined rules of Secret Detection analyzer - -In the following example, the disabled rules is assigned to `secrets` -by matching the `type` and `value` of identifiers: +In the following example `secret-detection-ruleset.toml` file, the disabled rules are assigned to +`secrets` by matching the `type` and `value` of identifiers: ```toml [secrets] @@ -260,29 +250,30 @@ by matching the `type` and `value` of identifiers: value = "RSA private key" ``` -#### Override predefined analyzer rules +### Override predefined analyzer rules + +If there are specific Secret Detection rules you want to customize, you can override them. For +example, you might increase the severity of specific secrets. To override rules: -1. In one or more `ruleset.identifier` subsections, list the rules that you want to override. Every `ruleset.identifier` section has: - - - a `type` field, to name the predefined rule identifier that the Secret Detection analyzer uses. - - a `value` field, to name the rule to be overridden. - +1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist. +1. Create a custom ruleset file named `secret-detection-ruleset.toml` in the `.gitlab` directory, if + one doesn't already exist. +1. In one or more `ruleset.identifier` subsections, list the rules to override. Every + `ruleset.identifier` section has: + - A `type` field for the predefined rule identifier. + - A `value` field for the rule name. 1. In the `ruleset.override` context of a `ruleset` section, provide the keys to override. Any combination of keys can be overridden. Valid keys are: - - description - message - name - severity (valid options are: Critical, High, Medium, Low, Unknown, Info) -##### Example: Override predefined rules of Secret Detection analyzer - -In the following example, rules -are matched by the `type` and `value` of identifiers and -then overridden: +In the following example `secret-detection-ruleset.toml` file, rules are matched by the `type` and +`value` of identifiers and then overridden: ```toml [secrets] @@ -297,166 +288,157 @@ then overridden: severity = "Info" ``` -#### Synthesize a custom configuration +### Synthesize a custom configuration -To create a custom configuration, you can use passthrough chains. +To create a custom configuration, you can use passthrough chains. Passthroughs can also be chained +to build more complex configurations. For more details, see +[SAST Customize ruleset](../sast/customize_rulesets.md). -1. In the `secret-detection-ruleset.toml` file, do one of the following: +In the `secret-detection-ruleset.toml` file, do one of the following: - - Define a custom ruleset: +- Define a custom ruleset, for example: - ```toml - [secrets] - description = 'secrets custom rules configuration' + ```toml + [secrets] + description = 'secrets custom rules configuration' - [[secrets.passthrough]] - type = "raw" - target = "gitleaks.toml" - value = """\ - title = "gitleaks config" - # add regexes to the regex table - [[rules]] - description = "Test for Raw Custom Rulesets" - regex = '''Custom Raw Ruleset T[est]{3}''' - """ - ``` + [[secrets.passthrough]] + type = "raw" + target = "gitleaks.toml" + value = """\ + title = "gitleaks config" + # add regexes to the regex table + [[rules]] + description = "Test for Raw Custom Rulesets" + regex = '''Custom Raw Ruleset T[est]{3}''' + """ + ``` - - Provide the name of the file containing a custom ruleset: +- Provide the name of the file containing a custom ruleset, for example: - ```toml - [secrets] - description = 'secrets custom rules configuration' + ```toml + [secrets] + description = 'secrets custom rules configuration' - [[secrets.passthrough]] - type = "file" - target = "gitleaks.toml" - value = "config/gitleaks.toml" - ``` + [[secrets.passthrough]] + type = "file" + target = "gitleaks.toml" + value = "config/gitleaks.toml" + ``` -Passthroughs can also be chained to build more complex configurations. -For more details, see [SAST Customize ruleset section](../sast/customize_rulesets.md). - -### Logging level - -To control the verbosity of logs set the `SECURE_LOG_LEVEL` CI/CD variable. Messages of this logging level or higher are output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. - -From highest to lowest severity, the logging levels are: - -- `fatal` -- `error` -- `warn` -- `info` (default) -- `debug` - -## Post-processing and revocation - -Upon detection of a secret, GitLab SaaS supports post-processing hooks. -For more information, see [Post-processing and revocation](post_processing.md). - -## Full History Secret Detection - -GitLab 12.11 introduced support for scanning the full history of a repository. This new functionality -is particularly useful when you are enabling Secret Detection in a repository for the first time and you -want to perform a full secret detection scan. Running a secret detection scan on the full history can take a long time, -especially for larger repositories with lengthy Git histories. We recommend not setting this CI/CD variable -as part of your normal job definition. - -A new configuration variable ([`SECRET_DETECTION_HISTORIC_SCAN`](#available-cicd-variables)) -can be set to change the behavior of the GitLab Secret Detection scan to run on the entire Git history of a repository. - -## Running Secret Detection in an offline environment +## Running Secret Detection in an offline environment **(PREMIUM SELF)** For self-managed GitLab instances in an environment with limited, restricted, or intermittent access -to external resources through the internet, some adjustments are required for the Secret Detection job to -run successfully. For more information, see [Offline environments](../offline_deployments/index.md). +to external resources through the internet, some configuration changes are required for the Secret +Detection job to run successfully. The instructions in this section must be completed together with +the instructions detailed in [offline environments](../offline_deployments/index.md). -### Requirements for offline Secret Detection +### Configure GitLab Runner -To use Secret Detection in an offline environment, you need: +By default, a runner tries to pull Docker images from the GitLab container registry even if a local +copy is available. We recommend using this default setting, to ensure Docker images remain current. +However, if no network connectivity is available, you must change the default GitLab Runner +`pull_policy` variable. -- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements). -- A Docker Container Registry with locally available copy of Secret Detection [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images. -- Configure certificate checking of packages (optional). +Configure the GitLab Runner CI/CD variable `pull_policy` to +[`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy). -GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy), -meaning the runner tries to pull Docker images from the GitLab container registry even if a local -copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy) -in an offline environment if you prefer using only locally available Docker images. However, we -recommend keeping the pull policy setting to `always` if not in an offline environment, as this -enables the use of updated scanners in your CI/CD pipelines. +### Use local Secret Detection analyzer image -### Make GitLab Secret Detection analyzer image available inside your Docker registry +Use a local Secret Detection analyzer image if you want to obtain the image from a local Docker +registry instead of the GitLab container registry. -Import the following default Secret Detection analyzer images from `registry.gitlab.com` into your -[local Docker container registry](../../packages/container_registry/index.md): +Prerequisites: -```plaintext -registry.gitlab.com/security-products/secret-detection:3 -``` +- Importing Docker images into a local offline Docker registry depends on your + network security policy. Consult your IT staff to find an accepted and approved process + to import or temporarily access external resources. -The process for importing Docker images into a local offline Docker registry depends on -**your network security policy**. Please consult your IT staff to find an accepted and approved -process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance) -with new definitions, and you may be able to make occasional updates on your own. +1. Import the default Secret Detection analyzer image from `registry.gitlab.com` into your + [local Docker container registry](../../packages/container_registry/index.md): -For details on saving and transporting Docker images as a file, see Docker's documentation on -[`docker save`](https://docs.docker.com/engine/reference/commandline/save/), [`docker load`](https://docs.docker.com/engine/reference/commandline/load/), -[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and [`docker import`](https://docs.docker.com/engine/reference/commandline/import/). + ```plaintext + registry.gitlab.com/security-products/secret-detection:3 + ``` -### Set Secret Detection CI/CD variables to use the local Secret Detection analyzer container image + The Secret Detection analyzer's image is [periodically updated](../index.md#vulnerability-scanner-maintenance) + so you may need to periodically update the local copy. -Add the following configuration to your `.gitlab-ci.yml` file. You must replace -`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry: +1. Set the CI/CD variable `SECURE_ANALYZERS_PREFIX` to the local Docker container registry. -```yaml -include: - - template: Security/Secret-Detection.gitlab-ci.yml + ```yaml + include: + - template: Security/Secret-Detection.gitlab-ci.yml -variables: - SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers" -``` + variables: + SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers" + ``` -The Secret Detection job should now use the local copy of the Secret Detection analyzer Docker image to scan your code and generate -security reports without requiring internet access. +The Secret Detection job should now use the local copy of the Secret Detection analyzer Docker +image, without requiring internet access. -#### If support for Custom Certificate Authorities are needed - -Support for custom certificate authorities was introduced in the following versions. - -| Analyzer | Version | -| -------- | ------- | -| secrets | [v3.0.0](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/releases/v3.0.0) | +### Configure a custom Certificate Authority To trust a custom Certificate Authority, set the `ADDITIONAL_CA_CERT_BUNDLE` variable to the bundle -of CA certs that you want to trust in the SAST environment. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following: +of CA certificates that you trust. Do this either in the `.gitlab-ci.yml` file, in a file +variable, or as a CI/CD variable. -```yaml -variables: - ADDITIONAL_CA_CERT_BUNDLE: | - -----BEGIN CERTIFICATE----- - MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB - ... - jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs= - -----END CERTIFICATE----- -``` +- In the `.gitlab-ci.yml` file, the `ADDITIONAL_CA_CERT_BUNDLE` value must contain the + [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). -The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/index.md#custom-cicd-variables), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate. + For example: + + ```yaml + variables: + ADDITIONAL_CA_CERT_BUNDLE: | + -----BEGIN CERTIFICATE----- + MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB + ... + jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs= + -----END CERTIFICATE----- + ``` + +- If using a file variable, set the value of `ADDITIONAL_CA_CERT_BUNDLE` to the path to the + certificate. + +- If using a variable, set the value of `ADDITIONAL_CA_CERT_BUNDLE` to the text + representation of the certificate. ## Troubleshooting -### Getting warning message `gl-secret-detection-report.json: no matching files` +### Set the logging level + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. + +Set the logging level to `debug` when you need diagnostic information in a Secret Detection job log. + +WARNING: +Debug logging can be a serious security risk. The output may contain the content of environment +variables and other secrets available to the job. The output is uploaded to the GitLab server and +visible in job logs. + +1. In the `.gitlab-ci.yml` file, set the `SECURE_LOG_LEVEL` CI/CD variable to `debug`. +1. Run the Secret Detection job. +1. Analyze the content of the Secret Detection job. +1. In the `.gitlab-ci.yml` file, set the `SECURE_LOG_LEVEL` CI/CD variable to `info` (default). + +### Warning: `gl-secret-detection-report.json: no matching files` For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload). ### Error: `Couldn't run the gitleaks command: exit status 2` -If a pipeline is triggered from a merge request containing 60 commits while the `GIT_DEPTH` variable's -value is less than that, the Secret Detection job fails as the clone is not deep enough to contain all of the -relevant commits. For information on the current default value, see the -[pipeline configuration documentation](../../../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone). +The Secret Detection analyzer relies on generating patches between commits to scan content for +secrets. If the number of commits in a merge request is greater than the value of the +[`GIT_DEPTH` CI/CD variable](../../../ci/runners/configure_runners.md#shallow-cloning), Secret +Detection [fails to detect secrets](#error-couldnt-run-the-gitleaks-command-exit-status-2). -To confirm this as the cause of the error, set the -[logging level](../../application_security/secret_detection/index.md#logging-level) to `debug`, then +For example, if a pipeline is triggered from a merge request containing 60 commits and the +`GIT_DEPTH` variable's value is less than 60, the Secret Detection job fails as the clone is not +deep enough to contain all of the relevant commits. To veridy the current value, see +[pipeline configuration](../../../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone). + +To confirm this as the cause of the error, set the [logging level](#set-the-logging-level) to `debug`, then rerun the pipeline. The logs should look similar to the following example. The text "object not found" is a symptom of this error. @@ -476,11 +458,12 @@ secret_detection: GIT_DEPTH: 100 ``` -### `secret-detection` job fails with `ERR fatal: ambiguous argument` message +### Error: `ERR fatal: ambiguous argument` -Your `secret-detection` job can fail with `ERR fatal: ambiguous argument` error if your -repository's default branch is unrelated to the branch the job was triggered for. -See issue [!352014](https://gitlab.com/gitlab-org/gitlab/-/issues/352014) for more details. +Secret Detection can fail with the message `ERR fatal: ambiguous argument` error if your +repository's default branch is unrelated to the branch the job was triggered for. See issue +[!352014](https://gitlab.com/gitlab-org/gitlab/-/issues/352014) for more details. -To resolve the issue, make sure to correctly [set your default branch](../../project/repository/branches/default.md#change-the-default-branch-name-for-a-project) on your repository. You should set it to a branch -that has related history with the branch you run the `secret-detection` job on. +To resolve the issue, make sure to correctly [set your default branch](../../project/repository/branches/default.md#change-the-default-branch-name-for-a-project) +on your repository. You should set it to a branch that has related history with the branch you run +the `secret-detection` job on. diff --git a/doc/user/group/saml_sso/example_saml_config.md b/doc/user/group/saml_sso/example_saml_config.md index 97e8f9c54a3..d09a8524247 100644 --- a/doc/user/group/saml_sso/example_saml_config.md +++ b/doc/user/group/saml_sso/example_saml_config.md @@ -31,20 +31,27 @@ If you are currently having an issue with GitLab, you may want to check your [su ## Azure Active Directory -Basic SAML app configuration: +This section has screenshots for the elements of Azure Active Directory configuration. + +### Basic SAML app configuration ![Azure AD basic SAML](img/AzureAD-basic_SAML.png) -User claims and attributes: +### User claims and attributes ![Azure AD user claims](img/AzureAD-claims.png) -SCIM mapping: +### SCIM mapping + +Provisioning: ![Azure AD SCIM Provisioning](img/AzureAD-scim_provisioning.png) + +Attribute mapping: + ![Azure AD SCIM Attribute Mapping](img/AzureAD-scim_attribute_mapping.png) -Group Sync: +### Group Sync ![Azure Group Claims](img/azure_configure_group_claim.png) diff --git a/doc/user/group/saml_sso/img/scim_token_v13_3.png b/doc/user/group/saml_sso/img/scim_token_v13_3.png deleted file mode 100644 index e98f755718a9fddb77ca830712ec254ddef30100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56821 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

x%fC0K8ze>wTT#1 zOanstPqMvGGhu9W$Dr3r#R=eAFn8M6G(eG9IPB zUEty_l^DGI58;^0IN<&jh`z#K)wsLZO7O-NKXt`&>+o0ZAiOx28^2HqCG@L|Z+Bp4 zt?Yh=a_jk0c92jpHo{v8lGCQ5!l+1f%!*6Di(7cc@rQq&2(dS?Xm%>H%ll=v)-`Ug z*hL&Tr7_7a{gJPzdvEz%boC#@MfH@G*TDY#TnQiaA*=Df{sXOj7Bp)Mtv{RP!VE@R zUM|`x-X+|HVz#crOcYKl2DMH7J5@OtqKn_4-casrpsziz9(mF_9MSdOj!>b=C|%~P zP0c^$;OfdwIKvaZnjpxLCAG(4B|>ccQ!Ua$xiP{8bXlKX66j$q0`A$)r*k)?dgWA7 zfq7T8Wd<@38(Ahvh{UUNNo|gU`*a5dvqpsPQBcpUBZ6;ZK-c8UT-1COZ^T(gY@eiC z0h`^V6A1O1odSAIrzcd@(^dUJdU)|)1Bhrum>9McczyDi!!2mEQA7P;A^mE$t zm6*}HkrT%FQG;q}o5?(BvzdBNU4B=oRV2f;yi}VDH?})E1w3|M2UUaEPmSS>(eQ_J zqO6#kwGiZNIyGY~$Tst`jx^FX7}0jza-mYSmlPg}1#BU9q<|8%4%WYZRYt&rdEZjvDzX!&AfrOU+^gE< zNmv5BJ|!N8!!IhK1+IOKUie4HqydWJ5u^tBOF;(HHnY}###bU8ghor&OC3~7yTcT@ zGdK7DtW!Vy;fFx!Q%R8{CXhz>h*l(k?(?~uYaKp{Jyf64%CRc54C~Q|*jE!9B@PEv zq6`;=Dw8LYpdDo^G-D?4AG~Z74@Jq`QZL61*1*Nl-`Z9;t^Zbs1}^?i-58AQu;MG( z`_`<97!O_`Yr|24V7icPoUEBon++t=zGo{mcT#d0)`ZE$;3(~Ba(2*6WUX}QyYvLg zb^k4nwNPdZpP&;Lc*KM0Ld6XuQCi1_mWLN>{Pjlx;MFRa zK`h1lycwN&nzZTQm{9lT+MYflt(4_sJZ`w%&)ZZweg`(<{y~aX1hRSpf~fehXm}qY zjg}o+ypz?fP}UV$mdVmXZObfnKKK71sZw(UY*rWnl&D#t5MpMef`)83lxlA1b*Ytcyg}IHRsEDM_-_kdEG!E7KsN_ zasF=vID7Ge;eA2wgk4gKfUXZG_%*%F3ph&|L1SQTTyqDi0LO^MaH{he>u-IVb7V`L^YUe0G9m9pN^=oZRwHWbI>33dzqaiyv1|B znJdA8Pf?O|n4{;X6_sKAn_$^pn_@7h5Y$%hIwo~eX>~z=x`wC=?r)grp|UR11_*Ri zSe3{kF?nOR?Ddq*-d*pj3Dv$fwT9I)pRAsLt2P9@1^8T4HkdG^!Zs4q5?SnNxFwO> zGyV~rg^_?b9m8X9JFKi_(?3VVOiTvN2^Pq#of91yHR`b`cTu?=jACXTByV2WY|fIm zygQf0JLb0aE){ZF%MHg^0J8$)pOf?}Y#9)}65DLMNIxf+%!`6oTzW3>v_Cds`Y*ak#oayyaWR{0^lD97&; zS$Vy|N!SBf?q&z|qk+pQJKD%`u9@?_>A<0u8np$exY`b)ynpmCygu`P&>?2z-G%N{ zb6*EEr&XD7wb2@#0mrxhP8V7`&+^tbFU_RZb@a^`s9{ArodmeSA;e~hoRJiCFb-x{L2bh`jx=pz-~9`*1l_&6wjU@bq1Ti4(@fL zDcVQjEidLX9XUUm%5S~PkwLiBJnIAfp6!V%ys~Lf0Q>07bbX|rmt4ojIZ%q1@wxG^ zg`_8Fp&1WcEX2ym#YNh;7jT&f#^HC;kVV}Gb~^I|)GsH`ZoJT{0go>ZQY{MTsR}uD z%UW}G^FM3M+EbB-i|%@;bZtpBN_x;&-HvstVoW}GIxEqBl(&{i@V1aR9^nSX&HPsW z53oKh>!p>byYM%JO1mcy1A{&t@qla8}6JoV%}WUiVg{h{>lZ60d_>P0rpg z`v4b!+>l)1zFkpy0$yyn#$rxdBwuw?nCB`)ok9{%P2n(2b6lPUP7-N-EpZkR;`;Qj075f&2k7R%j6d|o-{ z-tmwQTKOxH(^K=XpbHLD!I~Tr0m?ez;@!q}2|AmNz5Oy_ygvPvTs$j)(Uy!gD3RmN zC*t(r!fVZJJ*tUyiwER&Ad-mb`gc(qkk<38*XYH|-q5$Kc3MbjJs@=TdbvN`Ou*cx z`X!^Y1gfT9BGB6YR17d6p&FZ#7SXo2H=m{v+nfMkA$Z3Vp+LNP-#9U#3zyed`PQ(W zMk=&;vpa?u^nxYbPx0e_Y5#t7#J@M5f045w^6yMJJhBsiwJ;i%f=c6JOw0B=dEX@U zrTFglR{VnDLvf{3=oBF$;X1h>v*lL@7}qH-2Sz_!58N@R{iq` zt%KO)WfU)igdTi7Xz3%K!b|An>x%}?K!WheYR@I7mN$WhGn%;=mY0%9WXX*?&@*T^ zm$uB%XYU?VGTOd-7?_RCJIp;~PqASZ|Jg92O%&_B9|SHm2EN6Y|263m2T+b&8?lTA zdWs5_7RK`U4X4`jv?fG$K=ttd5zm44r_Q<_&DcmpkD4Ue9X`J?p_OrF?)E5CA3<_| z5vnsI(drciQ-zxL#1%@$ABYi-hPqYJnyW1nPi$p1wmJt z-MaeoQG4bmFw;*N%WWwuV~Ih$o96bf(n87~0&C@VhXu357h30CkDG@H?7YO{roMDN z30*J&6>Y_Lc6C0#UfH)v!JXbW@py|#DFbZL$YOp@@j;9Vr!oEzDoH-SGJPt%rQ=Zz zr9KL2a+^S+sT@4}f3feNc zbgMS+Ds0rxdQrARwE(>cDs8M=GF0)YDur~88juhmMZJTp^xBl9R!6+8u44&fB$*~} z)8MJI1l>{J1)^Kv3@JS2S|ceYT=_@=eD_9b2x7AAHyXEky)YLldT|ZVP2Nv1@=uVw zsQm)t(VW#0Y!ou3MhngzoE*E^zvwV(TUBT6MkTjaSru&k6=Js>C=e-#pwE;jJF)0U~fmAK#;af?v-tcNUFI+0a-$tM+qv;y4m2`EY7oDDnI($A=Y zG94!#;}gPA1yj6S1LAA599v1>!@6C=td49=gv#~KIo8Nt@<{^`jH{KZLN@gdiMtde z1ZSu?pvSrTe)uBauBq1+q3siv{X)}7Ql}4H=O;wIkR8uiMP#avg=6G%gv}!KN}3Ra zDiGl{hj;1gcj1`i%!pya{YZTzU~!&FYzu0Y6|B!nx2T;a`10EtaS>Eb^r>SX!VEAm z+i&il+th;H_*H3y^+c4@-Ss{j1?3?*@mi1?s=jXATVmxGpwl0;Skk=*L1D}>7>6%% znctYxASre?>1I5a{LKS06C_22W2|Pi4fVO+#Lru}aF)xtnB};T*39B~3oM1k<-Acs z*k9>eH_K{2sv*T8adosffI{HHe4XuSJ#>d#VFaMI@c`A`hRw< z6kmJE*i^~al>8|KviFV_wI;R^=dBs zdx~_m)i}2p1NqnnDy{3*fm}~1%@`GBJkW^##{wD;J2^@*H;9EDv>#@|$C})*@b3 zvV{HLs8Ns)+71e~8-}W}8*Pq=TO)e1pwL|vMgEb>azrRC*o zD7D|u) z!rW~Ms9U#O(#lMdUazbPHO?4vDZ9qm6qv5W>-D-A9w-r1GR}Yk!VV9Xiq0cP#8Wkz zeUtD=?XDsKkz+%zxQF%Wni&8+AVSeUN>Y#+=P5>&i<|1TV&Y!~F(QX-dqL(CKl>Jc z^Ww57d*@JrR@p*GZN;Y?)g0^~PqL~)k5qf?SVCs&YlZk5LT3>>#}8wV_eYVgCh~|4 zet{j#;_ZsxeQr^@bU({*b*v(^Udiqzhe4o|$Q@c%N$FfGEUY9riX7AiL`EZMyn>HH zIjRGn{=!Z<2F*Jp#r=@0T3&iw&VF8S?F+V$+CNIa*$nSOirayoQO zPQoPooa%qx*e4dG!hRD1=wQ^|Os7OIMwI2eb&Ept{eRKy;YeS$DZg;e&z@Wx^kqeK z7vTzzBU_b5eGfj+NN@H~jCnQCm9%ZfUl4*cws@m>U_ju#U{y5@ z3xJI4JMi7kI@91Idk#b$jPO`l-l%}`8;p$KNAG~aCsptlpi~1cb8DHWvGf%Z@^$)o zCAq*r22fH^*TWe0$ujyU~>Dw&OA)IWV_AC700JbX&elWXfqM1gA+h!7BDF^r(jvE92%enPQvd0Dmh@V zHWr|Tq%PFlQEU^i+zoZs{+?Fe*baD}b1W&0L|GXp_O^-WJ45NnC|^1l&bY|=%-HK+ z)vHb$;oVT7S7ki^j~#+@+Z`r7*Htc+MckAc04mM+i=ztOw5rQ#hn>6Ei&F;Qoz-)F z$0Hja1GQ{p#mj4s-?h+B!O+>zK+*=hDi=Z{GjllG#PRw=!-!e(^-f4JZML*?PT?7P zc>`%6WZ4QgwcDkOs>t1fx&AF;24$$V1AqKF{`nTD{M1K|@l_m#v2a@K)Rh?Kx(N}JhVO-(#uR3N$-<>p3YwDbHjaQg7h)mzN`p#{r)Qw!OdKYmlx86g` zJME1|g9LG=YEyQA@WAxa8ZFZ~x>wB|JK)_@qv|YFyLB<5u*VYbx%`BdSa4G64n7en zD&o-q&qixr9*mWUis{D5Z!?Rd*y`hI{CjQ_-y!R_b^jUARMsVzFL<1_QsSunmCTaUTX3Nf|Mpty&psz@?$G42?wpuk zUfxe>;(+>V6Ri5TZIaaTk94fV_G**IJH_wa>qN@u>9=k&Q~gVP?tF;A9NVm@qoih* z9xc@0mClctmuOr#j z^rp1|-R1?YRO^Dv`4fGwZy7Ig$M5WZBzb^?#yKiXyS!dR@U^pBRc828_LwdV0z3LI zc0d*fLY+(Q&=)0fJNoG=^ZOtLqPeg=!^LtTT-Z{}TS#!^w-P?LDWvc?l{9>cC!XI1 z+_XoNL>WxLfUs?Mqoz#5j|y9x$6uD^?P)$s^C?%&N`sU=0?xMMB*9UhsUQD_(I zRl#tE%0U1Ul4?fkLS}@K(f*xFQ7ZhIZ8$h8(*RDAd2P$??DTm0k*$a9@~9sT5=qh& zoj_DJI?XZ!xk6^+qi)C0A;kHwv#9{g>U2W4F7Hqi3yUWekca@X&%yAk3=BORv6}} z_vp(=OxQ-qL~2oo!DL)nvQr%eH^Pwt!j90*hb@a$(>raeJ}HA&0B;nj>ALf5>iWUA zoE53<&?-HduqoqO-`)A0q1JZj^iJd{0v)6iy(XWKj&dB2pnR4Lb{Y00ubk{FJ*KeiQ5!-tFzJBgrS{coF=X zTLml485X>3yYBu^m@2IQamf}*@9w~i?5{`~{6_XCo+k4ina;l6bIA^7pdx1C9nj!!6OnLXV|rf%;&io4T;0pUz}vssb5+kmM0Fv&~}ICY6ZNe{u4d^ zjV@=kc6uIA@8%)}7L+;*(>zF}>^k~-=9X#kiP7f8T5{=Hgnehgv}PDuVOLgMu3PxT zIk9hNs#K5qj5iIYqp8vB=#-<8cB2kDe!a#?uwOkobEYiJ(zT8o$6{fVq$hkBOHgA=l{*n(5Ciz?I@DB49Np4ErJ zt>+&=?1A-}5$4y9jGRs2hJZ8in^y@4bR^K}^zu3FX$p@>@jB$bpB-W4%vSD|%|^%? z1DMCL+OhnAW8S{_GTFP>`Rx{PcTQAA-;7&W@V1tET*u@l$nTP0y@iqI_ns{HPju#9 z2FbYg;YP^hgwQ~x9~wq%IH58vJy5APZq>|V>QbH-z0rU;;JCFw&E;0Zp(O_w_~8i2 z%5hDc*UZ*0CiGh4vm?8c^JFdgC*=6#4CVnT?a8j^y>S+P{*IdsRoJsw0bS-D8@Aq} z%m3#wFZk{p2sv-*v3GX2hbYNiW4NKl33|}K z44#eFd$+!Cx~`7aD;?z!dFj3EpXw2+KEvS?{_o7(|Fi!&c4NSRI;ll4ZWk_mnJ>(P zE*!z`m1TF~SX0A}_a&hfMH-4`4r_?yz7h2&DsQhsWnoJiWc;P-&HVlwX!}fN=H^Sw z{BF4*?FP;4zSaGo zTJC*yz%ltxj1LIAP@1O?pU`}UTdn3AU*z0|ItyN3GQUl)uO)%^pi9U^*P0J@JGa&Q z>L{XgB&kr{KWaj{{=1bp2?I9@s+^(rcK_z~6d)mE3oKH#y$@uMO!Fb!1Yo_Ud|L7% z?sbmKvkg#%WMp6f(Z%p|vzU%k zrg~h6`;=?iqlZvGyt-&OhFn`J1uKt?L6p5ntn5_qU{|G%zo)k64I;oCpU*&8!)BsT zy#!j5LKd31b-L(8WQi(ox!|=pN=42yETBeG(~lJA`ILYe{4bxOJN@-5@k&xZzs5(Q zbpGKLm{lQpb1EZ7r!w@Ud!_;{=+$X529_(xF3uY*ckK^nO4zY>q8hU=!!)QsMByE2zno13dzj4{ zLsy?!+G~@ZU!;x|{WP!LwCSAz5r%+~sHGP0>dAm*hO?cVuUu$Cq%`x=zm;+`ECv>QX^0)On2PrN)v!%TOk^J65g0 zC1)>+Cce>Pp}_Vhmfg?_vwpuPZdKLUxACOoC6`vN1@1;8cHB&~wJ#5EM+U z(zsSy)5d+J<6?+p){ZPFbca%kl+#nd3S3=GJu(X@wuKXVorl0J*&O|5 zJ5A+FP^dG$yZGwKPf>E{CT5K3@Yy7iBj++8g!9)n}Xj?4q zkh)pZzap7aVp!VPipp=C>eVT(1u~caIemPHhPeUl0&ff*;??_K9+V*>Z_va)=mtud z!`e*h7}f7dv46>xkjH(h2c_uC*wBS)5A%zJ%5|queX`5XQmVIVXT|{9+y-^6S_FAI znVUz%?m2oH=uX$8=&n?z_J+PicTW9Rghg!#6y%WB}&#{t6tj6DQu zR(=?%>IJ5OV2pub3L_6k{{vOJldubCvk4t7Y1-VAcyFseyU7gg_V_??63rSPj)c1L z-At&dDR5KOS^3J~~R* zyHQikqiN=dXxh2)S;hpoftow?x`i0|Y$K*Nb4KAq0Mb4R$ICZab$_C(CFHa}H2*B1Xb#a3jCib^1;wIEkm=_DfUg(C1uc>QQXNfg)EK z<a-}quViigY&x4 z(nYyK0+;JK3+N1eUZGOC>bW(GJ5Sl;{fKm8RG*)l*RC3(4a0Ik>}RDgDz2j4Ss^Lh z;i|UOoC+b`ncQu@2U;MKl%0{2GE4vQ7XLO#`77O!=CCFwrT+-K0Q_|@C-q0U)q*l> zQp=2F)xl5{MlA~JP}6^SXU3Uvu`2kygrGSB61betXuSNb7IKgDxeeO}rfQ1q~8K~2FNzluYjzGs}_ zAq$Z%Y{;KRU!kIUTIFgVex?Z5vw%xUW6~-}lKNlviI=!;7aQx9`v{@d*>6SCI7cDI8{D`WjX6TqFRu^!UognbJK!` zyN~@bTW4*n>Z3jW(p1fu`n83Y+GTt`-yl0X&jWsR){k2QH)5~Ld#N+>1bgRA`z{vk z)%n=f2ih2?RZpEM>#5t+%RC4C*EZea#&e;+6_H`Kd%JifMo?p)yI@ynH3XSy-`++@ zaBrjQXaYm9Vx?`Xv4VmqAnZniY&4nV9yMy+-L!$P(dn?#5$hPrPJm>1MSW~Qp7%>? z7dI!%&>B))RrkNU==+?$x8J!HdGzjnSD%W>e-~m1kibo!^Zwhp8oM06`upu1cDU|h zx!8?|x-QbZh%njEOMy&x3ia;0MH%@}|9qmp{|^quX6My2yGwi#uP3PABNm zUFCFtGGI0Kbq@!a0#*TlgNI3R_+7_&A*iT?BItPxw;OpxG4C&vZU80m#-5RAc9c#5 zHz9>*q1PVVX@1RE~s=JgEJDz`3uw-0`Fl-P}?KFzc zmmyp^9uHpyFF9h-sMF=i9j99d{twFDI;fIn*%!rO1|JyQZEyx>aCc{LcUZW)5AN=+ z3wO7{T^H`|?*91pe&^hM-#u|7UjNanqN7%J<}WL=qN=kp=gm5gr3ARDkYzdXR{sJ? zAWqC#6YncC?AHcj+R8l#jv6i7Y7`q=xda0d6r`sA3X?XgwTMY<5%8ZEmFU{T7EDpT z?6GhdD>4c5h~FCCbNVe5GTFhTVHI+wzo3%?A1iJe{CdPb zCvZL$pdkX+#R!Rdx9-QwiyQEC@imV=LE;&IyL@W7SXnW$nlrm<-FPUen(<^$?zD|8E1_E1^f5VjBg5kO+a zEQFR7kIDQgoC%4Bi5p6bE!RYWq3`fD={w44pS2KyuU1+?)7s!y-;sk32^xNt->+^8 zHs5OE$b98HuvJ<^OF{=|+x{ySAkfX1mjnR+80cRDZ%lHWjOxY0;~-0|`BYkkX5Y@p z(M?r@7?!4LenH(`&ddNHS?o|!tgo*6Yn2tA9HOCo-!2R?N(oS2g&e}~wb-zSJ&QR8 zXN5?`;NbPeM2phmeRI}$iv+`Ws8m#V2r3(d9aGISnJkwzUDuq=?D~pCaR;>wPdf6h z!cwNZi&*_5q~xs=uYaB782j5ov1Y{tw4uF2mY~xN{NL!j^KFb|S8Y&X$H;q%b1XF~ z>#0+UjEy*wtZ?S}SoksxgoyBXgN+E)KfI8VQHNrHKPwQ3>8qr9%N*3kaeH%_rEK#pTFLLnmr!?OUH#*iit&0+? zh44O8LhyJxrQ^ZQLgs6p=Dg@3gco?{OQHKXfy+M9%_9B}U-iGmWBuQsi@TMgKmmVW zLInNa{?v3c8vKxaXWZ=hv4#2Sj8d@O{Mhg=_jm`WBlfQ=$yHN9`3#}6{F5r8xAIDkoGum zNM|1OeECAk!pNs0eXY&=KwnFQ%|Wp#ZXB=Af?@5S*MhBzFoJll zQw!O@LDCcsS~J4Y=7Y-jrR4HxDFtm3xdWo}8^ZAnkT_|?YMRzKtP)sOpW1vu*Q0P= z`|0S|dzocGZRJ`kpEAShvn#c$8zBe3urb;DbNr_x9@+kPD!82f3;qc609qhH+@yvH z!u{|8`xvPS9Cty3ev5M52tE_wuciqAdtm;hN!$8KY(r!6!q)C-!zWJA>ut|T;iTs` z4?Y*!J3T>Tf2jYrhMpt}KzNz6iqH9_G?4%&{AKGFq1{;&8Q5hI6-L9!uQvE~x9h~< zo-q{G?JD_-T#>>+^O*5j~H;&wTqiqD@jxAFNY9gN-U7T=q{vbE#8-G(kR~|IvN}-60EwYufMi_ma6hvk7r5~k| zrdwWT$%mdjpU^BwpP*9TTguGw~>9-j_&$97KVrio|QmTo~aE`U8hNg z7_+4n%u84BigR}g7`7x%*nUatQuR2*SQ8IMKKNm7mN(ax%T(``6EoupF#aVa$9m?Y zZ>}A7ydr1bHxuJCcx&~^CFLU3IX^~^AdV$!DIvv)2txL+>O<&EY9k=XQqCr{g#9iY ztU(Z>v5y5DMFF$j_}illn@u=ueLzU- z-%f)Mji$WyC7jmWw28W>w)oj&K!<~kBBX8wf zQB?OIfOEPvRho18653VC ztq)+%EkCp{UhLF#I(`0>3DXX z2I%l$#a1Mf7BF2yP$`A@R6qU>-}jEfMA_gN2Y=V=FP-^Oq$uCq#XOqWfgPHi)U4P{ zafe&EU5y9H9!=4~3Y=~CYzkA(@|sV0nWmBpB~5 zD^dIfDvT141PcB_L=!Q8QLV#A5C(dAH(G)3Kp!e@Ku2qj?0gh~-YmNla7L@#Zi<&D z8Yf=8=VPAT0zY$i^pCz$-WBwGPoYakC-}KR{^F%jT^%Z$ouBO(+6h znK&rNDzEC2%UdlmXLXm{(DytV0&Zw%gt81;mg_qC4yTb>S&(BD0=lzd>Q&lr7~k45 zk?YE+%Pm8$KRCI-rc1#`0jvStjxHF$KlD4N7`4XAv=>}lY!s3|wo(t)sZCpOZ@j&8 zs&w4VI4IIc=#6BHdDxHer=!XKdr|ZMr*Vb+gyKknFC)$wKzKMy9Fin-?(FGj{T%7x zZ`PpCd4v@m4rbul4xE#~DgTn!FmP1Btnx zGHmy*bAwq=@!dEU8W=;|SeiH}duS%j~vkX=u`G?8h|&q3--N23%{ssvKJu*Z!r@KbRd4Pp6q-Ls7kyx4+QXtgm3abZgKbrn9or%C88z zhO%?8<*ZLM+kMg0d|(Ck7b$Y#7S1Q<-`!E%uc7?TzpKxU(u_U|@^DdO~-sbo%GdhxfN) zqWj0>WxeME#a+RnYc&8j+;;s&Dn!f0YexyJD8%KXHq1tUo1U|*rof(vGEW67+PW^d ztD5r4)+#nt1!Ph**XsbdNk=`~i!^f0-D58S9Q}?f@9E1-zOxgAqnC3nDZfc5?S-&R3Qni z6e-&QSTpq~*Py(6J<8e~WXoJ0{inOXRO1XIWj{5Jde^p~U`dBa8OH1Iy_q9;A=7&r z-W_UW3&t{W(5K1^ZeEuiyw?YdrVO*(;;JL&{0y+p18w|N)Q#7O6ejr)=f&jr68v@ zJt(r`@8Pr>vn>9vDM7GOW`Vld_L-gzaKtW&?T*OC&A<9QzL5)SZ{fip`xn!9bjnN5 zWTnBx`*RX$(~pK%Ti4Z@R~p1rV1QDT?tqFYY8 zm}JRb&!@?>SO%O^QeMZ9e+wlaHy`uAp!}%a0?qdXYx`_hqGpA;I6JR1j!MgR=N3rd zbDx7$V1xYaxzh;c^25DdtYod+;Ny5=v7j*tbgp@o01|}P58=^K0L7Op#*=x~ay~Zv zPC${j?6?T6jhAlH&q&{&o$1oT$gvm#M%Q2jxMb>FCUk#Ff>G#P^G4|>OsU@JR{a*Rv0}bvoU(!o^qW~!THZxhwrvjZC`9dZa z)v{IJL~*xVVtX-@z&Qw!1}cPYd=H7_t5M;+<+n!6I(u5Y{Gq7Jn$PH=@}uE|&4|nH zfH+<43P&;dxo@2E&!_?4;O&c><}PZvoWc)cjd0|sD&68vX9rYaWo2xz!x+#jZFg-!Z5@{hxhS^Ku@}14AlCPPW`!uBKR^-o+d6P1 zz(!~7vW+C-%M7vPQ=9Hry6zIPM6OTX?iLF@u^fSh4Sr9C%s5nqrA>uW`1kvhx6CIz ziKS~X%Lk?_7(>cxsIwQIAx}F~=f$#u^;m0BRci|ObnMw7s>$&YW#WO+PRE$-!aJ2L zTlYG%Os!-3H(i2jhT77(^ouGBzthz)7b!fC3iWCHo)Pm$GDa!-IQiV}2uM+bnhoTi><7}dq+bvYMGnaj3^*EzYwDgpzOCu`z2t^ka8sC zl8Y2(Xi^G?01FRGR=>WN_0imdKZlsE$P#TqP(9@3mtDUU#Bk_%*zD{vI1{Pkg8ld9 z8{EGsmvnI4Y-K#AR@&l*-G<}qA*{1-&aGP1jN>>BrZLFjI-op^;yp1 zLMJlDlCLgv&_g&hCV5xh%pl$j-oX^i7P3+OEXoR<@9dPK)@AA?euk$nPoqOtz1`XB zSmDZk@_r7^=0MKM^p9ArY^|H8vSn9)G$*NS536mpCrB?n8#~?#!nA zJcjdPHP$$_Jj}<(V1r!@5V2A$SrH6u_IQS+)DYSSjv2YQSzBg?4WN+=FwEr6*(=3@ zK2P1w^8>)F<2mUj=IwzNa-E#Tz@$K?Q;EXI+}W|BV+)?SU0`mE%y*g|CY5`^JSA?qo~Cwri@!0gbb&KPmwu%)8z^>0C1-IaOr?OIYg-b-y<1<6ExiE{;vZ0Z4-iAj=(9G`5-2zH7XZP!^ zNC7gzx=?B6k#b>d0}KYmiqV z#!8fX^`4QnzSNI$tjEaW(TIyk9I@Lfc>`7msNJY_Z=fBA%CUyR@~sr)KNKQ`K2zvyqSmDv?+zka7Nocie;sE_PAd|*l8ZHH%j1w+T1{PG3yS3hvnF}~kInm1DE-v-mt|$T@P2CVhs3MM?8=^L5iI~U&Q?tV=N zoWl|FGCnC+p1pB?w(oL76VTu0f($U??H?fGj9RnO+AGn(i zr`z*=r%I+%v;Q{u|7y6Rupsk6AZKlvq+G)PS~D4t1>0v+dpr4wQ0xa_?Zmq|xrA#2 z+vMk`2S(hc@W(>xacDv#;)gjbtegxpepur4iOmjZUvE>sj|x4%NpcpE{QSzA8uP35~s*l=;!o&|MOR zn*o1qH=JaOTZO~myhhn!n(ss33t(JE_qxcoJT<)J8JtAuPTYW|&<|K%_T21c>}_{* zsSV?1-!XQ)|Bf&uu!oS0vNV!NPegL)j0h};WCcOtgfj%CDV~eY;M&r?Mb(un(}^56 z!9WkjZ9G$-xJqK|#XGs%(U#mBM7hv$ibl+DMhMx-u)5zV4B_urBp1wIeIDyn3~1Y% zp$qQCaN1suq&r^>1TpW{YH4||;65Fz7Ev_0ld#_mW>a3J7$n)MWo_;c$_TH6>{uhc z@+AW~@mgTCq=>&EiGd`3{b9`OM?6oFYH6>mJg<1x3+htUVQ`hRV$>3UOEVjh2?Y+Ko{{dv#nyJz8}89P zm`ySL-6_uh^fbRT(sPW(I{lm+>3R%*OPIz1dK;pJUso*{V>9xq%kK>=<4!1$VIKi) z6b-zR{q@dQ?;tvTUcf)E8?79uoz~eg;|Ua!g6MkXmC=&qF<^~%uj679Bk>|tGKrrX zB~5-bziUox^OE%EkKCC74l62PFeGSLbT^!uX%to9e|!BR7D%MtrkwNkwwOD5`8=x<#=Y2SR^Ydb;ruv+%pC{^-IIg z?Eb-NVU?u_)wN#;PTLNxGv`c*a6%gFPj&wzRl&Y_uq-Jdi6crYXD$O!3}IkXPIpi& zHmXRrA2d3Q@ka_CE8Hhuri@(9UecP4kJtZ~7WWlj7~=f0OotiVhUL*s=B@8_W&r2u z;~GXTxS1o*G!W)jS~6Y0YV}UP)(JWH7y-iKOPXwVhUWy{{cxm5N^h!wRyl7VX?x(*QFr~k|* zWTjMqF3wZg+(Plh*{x5-a>?$oFhA3L6SScgQuw7#B7JHm?l!L>LB;*IM^0^CW$?0y zNJ;f^Df_XaRv0au;%Zy}`uEqb-e7#&HYV#5X)4aN7B++Vy-iM zRs6%Q5p);55(q}xqNsWuI&gNxdSZ#LDx(0njS#~|lTxC5c@Q^f zh!v#Yr%cxoWwam5rkVdkwcwd5nY#7WLJKoI`IO8^P1r+$(`_OXUm5pv><=vUIV<+_zFkP+OuZOn30WEWQx@((PQsfnMVgwXv$o zSyE;*COclfBb}Jl2RXoSIE9~3%_ODWHP;vMD@Oxk-iAFDj1H1!P$bEcxI5$VZ7o_uC;JLuP8!`C5X||4nBzmS>tjw2#Q;yCo4HFd zFNa?7MP3);4{jyWPtBF(Z==UGnJQgRC{1Uq=-?)R06{n`M9yrD`cu<37Z4yG zL8Gt7`FN`jJUJ>-s^2AsK584xwD?`)H@4yqL==6$$X|F-1Kn~VBXVSu^U3efVDFI3 z1=5EoA;yx*P#{E=x6>mJL$|?M_iOKhsZ?gj{k&#ee7B$fgJL#6i}l&+9(Dq^%HFpN-MMj-!h!Svb~B5jIkwGO`5UE4+{hx5mI+_FazbPd-y ziE_t3vtCp^brFJSVurz?@A9-y>7zdl96Im)>!*S1h6~Nm-|)#vg+Y`3#n2jrZZN?> z^X2Tu1AV4gNj>BIja^cez&d3m29-jmivEv~hq03FT>qBQq=tg$z&R&?-_A=={=#{M zkke8sfjTh-@>mHL1b?uba|q4a1$&+z7elpwZo>ZvPpHg%>W{N>ja6Ms*`TawiZlFL zq@g6kde+xjP7rd=g;b*LWe5u*m$Bll2J?}Zceyf~C?E)gZI!&|&cSd9+=znfX2Ue| zd@_L6KKRbc+CX6v>7t~x|Er|1vJ`Ey0K>Cl?=v=Rk|#i^rOSh!+QD@w>Bs2vIG7;Z z;&sH0hS13*cYpMWC|sk?P;wEWo`TmCSVrW<2zv0z&R@an6RR2~hBb~|%mW1%B9dss zWaFlnrh_vPwX*(xyLU&Ytyp%hU7eoo$)zwn*D?lmMWvwm}XjO+fuu2vN$e`k5H^;zA@=|>p!NQA(Vc{fE{FJ5ya?3THr8LWY( zjjoDsRBEjdAgZvbZS_;hVza1u0PI6Ak07zs5E+n|i5^vhW)Ly(VGjO)Nj}oCc{JM~Ji|P` zNMw`Cb4YtBYNXq%y-AeRgmz{F^L4+HnYI9xD*&r7yHCJZqgU!};uf%i-oO@I~} zbZ~>-WskSA6gRjavBF9JTY!e$yXJ=m;vT67CePq9^&mgqwKM7LBe13~?YX6!dr~_K z8%6QZb4 z)#$6A5b7CThxl=^#1}I}YS9_p9MH$Ye*TI6t!d^=-X%;066AY5Dqu~RQZkbJ5(TyGsi--k5adjd zz>0~3&+YO7htA;;2+Llx&^79@2L3N9;Z0u*T6&3KV*f31JnX+D9)g8( zITR7Wtxoh=)6FA2UU8IKS@s48oIdf^%~(rU6Wf`|LiC67*M3J@SBi+m@k8|LWI`wY zDgT3viarhAo7|qWACFqVa_}(2P&ZT1$mAX)=_UtF7E+V3Vw*%OrWT6)+r4kvGPzQZ z?^wt?=ebZPyqmJOw8=U7hfG4(ES^q*%mrcMf@^de)xl#X&|f-P&hy}4HRZFWUm@+A zM9i*%B_g+{s1tS`p!-ZDk9`7O6(!}P2#TX5mY*ucud?FEWM5DVs|@uK=@=buhCH8~ z!jNCmaf^A|q|ZKB0D%ekZlJ`*wN6Fda{EN_hS#Ghls)dvAOlUfyu> zK}0e5%cp+FC2~0arQZwGfy|LI3}FirC>Vg|Lhwhm%ejmUnFW?l{BIae>_G&5X>oBu zd?Ha2vN+ptzddU9*qo$td(9X@ZVdY1TBK9=soK>w|Bv!(nn&>0kYW$_xKw_vH6>W% zt0!f~@q)IEtfSQ6BmHY>%{e-s!dpiTuOShuc^a;+a)Fk_qsQ7}52Eu=Ombi5Hyjik z3M+qXE9Vi6ig!_MR06dDnm+)Ua+T;Vz40Jj+H)Z&OvF)4^Yy*wHCE5)#*)Z#w-+r* zr-l{hu#$ORI$@comQji9Gt=LyfBsf~Gu9sg1=hq@3)3McBr#VbsMBNZ2 z_|_2dIWE1#tf3C_gd~IBs#E_KsNZoXhl@^q(@8VL1JoeOD<-e;5bs zlk)tmmmcUSq*@NE(I7t-A86;xf#^DrMT%+uLDguH(3Yr`yEH6;DQr7k?HQX?V)01O zQewJ?xF*}iR6_Hv=hY+xV!vNK5d`fx@QOq(dW*82T1YJ`T#L%5j*vUrtLHT$B+Ou| z6;+FN;yUaZ9V7*BEQsP^*G9RCZcx&t*oaa}m#=?SPK(7!I2SUF??D(A(YE8!$WyU2 zcj@y2q2|DNGpwm>=iOszOqwf<4pqhFrkW+I| zt4hd{EkmZsYdp=c*Bni4ED;io8i>pn4~iZnq_s8&ai9?um(-R+(ZcoCZ|zVM7+$t=2gJlf$Kl)<|TpCD`CV?;da3EsuL`RMCj9qEFPYKR z{A$+)!~FH)X==W_s}qw~n49bf159@7h>633#1F5}5M-{Nk=np)%&wkAzOuLSyy854^VQ0x%+RC)$)=2~c5>^~|Tki`# zG(JGfSkY^!S+gR?dl zm){$mh@*Fq{$sKIh=hW~A6!v2j}VGxz1797tiTNpKnM)$2RVu0AoJ~^K!JIR{DHho zK)x1^&AHUg>hmnCSZ><;&~E|}b-CS91rvd7T7)gXvgs!x&t!B@XPnd+Xd)DqT87Ii zlo=#7D~I6tI*=akSvu#9z*7CNMR(v?ZtQ=Wr(W6qqObtuRRT2%p@3bU3BTnuG*tYn z3(G-S`65P3iQF;F2Y`m=^nRohoE!TMN+aZnfa^^3YP6<#=l^nUN@Z25 z-HYBhmyfeLmrugRiSJvti=ECq`|IBQctji7gD!YTtK9Jp z$xflFy10Iu#F(vp+6bx3$0jw5`6|dpp&PwHRw*J4*{$CM(DLgpg-6bvXIDR&YVh8D zsTNLXA;>JY<>xERX8D(zGT{|>`fkZW#pzxgxiI(GR3&T6`gWd#y!V#SnfubIeK%0sG4Cg*)UU)2hAE-EbX$>z%U!)IhU^fVs#Tm*gl70ky%@a_=u{~Wa0q+BYnogM?V@;%Tqj?u`O zV4ghkcm4VZX)uCwhKB+0LinvCVM(!c@#nCceL(fl7WAWHC(mjVn-lj4=Ym^j~?5GET$&0L_+rMNgs@y-JrVj+ z7{f`g>jU}PY6P0jKLQ%(8E>2&aS|W9_%)ye!kAkGXRm!x)B@LGbxk+ni<$h$XvBqt zOdGnmT9}Q8z<0Ufr=mXoj4p54HE=7^;)*Hiz%}qn*QMaPwU6l`=*lsn2rPM!;d4MZe+%TuhHn!n<E1k`J zQ-eO&D6AZqgV(9|y7!fpg?1EQvstF-#$za~gu)AtL}uknSu|GWF#3%vw3{k_qoS{u zTG)U@v?SG0e$TgwTzq|p_VMMr;xVNF-i5ntaK*ZHOT-WVaxjTA-Iwkc+j9T|MY)&O2;jC&zsHgSqQqG!3~hWSmU$tHJ@Xw}tSDAvJzPHV~y!+G_11|75A7h^lNDSIB~%=93>)KFeIE^gC!at@2Z zyQE;l9YGehf&+1-9{1;!Cn*~y`wb)u)&o$`K6>Ws z?cl9sUR=<|wM~(APt-e$J59J(v-z`3LE6~2 z$YP5+y6WsM@ryEeM*4Lq&|*GP$$ohY2u8B5>?tX@*t&!)+EBd#qvI7+!GRrT04D>I zug}+&CzH~^ACI7OJn=xsk6LsxkFiF{)gNafIh^7pl*=7Eg6zO;0(DX;T{Yks(&W>9 z!|_U~!p>s)nO34JlbU^E_a@yBT@|b57RibZHwmZo=)1C+q?_w| zzi0s%w^Id5FySpi#S1@G!sZoGH&7CwOoOVE`JMdJ>AhLDQXpsmc^Cy#0$$Hw$kU`g z2Ncj0Sj6)NPl;jFRe#2Dj`dV|>kwd$y_%V71n9 zfQi1ZY{E#lK%4G!P|nmTKMD0AnseCDR4fXcRzQnUCb-zh!Yqw?;Xbd7Aej_M! z!uf*cc1VPGly#I0ddo20%7{5;>gX3MG4WUl_YU2U1AVhORS&bGbcBhS`$4p;TXB6> zL46D%Opx6pKG21Y?-EEToYXnN3gHFg@>KueTdcM4Vmt#}k!ow=N-u!T*nE z(zk1om`7ysNTx6TAW9Fh7(m`PqB-FW+_J*+raz#!q?rHla$S+fzZu0V5EqRX?$L{e z2f+Aex7_P^K5ody9c|8%4tI_&`s%_%GiAzY^zT3%<=tHzF2C|nW}13uY48#iPIi3j zD+?(FTg*O64M2V}{T|I=q!N!@nnRNx0B5?2lliv6_%Mz;m+Y_k<*o2()V~NX5p;q~ zT{@Ed-qD)^{8&OFjN4S}>DlJ*bxDQy_Kz8Ce}{J((;ymudaMei*>0Fc^OHV^R{=j> z{NU>#0qaARxYlSoBL7MMhYd(?972^=mBgYR(FX3)l>EoY=q1!h}PUju>>kylZ zL&8V}b5H|1g=(raKYqg2J_EG-qa2H!y5>-blNvz;H{=wP3mcsIYs2jM@I0QXmP z2yA%*#*~}Ajqf~&8$Mj_-c$-?Z=fEA+#k>3)PE>Te0yyN>}0(nmAh0OQSb#UP$Aa; zObof)9`qbR1*vsWzn-RPz5UGeEddrKMckmEqg8M07>Yn@|2af{fsNC+4G(^kf)dMb za0|^B?b!`e`uW54P~m*PH5xHX;Z$%6M405JS(3s)*K3OgIO)docw0oyYQh%p&*Eyw z4t+pWy4b<>8A2ENC8)@C^+!w)Ofch50pqAr4tCp9wC##~WqohC6SLlNXyZ?C4XGML z@!E7@Yj}+ssT+R;vnTH9NlBIFeJZjj-{4_{bi!)5dUr{WgIwiDBjXMnpdD%9?JT2W ze72Dgqb1oL>|44G0q(TyB#R!m)S z$LpUbnZ~!Y3utfB-v!Zs6P=C5efbZNCU6fUJjE6t`~v+{oNv}OTBQecrG6^=&HKeo z@^?bcauU*%^WOwU=0-Axd0$oYg>RbG&*Q`xBnbRia)}cadmuh98mUED5pdA`#0bNM zvM-a_Cnr~^3wCVXiu`R8I3D}k(mI@-^r{oJbR`X+6C^!b9}C(OU}0k=VI|KHKK`}X z?t9N?TaHg%xzlX%W2Jue9rA@X?N##PYyI)iI+23R&P3fc@emo+8ylFxXnfiZmM)=2 zUDbRW$(Xc?oxEJ|fK1$m!RP2WEU4PKFRSGVadP!%F@^}0`RyPBzgrQ6{u zh>fIE@*@!(wKx_tj1*D;Pz4yAGGk-Kw z_@|mSK7W06_{N9IW459lE?>02#=Xc{%Xkv~+gQW5FK-SS{cGhegasSQWUlEos=iU=encO`n(&w`tR1r%YD^iy@V@-=R3Klv_1IF(>N;uaq3TOr_t`hBq z?Hdl%!viJ1k`lvzSOaL55}s_z?rBb8hs0LTkNm*xAH*FFpRrjn zG_b#R3HxfI${*z6^b&x?`uvHfWdUU71?LdSviTM)ovqnZ>C zMEhKG{aC4vvQo*Q2a2W{;WWp;fW|^@Y%K^SmNoQu zMslH`>C?jjwT{lLlFr;_N=nm>D?g?+rvaR@0fo@wJW%bIA`pB1n;5Xc9++;L*1Tlr z(aXJ;PNhQaw3cH(v_csz#kOLGcR?p9_S=h*C0ni2QQW4ryohajo+b>8dZ_V#?qos^?bNxn=+onxHzpphLb>|fN5U`w=d987az!8QW5Y6gj76BRh3|# zTCkGJ^BqG3t;y)`XYvPlwB+JukdZ_o&R0d7iDdSKui<{jbo1kf(glt{`&qT`tdGW9;_{LoU#C zk|jIVcTN=uvG7UKtyrQSFfM+%NvyFK{c1XMzpKU3h&=3%g#Ij!%tW_f*uc@#7d;%K z!KQOM%YopP(`U`!F#8eulvfO*k=>Tu`c@+Zyi6>>u&%miPRv+J zlwQAHq9SZ9$^ET{@cT=)m5v0dF@~4W67Rj36jGl~?(I@Q)i2D{&b;Mu>Isu79^LSc zDNS~?>#@+E4GSKz{7Z#)gfP>veVh< zS9dhtCj++IQ1UcBJ#T*ogWHXTf|0IhoPM?c6~E$JHP`~y8Qx12ii0tFt$Ax>^do-q zWdRntxI-pUGP7(N0f0yTbwEs(5#e*eJpp~`MTQWUMr-_pe9~v=UBPvR7>L&?f0^7U zSvWDLh5$hC^1wE;vL5&ecA2``e$M;b%$U1Nba+3C;_YCJiHa=K(Z)k!fd4DB>W6Ld zaD>7xLmC$q^Wv>MV?mNa)NqHgt^(j{LqFg!xlw-BqxObR7w0D=dL+&`k*rNQSqPdU zxzJEAJuU%k$h3+5C=}hZ+%CIl~sm+z#h3dGxbX^ ze(WhaZn>%^UMZ8sYt4`r!+9iq5 zm=9^>`l^Tt@o$caoy<{wfNe6zUJcLxX*1kb`=fK#!9dZ!as-5F_#5I!hAsW-I2xe< zihC|TN>ytj{v_6(wb08lAwJHh*HlX6I{o|>J?roQ8n0UF0iajuE|{eucg z^%*HkSV$`xL1J2^j9sdPx4xY453SoU-@hY@O52mRazIe+rDmMctVrxL=*8(iC45c|4W%5$5+`^VOJ^PTQaPrg zx^pVtS7-gVN+$9^fwp3#=-1gFPp!sdz-!%Ev6clU)3^Q){f>$o#A`DR1%PabuT2R zQK*;4)3vGJK9W^yXQx}}F>1_Ej&Exn$DHwJSXR(ZSs60_pcgS=oh5KqHAVvsu0E)H z5sn%MoT`h32d2=xDEX3r0}Q!j=joiC0~>VtjBK*1>tmirR$Sh(Bf!8m_>ajnJ9>2v z-W)*Qs;f*klU^VB z(%(_CW*sULqBML+vR2Y2wjTy z+dmW=LE7=9bf(C)DG!ly;`qjVnu|<46BRtMiU&b92@-U5Ns=A54TYH+R^g=D#e&C1 zFLps9k_9F_Ui4xD$5^QTM}g*#DETW-dB|@Tle{C2WI%?Cu*q&ZLg+wmSdroet8Qr@b3c$5$TskFfgn<31NZXNh2$n zQRQ?x#0!}}4uRB00$pxfqPPW>IzaaR@vF20N-mK%YK8VUr=UaU{6=1{nQdWJEGBkJlstP%1RTG-I_{;+fCKQ(kB*KCwZ+0A6;-R|f@Wh{ zB@1~CCe1%`GFx>Pj39U0OwS@#BPM5KvaP%L<&=T{Z=WLdjwsptb(dW^2l&MaaI_)hrC(0M2<9EyQY=&2Wm%Xo~WjoVtpnjBZopJ zUqD2D%GIL;CyYb@<@c@3t<0tFCGuhRj!;C-pojS{!Mp#bud9xV>ihPf0xANc64KI0 zDKQ`j!;sS5CEXwmLo3~(bPhEP-Q6t=H3I`f2`DjuQX>tI-}kK->#g_RALp!l?mc^* z&)sXUb?@G1pU*~_`u!N+bL45#smcBf?#hcWw%HU-bNriwowyc=r6FAj1GMGsV&KmGHi$bV_kmx+Mlb%abZbC!EU~a1KLUEu2~Ib z`#oIv;Ij+oh|5=;&M=y)ofXtW9MyXfCgpKd>Z_7Gt z{5XKQ+k3^Xl)ITT&63Mghro8wig1fn~4K- zT31Bhv5+tch;2KAenmFXE`D+yi#`#lkYR1i6_YSW(9JQWWL|X)8h#jqGZ$1bHjvs_ zSc3#fS3fLHfU6+Y`lVOVltwJ5QGEc~oLmxAeoc#REVdX7b!E__>`gxYg}+OkBkC-$ zD!v6Gr?%txY|qz(1_*lw%W*e)e$oa_gT)m1loh5&dj!MZ^g-WR2*qv8?HGN zTWKsFW0q$Eno%<0BGG&KJCS;+o{w4Z51Gm-++jD5f? zP{G}3Snt>%OKu!tYjiDY#{o@``{xCWYvo!!cTYqe+Di?xM>sm?qtz^5uoUU;Kh75E zDNN1GF3^*p0X#d83Jo=m*%1l%RA%MrZ{zX9>z1J_FxXMn`q83MF)??R zptr8?IXBY@B!&=bpI`c-H;E9vsc%tEQ7ZzDQL;}pu0(EG7Rs@D=0{a@`l8+B?E%*0 zUm0>nh|2wa1(qRruFu>=*4 z@FqgUg}sC2I! z2{gx`@2(j?mbH|`dyPN%pry-U&QKP_zHL|-Ia|QZR~EO|`k~+N4qoHB1Z!=jq&>?& z>a+|TYF z_Gk9b)7lZ__1mxHMVR=?78_g}YV@LQb!av%pD)%i>O?d`6`hc_M~c>W2(d=(`dB6@ zOyu&CSzPVgdWP4H?od}eR3=4qq0}JOzm&wo(+Y3G;0uD z^cPJLDH)#(=l`%+NlaQMRb`Tt&>dP&;M1USN?z=RE!DU%in<5-s;y)T;qv^W)@|#Z zPo4)TT9v_2D|Bwl@Ln6Vy!4FxA~04}bTxKYL2t)F_orrN26BW`US9K^x$MlHW!Euw z5<4U|qJGN3}FQeaaELtxodIdh~O#-_Zo<3T|J8V9kC9@DZQix0MR$Z!sIYY>& z&t{g25~d`-JnO%hcu-1+^IlLkT%%01>vQvdUjc4#sR9l0f4LX`+qd#R@0}i^@?376 zZmtN4clp;zZ|XOyWPJ>OdtLRo za25pk!)R4Immo@GcWMlK@mz`Qri8H^d zC~jGhHpT(5RhV$@CoOgb{BWI@3g%P*>^`@uox3=w1DdFeMJ;7%u?@W|Pb(6j5_iez z<1{JsS6{MijBpuS;GWnxMF3L_42p7sk=?JcYaAIB$9>p^^JzG4#@A!tHN@x^Vdoy= z*8;`b!O`yM+v^O+YH^B*QGy6nj`jKYYpdep{u7cCC+0w#P$Z#j$@Ww|SuVxQ)<&nQKef(^t zJGGA;^@b3L|>=CO#2&u9)sLH^a!%Z`+3>!`6z2zOc-SU{*x3?G;9=yuL0c4ytvrg z5YLG^-m>Z2X)X^~+m#njsFEMm<#RPn%FuhdPS6Jj<+61V_Ki+A?#K%B4ACCSQPkYg z6=?8Yy4pS>m{Ht$p^{*(toIjOXO4^c*X-_C(I<_qqjHVBM~Jj%%NqOQQ(B{bvZ6mS@6iS@-q>Qp34jG zily#;lP%iAV;alwx0x8r|!EA>|6iKW$K;N ziKC`liWgWLZu{<>Kws@ezWD(b9X4qv&pB#{lief3gn1V=CQ&Wq+z!-}!_gB>OH5$; zz5j3OjCSTw^W6ck7@2GM&Bum8^x#dq>nYi5`_qqBSxnZI3 zU&YCoy+eS}7fdqOyXQCX#T)N4QEVD3MiYtJ3_QMXUd~-yKz$~?kOxAtumIQl*-Sg2 zLG*Vl8;~G!^^NCN?DqbD?@DFmL)DRYb)RJ7AhPOA>=@ou;LpJ?z>OFJApODMm$Z1` zI$1ApgYz?x>42;^O?~!^FX(3{Y$)xV>HjCE`rn@V)95~Z&|2~1(Ubr4EOsCeOdH|* z=hE1IqOqI=Ahl;lhu9r;cx_bng_B38gR-tR$Q-tYs_~kbz&jqM;^_%sFq4GKE@`Ae-Q<9w60h;8Sj3*vFVlBA&&i8(Jj(6Yc zRd3erRrin|4mmq{luz+LF)p6cC3~dVFC`O}b>G^|2Ahsx&P|-|i%44Y>dexflDZ?r zmgp`YpAck2!*@x!M|Z!)Oc|8O6+_7~;~a}X1|-yoHRDb$T>dOq1FNDT)5Rtevq&`X z-BxtZs7YO}2dcJqj0QHPK153fj{l^t9s{bVTx1Wxg&kWN;@d-b3lWbt-cZ&KK;41U zZy%g9yk$&fj3Mu;@(CFbrFQ zV`og&Va2qhhI}$IgXErSu_=WlSu5iebBfsk&S7J+y~P5*eZ~i^!E|aDZMs~2UtZd( zi;0=}EV0&Qljzi55Xzsp+Joo}UFY+&R@XRFrW;MaD?}0>K4K0q&p=_>gGr z2jh{!tj{pTc(U#KVtrGj^Ij7mSm#dQa4odJ5O+bvO}HS|tK_eP4pqAyFltcR$k$3Q z5?%gP*N#+pL2)kS2rTYZ&&vKBvf?pCuBtKyQleFQ4}Ne?q&a|Vb$aQMEI|AvmPO9^ ztTuivR7PAWxvD&iZnAUs$Bf1sk^v&^1cq$`H~3vBvC-7GB(3fRALw=JdX_(h$pEhc zN#jR8d9GoIiPv6#Z;k=PR|}K)x?bU0QN&Mq@bWPqi735f(x(>G-Zw@6umu z26%}wKi3$2Q?vhZzDlGXGbHi5T-{1;UPg>d@!PaXe?Jb9py`V#0ZvgKG#o=3{?;lu z_s2`7Cl)brL;(&s({ZP_0oGB zCps=>ec>nXQ)xWcA|N+J2!Bz5o-Jc#3p*=3WfIZ8n3HPFCBDbrhwX}HDy2(SBi`3D zUfyn;r7BOm7ZFx;lqry02f*sQndYc0IX7o<;wl941|&GvW<~ldu(j2?oPfBLYm+qZ zsbEpvX%W<>xxm>0UOgbuN^L5ntE6vUU<5+q@k?y-0(l#ec11y<*DceE56388$q2iFC4^i} z&^J{((Ir#ZnH|CbZ61v98A_~P_grDQ!cMa|@nEm_7=QBn^T31{idumV5MsupMYPzK zsGWA#@-ly1DoqYDx{b0SKu zb)w_Co2G>GUQc~p9=rzI9)^T#a3{hQMXL$s8rg=YhoDfKFenA+!O}N5<)*AzrY8=C z3yyf90SlE`d_|IV3GkWMVSkl`N*f*TKNl>w<>PYsI%|)XeGm1i$U7vFuv;>TTW8*!X@@{X^V6dx!~xF{^*9VGtv@ke2m8(xlW;fk}G zfcuOiXZ_b5?YicTEI56jki_c_MU*7dwvt54!Q9X2*KQPh5W2+$TUkVmf@*^yWrvLe z&_-w^N7pkBT#^Q1bKJvUw}HJsBy9Z-*0%ZVYqfv7zZ|1#Xhk`E7?G^`_hfH?EK5^j zphS4lRsK_0w6tWauZ4R7;AQj>zVbm`3{@QqW$M%O{(wo}Rd-v8P^gF2-)l?5IfV5t z`r3Bkm%k~P%H(2noR_O#@-}P|OOixl4WNQ;zRSIVe2YcP8$1UMTnM{n;v~V-4;sD_)~P= z@muY5iBuFLcM%tx?jkC;e9+;)a=ZzL0_RFv_0UzBhZF)W0lL10p+T0J5&1Uwf5&%S zIoq99e7xh^erp%`mo5upRL7Hl`7N6wEodh*V>UQBt#WwNDfX3~9;n^BHm`pJ1I~H~ z+z2=z;=nzqwm_s9rYVrzDbRA-pYrTo+jiIx3a>Kys~Fvfd|ssqfVB8*F-X;cQIMOZ zFfc#2c}@%yP#HOHAE4fiMhw?MTq2)1TfP*WQgy~mk5sDt8Lh(a{}Yy}D$C7=Q9OkT z-4B>UeuDd}Tr*Go+UcS0qODl@h?D@nJW+(PO#?m9f-bPmsBL5H*K-jD>|FZ$-#3Uq z5u&hPR%KZ`K-Bd58VqBiOer{JGqiL|HXbk5;yUeA+I~CkW|0^{@}IsoPH?wSv$#j& z+?LO?;IXBXKJ7gCtL7e9h+@NCKC$g+<*@)xnoZ;-&KrAKqJM8Vu~ZUU`76$o#3-H? z?82dKTBJ$4;9?+uyr8#ry6WZlDI2BW!DG1`v4t#yBkPH7Y{tLlOwcx$_*awudM&~~ zUK+63GzksS6~_GO$Q}_@MwNKI+G$CpA;?+1fZq-d6>dCmXBKC+W4s9bT5SA%xKM>} zoY8d=?NtniHeY3P^DGhr3h}|hn5?RBvqdDJ*3n^9ed>IXeg&T9q%ETIhWc+}QIzd! zC$ro?qD@Y;-o=YIIvhJj{~`IksN-S3Hmam4%F0kN{>#MRYPmry(kki6Be;z8DSmpw==PJJncrNBlXLTxhxLHkDmd==E~vL@hHi z@OH#M=!SvLGuf=E@J`aJOiNh=1;`kKhS0@dNaT&Bl#<;oS=iM0(-!$W!E%+$XKRWj zoki>`E5vj=)$wb&7ZT7)@CkJJB`0o`4RSV8ztEcr{*_Fr9w?Y8Fb-rAsU@!0pFEzk2A RYX3D=UPeW_O7i39e**%x!3h8W diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 25060f8e749..8578dac65e3 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -122,7 +122,7 @@ prompts the user to sign in again through SSO. An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/297389) to add a similar SSO requirement for API activity. -SSO has the following effects when enabled: +SSO enforcement has the following effects when enabled: - For groups, users can't share a project in the group outside the top-level group, even if the project is forked. @@ -157,8 +157,8 @@ If you have any questions on configuring the SAML app, please contact your provi Follow the Azure documentation on [configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) with the notes below for consideration. -For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). The video is outdated in regard to -objectID mapping and the [SCIM documentation should be followed](scim_setup.md#azure-configuration-steps). +For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). +The video is outdated in regard to objectID mapping and you should follow the [SCIM documentation](scim_setup.md#configure-azure-active-directory). | GitLab Setting | Azure Field | | ------------------------------------ | ------------------------------------------ | @@ -168,7 +168,7 @@ objectID mapping and the [SCIM documentation should be followed](scim_setup.md#a | Identity provider single sign-on URL | Login URL | | Certificate fingerprint | Thumbprint | -The recommended attributes and claims settings are: +The recommended attributes are: - **Unique User Identifier (Name identifier)** set to `user.objectID`. - **nameid-format** set to persistent. diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index c5db06eefe1..dde054087cf 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -5,110 +5,129 @@ group: Authentication and Authorization 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 --- -# SCIM provisioning using SAML SSO for GitLab.com groups **(PREMIUM SAAS)** +# Configure SCIM for GitLab.com groups **(PREMIUM SAAS)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10. -System for Cross-domain Identity Management (SCIM), is an open standard that enables the -automation of user provisioning. When SCIM is provisioned for a GitLab group, membership of -that group is synchronized between GitLab and the identity provider. +You can use the open standard System for Cross-domain Identity Management (SCIM) to automatically: + +- Create users. +- Remove users (deactivate SCIM identity). + +GitLab SAML SSO SCIM doesn't support updating users. + +When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider. The GitLab [SCIM API](../../../api/scim.md) implements part of [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644). -## Features +## Configure GitLab -The following actions are available: +Prerequisites: -- Create users -- Remove users (deactivate SCIM identity) +- [Group single sign-on](index.md) must be configured. -The following identity providers are supported: - -- Azure -- Okta - -NOTE: -Other providers can work with GitLab but they have not been tested and are not supported. - -## Requirements - -- [Group Single Sign-On](index.md) must be configured. - -## GitLab configuration - -Once [Group Single Sign-On](index.md) has been configured, we can: +To configure GitLab SAML SSO SCIM: 1. On the top bar, select **Menu > Groups** and find your group. 1. On the left sidebar, select **Settings > SAML SSO**. 1. Select **Generate a SCIM token**. -1. Save the token and URL for use in the next step. +1. For configuration of your identity provider, save the: + - Token from the **Your SCIM token** field. + - URL from the **SCIM API endpoint URL** field. -![SCIM token configuration](img/scim_token_v13_3.png) +## Configure an identity provider -## Identity Provider configuration +You can configure one of the following as an identity provider: -- [Azure](#azure-configuration-steps) -- [Okta](#okta-configuration-steps) +- [Azure Active Directory](#configure-azure-active-directory). +- [Okta](#configure-okta). +- [OneLogin](#configure-onelogin). -### Azure configuration steps +NOTE: +Other providers can work with GitLab but they have not been tested and are not supported. -The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM. You can refer to [Azure SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#getting-started). +### Configure Azure Active Directory -1. In your app, go to the Provisioning tab, and set the **Provisioning Mode** to **Automatic**. - Then fill in the **Admin Credentials**, and save. The **Tenant URL** and **secret token** are the items - retrieved in the [previous step](#gitlab-configuration). +The SAML application created during [single sign-on](index.md) set up for +[Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) +must be set up for SCIM. For an example, see [example configuration](example_saml_config.md#scim-mapping). -1. After saving, two more tabs appear: +To configure Azure Active Directory for SCIM: - - **Settings**: We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox. - You also control what is actually synced by selecting the **Scope**. For example, **Sync only assigned users and groups** only syncs the users and groups assigned to the application. Otherwise, it syncs the whole Active Directory. +1. In your app, go to the **Provisioning** tab and select **Get started**. +1. Set the **Provisioning Mode** to **Automatic**. +1. Complete the **Admin Credentials** using the value of: + - **SCIM API endpoint URL** in GitLab for the **Tenant URL** field. + - **Your SCIM token** in GitLab for the **Secret Token** field. +1. Select **Test Connection**. If the test is successful, save your configuration before continuing, or see the + [troubleshooting](#troubleshooting) information. +1. Select **Save**. - - **Mappings**: We recommend keeping **Provision Azure Active Directory Users** enabled, and disable **Provision Azure Active Directory Groups**. - Leaving **Provision Azure Active Directory Groups** enabled does not break the SCIM user provisioning, but it causes errors in Azure AD that may be confusing and misleading. +After saving, **Settings** and **Mappings** sections appear. -1. You can then test the connection by selecting **Test Connection**. If the connection is successful, save your configuration before moving on. See below for [troubleshooting](#troubleshooting). - -#### Configure attribute mapping - -Follow [Azure documentation to configure the attribute mapping](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes). - -The following table below provides an attribute mapping known to work with GitLab. If -your SAML configuration differs from [the recommended SAML settings](index.md#azure-setup-notes), -modify the corresponding `customappsso` settings accordingly. In particular, the `externalId` must -match the [SAML NameID](index.md#nameid). -If a mapping is not listed in the table, use the Azure defaults. -For a list of required attributes, refer to the [SCIM API documentation](../../../api/scim.md). - -| Azure Active Directory Attribute | `customappsso` Attribute | Matching precedence | -| -------------------------------- | ------------------------------ | ------------------- | -| `objectId` | `externalId` | 1 | -| `userPrincipalName` | `emails[type eq "work"].value` | | -| `mailNickname` | `userName` | | - -For guidance, you can view [an example configuration](example_saml_config.md#azure-active-directory). - -1. Below the mapping list select **Show advanced options > Edit attribute list for AppName**. -1. Ensure the `id` is the primary and required field, and `externalId` is also required. - - NOTE: - `username` should neither be primary nor required as we don't support - that field on GitLab SCIM yet. - -1. Save all changes. -1. In the **Provisioning** step, set the `Provisioning Status` to `On`. - -Once enabled, the synchronization details and any errors appears on the -bottom of the **Provisioning** screen, together with a link to the audit events. +1. Under **Settings**, if required, set a notification email and select the + **Send an email notification when a failure occurs** checkbox. +1. Under **Mappings**, we recommend you: + 1. Keep **Provision Azure Active Directory Users** enabled and select the **Provision Azure Active Directory Users** + link to [configure attribute mappings](#configure-attribute-mappings). + 1. Below the mapping list select the **Show advanced options** checkbox. + 1. Select the **Edit attribute list for customappsso** link. + 1. Ensure the `id` is the primary and required field, and `externalId` is also required. + 1. Select **Save**. +1. Return to the **Provisioning** tab, saving unsaved changes if necessary. +1. Select **Edit attribute mappings**. +1. Under **Mappings**: + 1. Select **Provision Azure Active Directory Groups**. + 1. On the Attribute Mapping page, turn off the **Enabled** toggle. Leaving it turned on doesn't break the SCIM user + provisioning, but it causes errors in Azure Active Directory that may be confusing and misleading. + 1. Select **Save**. +1. Return to the **Provisioning** tab, saving unsaved changes if necessary. +1. Select **Edit attribute mappings**. +1. Turn on the **Provisioning Status** toggle. Synchronization details and any errors appears on the bottom of the + **Provisioning** screen, together with a link to the audit events. WARNING: -Once synchronized, changing the field mapped to `id` and `externalId` may cause a number of errors. These include provisioning errors, duplicate users, and may prevent existing users from accessing the GitLab group. +Once synchronized, changing the field mapped to `id` and `externalId` may cause a number of errors. These include +provisioning errors, duplicate users, and may prevent existing users from accessing the GitLab group. -### Okta configuration steps +#### Configure attribute mappings + +While [configuring Azure Active Directory for SCIM](#configure-azure-active-directory), you configure attribute mappings. +For an example, see [example configuration](example_saml_config.md#scim-mapping). + +The following table provides attribute mappings known to work with GitLab. + +| Source attribute | Target attribute | Matching precedence | +|:--------------------|:-------------------------------|:--------------------| +| `objectId` | `externalId` | 1 | +| `userPrincipalName` | `emails[type eq "work"].value` | | +| `mailNickname` | `userName` | | + +Each attribute mapping has: + +- An Azure Active Directory attribute (source attribute). +- A `customappsso` attribute (target attribute). +- A matching precedence. + +For each attribute: + +1. Select the attribute to edit it. +1. Select the required settings. +1. Select **Ok**. + +If your SAML configuration differs from [the recommended SAML settings](index.md#azure-setup-notes), select the mapping +attributes and modify them accordingly. In particular, the `objectId` source attribute must map to the `externalId` +target attribute. + +If a mapping is not listed in the table, use the Azure Active Directory defaults. For a list of required attributes, +refer to the [SCIM API documentation](../../../api/scim.md). + +### Configure Okta Before you start this section: - Check that you are using Okta [Lifecycle Management](https://www.okta.com/products/lifecycle-management/) product. This product tier is required to use SCIM on Okta. To check which Okta product you are using, check your signed Okta contract, contact your Okta AE, CSM, or Okta support. -- Complete the [GitLab configuration](#gitlab-configuration) process. +- Complete the [GitLab configuration](#configure-gitlab) process. - Complete the setup for SAML application for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/main/), as described in the [Okta setup notes](index.md#okta-setup-notes). - Check that your Okta SAML setup matches our documentation exactly, especially the NameID configuration. Otherwise, the Okta SCIM app may not work properly. @@ -140,7 +159,7 @@ The Okta GitLab application currently only supports SCIM. Continue using the separate Okta [SAML SSO](index.md) configuration along with the new SCIM application described above. An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/216173) to add SAML support to the Okta GitLab application. -### OneLogin +### Configure OneLogin As the developers of this app, OneLogin provides a "GitLab (SaaS)" app in their catalog, which includes a SCIM integration. Please reach out to OneLogin if you encounter issues. @@ -317,4 +336,4 @@ and the error response can include a HTML result of the GitLab URL `https://gitl This error is harmless and occurs because Group provisioning was turned on but GitLab SCIM integration does not support it nor require it. To remove the error, follow the instructions in the Azure configuration guide to disable the option -[`Synchronize Azure Active Directory Groups to AppName`](#azure-configuration-steps). +[`Synchronize Azure Active Directory Groups to AppName`](#configure-azure-active-directory). diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md index 6e532a6c14f..b2586383b43 100644 --- a/doc/user/project/integrations/hangouts_chat.md +++ b/doc/user/project/integrations/hangouts_chat.md @@ -10,7 +10,7 @@ Integrate your project to send notifications from GitLab to a room of your choice in [Google Chat](https://chat.google.com/) (former Google Hangouts). -## How it works +## Integration workflow To enable this integration, first you need to create a webhook for the room in Google Chat where you want to receive the notifications from your project. @@ -23,9 +23,9 @@ notifications to Google Chat: ![Google Chat integration illustration](img/google_chat_integration_v13_11.png) -## In Google Chat +## Enable the integration in Google Chat -Select a room and create a webhook: +To enable the integration in Google Chat: 1. Enter the room where you want to receive notifications from GitLab. 1. Open the room dropdown menu on the top-left and select **Manage webhooks**. @@ -36,20 +36,6 @@ Select a room and create a webhook: For further details, see [the Google Chat documentation for configuring webhooks](https://developers.google.com/chat/how-tos/webhooks). -## In GitLab - -Enable the Google Chat integration in GitLab: - -1. In your project, go to **Settings > Integrations** and select **Google Chat**. -1. Scroll down to the end of the page where you find a **Webhook** field. -1. Enter the webhook URL you copied from Google Chat. -1. Select the events you want to be notified about in your Google Chat room. -1. Optional. Select **Test settings** to verify the connection. -1. Select **Save changes**. - -To test the integration, make a change based on the events you selected and -see the notification in your Google Chat room. - ### Enable threads in Google Chat > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27823) in GitLab 15.4. @@ -62,3 +48,17 @@ To enable threaded notifications for the same GitLab object (for example, an iss 1. Select **Create**. You cannot enable threaded replies for existing Google Chat spaces. + +## Enable the integration in GitLab + +To enable the integration in GitLab: + +1. In your project, go to **Settings > Integrations** and select **Google Chat**. +1. Scroll down to the end of the page where you find a **Webhook** field. +1. Enter the webhook URL you copied from Google Chat. +1. Select the events you want to be notified about in your Google Chat room. +1. Optional. Select **Test settings** to verify the connection. +1. Select **Save changes**. + +To test the integration, make a change based on the events you selected and +see the notification in your Google Chat room. diff --git a/lib/api/branches.rb b/lib/api/branches.rb index 90db81cea1d..5588818cbaf 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -52,13 +52,19 @@ module API merged_branch_names = repository.merged_branch_names(branches.map(&:name)) + expiry_time = if Feature.enabled?(:increase_branch_cache_expiry, type: :ops) + 60.minutes + else + 10.minutes + end + present_cached( branches, with: Entities::Branch, current_user: current_user, project: user_project, merged_branch_names: merged_branch_names, - expires_in: 10.minutes, + expires_in: expiry_time, cache_context: -> (branch) { [current_user&.cache_key, merged_branch_names.include?(branch.name)] } ) end diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb index 29e93dd3eb4..8e28588a7b5 100644 --- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb +++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb @@ -21,7 +21,6 @@ module Gitlab CATEGORIES_FOR_TOTALS = %w[ analytics compliance - ecosystem epic_boards_usage epics_usage error_tracking @@ -36,6 +35,7 @@ module Gitlab ci_users deploy_token_packages code_review + ecosystem error_tracking ide_edit importer diff --git a/lib/gitlab/usage_data_counters/known_events/ecosystem.yml b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml index f594c6a1b7c..7f7c9166086 100644 --- a/lib/gitlab/usage_data_counters/known_events/ecosystem.yml +++ b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml @@ -8,14 +8,6 @@ category: ecosystem redis_slot: ecosystem aggregation: weekly -- name: i_ecosystem_jira_service_list_issues - category: ecosystem - redis_slot: ecosystem - aggregation: weekly -- name: i_ecosystem_jira_service_create_issue - category: ecosystem - redis_slot: ecosystem - aggregation: weekly - name: i_ecosystem_slack_service_issue_notification category: ecosystem redis_slot: ecosystem diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0742b7bba2b..d88d610b7f9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -46000,6 +46000,9 @@ msgstr "" msgid "cannot be changed if shared runners are enabled" msgstr "" +msgid "cannot be changed since member is associated with a custom role" +msgstr "" + msgid "cannot be enabled" msgstr "" diff --git a/package.json b/package.json index 286a6a72d28..7ae17f15fea 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "codesandbox-api": "0.0.23", "compression-webpack-plugin": "^5.0.2", "copy-webpack-plugin": "^6.4.1", - "core-js": "^3.25.0", + "core-js": "^3.25.1", "cron-validator": "^1.1.1", "cronstrue": "^1.122.0", "cropper": "^2.3.0", @@ -245,7 +245,7 @@ "sass": "^1.49.9", "stylelint": "^14.9.1", "timezone-mock": "^1.0.8", - "webpack-dev-server": "4.10.1", + "webpack-dev-server": "4.11.0", "xhr-mock": "^2.5.1", "yarn-check-webpack-plugin": "^1.2.0", "yarn-deduplicate": "^6.0.0" diff --git a/scripts/trigger-build.rb b/scripts/trigger-build.rb index b2bf2d5c680..b368bbdb1f1 100755 --- a/scripts/trigger-build.rb +++ b/scripts/trigger-build.rb @@ -159,44 +159,6 @@ module Trigger end end - class Omnibus < Base - def self.access_token - # Default to "Multi-pipeline (from 'gitlab-org/gitlab' 'e2e:package-and-test' job)" at https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/settings/access_tokens - ENV['OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN'] || super - end - - private - - def downstream_project_path - ENV.fetch('OMNIBUS_PROJECT_PATH', 'gitlab-org/build/omnibus-gitlab-mirror') - end - - def ref_param_name - 'OMNIBUS_BRANCH' - end - - def primary_ref - 'master' - end - - def trigger_stable_branch_if_detected? - true - end - - def extra_variables - { - 'GITLAB_VERSION' => ENV['CI_COMMIT_SHA'], - 'IMAGE_TAG' => ENV['CI_COMMIT_SHA'], - 'SKIP_QA_DOCKER' => 'true', - 'SKIP_QA_TEST' => 'true', - 'ALTERNATIVE_SOURCES' => 'true', - 'SECURITY_SOURCES' => Trigger.security? ? 'true' : 'false', - 'ee' => Trigger.ee? ? 'true' : 'false', - 'CACHE_UPDATE' => ENV['OMNIBUS_GITLAB_CACHE_UPDATE'] - } - end - end - class CNG < Base def variables # Delete variables that aren't useful when using native triggers. @@ -467,8 +429,6 @@ end if $0 == __FILE__ case ARGV[0] - when 'omnibus' - Trigger::Omnibus.new.invoke!(downstream_job_name: 'Trigger:qa-test').wait! when 'cng' Trigger::CNG.new.invoke!.wait! when 'gitlab-com-database-testing' diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 2716244b7f3..fbf510a419f 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -195,6 +195,15 @@ RSpec.describe Member do expect(member).not_to be_valid end end + + context 'access_level cannot be changed' do + it 'is invalid' do + member.access_level = Gitlab::Access::MAINTAINER + + expect(member).not_to be_valid + expect(member.errors.full_messages).to include( "Access level cannot be changed since member is associated with a custom role") + end + end end end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index 2c0f6943243..f7539e13b80 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -211,6 +211,68 @@ RSpec.describe API::Branches do end it_behaves_like 'repository branches' + + context 'caching' do + it 'caches the query' do + get api(route), params: { per_page: 1 } + + expect(API::Entities::Branch).not_to receive(:represent) + + get api(route), params: { per_page: 1 } + end + + context 'when increase_branch_cache_expiry is enabled' do + it 'uses the cache up to 60 minutes' do + time_of_request = Time.current + + get api(route), params: { per_page: 1 } + + travel_to time_of_request + 59.minutes do + expect(API::Entities::Branch).not_to receive(:represent) + + get api(route), params: { per_page: 1 } + end + end + + it 'requests for new value after 60 minutes' do + get api(route), params: { per_page: 1 } + + travel_to 61.minutes.from_now do + expect(API::Entities::Branch).to receive(:represent) + + get api(route), params: { per_page: 1 } + end + end + end + + context 'when increase_branch_cache_expiry is disabled' do + before do + stub_feature_flags(increase_branch_cache_expiry: false) + end + + it 'uses the cache up to 10 minutes' do + time_of_request = Time.current + + get api(route), params: { per_page: 1 } + + travel_to time_of_request + 9.minutes do + expect(API::Entities::Branch).not_to receive(:represent) + + get api(route), params: { per_page: 1 } + end + end + + it 'requests for new value after 10 minutes' do + get api(route), params: { per_page: 1 } + + travel_to 11.minutes.from_now do + expect(API::Entities::Branch).to receive(:represent) + + get api(route), params: { per_page: 1 } + end + end + end + end end context 'when unauthenticated', 'and project is private' do diff --git a/spec/scripts/trigger-build_spec.rb b/spec/scripts/trigger-build_spec.rb index 9c2033bf493..46023d5823d 100644 --- a/spec/scripts/trigger-build_spec.rb +++ b/spec/scripts/trigger-build_spec.rb @@ -244,156 +244,6 @@ RSpec.describe Trigger do end end - describe Trigger::Omnibus do - describe '#variables' do - it 'invokes the trigger with expected variables' do - expect(subject.variables).to include( - 'SKIP_QA_TEST' => 'true', - 'SKIP_QA_DOCKER' => 'true', - 'ALTERNATIVE_SOURCES' => 'true', - 'CACHE_UPDATE' => env['OMNIBUS_GITLAB_CACHE_UPDATE'] - ) - end - - context 'when CI_COMMIT_SHA is set' do - before do - stub_env('CI_COMMIT_SHA', 'ci_commit_sha') - end - - it 'sets GITLAB_VERSION & IMAGE_TAG to ci_commit_sha' do - expect(subject.variables).to include( - 'GITLAB_VERSION' => 'ci_commit_sha', - 'IMAGE_TAG' => 'ci_commit_sha' - ) - end - end - - context 'when Trigger.security? is true' do - before do - allow(Trigger).to receive(:security?).and_return(true) - end - - it 'sets SECURITY_SOURCES to true' do - expect(subject.variables['SECURITY_SOURCES']).to eq('true') - end - end - - context 'when Trigger.security? is false' do - before do - allow(Trigger).to receive(:security?).and_return(false) - end - - it 'sets SECURITY_SOURCES to false' do - expect(subject.variables['SECURITY_SOURCES']).to eq('false') - end - end - - context 'when Trigger.ee? is true' do - before do - allow(Trigger).to receive(:ee?).and_return(true) - end - - it 'sets ee to true' do - expect(subject.variables['ee']).to eq('true') - end - end - - context 'when Trigger.ee? is false' do - before do - allow(Trigger).to receive(:ee?).and_return(false) - end - - it 'sets ee to false' do - expect(subject.variables['ee']).to eq('false') - end - end - end - - describe '.access_token' do - context 'when OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN is set' do - let(:omnibus_gitlab_project_access_token) { 'omnibus_gitlab_project_access_token' } - - before do - stub_env('OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN', omnibus_gitlab_project_access_token) - end - - it 'returns the omnibus-specific access token' do - expect(described_class.access_token).to eq(omnibus_gitlab_project_access_token) - end - end - - context 'when OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN is not set' do - before do - stub_env('OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN', nil) - end - - it 'returns the default access token' do - expect(described_class.access_token).to eq(Trigger::Base.access_token) - end - end - end - - describe '#invoke!' do - let(:downstream_project_path) { 'gitlab-org/build/omnibus-gitlab-mirror' } - let(:ref) { 'master' } - - let(:env) do - super().merge( - 'QA_IMAGE' => 'qa_image', - 'GITLAB_QA_OPTIONS' => 'gitlab_qa_options', - 'QA_TESTS' => 'qa_tests', - 'ALLURE_JOB_NAME' => 'allure_job_name' - ) - end - - describe '#downstream_project_path' do - context 'when OMNIBUS_PROJECT_PATH is set' do - let(:downstream_project_path) { 'omnibus_project_path' } - - before do - stub_env('OMNIBUS_PROJECT_PATH', downstream_project_path) - end - - it 'triggers the pipeline on the correct project' do - expect_run_trigger_with_params - - subject.invoke! - end - end - end - - describe '#ref' do - context 'when OMNIBUS_BRANCH is set' do - let(:ref) { 'omnibus_branch' } - - before do - stub_env('OMNIBUS_BRANCH', ref) - end - - it 'triggers the pipeline on the correct ref' do - expect_run_trigger_with_params - - subject.invoke! - end - end - end - - context 'when CI_COMMIT_REF_NAME is a stable branch' do - let(:ref) { '14-10-stable' } - - before do - stub_env('CI_COMMIT_REF_NAME', "#{ref}-ee") - end - - it 'triggers the pipeline on the correct ref' do - expect_run_trigger_with_params - - subject.invoke! - end - end - end - end - describe Trigger::CNG do describe '#variables' do it 'does not include redundant variables' do diff --git a/yarn.lock b/yarn.lock index 954169a5f33..0aa2aaef360 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3760,10 +3760,10 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== -core-js@^3.25.0: - version "3.25.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.0.tgz#be71d9e0dd648ffd70c44a7ec2319d039357eceb" - integrity sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA== +core-js@^3.25.1: + version "3.25.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.1.tgz#5818e09de0db8956e16bf10e2a7141e931b7c69c" + integrity sha512-sr0FY4lnO1hkQ4gLDr24K0DGnweGO1QwSj5BpfQjpSJPdqWalja4cTps29Y/PJVG/P7FYlPDkH3hO+Tr0CvDgQ== core-util-is@~1.0.0: version "1.0.3" @@ -12114,10 +12114,10 @@ webpack-dev-middleware@^5.3.1: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@4.10.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz#124ac9ac261e75303d74d95ab6712b4aec3e12ed" - integrity sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw== +webpack-dev-server@4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.0.tgz#290ee594765cd8260adfe83b2d18115ea04484e7" + integrity sha512-L5S4Q2zT57SK7tazgzjMiSMBdsw+rGYIX27MgPgx7LDhWO0lViPrHKoLS7jo5In06PWYAhlYu3PbyoC6yAThbw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5"