summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-27 18:09:39 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-27 18:09:39 +0000
commit3e1f93c033ed7744696f7763716b51ab5acda17a (patch)
tree9208f71b8b7461a34560ac2b7f5d01f26b5cd80c
parentab421e159d39cf91a95f4a911821308d258e77d9 (diff)
downloadgitlab-ce-3e1f93c033ed7744696f7763716b51ab5acda17a.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue56
-rw-r--r--app/models/deployment.rb2
-rw-r--r--app/policies/project_policy.rb26
-rw-r--r--app/services/auth/container_registry_authentication_service.rb6
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml2
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml2
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml6
-rw-r--r--config/feature_flags/development/container_registry_legacy_authentication_for_deploy_tokens.yml8
-rw-r--r--db/post_migrate/20220620151740_add_indexes_issues_on_project_id_and_closed_at.rb9
-rw-r--r--doc/administration/packages/container_registry.md2
-rw-r--r--doc/user/application_security/policies/scan-execution-policies.md26
-rw-r--r--lib/api/maven_packages.rb4
-rw-r--r--qa/Dockerfile4
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js23
-rw-r--r--spec/models/deployment_spec.rb31
-rw-r--r--spec/policies/project_policy_spec.rb118
-rw-r--r--spec/requests/api/maven_packages_spec.rb40
-rw-r--r--spec/support/shared_contexts/project_features_shared_context.rb28
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb6
20 files changed, 308 insertions, 104 deletions
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index af0c1e9619e..0ba5465411d 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { GlSprintf, GlSafeHtmlDirective as SafeHtml, GlAvatarLink, GlAvatar } from '@gitlab/ui';
import $ from 'jquery';
import { escape, isEmpty } from 'lodash';
import { mapGetters, mapActions } from 'vuex';
@@ -11,7 +11,6 @@ import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import { __, s__, sprintf } from '~/locale';
-import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
@@ -31,11 +30,12 @@ export default {
name: 'NoteableNote',
components: {
GlSprintf,
- userAvatarLink,
noteHeader,
noteActions,
NoteBody,
TimelineEntryItem,
+ GlAvatarLink,
+ GlAvatar,
},
directives: {
SafeHtml,
@@ -196,13 +196,11 @@ export default {
return fileResolvedFromAvailableSource || null;
},
- avatarSize() {
- // Use a different size if shown on a Merge Request Diff
- if (this.line && !this.isOverviewTab) {
- return 24;
- }
-
- return 40;
+ isMRDiffView() {
+ return this.line && !this.isOverviewTab;
+ },
+ authorAvatarAdaptiveSize() {
+ return { default: 24, md: 32 };
},
},
created() {
@@ -428,19 +426,33 @@ export default {
</template>
</gl-sprintf>
</div>
- <div class="timeline-icon">
- <user-avatar-link
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="avatarSize"
- lazy
- >
- <template #avatar-badge>
- <slot name="avatar-badge"></slot>
- </template>
- </user-avatar-link>
+
+ <div v-if="isMRDiffView" class="gl-float-left gl-mt-n1 gl-mr-3">
+ <gl-avatar-link :href="author.path">
+ <gl-avatar
+ :src="author.avatar_url"
+ :entity-name="author.username"
+ :alt="author.name"
+ :size="24"
+ />
+
+ <slot name="avatar-badge"></slot>
+ </gl-avatar-link>
+ </div>
+
+ <div v-else class="gl-float-left gl-pl-3 gl-mr-3 gl-md-pl-2 gl-md-pr-2">
+ <gl-avatar-link :href="author.path">
+ <gl-avatar
+ :src="author.avatar_url"
+ :entity-name="author.username"
+ :alt="author.name"
+ :size="authorAvatarAdaptiveSize"
+ />
+
+ <slot name="avatar-badge"></slot>
+ </gl-avatar-link>
</div>
+
<div class="timeline-content">
<div class="note-header">
<note-header
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 64f284af43c..c25ba6f9268 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -185,7 +185,7 @@ class Deployment < ApplicationRecord
def self.last_deployment_group_for_environment(env)
return self.none unless env.last_deployment_pipeline&.latest_successful_builds&.present?
- BatchLoader.for(env).batch do |environments, loader|
+ BatchLoader.for(env).batch(default_value: self.none) do |environments, loader|
latest_successful_build_ids = []
environments_hash = {}
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 7aba5e93139..872470023eb 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -59,7 +59,13 @@ class ProjectPolicy < BasePolicy
desc "Container registry is disabled"
condition(:container_registry_disabled, scope: :subject) do
- !access_allowed_to?(:container_registry)
+ if user.is_a?(DeployToken)
+ (!user.read_registry? && !user.write_registry?) ||
+ user.revoked? ||
+ !project.container_registry_enabled?
+ else
+ !access_allowed_to?(:container_registry)
+ end
end
desc "Container registry is enabled for everyone with access to the project"
@@ -88,6 +94,16 @@ class ProjectPolicy < BasePolicy
user.is_a?(DeployKey) && user.can_push_to?(project)
end
+ desc "Deploy token with read_container_image scope"
+ condition(:read_container_image_deploy_token) do
+ user.is_a?(DeployToken) && user.has_access_to?(project) && user.read_registry?
+ end
+
+ desc "Deploy token with create_container_image scope"
+ condition(:create_container_image_deploy_token) do
+ user.is_a?(DeployToken) && user.has_access_to?(project) && user.write_registry?
+ end
+
desc "Deploy token with read_package_registry scope"
condition(:read_package_registry_deploy_token) do
user.is_a?(DeployToken) && user.has_access_to?(project) && user.read_package_registry
@@ -698,6 +714,14 @@ class ProjectPolicy < BasePolicy
enable :push_code
end
+ rule { read_container_image_deploy_token }.policy do
+ enable :read_container_image
+ end
+
+ rule { create_container_image_deploy_token }.policy do
+ enable :create_container_image
+ end
+
rule { read_package_registry_deploy_token }.policy do
enable :read_package
enable :read_project
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 6d6d8641d9d..e806bef46fe 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -215,15 +215,13 @@ module Auth
def deploy_token_can_pull?(requested_project)
has_authentication_ability?(:read_container_image) &&
deploy_token.present? &&
- deploy_token.has_access_to?(requested_project) &&
- deploy_token.read_registry?
+ can?(deploy_token, :read_container_image, requested_project)
end
def deploy_token_can_push?(requested_project)
has_authentication_ability?(:create_container_image) &&
deploy_token.present? &&
- deploy_token.has_access_to?(requested_project) &&
- deploy_token.write_registry?
+ can?(deploy_token, :create_container_image, requested_project)
end
##
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index c0fabb1d42e..b31576b5c48 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -1,7 +1,7 @@
- if Gitlab.config.packages.enabled
%section.settings.as-package.no-animate#js-package-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Package Registry')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? _('Collapse') : _('Expand')
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index 5e3f0d6f2aa..0adb6cbbcf0 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -1,6 +1,6 @@
- expanded = local_assigns.fetch(:expanded)
-%h4
+%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Variables')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index b635e7198cb..f0f7e6868da 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -14,7 +14,7 @@
%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Continuous Integration and Deployment')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? _('Collapse') : _('Expand')
@@ -29,7 +29,7 @@
- if Gitlab.config.registry.enabled
%section.settings.as-registry.no-animate#js-registry-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Container Registry')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? _('Collapse') : _('Expand')
@@ -41,7 +41,7 @@
- if Feature.enabled?(:runner_registration_control)
%section.settings.as-runner.no-animate#js-runner-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('Runners|Runner registration')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? 'Collapse' : 'Expand'
diff --git a/config/feature_flags/development/container_registry_legacy_authentication_for_deploy_tokens.yml b/config/feature_flags/development/container_registry_legacy_authentication_for_deploy_tokens.yml
new file mode 100644
index 00000000000..fefc84ed0a0
--- /dev/null
+++ b/config/feature_flags/development/container_registry_legacy_authentication_for_deploy_tokens.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_legacy_authentication_for_deploy_tokens
+introduced_by_url: https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/2470
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365968
+milestone: '15.1'
+type: development
+group: group::package
+default_enabled: false
diff --git a/db/post_migrate/20220620151740_add_indexes_issues_on_project_id_and_closed_at.rb b/db/post_migrate/20220620151740_add_indexes_issues_on_project_id_and_closed_at.rb
index 20db2f0c88e..066e72dce45 100644
--- a/db/post_migrate/20220620151740_add_indexes_issues_on_project_id_and_closed_at.rb
+++ b/db/post_migrate/20220620151740_add_indexes_issues_on_project_id_and_closed_at.rb
@@ -9,11 +9,16 @@ class AddIndexesIssuesOnProjectIdAndClosedAt < Gitlab::Database::Migration[2.0]
def up
# Index to improve performance when sorting issues by closed_at desc
- add_concurrent_index :issues, 'project_id, closed_at DESC NULLS LAST, state_id, id', name: NEW_INDEX_NAME_1
+ unless index_exists_by_name?(:issues, NEW_INDEX_NAME_1)
+ add_concurrent_index :issues, 'project_id, closed_at DESC NULLS LAST, state_id, id', name: NEW_INDEX_NAME_1
+ end
# Index to improve performance when sorting issues by closed_at asc
# This replaces the old index which didn't account for state_id and id
- add_concurrent_index :issues, [:project_id, :closed_at, :state_id, :id], name: NEW_INDEX_NAME_2
+ unless index_exists_by_name?(:issues, NEW_INDEX_NAME_2)
+ add_concurrent_index :issues, [:project_id, :closed_at, :state_id, :id], name: NEW_INDEX_NAME_2
+ end
+
remove_concurrent_index_by_name :issues, OLD_INDEX_NAME
end
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 43548d21f70..d6cadbab6a6 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -938,7 +938,7 @@ Prerequisites:
[cloud native chart](https://docs.gitlab.com/charts/charts/registry/#garbage-collection).
- You must set the Registry to [read-only mode](#performing-garbage-collection-without-downtime).
Running garbage collection causes downtime for the Container Registry. When you run this command
- on an instance in an environment where another instances is still writing to the Registry storage,
+ on an instance in an environment where another instance is still writing to the Registry storage,
referenced manifests are removed.
### Understanding the content-addressable layers
diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md
index 8d56effd9a4..50bb36a6a32 100644
--- a/doc/user/application_security/policies/scan-execution-policies.md
+++ b/doc/user/application_security/policies/scan-execution-policies.md
@@ -88,9 +88,8 @@ This rule enforces the defined actions and schedules a scan on the provided date
|------------|------|-----------------|-------------|
| `type` | `string` | `schedule` | The rule's type. |
| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
-| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. |
-| `agents` | `object` | | The name of the [GitLab agents](../../clusters/agent/index.md) where [cluster image scanning](../../clusters/agent/vulnerabilities.md) will run. The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. <!--- start_remove The following content will be removed on remove_date: '2022-08-22' --> |
-| `clusters` (removed) | `object` | | This field was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/356465) in 15.0. Use the `agents` field instead. The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. <!--- end_remove --> |
+| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. <!--- start_remove The following content will be removed on remove_date: '2022-08-22' --> |
+| `clusters` (removed) | `object` | | This field was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/356465) in 15.0. The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. <!--- end_remove --> |
GitLab supports the following types of CRON syntax for the `cadence` field:
@@ -99,20 +98,11 @@ GitLab supports the following types of CRON syntax for the `cadence` field:
It is possible that other elements of the CRON syntax will work in the cadence field, however, GitLab does not officially test or support them.
-### `agent` schema
-
-Use this schema to define `agents` objects in the [`schedule` rule type](#schedule-rule-type).
-
-| Field | Type | Possible values | Description |
-|--------------|---------------------|--------------------------|-------------|
-| `namespaces` | `array` of `string` | | The namespace that is scanned. If empty, all namespaces will be scanned. |
-
<!--- start_remove The following content will be removed on remove_date: '2022-08-22' -->
### `cluster` schema (removed)
This schema was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/356465) in 15.0.
-Use the [`agent` schema](#agent-schema) instead.
Use this schema to define `clusters` objects in the [`schedule` rule type](#schedule-rule-type).
@@ -203,18 +193,6 @@ scan_execution_policy:
variables:
SAST_EXCLUDED_ANALYZERS: brakeman
- scan: container_scanning
-- name: Enforce Cluster Image Scanning on production-cluster every 24h
- description: This policy enforces Cluster Image Scanning scan to run every 24 hours
- enabled: true
- rules:
- - type: schedule
- cadence: "15 3 * * *"
- agents:
- production-agent:
- namespaces:
- - production-namespace
- actions:
- - scan: cluster_image_scanning
```
In this example:
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 2fed724f947..e2481dcb8c1 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -35,6 +35,8 @@ module API
name, _, format = file_name.rpartition('.')
if %w(md5 sha1).include?(format)
+ unprocessable_entity! if Gitlab::FIPS.enabled? && format == 'md5'
+
[name, format]
else
[file_name, format]
@@ -109,6 +111,7 @@ module API
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
get 'packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
# return a similar failure to authorize_read_package!(project)
+
forbidden! unless path_exists?(params[:path])
file_name, format = extract_format(params[:file_name])
@@ -241,6 +244,7 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
put ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
+ unprocessable_entity! if Gitlab::FIPS.enabled? && params['file.md5']
authorize_upload!
bad_request!('File is too large') if user_project.actual_limits.exceeded?(:maven_max_file_size, params[:file].size)
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 5d046636984..74df07aa609 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -54,4 +54,8 @@ COPY ./INSTALLATION_TYPE ./VERSION /home/gitlab/
COPY ./qa /home/gitlab/qa
+# Add JH files when JH dir exist.
+COPY ./j[h]/qa /home/gitlab/jh/qa
+COPY ./j[h]/lib /home/gitlab/jh/lib
+
ENTRYPOINT ["bin/test"]
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 385edc59eb6..3350609bb90 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -1,20 +1,15 @@
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
-
+import { GlAvatar } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
-
import DiffsModule from '~/diffs/store/modules';
-
import NoteActions from '~/notes/components/note_actions.vue';
import NoteBody from '~/notes/components/note_body.vue';
import NoteHeader from '~/notes/components/note_header.vue';
import issueNote from '~/notes/components/noteable_note.vue';
import NotesModule from '~/notes/stores/modules';
import { NOTEABLE_TYPE_MAPPING } from '~/notes/constants';
-
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-
import { noteableDataMock, notesDataMock, note } from '../mock_data';
Vue.use(Vuex);
@@ -205,19 +200,21 @@ describe('issue_note', () => {
await nextTick();
- expect(wrapper.findComponent(UserAvatarLink).props('imgSize')).toBe(24);
+ const avatar = wrapper.findComponent(GlAvatar);
+ const avatarProps = avatar.props();
+ expect(avatarProps.size).toBe(24);
});
});
- it('should render user information', () => {
+ it('should render user avatar', () => {
const { author } = note;
- const avatar = wrapper.findComponent(UserAvatarLink);
+ const avatar = wrapper.findComponent(GlAvatar);
const avatarProps = avatar.props();
- expect(avatarProps.linkHref).toBe(author.path);
- expect(avatarProps.imgSrc).toBe(author.avatar_url);
- expect(avatarProps.imgAlt).toBe(author.name);
- expect(avatarProps.imgSize).toBe(40);
+ expect(avatarProps.src).toBe(author.avatar_url);
+ expect(avatarProps.entityName).toBe(author.username);
+ expect(avatarProps.alt).toBe(author.name);
+ expect(avatarProps.size).toEqual({ default: 24, md: 32 });
});
it('should render note header content', () => {
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index a3a4f0a5d38..0a4ee73f3d3 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -692,6 +692,37 @@ RSpec.describe Deployment do
.to contain_exactly(stop_env_b)
end
end
+
+ context 'When last deployment for environment is a retried build' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:environment_b) { create(:environment, project: project) }
+
+ let(:build_a) do
+ create(:ci_build, :success, project: project, pipeline: pipeline, environment: environment.name)
+ end
+
+ let(:build_b) do
+ create(:ci_build, :success, project: project, pipeline: pipeline, environment: environment_b.name)
+ end
+
+ let!(:deployment_a) do
+ create(:deployment, :success, project: project, environment: environment, deployable: build_a)
+ end
+
+ let!(:deployment_b) do
+ create(:deployment, :success, project: project, environment: environment_b, deployable: build_b)
+ end
+
+ before do
+ # Retry build_b
+ build_b.update!(retried: true)
+
+ # New successful build after retry.
+ create(:ci_build, :success, project: project, pipeline: pipeline, environment: environment_b.name)
+ end
+
+ it { expect(subject_method(environment_b)).not_to be_nil }
+ end
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 6857865c7cf..eaace86025c 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1098,25 +1098,117 @@ RSpec.describe ProjectPolicy do
subject { described_class.new(deploy_token, project) }
- context 'a deploy token with read_package_registry scope' do
- let(:deploy_token) { create(:deploy_token, read_package_registry: true) }
+ context 'private project' do
+ let(:project) { private_project }
- it { is_expected.to be_allowed(:read_package) }
- it { is_expected.to be_allowed(:read_project) }
- it { is_expected.to be_disallowed(:create_package) }
+ context 'a deploy token with read_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: true, write_registry: false) }
- it_behaves_like 'package access with repository disabled'
+ it { is_expected.to be_allowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+
+ context 'with registry disabled' do
+ include_context 'registry disabled via project features'
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+ end
+
+ context 'a deploy token with write_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: false, write_registry: true) }
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_allowed(:create_container_image) }
+
+ context 'with registry disabled' do
+ include_context 'registry disabled via project features'
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+ end
+
+ context 'a deploy token with no registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: false, write_registry: false) }
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+
+ context 'a deploy token with read_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_repository: false, read_registry: false, read_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_project) }
+ it { is_expected.to be_allowed(:read_package) }
+ it { is_expected.to be_disallowed(:create_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+
+ context 'a deploy token with write_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_repository: false, read_registry: false, write_package_registry: true) }
+
+ it { is_expected.to be_allowed(:create_package) }
+ it { is_expected.to be_allowed(:read_package) }
+ it { is_expected.to be_allowed(:read_project) }
+ it { is_expected.to be_disallowed(:destroy_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
end
- context 'a deploy token with write_package_registry scope' do
- let(:deploy_token) { create(:deploy_token, write_package_registry: true) }
+ context 'public project' do
+ let(:project) { public_project }
+
+ context 'a deploy token with read_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: true, write_registry: false) }
- it { is_expected.to be_allowed(:create_package) }
- it { is_expected.to be_allowed(:read_package) }
- it { is_expected.to be_allowed(:read_project) }
- it { is_expected.to be_disallowed(:destroy_package) }
+ it { is_expected.to be_allowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
- it_behaves_like 'package access with repository disabled'
+ context 'with registry disabled' do
+ include_context 'registry disabled via project features'
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+
+ context 'with registry private' do
+ include_context 'registry set to private via project features'
+
+ it { is_expected.to be_allowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+ end
+
+ context 'a deploy token with write_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: false, write_registry: true) }
+
+ it { is_expected.to be_allowed(:read_container_image) }
+ it { is_expected.to be_allowed(:create_container_image) }
+
+ context 'with registry disabled' do
+ include_context 'registry disabled via project features'
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
+
+ context 'with registry private' do
+ include_context 'registry set to private via project features'
+
+ it { is_expected.to be_allowed(:read_container_image) }
+ it { is_expected.to be_allowed(:create_container_image) }
+ end
+ end
+
+ context 'a deploy token with no registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_registry: false, write_registry: false) }
+
+ it { is_expected.to be_disallowed(:read_container_image) }
+ it { is_expected.to be_disallowed(:create_container_image) }
+ end
end
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index bc325aad823..ba82d2facc6 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -226,14 +226,26 @@ RSpec.describe API::MavenPackages do
end
end
+ shared_examples 'file download in FIPS mode' do
+ context 'in FIPS mode', :fips_mode do
+ it_behaves_like 'successfully returning the file'
+
+ it 'rejects the request for an md5 file' do
+ download_file(file_name: package_file.file_name + '.md5')
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+ end
+
describe 'GET /api/v4/packages/maven/*path/:file_name' do
context 'a public project' do
subject { download_file(file_name: package_file.file_name) }
shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
-
it_behaves_like 'successfully returning the file'
+ it_behaves_like 'file download in FIPS mode'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -402,8 +414,8 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
-
it_behaves_like 'successfully returning the file'
+ it_behaves_like 'file download in FIPS mode'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -625,8 +637,8 @@ RSpec.describe API::MavenPackages do
subject { download_file(file_name: package_file.file_name) }
it_behaves_like 'tracking the file download event'
-
it_behaves_like 'successfully returning the file'
+ it_behaves_like 'file download in FIPS mode'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -833,6 +845,16 @@ RSpec.describe API::MavenPackages do
subject { upload_file_with_token(params: params) }
+ context 'FIPS mode', :fips_mode do
+ it_behaves_like 'package workhorse uploads'
+
+ it 'rejects the request for md5 file' do
+ upload_file_with_token(params: params, file_extension: 'jar.md5')
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
context 'file size is too large' do
it 'rejects the request' do
allow_next_instance_of(UploadedFile) do |uploaded_file|
@@ -995,12 +1017,22 @@ RSpec.describe API::MavenPackages do
end
context 'for md5 file' do
+ subject { upload_file_with_token(params: params, file_extension: 'jar.md5') }
+
it 'returns an empty body' do
- upload_file_with_token(params: params, file_extension: 'jar.md5')
+ subject
expect(response.body).to eq('')
expect(response).to have_gitlab_http_status(:ok)
end
+
+ context 'with FIPS mode enabled', :fips_mode do
+ it 'rejects the request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
end
end
diff --git a/spec/support/shared_contexts/project_features_shared_context.rb b/spec/support/shared_contexts/project_features_shared_context.rb
new file mode 100644
index 00000000000..40d9cb29c14
--- /dev/null
+++ b/spec/support/shared_contexts/project_features_shared_context.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'repository disabled via project features' do
+ before do
+ project.project_feature.update_columns(
+ # Disable merge_requests and builds as well, since merge_requests and
+ # builds cannot have higher visibility than repository.
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::DISABLED)
+ end
+end
+
+RSpec.shared_context 'registry disabled via project features' do
+ before do
+ project.project_feature.update_columns(
+ container_registry_access_level: ProjectFeature::DISABLED
+ )
+ end
+end
+
+RSpec.shared_context 'registry set to private via project features' do
+ before do
+ project.project_feature.update_columns(
+ container_registry_access_level: ProjectFeature::PRIVATE
+ )
+ end
+end
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
index 63e4d458ad4..c4083df47e2 100644
--- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -345,16 +345,7 @@ RSpec.shared_examples 'project policies as admin without admin mode' do
end
RSpec.shared_examples 'package access with repository disabled' do
- context 'when repository is disabled' do
- before do
- project.project_feature.update!(
- # Disable merge_requests and builds as well, since merge_requests and
- # builds cannot have higher visibility than repository.
- merge_requests_access_level: ProjectFeature::DISABLED,
- builds_access_level: ProjectFeature::DISABLED,
- repository_access_level: ProjectFeature::DISABLED)
- end
+ include_context 'repository disabled via project features'
- it { is_expected.to be_allowed(:read_package) }
- end
+ it { is_expected.to be_allowed(:read_package) }
end
diff --git a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
index 7677e5d8cb2..f18869fb380 100644
--- a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
@@ -142,9 +142,9 @@ RSpec.shared_examples 'logs an auth warning' do |requested_actions|
requested_project_path: project.full_path,
requested_actions: requested_actions,
authorized_actions: [],
- user_id: current_user.id,
- username: current_user.username
- }
+ user_id: current_user&.id,
+ username: current_user&.username
+ }.compact
end
it do