Commit 7ce3da53 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents dcaada67 54dd0ddb
---
title: 'Improve Vulnerability Tracking: Add fingerprints table'
merge_request: 52720
author:
type: added
---
title: Update Ruby detection rules for SAST
merge_request: 53414
author:
type: changed
# frozen_string_literal: true
class AddFindingFingerprintTable < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
FINGERPRINT_IDX = :idx_vuln_fingerprints_on_occurrences_id_and_fingerprint
UNIQ_IDX = :idx_vuln_fingerprints_uniqueness
def up
with_lock_retries do
create_table :vulnerability_finding_fingerprints do |t|
t.references :finding,
index: true,
null: false,
foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
t.timestamps_with_timezone null: false
t.integer :algorithm_type, null: false
t.binary :fingerprint_sha256, null: false
t.index %i[finding_id fingerprint_sha256],
name: FINGERPRINT_IDX,
unique: true # only one link should exist between occurrence and the fingerprint
t.index %i[finding_id algorithm_type fingerprint_sha256],
name: UNIQ_IDX,
unique: true # these should be unique
end
end
end
def down
with_lock_retries do
drop_table :vulnerability_finding_fingerprints
end
end
end
......@@ -3,6 +3,7 @@
class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration[6.0]
DOWNTIME = false
# rubocop:disable Migration/CreateTableWithForeignKeys
def change
create_table :vulnerability_findings_remediations do |t|
t.references :vulnerability_occurrence, index: false, foreign_key: { on_delete: :cascade }
......@@ -13,4 +14,5 @@ class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration
t.index [:vulnerability_occurrence_id, :vulnerability_remediation_id], unique: true, name: 'index_vulnerability_findings_remediations_on_unique_keys'
end
end
# rubocop:enable Migration/CreateTableWithForeignKeys
end
6643e5b4c5597d92c94115f392bfbd5cfce9884eb0bcb18f9629855f3711eed0
\ No newline at end of file
......@@ -18142,6 +18142,24 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
CREATE TABLE vulnerability_finding_fingerprints (
id bigint NOT NULL,
finding_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
algorithm_type integer NOT NULL,
fingerprint_sha256 bytea NOT NULL
);
CREATE SEQUENCE vulnerability_finding_fingerprints_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE vulnerability_finding_fingerprints_id_seq OWNED BY vulnerability_finding_fingerprints.id;
CREATE TABLE vulnerability_finding_links (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
......@@ -19383,6 +19401,8 @@ ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_finding_fingerprints ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_fingerprints_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_finding_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_links_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_findings_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_findings_remediations_id_seq'::regclass);
......@@ -20958,6 +20978,9 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
ALTER TABLE ONLY vulnerability_finding_fingerprints
ADD CONSTRAINT vulnerability_finding_fingerprints_pkey PRIMARY KEY (id);
ALTER TABLE ONLY vulnerability_finding_links
ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
......@@ -21295,6 +21318,10 @@ CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan
CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
CREATE UNIQUE INDEX idx_vuln_fingerprints_on_occurrences_id_and_fingerprint ON vulnerability_finding_fingerprints USING btree (finding_id, fingerprint_sha256);
CREATE UNIQUE INDEX idx_vuln_fingerprints_uniqueness ON vulnerability_finding_fingerprints USING btree (finding_id, algorithm_type, fingerprint_sha256);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_link_type ON vulnerability_external_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 1);
......@@ -23597,6 +23624,8 @@ CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_f
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
CREATE INDEX index_vulnerability_finding_fingerprints_on_finding_id ON vulnerability_finding_fingerprints USING btree (finding_id);
CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id);
CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id);
......@@ -26120,6 +26149,9 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_finding_fingerprints
ADD CONSTRAINT fk_rails_fa411253b2 FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
......
......@@ -413,11 +413,14 @@ For example:
## Sidekiq Logs
NOTE:
In Omnibus GitLab `12.10` or earlier, the Sidekiq log lives in `/var/log/gitlab/gitlab-rails/sidekiq.log`.
For Omnibus installations, some Sidekiq logs reside in `/var/log/gitlab/sidekiq/current` and as follows.
### `sidekiq.log`
This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for
This file lives in `/var/log/gitlab/sidekiq/current` for
Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq.log` for
installations from source.
......
# frozen_string_literal: true
module SecurityAndCompliancePermissions
extend ActiveSupport::Concern
included do
before_action :ensure_security_and_compliance_enabled!
end
private
def ensure_security_and_compliance_enabled!
render_404 unless can?(current_user, :access_security_and_compliance, project)
end
end
......@@ -62,7 +62,7 @@ module EE
attrs << :maintenance_mode_message
end
attrs << :new_user_signups_cap if ::Feature.enabled?(:admin_new_user_signups_cap, default_enabled: true )
attrs << :new_user_signups_cap
attrs
end
......
......@@ -7,6 +7,8 @@ module EE
extend ::Gitlab::Utils::Override
prepended do
include SecurityAndCompliancePermissions
alias_method :vulnerable, :project
before_action :ensure_security_dashboard_feature_enabled!, except: [:show]
......
# frozen_string_literal: true
class Projects::AuditEventsController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include Gitlab::Utils::StrongMemoize
include LicenseHelper
include AuditEvents::EnforcesValidDateParams
......
......@@ -2,6 +2,8 @@
module Projects
class DependenciesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action :authorize_read_dependency_list!
feature_category :dependency_scanning
......
......@@ -2,6 +2,8 @@
module Projects
class LicensesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action :authorize_read_licenses!, only: [:index]
before_action :authorize_admin_software_license_policy!, only: [:create, :update]
......
......@@ -2,6 +2,8 @@
module Projects
class OnDemandScansController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action do
push_frontend_feature_flag(:security_on_demand_scans_site_validation, @project, default_enabled: :yaml)
push_frontend_feature_flag(:security_dast_site_profiles_additional_fields, @project, default_enabled: :yaml)
......
......@@ -3,6 +3,7 @@
module Projects
module Security
class ApiFuzzingConfigurationController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include SecurityDashboardsPermissions
alias_method :vulnerable, :project
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class CorpusManagementController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action do
render_404 unless Feature.enabled?(:corpus_management, @project, default_enabled: :yaml)
authorize_read_coverage_fuzzing!
......
......@@ -3,6 +3,7 @@
module Projects
module Security
class DashboardController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include SecurityDashboardsPermissions
alias_method :vulnerable, :project
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class DastProfilesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action do
authorize_read_on_demand_scans!
push_frontend_feature_flag(:security_on_demand_scans_site_validation, @project, default_enabled: :yaml)
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class DastScannerProfilesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action :authorize_read_on_demand_scans!
feature_category :dynamic_application_security_testing
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class DastSiteProfilesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action do
authorize_read_on_demand_scans!
push_frontend_feature_flag(:security_dast_site_profiles_additional_fields, @project, default_enabled: :yaml)
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class DiscoverController < Projects::ApplicationController
include SecurityAndCompliancePermissions
feature_category :navigation
def show
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class NetworkPoliciesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
POLLING_INTERVAL = 5_000
before_action :authorize_read_threat_monitoring!
......
......@@ -3,6 +3,7 @@
module Projects
module Security
class SastConfigurationController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include CreatesCommit
include SecurityDashboardsPermissions
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class ScannedResourcesController < ::Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action :authorize_read_vulnerability!
before_action :scanned_resources
......
......@@ -6,6 +6,7 @@ module Projects
class NotesController < Projects::ApplicationController
extend ::Gitlab::Utils::Override
include SecurityAndCompliancePermissions
include SecurityDashboardsPermissions
include NotesActions
include NotesHelper
......
......@@ -3,6 +3,7 @@
module Projects
module Security
class VulnerabilitiesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include SecurityDashboardsPermissions
include IssuableActions
include RendersNotes
......
......@@ -3,6 +3,7 @@
module Projects
module Security
class VulnerabilityReportController < Projects::ApplicationController
include SecurityAndCompliancePermissions
include SecurityDashboardsPermissions
before_action do
......
......@@ -3,6 +3,8 @@
module Projects
module Security
class WafAnomaliesController < Projects::ApplicationController
include SecurityAndCompliancePermissions
POLLING_INTERVAL = 5_000
before_action :authorize_read_waf_anomalies!
......
......@@ -2,6 +2,8 @@
module Projects
class ThreatMonitoringController < Projects::ApplicationController
include SecurityAndCompliancePermissions
before_action :authorize_read_threat_monitoring!
before_action do
push_frontend_feature_flag(:threat_monitoring_alerts, project)
......
......@@ -84,7 +84,6 @@ module EE
end
def show_new_user_signups_cap_reached?
return false unless ::Feature.enabled?(:admin_new_user_signups_cap, default_enabled: true )
return false unless current_user&.admin?
return false if user_dismissed?(NEW_USER_SIGNUPS_CAP_REACHED)
......
......@@ -358,7 +358,6 @@ module EE
end
def should_apply_user_signup_cap?
::Feature.enabled?(:admin_new_user_signups_cap, default_enabled: true ) &&
::Gitlab::CurrentSettings.new_user_signups_cap.present?
end
......
......@@ -24,6 +24,7 @@ class InstanceSecurityDashboard
def projects
Project.where(id: visible_users_security_dashboard_projects)
.with_feature_available_for_user(:security_and_compliance, user)
end
def vulnerabilities
......
......@@ -52,7 +52,6 @@ module EE
def user_cap_increased?
return false unless application_setting.previous_changes.key?(:new_user_signups_cap)
return false unless ::Feature.enabled?(:admin_new_user_signups_cap, default_enabled: true )
previous_user_cap, current_user_cap = application_setting.previous_changes[:new_user_signups_cap]
......
- return unless ::Feature.enabled?(:admin_new_user_signups_cap, default_enabled: true )
.form-group
= form.label :new_user_signups_cap, s_('AdminArea|User cap'), class: 'label-bold'
= form.number_field :new_user_signups_cap, class: 'form-control gl-form-input', max: License.current&.restricted_user_count
......
---
name: admin_new_user_signups_cap
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45643
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292600
milestone: '13.6'
type: development
group: group::purchase
default_enabled: true
......@@ -74,39 +74,17 @@ RSpec.describe RegistrationsController do
end
end
context 'when user signup cap setting is enabled' do
context 'when user signup cap is set' do
before do
stub_application_setting(new_user_signups_cap: true)
stub_application_setting(new_user_signups_cap: 1)
end
it_behaves_like 'blocked user by default'
context 'when feature flag is disabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
context 'when require admin approval setting is disabled' do
before do
stub_application_setting(require_admin_approval_after_user_signup: false)
end
it_behaves_like 'active user by default'
end
context 'when require admin approval setting is enabled' do
before do
stub_application_setting(require_admin_approval_after_user_signup: true)
end
it_behaves_like 'blocked user by default'
end
end
end
context 'when user signup cap setting is disabled' do
context 'when user signup cap is not set' do
before do
stub_application_setting(admin_new_user_signups_cap: false)
stub_application_setting(new_user_signups_cap: nil)
end
context 'when require admin approval setting is disabled' do
......
......@@ -6,20 +6,23 @@ RSpec.describe Projects::DependenciesController do
describe 'GET #index' do
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, :repository, :private) }
let(:params) { { namespace_id: project.namespace, project_id: project } }
before do
project.add_developer(developer)
project.add_guest(guest)
sign_in(user)
end
context 'with authorized user' do
let_it_be(:project) { create(:project, :repository, :public) }
before do
project.add_developer(developer)
project.add_guest(guest)
include_context '"Security & Compliance" permissions' do
let(:user) { developer }
let(:valid_request) { get :index, params: params }
end
context 'with authorized user' do
context 'when feature is available' do
before do
stub_licensed_features(dependency_scanning: true, license_scanning: true, security_dashboard: true)
......@@ -138,14 +141,6 @@ RSpec.describe Projects::DependenciesController do
expect(json_response['dependencies'].length).to eq(3)
end
end
context 'without authorized user to see vulnerabilities' do
let(:user) { guest }
it 'return vulnerable dependencies' do
expect(json_response['dependencies']).to be_empty
end
end
end
context 'with pagination params' do
......@@ -247,7 +242,6 @@ RSpec.describe Projects::DependenciesController do
end
context 'with unauthorized user' do
let(:project) { create(:project, :repository, :private) }
let(:user) { guest }
before do
......
......@@ -13,6 +13,14 @@ RSpec.describe Projects::LicensesController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get :index, params: params }
before_request do
project.add_reporter(user)
end
end
context 'with authorized user' do
context 'when feature is available' do
before do
......@@ -347,6 +355,7 @@ RSpec.describe Projects::LicensesController do
end
describe "POST #create" do
let(:current_user) { create(:user) }
let(:project) { create(:project, :repository, :private) }
let(:mit_license) { create(:software_license, :mit) }
let(:default_params) do
......@@ -360,9 +369,16 @@ RSpec.describe Projects::LicensesController do
}
end
context "when authenticated" do
let(:current_user) { create(:user) }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { post :create, xhr: true, params: default_params }
before_request do
project.add_reporter(current_user)
sign_in(current_user)
end
end
context "when authenticated" do
before do
stub_licensed_features(license_scanning: true)
sign_in(current_user)
......@@ -465,6 +481,7 @@ RSpec.describe Projects::LicensesController do
end
describe "PATCH #update" do
let(:current_user) { create(:user) }
let(:project) { create(:project, :repository, :private) }
let(:software_license_policy) { create(:software_license_policy, project: project, software_license: mit_license) }
let(:mit_license) { create(:software_license, :mit) }
......@@ -478,9 +495,16 @@ RSpec.describe Projects::LicensesController do
}
end
context "when authenticated" do
let(:current_user) { create(:user) }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { post :create, xhr: true, params: default_params }
before_request do
project.add_reporter(current_user)
sign_in(current_user)
end
end
context "when authenticated" do
before do
stub_licensed_features(license_scanning: true)
sign_in(current_user)
......
......@@ -8,14 +8,23 @@ RSpec.describe Projects::Security::ApiFuzzingConfigurationController do
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
subject(:request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
before_all do
group.add_developer(developer)
group.add_guest(guest)
end
describe 'GET #show' do
subject(:request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
stub_licensed_features(security_dashboard: true)
sign_in(developer)
end
end
describe 'GET #show' do
render_views
it_behaves_like SecurityDashboardsPermissions do
......
......@@ -3,8 +3,14 @@
require 'spec_helper'
RSpec.describe Projects::Security::ConfigurationController do
let(:group) { create(:group) }
let(:project) { create(:project, :repository, namespace: group) }
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be_with_refind(:project) { create(:project, :repository, namespace: group) }
before do
stub_licensed_features(security_dashboard: true)
group.add_developer(user)
end
describe 'GET #show' do
using RSpec::Parameterized::TableSyntax
......@@ -34,6 +40,10 @@ RSpec.describe Projects::Security::ConfigurationController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
end
it 'responds with the correct status' do
request
......@@ -134,7 +144,6 @@ RSpec.describe Projects::Security::ConfigurationController do
end
before do
stub_licensed_features(security_dashboard: true)
project.add_maintainer(maintainer)
project.add_developer(developer)
sign_in(user)
......
......@@ -7,6 +7,19 @@ RSpec.describe Projects::Security::DashboardController do
let_it_be(:project) { create(:project, :repository, :public, namespace: group) }
let_it_be(:user) { create(:user) }
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get :index, params: { namespace_id: project.namespace, project_id: project } }
before_request do
sign_in(user)
end
end
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
......@@ -15,11 +28,6 @@ RSpec.describe Projects::Security::DashboardController do
end
end
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
end
describe 'GET #index' do
let(:pipeline) { create(:ci_pipeline, sha: project.commit.id, project: project, user: user) }
......
......@@ -54,10 +54,18 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
end
describe 'GET #summary' do
subject { get :summary, params: action_params, format: :json }
subject(:request) { get :summary, params: action_params, format: :json }
let_it_be(:kubernetes_namespace) { environment.deployment_namespace }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
before do
group.add_developer(user)
......@@ -160,7 +168,15 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
end
describe 'GET #index' do
subject { get :index, params: action_params, format: :json }
subject(:request) { get :index, params: action_params, format: :json }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
let(:service) { instance_double('NetworkPolicies::ResourcesService', execute: ServiceResponse.success(payload: [policy])) }
......@@ -198,7 +214,7 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
end
describe 'POST #create' do
subject { post :create, params: action_params.merge(manifest: manifest), format: :json }
subject(:request) { post :create, params: action_params.merge(manifest: manifest), format: :json }
let(:service) { instance_double('NetworkPolicies::DeployResourceService', execute: ServiceResponse.success(payload: policy)) }
let(:policy) do
......@@ -210,6 +226,14 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
before do
group.add_developer(user)
......@@ -240,7 +264,7 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
end
describe 'PUT #update' do
subject { put :update, params: action_params.merge(id: 'example-policy', manifest: manifest, enabled: enabled), as: :json }
subject(:request) { put :update, params: action_params.merge(id: 'example-policy', manifest: manifest, enabled: enabled), as: :json }
let(:enabled) { nil }
let(:service) { instance_double('NetworkPolicies::DeployResourceService', execute: ServiceResponse.success(payload: policy)) }
......@@ -253,6 +277,14 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
before do
group.add_developer(user)
......@@ -283,10 +315,18 @@ RSpec.describe Projects::Security::NetworkPoliciesController do
end
describe 'DELETE #destroy' do
subject { delete :destroy, params: action_params.merge(id: 'example-policy', manifest: manifest), format: :json }
subject(:request) { delete :destroy, params: action_params.merge(id: 'example-policy', manifest: manifest), format: :json }
let(:service) { instance_double('NetworkPolicies::DeleteResourceService', execute: ServiceResponse.success) }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
before do
group.add_developer(user)
......
......@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::Security::SastConfigurationController do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:project) { create(:project, :repository, namespace: group) }
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
......@@ -13,11 +13,23 @@ RSpec.describe Projects::Security::SastConfigurationController do
group.add_guest(guest)
end
before do
stub_licensed_features(security_dashboard: true)
end
describe 'GET #show' do
subject(:request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
render_views
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
sign_in(developer)
end
end
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
let(:security_dashboard_action) { request }
......@@ -25,8 +37,6 @@ RSpec.describe Projects::Security::SastConfigurationController do
context 'with authorized user' do
before do
stub_licensed_features(security_dashboard: true)
sign_in(developer)
end
......@@ -58,8 +68,6 @@ RSpec.describe Projects::Security::SastConfigurationController do
context 'with unauthorized user' do
before do
stub_licensed_features(security_dashboard: true)
sign_in(guest)
end
......@@ -72,39 +80,38 @@ RSpec.describe Projects::Security::SastConfigurationController do
end
describe 'POST #create' do
let_it_be(:project) { create(:project, :repository, namespace: group) }
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project.to_param,
sast_configuration: {
secure_analyzers_prefix: 'localhost:5000/analyzers',
sast_analyzer_image_tag: '1',
sast_excluded_paths: 'docs',
stage: 'security',
search_max_depth: 11
},
format: :json
}
end
before do
stub_licensed_features(security_dashboard: true)
subject(:request) { post :create, params: params, as: :json }
before do
sign_in(developer)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
end
context 'with valid params' do
it 'returns the new merge request url' do
params = {
secure_analyzers_prefix: 'localhost:5000/analyzers',
sast_analyzer_image_tag: '1',
sast_excluded_paths: 'docs',
stage: 'security',
search_max_depth: 11
}
create_sast_configuration user: developer, project: project, params: params
request
expect(json_response["message"]).to eq("success")
expect(json_response["filePath"]).to match(/#{Gitlab::Routing.url_helpers.project_new_merge_request_url(project, {})}(.*)description(.*)source_branch/)
end
end
end
def create_sast_configuration(user:, project:, params:)
post_params = {
namespace_id: project.namespace.to_param,
project_id: project.to_param,
sast_configuration: params,
format: :json
}
post :create, params: post_params, as: :json
end
end
......@@ -16,13 +16,18 @@ RSpec.describe Projects::Security::ScannedResourcesController do
end
describe 'GET index' do
let(:subject) { get :index, params: action_params, format: :csv }
let(:parsed_csv_data) { CSV.parse(subject.body, headers: true) }
subject(:request) { get :index, params: action_params, format: :csv }
before do
project.add_developer(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
end
context 'when DAST security scan is found' do
before do
create(:ci_build, :success, name: 'dast_job', pipeline: pipeline, project: project) do |job|
......
......@@ -9,14 +9,6 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
let!(:note) { create(:note, noteable: vulnerability, project: project) }
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
let(:security_dashboard_action) do
get :index, params: { namespace_id: project.namespace, project_id: project, vulnerability_id: vulnerability }
end
end
before do
stub_licensed_features(security_dashboard: true)
end
......@@ -31,6 +23,15 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { view_all_notes }
end
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
let(:security_dashboard_action) { view_all_notes }
end
it 'responds with array of notes' do
view_all_notes
......@@ -63,6 +64,10 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { create_note }
end
context 'when note is empty' do
let(:note_params) { { note: '' } }
......@@ -156,6 +161,10 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { update_note }
end
context 'when user is not an author of the note' do
it 'returns status 404' do
update_note
......@@ -201,6 +210,10 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { delete_note }
end
context 'when user is not an author of the note' do
it 'does not delete the note' do
expect { delete_note }.not_to change { Note.count }
......@@ -229,6 +242,7 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
end
describe 'POST toggle_award_emoji' do
let(:emoji_name) { 'thumbsup' }
let(:request_params) do
{
id: note,
......@@ -246,7 +260,9 @@ RSpec.describe Projects::Security::Vulnerabilities::NotesController do
project.add_developer(user)
end
let(:emoji_name) { 'thumbsup' }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { toggle_award_emoji }
end
it 'creates the award emoji' do
expect { toggle_award_emoji }.to change { note.award_emoji.count }.by(1)
......
......@@ -7,20 +7,22 @@ RSpec.describe Projects::Security::VulnerabilitiesController do
let_it_be(:project) { create(:project, :repository, :public, namespace: group) }
let_it_be(:user) { create(:user) }
render_views
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
sign_in(user)
end
describe 'GET #show' do
let_it_be(:pipeline) { create(:ci_pipeline, sha: project.commit.id, project: project, user: user) }
let_it_be(:vulnerability) { create(:vulnerability, project: project) }
render_views
subject(:show_vulnerability) { get :show, params: { namespace_id: project.namespace, project_id: project, id: vulnerability.id } }
def show_vulnerability
sign_in(user)
get :show, params: { namespace_id: project.namespace, project_id: project, id: vulnerability.id }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { show_vulnerability }
end
context "when there's an attached pipeline" do
......@@ -58,11 +60,10 @@ RSpec.describe Projects::Security::VulnerabilitiesController do
let_it_be(:vulnerability) { create(:vulnerability, project: project, author: user) }
let_it_be(:discussion_note) { create(:discussion_note_on_vulnerability, noteable: vulnerability, project: vulnerability.project) }
render_views
subject(:show_vulnerability_discussion_list) { get :discussions, params: { namespace_id: project.namespace, project_id: project, id: vulnerability } }
def show_vulnerability_discussion_list
sign_in(user)
get :discussions, params: { namespace_id: project.namespace, project_id: project, id: vulnerability }
include_context '"Security & Compliance" permissions' do
let(:valid_request) { show_vulnerability_discussion_list }
end
it 'renders discussions' do
......@@ -70,7 +71,6 @@ RSpec.describe Projects::Security::VulnerabilitiesController do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('entities/discussions')
expect(json_response.pluck('id')).to eq([discussion_note.discussion_id])
end
end
......
......@@ -7,6 +7,19 @@ RSpec.describe Projects::Security::VulnerabilityReportController do
let_it_be(:project) { create(:project, :repository, :public, namespace: group) }
let_it_be(:user) { create(:user) }
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get :index, params: { namespace_id: project.namespace, project_id: project } }
before_request do
sign_in(user)
end
end
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
......@@ -15,11 +28,6 @@ RSpec.describe Projects::Security::VulnerabilityReportController do
end
end
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
end
describe 'GET #index' do
let(:pipeline) { create(:ci_pipeline, sha: project.commit.id, project: project, user: user) }
......
......@@ -15,7 +15,7 @@ RSpec.describe Projects::Security::WafAnomaliesController do
let(:es_client) { nil }
describe 'GET #summary' do
subject { get :summary, params: action_params, format: :json }
subject(:request) { get :summary, params: action_params, format: :json }
before do
stub_licensed_features(threat_monitoring: true)
......@@ -28,6 +28,14 @@ RSpec.describe Projects::Security::WafAnomaliesController do
end
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
group.add_developer(user)
end
end
context 'with authorized user' do
before do
group.add_developer(user)
......
......@@ -281,23 +281,6 @@ RSpec.describe 'Admin updates EE-only settings' do
end
context 'sign up settings' do
context 'when feature flag is disabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
it 'does not render user cap form group' do
visit general_admin_application_settings_path
expect(page).not_to have_field('User cap')
end
end
context 'when feature flag is enabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: true)
end
context 'when license has active user count' do
let(:license) { create(:license, restrictions: { active_user_count: 1 }) }
......@@ -347,7 +330,6 @@ RSpec.describe 'Admin updates EE-only settings' do
end
end
end
end
def current_settings
ApplicationSetting.current_without_cache
......
......@@ -42,6 +42,10 @@ RSpec.describe 'Projects > Audit Events', :js do
allow(LicenseHelper).to receive(:show_promotions?).and_return(true)
end
include_context '"Security & Compliance" permissions' do
let(:response) { inspect_requests { visit project_audit_events_path(project) }.first }
end
it 'returns 200' do
reqs = inspect_requests do
visit project_audit_events_path(project)
......
......@@ -266,6 +266,10 @@ RSpec.describe 'Promotions', :js do
sign_in(user)
end
include_context '"Security & Compliance" permissions' do
let(:response) { inspect_requests { visit project_audit_events_path(project) }.first }
end
it 'appears on the page' do
visit project_audit_events_path(project)
......
......@@ -351,15 +351,6 @@ RSpec.describe EE::UserCalloutsHelper do
it { is_expected.to eq(false) }
end
context 'when feature flag is disabled' do
before do
allow(helper).to receive(:current_user).and_return(admin)
stub_feature_flags(admin_new_user_signups_cap: false)
end
it { is_expected.to eq(false) }
end
context 'when feature flag is enabled' do
where(:new_user_signups_cap, :active_user_count, :result) do
nil | 10 | false
......
......@@ -766,15 +766,6 @@ RSpec.describe ApplicationSetting do
describe '#should_apply_user_signup_cap?' do
subject { setting.should_apply_user_signup_cap? }
context 'when feature admin_new_user_signups_cap is disabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
it { is_expected.to be false }
end
context 'when feature admin_new_user_signups_cap is enabled' do
before do
allow(Gitlab::CurrentSettings).to receive(:new_user_signups_cap).and_return(new_user_signups_cap)
end
......@@ -791,5 +782,4 @@ RSpec.describe ApplicationSetting do
it { is_expected.to be true }
end
end
end
end
......@@ -107,18 +107,6 @@ RSpec.describe User do
allow(Gitlab::CurrentSettings).to receive(:new_user_signups_cap).and_return(new_user_signups_cap)
end
context 'when feature is disabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
it 'does not call SetUserStatusBasedOnUserCapSettingWorker' do
expect(SetUserStatusBasedOnUserCapSettingWorker).not_to receive(:perform_async)
create(:user, state: 'blocked_pending_approval')
end
end
context 'when user cap is not set' do
it 'does not call SetUserStatusBasedOnUserCapSettingWorker' do
expect(SetUserStatusBasedOnUserCapSettingWorker).not_to receive(:perform_async)
......
......@@ -85,19 +85,51 @@ RSpec.describe InstanceSecurityDashboard do
describe '#projects' do
context 'when the user cannot read all resources' do
context 'when the `security_and_compliance` is enabled for the project' do
before do
ProjectFeature.update_all(security_and_compliance_access_level: Featurable::ENABLED)
end
it 'returns only projects on their dashboard that they can read' do
expect(subject.projects).to contain_exactly(project1)
end
end
context 'when the `security_and_compliance` is disabled for the project' do
before do
project1.project_feature.update_column(:security_and_compliance_access_level, Featurable::DISABLED)
end
it 'returns only projects on their dashboard that they can read' do
expect(subject.projects).to be_empty
end
end
end
context 'when the user can read all resources' do
let(:project_ids) { [project1.id, project2.id] }
let(:user) { create(:auditor) }
context 'when the `security_and_compliance` is enabled for the project' do
before do
ProjectFeature.update_all(security_and_compliance_access_level: Featurable::ENABLED)
end
it "returns all projects on the user's dashboard" do
expect(subject.projects).to contain_exactly(project1, project2, project3)
end
end
context 'when the `security_and_compliance` is disabled for the project' do
before do
project1.project_feature.update_column(:security_and_compliance_access_level, Featurable::DISABLED)
end
it "returns only the feature enabled projects on the user's dashboard" do
expect(subject.projects).to contain_exactly(project2, project3)
end
end
end
end
describe '#vulnerabilities' do
......
......@@ -7,7 +7,6 @@ RSpec.describe 'callout alerts' do
describe 'new_user_signups_cap_reached' do
let_it_be(:user) { create(:admin) }
let(:enabled) { true }
let(:billable_users) { [double(:billable_user)] }
let(:help_page_href) { help_page_path('user/admin_area/settings/sign_up_restrictions.md') }
let(:expected_content) { 'Your instance has reached its user cap' }
......@@ -30,7 +29,6 @@ RSpec.describe 'callout alerts' do
end
before do
stub_feature_flags(admin_new_user_signups_cap: enabled)
stub_application_setting(new_user_signups_cap: 1)
allow(User).to receive(:billable).and_return(billable_users)
......@@ -47,12 +45,6 @@ RSpec.describe 'callout alerts' do
it_behaves_like 'a hidden alert'
end
context 'when feature disabled' do
let(:enabled) { false }
it_behaves_like 'a hidden alert'
end
context 'when user is not admin' do
let_it_be(:user) { create(:user) }
......
......@@ -9,6 +9,15 @@ RSpec.describe Projects::OnDemandScansController, type: :request do
let(:user) { create(:user) }
shared_examples 'on-demand scans page' do
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get path }
before_request do
project.add_developer(user)
login_as(user)
end
end
context 'feature available' do
before do
stub_licensed_features(security_on_demand_scans: true)
......
......@@ -7,16 +7,24 @@ RSpec.describe Projects::Security::CorpusManagementController, type: :request do
let(:user) { create(:user) }
describe 'GET #show' do
context 'feature available' do
before do
stub_licensed_features(coverage_fuzzing: true)
login_as(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get project_security_configuration_corpus_management_path(project) }
before_request do
project.add_developer(user)
end
end
context 'feature available' do
context 'user authorized' do
before do
project.add_developer(user)
login_as(user)
end
it 'can access page' do
......@@ -29,8 +37,6 @@ RSpec.describe Projects::Security::CorpusManagementController, type: :request do
context 'user not authorized' do
before do
project.add_guest(user)
login_as(user)
end
it 'sees a 404 error' do
......@@ -43,14 +49,13 @@ RSpec.describe Projects::Security::CorpusManagementController, type: :request do
context 'feature not available' do
before do
project.add_developer(user)
stub_licensed_features(coverage_fuzzing: false)
login_as(user)
project.add_developer(user)
end
context 'license doesnt\'t support the feature' do
it 'sees a 404 error' do
stub_licensed_features(coverage_fuzzing: false)
get project_security_configuration_corpus_management_path(project)
expect(response).to have_gitlab_http_status(:not_found)
......
......@@ -7,16 +7,24 @@ RSpec.describe Projects::Security::DastProfilesController, type: :request do
let(:user) { create(:user) }
describe 'GET #index' do
context 'feature available' do
before do
stub_licensed_features(security_on_demand_scans: true)
login_as(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get project_security_configuration_dast_profiles_path(project) }
before_request do
project.add_developer(user)
end
end
context 'feature available' do
context 'user authorized' do
before do
project.add_developer(user)
login_as(user)
end
it 'can access page' do
......@@ -29,8 +37,6 @@ RSpec.describe Projects::Security::DastProfilesController, type: :request do
context 'user not authorized' do
before do
project.add_guest(user)
login_as(user)
end
it 'sees a 404 error' do
......@@ -43,14 +49,12 @@ RSpec.describe Projects::Security::DastProfilesController, type: :request do
context 'feature not available' do
before do
stub_licensed_features(security_on_demand_scans: false)
project.add_developer(user)
login_as(user)
end
context 'license doesnt\'t support the feature' do
it 'sees a 404 error' do
stub_licensed_features(security_on_demand_scans: false)
get project_security_configuration_dast_profiles_path(project)
expect(response).to have_gitlab_http_status(:not_found)
......
......@@ -24,6 +24,15 @@ RSpec.describe Projects::Security::DastScannerProfilesController, type: :request
end
shared_examples 'a GET request' do
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get path }
before_request do
project.add_developer(user)
login_as(user)
end
end
context 'feature available' do
include_context 'on-demand scans feature available'
......
......@@ -17,6 +17,15 @@ RSpec.describe Projects::Security::DastSiteProfilesController, type: :request do
end
shared_examples 'a GET request' do
include_context '"Security & Compliance" permissions' do
let(:valid_request) { get path }
before_request do
with_feature_available
with_user_authorized
end
end
context 'feature available' do
before do
with_feature_available
......
......@@ -12,7 +12,7 @@ RSpec.describe Projects::Security::ScannedResourcesController, type: :request do
let_it_be(:pipeline_id) { pipeline.id }
let(:parsed_csv_data) { CSV.parse(response.body, headers: true) }
subject { get project_security_scanned_resources_path(project, :csv, pipeline_id: pipeline_id) }
subject(:request) { get project_security_scanned_resources_path(project, :csv, pipeline_id: pipeline_id) }
before do
stub_licensed_features(dast: true, security_dashboard: true)
......@@ -20,6 +20,14 @@ RSpec.describe Projects::Security::ScannedResourcesController, type: :request do
login_as(user)
end
include_context '"Security & Compliance" permissions' do
let(:valid_request) { request }
before_request do
project.add_developer(user)
end
end
shared_examples 'returns a 404' do
it 'will return a 404' do
subject
......
......@@ -234,16 +234,6 @@ RSpec.describe ApplicationSettings::UpdateService do
include_examples 'worker is called'
end
end
context 'when feature is disabled' do
let(:opts) { { new_user_signups_cap: 10 } }
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
include_examples 'worker is not called'
end
end
end
end
......@@ -110,18 +110,6 @@ RSpec.describe Users::BuildService do
expect(user).to be_active
end
end
context 'when feature is disabled' do
before do
stub_feature_flags(admin_new_user_signups_cap: false)
end
it 'does not set the user state to blocked_pending_approval' do
user = service.execute
expect(user).to be_active
end
end
end
end
end
......
# frozen_string_literal: true
RSpec.shared_context '"Security & Compliance" permissions' do
let(:project_instance) { an_instance_of(Project) }
let(:user_instance) { an_instance_of(User) }
let(:before_request_defined) { false }
let(:valid_request) {}
def self.before_request(&block)
return unless block
let(:before_request_call) { instance_exec(&block) }
let(:before_request_defined) { true }
end
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user_instance, :access_security_and_compliance, project_instance).and_return(true)
end
context 'when the "Security & Compliance" feature is disabled' do
subject { response }
before do
before_request_call if before_request_defined
allow(Ability).to receive(:allowed?).with(user_instance, :access_security_and_compliance, project_instance).and_return(false)
valid_request
end
it { is_expected.to have_gitlab_http_status(:not_found) }
end
end
......@@ -66,7 +66,8 @@ brakeman-sast:
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /brakeman/
exists:
- 'config/routes.rb'
- '**/*.rb'
- '**/Gemfile'
eslint-sast:
extends: .sast-analyzer
......
......@@ -38,6 +38,7 @@ Migration/UpdateLargeTable:
- :users
- :user_preferences
- :user_details
- :vulnerability_occurrences
- :web_hook_logs
DeniedMethods:
- :change_column_type_concurrently
......
......@@ -7,6 +7,8 @@ RSpec.describe Projects::Security::ConfigurationController do
let(:user) { create(:user) }
before do
allow(controller).to receive(:ensure_security_and_compliance_enabled!)
sign_in(user)
end
......
......@@ -537,7 +537,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
expect(pipeline.builds.map(&:name)).to match_array(%w[build code_quality eslint-sast secret_detection_default_branch test])
expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection_default_branch test])
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment