Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
dbd782cf
Commit
dbd782cf
authored
Dec 29, 2021
by
Alper Akgun
Committed by
Dmitry Gruzd
Dec 29, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Secure onboarding progress trial actions
parent
b2f94bbd
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
151 additions
and
33 deletions
+151
-33
app/models/onboarding_progress.rb
app/models/onboarding_progress.rb
+20
-6
db/migrate/20211220174504_add_secure_scanning_actions_to_onboarding_progresses.rb
...4_add_secure_scanning_actions_to_onboarding_progresses.rb
+15
-0
db/schema_migrations/20211220174504
db/schema_migrations/20211220174504
+1
-0
db/structure.sql
db/structure.sql
+8
-1
ee/app/models/security/scan.rb
ee/app/models/security/scan.rb
+1
-1
ee/app/workers/security/store_scans_worker.rb
ee/app/workers/security/store_scans_worker.rb
+5
-3
ee/spec/models/security/scan_spec.rb
ee/spec/models/security/scan_spec.rb
+12
-0
ee/spec/workers/security/store_scans_worker_spec.rb
ee/spec/workers/security/store_scans_worker_spec.rb
+18
-8
spec/models/onboarding_progress_spec.rb
spec/models/onboarding_progress_spec.rb
+71
-14
No files found.
app/models/onboarding_progress.rb
View file @
dbd782cf
...
...
@@ -20,7 +20,14 @@ class OnboardingProgress < ApplicationRecord
:issue_created
,
:issue_auto_closed
,
:repository_imported
,
:repository_mirrored
:repository_mirrored
,
:secure_dependency_scanning_run
,
:secure_container_scanning_run
,
:secure_dast_run
,
:secure_secret_detection_run
,
:secure_coverage_fuzzing_run
,
:secure_api_fuzzing_run
,
:secure_cluster_image_scanning_run
].
freeze
scope
:incomplete_actions
,
->
(
actions
)
do
...
...
@@ -52,12 +59,19 @@ class OnboardingProgress < ApplicationRecord
where
(
namespace:
namespace
).
any?
end
def
register
(
namespace
,
action
)
return
unless
root_namespace?
(
namespace
)
&&
ACTIONS
.
include?
(
action
)
def
register
(
namespace
,
actions
)
actions
=
Array
(
actions
)
return
unless
root_namespace?
(
namespace
)
&&
actions
.
difference
(
ACTIONS
).
empty?
action_column
=
column_name
(
action
)
onboarding_progress
=
find_by
(
namespace:
namespace
,
action_column
=>
nil
)
onboarding_progress
&
.
update!
(
action_column
=>
Time
.
current
)
onboarding_progress
=
find_by
(
namespace:
namespace
)
return
unless
onboarding_progress
now
=
Time
.
current
nil_actions
=
actions
.
select
{
|
action
|
onboarding_progress
[
column_name
(
action
)].
nil?
}
return
if
nil_actions
.
empty?
updates
=
nil_actions
.
inject
({})
{
|
sum
,
action
|
sum
.
merge!
({
column_name
(
action
)
=>
now
})
}
onboarding_progress
.
update!
(
updates
)
end
def
completed?
(
namespace
,
action
)
...
...
db/migrate/20211220174504_add_secure_scanning_actions_to_onboarding_progresses.rb
0 → 100644
View file @
dbd782cf
# frozen_string_literal: true
class
AddSecureScanningActionsToOnboardingProgresses
<
Gitlab
::
Database
::
Migration
[
1.0
]
def
change
change_table
(
:onboarding_progresses
,
bulk:
true
)
do
|
t
|
t
.
column
:secure_dependency_scanning_run_at
,
:datetime_with_timezone
t
.
column
:secure_container_scanning_run_at
,
:datetime_with_timezone
t
.
column
:secure_dast_run_at
,
:datetime_with_timezone
t
.
column
:secure_secret_detection_run_at
,
:datetime_with_timezone
t
.
column
:secure_coverage_fuzzing_run_at
,
:datetime_with_timezone
t
.
column
:secure_cluster_image_scanning_run_at
,
:datetime_with_timezone
t
.
column
:secure_api_fuzzing_run_at
,
:datetime_with_timezone
end
end
end
db/schema_migrations/20211220174504
0 → 100644
View file @
dbd782cf
80c1ad5815ef68ab1a7d63566d478683b3f9a5169ed15ecd6f44f7f542d40dc8
\ No newline at end of file
db/structure.sql
View file @
dbd782cf
...
...
@@ -16778,7 +16778,14 @@ CREATE TABLE onboarding_progresses (
issue_auto_closed_at timestamp with time zone,
repository_imported_at timestamp with time zone,
repository_mirrored_at timestamp with time zone,
issue_created_at timestamp with time zone
issue_created_at timestamp with time zone,
secure_dependency_scanning_run_at timestamp with time zone,
secure_container_scanning_run_at timestamp with time zone,
secure_dast_run_at timestamp with time zone,
secure_secret_detection_run_at timestamp with time zone,
secure_coverage_fuzzing_run_at timestamp with time zone,
secure_cluster_image_scanning_run_at timestamp with time zone,
secure_api_fuzzing_run_at timestamp with time zone
);
CREATE SEQUENCE onboarding_progresses_id_seq
ee/app/models/security/scan.rb
View file @
dbd782cf
...
...
@@ -30,7 +30,7 @@ module Security
enum
status:
{
created:
0
,
succeeded:
1
,
failed:
2
}
scope
:by_scan_types
,
->
(
scan_types
)
{
where
(
scan_type:
sanitize_scan_types
(
scan_types
))
}
scope
:distinct_scan_types
,
->
{
select
(
:scan_type
).
distinct
.
pluck
(
:scan_type
)
}
scope
:scoped_project
,
->
{
where
(
'security_scans.project_id = projects.id'
)
}
scope
:has_dismissal_feedback
,
->
do
...
...
ee/app/workers/security/store_scans_worker.rb
View file @
dbd782cf
...
...
@@ -25,10 +25,12 @@ module Security
private
def
record_onboarding_progress
(
pipeline
)
# We only record SAST scans since it's a Free feature and available to all users
return
unless
pipeline
.
security_scans
.
sast
.
any?
recordable_scan_actions
=
Security
::
Scan
.
scan_types
.
keys
.
inject
({})
{
|
hash
,
scan_type
|
hash
.
merge!
(
scan_type
=>
"secure_
#{
scan_type
}
_run"
.
to_sym
)
}
.
merge
(
'sast'
=>
:security_scan_enabled
)
# sast has an exceptional action name
OnboardingProgressService
.
new
(
pipeline
.
project
.
namespace
).
execute
(
action: :security_scan_enabled
)
actions
=
pipeline
.
security_scans
.
distinct_scan_types
.
map
{
|
scan_type
|
recordable_scan_actions
[
scan_type
]
}
OnboardingProgressService
.
new
(
pipeline
.
project
.
namespace
).
execute
(
action:
actions
)
end
end
end
ee/spec/models/security/scan_spec.rb
View file @
dbd782cf
...
...
@@ -86,6 +86,18 @@ RSpec.describe Security::Scan do
end
end
describe
'.distinct_scan_types'
do
let_it_be
(
:sast_scan
)
{
create
(
:security_scan
,
scan_type: :sast
)
}
let_it_be
(
:sast_scan2
)
{
create
(
:security_scan
,
scan_type: :sast
)
}
let_it_be
(
:dast_scan
)
{
create
(
:security_scan
,
scan_type: :dast
)
}
let
(
:expected_scans
)
{
%w(sast dast)
}
subject
{
described_class
.
distinct_scan_types
}
it
{
is_expected
.
to
match_array
(
expected_scans
)
}
end
describe
'.latest_successful'
do
let!
(
:first_successful_scan
)
{
create
(
:security_scan
,
latest:
false
,
status: :succeeded
)
}
let!
(
:second_successful_scan
)
{
create
(
:security_scan
,
latest:
true
,
status: :succeeded
)
}
...
...
ee/spec/workers/security/store_scans_worker_spec.rb
View file @
dbd782cf
...
...
@@ -38,16 +38,26 @@ RSpec.describe Security::StoreScansWorker do
expect
(
Security
::
StoreScansService
).
to
have_received
(
:execute
)
end
it_behaves_like
'records an onboarding progress action'
,
:security_scan_enabled
do
let
(
:namespace
)
{
pipeline
.
project
.
namespace
}
end
scan_types_actions
=
{
"sast"
=>
:security_scan_enabled
,
"dependency_scanning"
=>
:secure_dependency_scanning_run
,
"container_scanning"
=>
:secure_container_scanning_run
,
"dast"
=>
:secure_dast_run
,
"secret_detection"
=>
:secure_secret_detection_run
,
"coverage_fuzzing"
=>
:secure_coverage_fuzzing_run
,
"api_fuzzing"
=>
:secure_api_fuzzing_run
,
"cluster_image_scanning"
=>
:secure_cluster_image_scanning_run
}.
freeze
context
'dast scan'
do
let_it_be
(
:dast_scan
)
{
create
(
:security_scan
,
scan_type: :dast
)
}
let_it_be
(
:pipeline
)
{
dast_scan
.
pipeline
}
let_it_be
(
:dast_build
)
{
pipeline
.
security_scans
.
dast
.
last
&
.
build
}
scan_types_actions
.
each
do
|
scan_type
,
action
|
context
"security
#{
scan_type
}
"
do
let_it_be
(
:scan
)
{
create
(
:security_scan
,
scan_type:
scan_type
)
}
let_it_be
(
:pipeline
)
{
scan
.
pipeline
}
it_behaves_like
'does not record an onboarding progress action'
it_behaves_like
'records an onboarding progress action'
,
[
action
]
do
let
(
:namespace
)
{
pipeline
.
project
.
namespace
}
end
end
end
end
end
...
...
spec/models/onboarding_progress_spec.rb
View file @
dbd782cf
...
...
@@ -131,29 +131,86 @@ RSpec.describe OnboardingProgress do
end
describe
'.register'
do
subject
(
:register_action
)
{
described_class
.
register
(
namespace
,
action
)
}
context
'for a single action'
do
subject
(
:register_action
)
{
described_class
.
register
(
namespace
,
action
)
}
context
'when the namespace was onboarded'
do
before
do
described_class
.
onboard
(
namespace
)
end
context
'when the namespace was onboarded'
do
before
do
described_class
.
onboard
(
namespace
)
end
it
'registers the action for the namespace'
do
expect
{
register_action
}.
to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
false
).
to
(
true
)
end
it
'registers the action for the namespace'
do
expect
{
register_action
}.
to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
false
).
to
(
true
)
end
context
'when the action does not exist'
do
let
(
:action
)
{
:foo
}
it
'does not override timestamp'
,
:aggregate_failures
do
expect
(
described_class
.
find_by_namespace_id
(
namespace
.
id
).
subscription_created_at
).
to
be_nil
register_action
expect
(
described_class
.
find_by_namespace_id
(
namespace
.
id
).
subscription_created_at
).
not_to
be_nil
expect
{
described_class
.
register
(
namespace
,
action
)
}.
not_to
change
{
described_class
.
find_by_namespace_id
(
namespace
.
id
).
subscription_created_at
}
end
context
'when the action does not exist'
do
let
(
:action
)
{
:foo
}
it
'does not register the action for the namespace'
do
expect
{
register_action
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
nil
)
end
end
end
context
'when the namespace was not onboarded'
do
it
'does not register the action for the namespace'
do
expect
{
register_action
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
nil
)
expect
{
register_action
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
false
)
end
end
end
context
'when the namespace was not onboarded'
do
it
'does not register the action for the namespace'
do
expect
{
register_action
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action
)
}.
from
(
false
)
context
'for multiple actions'
do
let
(
:action1
)
{
:security_scan_enabled
}
let
(
:action2
)
{
:secure_dependency_scanning_run
}
let
(
:actions
)
{
[
action1
,
action2
]
}
subject
(
:register_action
)
{
described_class
.
register
(
namespace
,
actions
)
}
context
'when the namespace was onboarded'
do
before
do
described_class
.
onboard
(
namespace
)
end
it
'registers the actions for the namespace'
do
expect
{
register_action
}.
to
change
{
[
described_class
.
completed?
(
namespace
,
action1
),
described_class
.
completed?
(
namespace
,
action2
)]
}.
from
([
false
,
false
]).
to
([
true
,
true
])
end
it
'does not override timestamp'
,
:aggregate_failures
do
described_class
.
register
(
namespace
,
[
action1
])
expect
(
described_class
.
find_by_namespace_id
(
namespace
.
id
).
security_scan_enabled_at
).
not_to
be_nil
expect
(
described_class
.
find_by_namespace_id
(
namespace
.
id
).
secure_dependency_scanning_run_at
).
to
be_nil
expect
{
described_class
.
register
(
namespace
,
[
action1
,
action2
])
}.
not_to
change
{
described_class
.
find_by_namespace_id
(
namespace
.
id
).
security_scan_enabled_at
}
expect
(
described_class
.
find_by_namespace_id
(
namespace
.
id
).
secure_dependency_scanning_run_at
).
not_to
be_nil
end
context
'when one of the actions does not exist'
do
let
(
:action2
)
{
:foo
}
it
'does not register any action for the namespace'
do
expect
{
register_action
}.
not_to
change
{
[
described_class
.
completed?
(
namespace
,
action1
),
described_class
.
completed?
(
namespace
,
action2
)]
}.
from
([
false
,
nil
])
end
end
end
context
'when the namespace was not onboarded'
do
it
'does not register the action for the namespace'
do
expect
{
register_action
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action1
)
}.
from
(
false
)
expect
{
described_class
.
register
(
namespace
,
action
)
}.
not_to
change
{
described_class
.
completed?
(
namespace
,
action2
)
}.
from
(
false
)
end
end
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment