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
9f625452
Commit
9f625452
authored
Jun 04, 2020
by
Francisco Javier López
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding snippet repository validation after bundle import
parent
d1edb853
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
226 additions
and
18 deletions
+226
-18
app/services/snippets/repository_validation_service.rb
app/services/snippets/repository_validation_service.rb
+72
-0
changelogs/unreleased/security-fj-add-snippet-repository-validation-bundle-import.yml
...ty-fj-add-snippet-repository-validation-bundle-import.yml
+5
-0
lib/gitlab/import_export/snippet_repo_restorer.rb
lib/gitlab/import_export/snippet_repo_restorer.rb
+11
-1
locale/gitlab.pot
locale/gitlab.pot
+21
-0
spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
+47
-17
spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
+1
-0
spec/services/snippets/repository_validation_service_spec.rb
spec/services/snippets/repository_validation_service_spec.rb
+69
-0
No files found.
app/services/snippets/repository_validation_service.rb
0 → 100644
View file @
9f625452
# frozen_string_literal: true
module
Snippets
class
RepositoryValidationService
attr_reader
:current_user
,
:snippet
,
:repository
RepositoryValidationError
=
Class
.
new
(
StandardError
)
def
initialize
(
user
,
snippet
)
@current_user
=
user
@snippet
=
snippet
@repository
=
snippet
.
repository
end
def
execute
if
snippet
.
nil?
return
service_response_error
(
'No snippet found.'
,
404
)
end
check_branch_count!
check_branch_name_default!
check_tag_count!
check_file_count!
check_size!
ServiceResponse
.
success
(
message:
'Valid snippet repository.'
)
rescue
RepositoryValidationError
=>
e
ServiceResponse
.
error
(
message:
"Error:
#{
e
.
message
}
"
,
http_status:
400
)
end
private
def
check_branch_count!
return
if
repository
.
branch_count
==
1
raise
RepositoryValidationError
,
_
(
'Repository has more than one branch.'
)
end
def
check_branch_name_default!
branches
=
repository
.
branch_names
return
if
branches
.
first
==
Gitlab
::
Checks
::
SnippetCheck
::
DEFAULT_BRANCH
raise
RepositoryValidationError
,
_
(
'Repository has an invalid default branch name.'
)
end
def
check_tag_count!
return
if
repository
.
tag_count
==
0
raise
RepositoryValidationError
,
_
(
'Repository has tags.'
)
end
def
check_file_count!
file_count
=
repository
.
ls_files
(
nil
).
size
limit
=
Snippet
.
max_file_limit
(
current_user
)
if
file_count
>
limit
raise
RepositoryValidationError
,
_
(
'Repository files count over the limit'
)
end
if
file_count
==
0
raise
RepositoryValidationError
,
_
(
'Repository must contain at least 1 file.'
)
end
end
def
check_size!
return
unless
snippet
.
repository_size_checker
.
above_size_limit?
raise
RepositoryValidationError
,
_
(
'Repository size is above the limit.'
)
end
end
end
changelogs/unreleased/security-fj-add-snippet-repository-validation-bundle-import.yml
0 → 100644
View file @
9f625452
---
title
:
Add snippet repository validation after bundle import
merge_request
:
author
:
type
:
security
lib/gitlab/import_export/snippet_repo_restorer.rb
View file @
9f625452
...
...
@@ -3,7 +3,7 @@
module
Gitlab
module
ImportExport
class
SnippetRepoRestorer
<
RepoRestorer
attr_reader
:snippet
attr_reader
:snippet
,
:user
SnippetRepositoryError
=
Class
.
new
(
StandardError
)
...
...
@@ -33,6 +33,16 @@ module Gitlab
def
create_repository_from_bundle
repository
.
create_from_bundle
(
path_to_bundle
)
snippet
.
track_snippet_repository
(
repository
.
storage
)
response
=
Snippets
::
RepositoryValidationService
.
new
(
user
,
snippet
).
execute
if
response
.
error?
repository
.
remove
snippet
.
snippet_repository
.
delete
snippet
.
repository
.
expire_exists_cache
raise
SnippetRepositoryError
,
_
(
"Invalid repository bundle for snippet with id %{snippet_id}"
)
%
{
snippet_id:
snippet
.
id
}
end
end
def
create_repository_from_db
...
...
locale/gitlab.pot
View file @
9f625452
...
...
@@ -12353,6 +12353,9 @@ msgstr ""
msgid "Invalid query"
msgstr ""
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
msgid "Invalid repository path"
msgstr ""
...
...
@@ -19054,15 +19057,33 @@ msgstr ""
msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
msgstr ""
msgid "Repository files count over the limit"
msgstr ""
msgid "Repository has an invalid default branch name."
msgstr ""
msgid "Repository has more than one branch."
msgstr ""
msgid "Repository has no locks."
msgstr ""
msgid "Repository has tags."
msgstr ""
msgid "Repository maintenance"
msgstr ""
msgid "Repository mirroring"
msgstr ""
msgid "Repository must contain at least 1 file."
msgstr ""
msgid "Repository size is above the limit."
msgstr ""
msgid "Repository static objects"
msgstr ""
...
...
spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
View file @
9f625452
...
...
@@ -4,9 +4,9 @@ require 'spec_helper'
describe
Gitlab
::
ImportExport
::
SnippetRepoRestorer
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
project:
project
,
author:
user
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
project:
project
,
author:
user
)
}
let
(
:shared
)
{
project
.
import_export_shared
}
let
(
:exporter
)
{
Gitlab
::
ImportExport
::
SnippetsRepoSaver
.
new
(
project:
project
,
shared:
shared
,
current_user:
user
)
}
let
(
:restorer
)
do
...
...
@@ -57,33 +57,63 @@ describe Gitlab::ImportExport::SnippetRepoRestorer do
it_behaves_like
'no bundle file present'
end
context
'when the snippet bundle exists'
do
let!
(
:snippet_with_repo
)
{
create
(
:project_snippet
,
:repository
,
project:
project
)
}
context
'when the snippet
repository
bundle exists'
do
let!
(
:snippet_with_repo
)
{
create
(
:project_snippet
,
:repository
,
project:
project
,
author:
user
)
}
let
(
:bundle_path
)
{
::
Gitlab
::
ImportExport
.
snippets_repo_bundle_path
(
shared
.
export_path
)
}
let
(
:snippet_bundle_path
)
{
File
.
join
(
bundle_path
,
"
#{
snippet_with_repo
.
hexdigest
}
.bundle"
)
}
let
(
:result
)
{
exporter
.
save
}
let
(
:repository
)
{
snippet
.
repository
}
before
do
expect
(
exporter
.
save
).
to
be_truthy
end
it
'creates the repository from the bundle'
do
expect
(
snippet
.
repository_exists?
).
to
be_falsey
expect
(
snippet
.
snippet_repository
).
to
be_nil
expect
(
snippet
.
repository
).
to
receive
(
:create_from_bundle
).
and_call_original
context
'when it is valid'
do
before
do
allow
(
repository
).
to
receive
(
:branch_count
).
and_return
(
1
)
allow
(
repository
).
to
receive
(
:tag_count
).
and_return
(
0
)
allow
(
repository
).
to
receive
(
:branch_names
).
and_return
([
'master'
])
allow
(
repository
).
to
receive
(
:ls_files
).
and_return
([
'foo'
])
end
expect
(
restorer
.
restore
).
to
be_truthy
expect
(
snippet
.
repository_exists?
).
to
be_truth
y
expect
(
snippet
.
snippet_repository
).
not_
to
be_nil
end
it
'creates the repository from the bundle'
do
expect
(
snippet
.
repository_exists?
).
to
be_false
y
expect
(
snippet
.
snippet_repository
).
to
be_nil
expect
(
repository
).
to
receive
(
:create_from_bundle
).
and_call_original
it
'sets same shard in snippet repository as in the repository storage'
do
expect
(
snippet
).
to
receive
(
:repository_storage
).
and_return
(
'picked'
)
expect
(
snippet
.
repository
).
to
receive
(
:create_from_bundle
)
expect
(
restorer
.
restore
).
to
be_truthy
expect
(
snippet
.
repository_exists?
).
to
be_truthy
expect
(
snippet
.
snippet_repository
).
not_to
be_nil
end
restorer
.
restore
it
'sets same shard in snippet repository as in the repository storage'
do
expect
(
repository
).
to
receive
(
:storage
).
and_return
(
'picked'
)
expect
(
repository
).
to
receive
(
:create_from_bundle
)
expect
(
snippet
.
snippet_repository
.
shard_name
).
to
eq
'picked'
expect
(
restorer
.
restore
).
to
be_truthy
expect
(
snippet
.
snippet_repository
.
shard_name
).
to
eq
'picked'
end
end
context
'when it is invalid'
do
it
'returns false and deletes the repository from disk and the database'
do
gitlab_shell
=
Gitlab
::
Shell
.
new
shard_name
=
snippet
.
repository
.
shard
path
=
snippet
.
disk_path
+
'.git'
error_response
=
ServiceResponse
.
error
(
message:
'Foo'
,
http_status:
400
)
allow_next_instance_of
(
Snippets
::
RepositoryValidationService
)
do
|
instance
|
allow
(
instance
).
to
receive
(
:execute
).
and_return
(
error_response
)
end
aggregate_failures
do
expect
(
restorer
.
restore
).
to
be
false
expect
(
shared
.
errors
.
first
).
to
match
(
/Invalid repository bundle/
)
expect
(
snippet
.
repository_exists?
).
to
eq
false
expect
(
snippet
.
reload
.
snippet_repository
).
to
be_nil
expect
(
gitlab_shell
.
repository_exists?
(
shard_name
,
path
)).
to
eq
false
end
end
end
end
end
spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
View file @
9f625452
...
...
@@ -38,6 +38,7 @@ describe Gitlab::ImportExport::SnippetsRepoRestorer do
expect
(
snippet1
.
repository_exists?
).
to
be
false
expect
(
snippet2
.
repository_exists?
).
to
be
false
allow_any_instance_of
(
Snippets
::
RepositoryValidationService
).
to
receive
(
:execute
).
and_return
(
ServiceResponse
.
success
)
expect
(
Gitlab
::
ImportExport
::
SnippetRepoRestorer
).
to
receive
(
:new
).
with
(
hash_including
(
snippet:
snippet1
,
path_to_bundle:
bundle_path
(
snippet1
))).
and_call_original
expect
(
Gitlab
::
ImportExport
::
SnippetRepoRestorer
).
to
receive
(
:new
).
with
(
hash_including
(
snippet:
snippet2
,
path_to_bundle:
bundle_path
(
snippet2
))).
and_call_original
expect
(
restorer
.
restore
).
to
be_truthy
...
...
spec/services/snippets/repository_validation_service_spec.rb
0 → 100644
View file @
9f625452
# frozen_string_literal: true
require
'spec_helper'
describe
Snippets
::
RepositoryValidationService
do
describe
'#execute'
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:snippet
)
{
create
(
:personal_snippet
,
:empty_repo
,
author:
user
)
}
let
(
:repository
)
{
snippet
.
repository
}
let
(
:service
)
{
described_class
.
new
(
user
,
snippet
)
}
subject
{
service
.
execute
}
before
do
allow
(
repository
).
to
receive
(
:branch_count
).
and_return
(
1
)
allow
(
repository
).
to
receive
(
:ls_files
).
and_return
([
'foo'
])
allow
(
repository
).
to
receive
(
:branch_names
).
and_return
([
'master'
])
end
it
'returns error when the repository has more than one branch'
do
allow
(
repository
).
to
receive
(
:branch_count
).
and_return
(
2
)
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository has more than one branch/
end
it
'returns error when existing branch name is not the default one'
do
allow
(
repository
).
to
receive
(
:branch_names
).
and_return
([
'foo'
])
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository has an invalid default branch name/
end
it
'returns error when the repository has tags'
do
allow
(
repository
).
to
receive
(
:tag_count
).
and_return
(
1
)
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository has tags/
end
it
'returns error when the repository has more file than the limit'
do
limit
=
Snippet
.
max_file_limit
(
user
)
+
1
files
=
Array
.
new
(
limit
)
{
FFaker
::
Filesystem
.
file_name
}
allow
(
repository
).
to
receive
(
:ls_files
).
and_return
(
files
)
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository files count over the limit/
end
it
'returns error when the repository has no files'
do
allow
(
repository
).
to
receive
(
:ls_files
).
and_return
([])
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository must contain at least 1 file/
end
it
'returns error when the repository size is over the limit'
do
expect_any_instance_of
(
Gitlab
::
RepositorySizeChecker
).
to
receive
(
:above_size_limit?
).
and_return
(
true
)
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
match
/Repository size is above the limit/
end
it
'returns success when no validation errors are raised'
do
expect
(
subject
).
to
be_success
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