Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-04 03:09:16 +00:00
parent 78d059aba9
commit 83315ad1b3
20 changed files with 306 additions and 186 deletions

View File

@ -1553,6 +1553,10 @@ class MergeRequest < ApplicationRecord
%r{\Arefs/#{Repository::REF_MERGE_REQUEST}/\d+/train\z}o.match?(ref)
end
def train
MergeTrains::Train.new(target_project.id, target_branch)
end
def in_locked_state
lock_mr
yield

View File

@ -757,8 +757,8 @@ For more information, see the [GitLab API user method documentation](https://pyt
You can configure OIDC group membership to:
- Require users to be members of a certain group.
- Assign users [external roles](../../user/admin_area/external_users.md), or as
administrators based on group membership.
- Assign users [external](../../user/admin_area/external_users.md), administrator or
[auditor](../auditor_users.md) roles based on group membership.
GitLab checks these groups on each sign in and updates user attributes as necessary.
This feature **does not** allow you to automatically add users to GitLab
@ -921,6 +921,83 @@ For self-compiled installations:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#installations-from-source)
for the changes to take effect.
### Auditor groups **(PREMIUM SELF)**
Your IdP must pass group information to GitLab in the OIDC response. To use this
response to assign users as auditors based on group membership, configure GitLab to identify:
- Where to look for the groups in the OIDC response, using the `groups_attribute` setting.
- Which group memberships grant the user auditor access, using the `auditor_groups`
setting.
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "openid_connect",
label: "Provider name",
args: {
name: "openid_connect",
scope: ["openid","profile","email","groups"],
response_type: "code",
issuer: "<your_oidc_url>",
discovery: true,
client_auth_method: "query",
uid_field: "<uid_field>",
client_options: {
identifier: "<your_oidc_client_id>",
secret: "<your_oidc_client_secret>",
redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback",
gitlab: {
groups_attribute: "groups",
auditor_groups: ["Auditor"]
}
}
}
}
]
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation)
for the changes to take effect.
For self-compiled installations:
1. Edit `/home/git/gitlab/config/gitlab.yml`:
```yaml
production: &base
omniauth:
providers:
- { name: 'openid_connect',
label: 'Provider name',
args: {
name: 'openid_connect',
scope: ['openid','profile','email','groups'],
response_type: 'code',
issuer: '<your_oidc_url>',
discovery: true,
client_auth_method: 'query',
uid_field: '<uid_field>',
client_options: {
identifier: '<your_oidc_client_id>',
secret: '<your_oidc_client_secret>',
redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback',
gitlab: {
groups_attribute: "groups",
auditor_groups: ["Auditor"]
}
}
}
}
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#installations-from-source)
for the changes to take effect.
### Administrator groups
Your IdP must pass group information to GitLab in the OIDC response. To use this

View File

@ -165,7 +165,8 @@ require `Administrator` to approve every deployment job in `Production`.
### Allow self-approval **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381418) in GitLab 15.8.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381418) in GitLab 15.8.
> - Automatic approval [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124638) in GitLab 16.2 due to [usability issues](https://gitlab.com/gitlab-org/gitlab/-/issues/391258).
By default, the user who triggers a deployment pipeline can't also approve the deployment job.
To allow self-approval of a deployment job:
@ -175,9 +176,6 @@ To allow self-approval of a deployment job:
1. Expand **Protected environments**.
1. From the **Approval options**, select the **Allow pipeline triggerer to approve deployment** checkbox.
When a pipeline runs, deployment jobs are automatically approved in the pipeline if the user who
triggered the deployment is allowed to approve.
## Approve or reject a deployment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342180/) in GitLab 14.9

View File

@ -212,6 +212,75 @@ For authentication CI/CD variables, see [Authentication](authentication.md).
| `DAST_WEBSITE` | URL | `https://example.com` | The URL of the website to scan. |
| `SECURE_ANALYZERS_PREFIX` | URL | `registry.organization.com` | Set the Docker registry base address from which to download the analyzer. |
## Managing scope
Scope controls what URLs DAST follows when crawling the target application. Properly managed scope minimizes scan run time while ensuring only the target application is checked for vulnerabilities.
### Types of scope
There are three types of scope:
- in scope
- out of scope
- excluded from scope
#### In scope
DAST follows in-scope URLs and searches the DOM for subsequent actions to perform to continue the crawl.
Recorded in-scope HTTP messages are passively checked for vulnerabilities and used to build attacks when running a full scan.
#### Out of scope
DAST follows out-of-scope URLs for non-document content types such as image, stylesheet, font, script, or AJAX request.
[Authentication](#scope-works-differently-during-authentication) aside, DAST does not follow out-of-scope URLs for full page loads, such as when clicking a link to an external website.
Except for passive checks that search for information leaks, recorded HTTP messages for out-of-scope URLs are not checked for vulnerabilities.
#### Excluded from scope
DAST does not follow excluded-from-scope URLs. Except for passive checks that search for information leaks, recorded HTTP messages for excluded-from-scope URLs are not checked for vulnerabilities.
### Scope works differently during authentication
Many target applications have an authentication process that depends on external websites, such as when using an identity access management provider for single sign on (SSO).
To ensure that DAST can authenticate with these providers, DAST follows out-of-scope URLs for full page loads during authentication. DAST does not follow excluded-from-scope URLs.
### How DAST blocks HTTP requests
DAST instructs the browser to make the HTTP request as usual when blocking a request due to scope rules. The request is subsequently intercepted and rejected with the reason `BlockedByClient`.
This approach allows DAST to record the HTTP request while ensuring it never reaches the target server. Passive checks such as [200.1](checks/200.1.md) use these recorded requests to verify information sent to external hosts.
### How to configure scope
By default, URLs matching the host of the target application are considered in-scope. All other hosts are considered out-of-scope.
Scope is configured using the following variables:
- Use `DAST_BROWSER_ALLOWED_HOSTS` to add in-scope hosts.
- Use `DAST_BROWSER_IGNORED_HOSTS` to add to out-of-scope hosts.
- Use `DAST_BROWSER_EXCLUDED_HOSTS` to add to excluded-from-scope hosts.
- Use `DAST_EXCLUDE_URLS` to set specific URLs to be excluded-from-scope.
Rules:
- Excluding a host is given priority over ignoring a host, which is given priority over allowing a host.
- Configuring scope for a host does not configure scope for the subdomains of that host.
- Configuring scope for a host does not configure scope for all ports on that host.
The following could be a typical configuration:
```yaml
include:
- template: DAST.gitlab-ci.yml
dast:
variables:
DAST_WEBSITE: "https://my.site.com" # my.site.com URLs are considered in-scope by default
DAST_BROWSER_ALLOWED_HOSTS: "api.site.com:8443" # include the API as part of the scan
DAST_BROWSER_IGNORED_HOSTS: "analytics.site.com" # explicitly disregard analytics from the scan
DAST_BROWSER_EXCLUDED_HOSTS: "ads.site.com" # don't visit any URLs on the ads subdomain
DAST_EXCLUDE_URLS: "https://my.site.com/user/logout" # don't visit this URL
```
## Vulnerability detection
Vulnerability detection is gradually being migrated from the default Zed Attack Proxy (ZAP) solution

View File

@ -15527,9 +15527,6 @@ msgstr ""
msgid "DeploymentApprovals|Set how approval rules are applied to deployments in protected environments."
msgstr ""
msgid "DeploymentApprovals|When a pipeline runs, deployment jobs will automatically be approved in the pipeline if the triggerer is allowed to approve."
msgstr ""
msgid "DeploymentApproval| Current approvals: %{current}"
msgstr ""

View File

@ -0,0 +1,51 @@
plugins {
id 'java'
id 'maven-publish'
id 'application'
}
repositories {
maven {
url "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
name = '<%= maven_header_name %>'
value = project.property('Token')
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
dependencies {
implementation group: '<%= group_id %>', name: '<%= artifact_id %>', version: '<%= package_version %>'
testImplementation 'junit:junit:4.12'
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId '<%= group_id %>'
artifactId '<%= artifact_id %>'
version '<%= package_version %>'
from components.java
}
}
repositories {
maven {
url "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/maven"
credentials(HttpHeaderCredentials) {
name = '<%= maven_header_name %>'
value = project.property('Token')
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
application {
mainClassName = 'gradle_maven_app.App'
}

View File

@ -1,27 +0,0 @@
plugins {
id 'java'
id 'application'
}
repositories {
maven {
url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
name = '<%= maven_header_name %>'
value = <%= token %>
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
dependencies {
implementation group: '<%= group_id %>', name: '<%= artifact_id %>', version: '<%= package_version %>'
testImplementation 'junit:junit:4.12'
}
application {
mainClassName = 'gradle_maven_app.App'
}

View File

@ -1,27 +0,0 @@
plugins {
id 'java'
id 'maven-publish'
}
publishing {
publications {
library(MavenPublication) {
groupId '<%= group_id %>'
artifactId '<%= artifact_id %>'
version '<%= package_version %>'
from components.java
}
}
repositories {
maven {
url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven"
credentials(HttpHeaderCredentials) {
name = "Private-Token"
value = "<%= personal_access_token %>"
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}

View File

@ -1,8 +0,0 @@
build:
image: gradle:6.5-jdk11
script:
- 'gradle build'
only:
- "<%= client_project.default_branch %>"
tags:
- "runner-for-<%= client_project.group.name %>"

View File

@ -0,0 +1,23 @@
stages:
- publish
- install
publish:
stage: publish
image: gradle:6.5-jdk11
script:
- 'gradle -PToken=<%= token %> publish'
only:
- "<%= project.default_branch %>"
tags:
- "runner-for-<%= project.name %>"
install:
stage: install
image: gradle:6.5-jdk11
script:
- 'gradle -PToken=<%= token %> build'
only:
- "<%= project.default_branch %>"
tags:
- "runner-for-<%= project.name %>"

View File

@ -1,8 +0,0 @@
deploy:
image: gradle:6.5-jdk11
script:
- 'gradle publish'
only:
- "<%= package_project.default_branch %>"
tags:
- "runner-for-<%= package_project.group.name %>"

View File

@ -1,8 +0,0 @@
install:
image: maven:3.6-jdk-11
script:
- "mvn install -U -s settings.xml"
only:
- "<%= imported_project.default_branch %>"
tags:
- "runner-for-<%= imported_project.group.name %>"

View File

@ -1,23 +0,0 @@
<settings>
<servers>
<server>
<id>central-proxy</id>
<configuration>
<httpHeaders>
<property>
<name>Private-Token</name>
<value><%= personal_access_token %></value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
<mirrors>
<mirror>
<id>central-proxy</id>
<name>GitLab proxy of central repo</name>
<url><%= gitlab_address_with_port %>/api/v4/groups/<%= imported_project.group.id %>/-/packages/maven</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>

View File

@ -1,8 +0,0 @@
install:
image: maven:3.6-jdk-11
script:
- 'mvn install -U -s settings.xml'
only:
- "<%= imported_project.default_branch %>"
tags:
- "runner-for-<%= imported_project.name %>"

View File

@ -1,23 +0,0 @@
<settings>
<servers>
<server>
<id>central-proxy</id>
<configuration>
<httpHeaders>
<property>
<name>Private-Token</name>
<value><%= personal_access_token %></value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
<mirrors>
<mirror>
<id>central-proxy</id>
<name>GitLab proxy of central repo</name>
<url><%= gitlab_address_with_port %>/api/v4/projects/<%= imported_project.id %>/packages/maven</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>

View File

@ -14,6 +14,6 @@ run:
install:
stage: install
script:
- "pip install <%= package.name %> --no-deps --index-url <%= uri.scheme %>://<%= personal_access_token %>:<%= personal_access_token %>@<%= gitlab_host_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host <%= gitlab_host_with_port %>"
- "pip install <%= package.name %> --no-deps --index-url <%= uri.scheme %>://${PERSONAL_ACCESS_TOKEN}:${PERSONAL_ACCESS_TOKEN}@<%= gitlab_host_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host <%= gitlab_host_with_port %>"
tags:
- runner-for-<%= project.name %>

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Package', :object_storage, :skip_live_env, except: { job: 'relative-url' } do
RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' } do
describe 'Maven project level endpoint', product_group: :package_registry do
include Runtime::Fixtures
include Support::Helpers::MaskToken

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Package', :object_storage, :skip_live_env, except: { job: 'relative-url' }, product_group: :package_registry do
RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do
describe 'Maven Repository with Gradle' do
using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
include_context 'packages registry qa scenario'
include Support::Helpers::MaskToken
let(:group_id) { 'com.gitlab.qa' }
let(:artifact_id) { "maven_gradle-#{SecureRandom.hex(8)}" }
@ -13,6 +13,52 @@ module QA
let(:package_version) { '1.3.7' }
let(:package_type) { 'maven_gradle' }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = "#{package_type}_project"
project.initialize_with_readme = true
project.visibility = :private
end
end
let(:runner) do
Resource::ProjectRunner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = ["runner-for-#{project.name}"]
runner.executor = :docker
runner.project = project
end
end
let(:gitlab_address_with_port) do
uri = URI.parse(Runtime::Scenario.gitlab_address)
"#{uri.scheme}://#{uri.host}:#{uri.port}"
end
let(:project_deploy_token) do
Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'package-deploy-token'
deploy_token.project = project
deploy_token.scopes = %w[
read_repository
read_package_registry
write_package_registry
]
end
end
let(:project_inbound_job_token_disabled) do
Resource::CICDSettings.fabricate_via_api! do |settings|
settings.project_path = project.full_path
settings.inbound_job_token_scope_enabled = false
end
end
before do
Flow::Login.sign_in_unless_signed_in
runner
end
where(:case_name, :authentication_token_type, :maven_header_name, :testcase) do
'using personal access token' | :personal_access_token | 'Private-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347601'
'using ci job token' | :ci_job_token | 'Job-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347603'
@ -23,38 +69,47 @@ module QA
let(:token) do
case authentication_token_type
when :personal_access_token
"\"#{personal_access_token}\""
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project)
when :ci_job_token
package_project_inbound_job_token_disabled
client_project_inbound_job_token_disabled
'System.getenv("CI_JOB_TOKEN")'
project_inbound_job_token_disabled
'${CI_JOB_TOKEN}'
when :project_deploy_token
"\"#{project_deploy_token.token}\""
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
end
end
it 'pushes and pulls a maven package via gradle', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_package.yaml.erb')).result(binding)
build_upload_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_upload.gradle.erb')).result(binding)
gradle_publish_install_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_install_package.yaml.erb')).result(binding)
build_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build.gradle.erb')).result(binding)
commit.project = package_project
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: gradle_upload_yaml },
{ file_path: 'build.gradle', content: build_upload_gradle }
{ file_path: '.gitlab-ci.yml', content: gradle_publish_install_yaml },
{ file_path: 'build.gradle', content: build_gradle }
])
end
end
package_project.visit!
project.visit!
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('deploy')
pipeline.click_job('publish')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 800)
job.click_element(:pipeline_path)
end
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('install')
end
Page::Project::Job::Show.perform do |job|
@ -72,33 +127,6 @@ module QA
Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package_name, package_version)
end
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
gradle_install_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_install_package.yaml.erb')).result(binding)
build_install_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_install.gradle.erb')).result(binding)
commit.project = client_project
commit.commit_message = 'Add files'
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: gradle_install_yaml },
{ file_path: 'build.gradle', content: build_install_gradle }
])
end
end
client_project.visit!
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('build')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 800)
end
end
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Package', :object_storage, :skip_live_env, except: { job: 'relative-url' }, product_group: :package_registry do
RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do
describe 'PyPI Repository' do
include Runtime::Fixtures
include Support::Helpers::MaskToken
@ -30,7 +30,11 @@ module QA
end
let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
let(:personal_access_token) { use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project) }
let!(:personal_access_token) do
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project)
end
let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
let(:gitlab_host_with_port) do
# Don't specify port if it is a standard one

View File

@ -9,6 +9,7 @@ module QA
ci_variable.project = project
ci_variable.key = name
ci_variable.value = value
ci_variable.masked = true
end
"${#{name}}"
end