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
9adcdaab
Commit
9adcdaab
authored
Sep 12, 2019
by
Mark Chao
Committed by
Bob Van Landuyt
Oct 01, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix private feature Elasticsearch leak
Add spec to test different combinations.
parent
7b621c27
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
216 additions
and
1 deletion
+216
-1
app/models/project.rb
app/models/project.rb
+6
-1
changelogs/unreleased/security-29491.yml
changelogs/unreleased/security-29491.yml
+5
-0
spec/models/project_spec.rb
spec/models/project_spec.rb
+30
-0
spec/support/helpers/project_helpers.rb
spec/support/helpers/project_helpers.rb
+25
-0
spec/support/helpers/search_results_helpers.rb
spec/support/helpers/search_results_helpers.rb
+32
-0
spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
..._contexts/policies/project_policy_table_shared_context.rb
+118
-0
No files found.
app/models/project.rb
View file @
9adcdaab
...
...
@@ -482,7 +482,7 @@ class Project < ApplicationRecord
# the feature is either public, enabled, or internal with permission for the user.
# Note: this scope doesn't enforce that the user has access to the projects, it just checks
# that the user has access to the feature. It's important to use this scope with others
# that checks project authorizations first.
# that checks project authorizations first
(e.g. `filter_by_feature_visibility`)
.
#
# This method uses an optimised version of `with_feature_access_level` for
# logged in users to more efficiently get private projects with the given
...
...
@@ -510,6 +510,11 @@ class Project < ApplicationRecord
end
end
# This scope returns projects where user has access to both the project and the feature.
def
self
.
filter_by_feature_visibility
(
feature
,
user
)
with_feature_available_for_user
(
feature
,
user
).
public_or_visible_to_user
(
user
)
end
scope
:active
,
->
{
joins
(
:issues
,
:notes
,
:merge_requests
).
order
(
'issues.created_at, notes.created_at, merge_requests.created_at DESC'
)
}
scope
:abandoned
,
->
{
where
(
'projects.last_activity_at < ?'
,
6
.
months
.
ago
)
}
...
...
changelogs/unreleased/security-29491.yml
0 → 100644
View file @
9adcdaab
---
title
:
Fix private feature Elasticsearch leak
merge_request
:
author
:
type
:
security
spec/models/project_spec.rb
View file @
9adcdaab
...
...
@@ -3469,6 +3469,36 @@ describe Project do
end
end
describe
'.filter_by_feature_visibility'
do
include_context
'ProjectPolicyTable context'
include
ProjectHelpers
using
RSpec
::
Parameterized
::
TableSyntax
set
(
:group
)
{
create
(
:group
)
}
let!
(
:project
)
{
create
(
:project
,
project_level
,
namespace:
group
)
}
let
(
:user
)
{
create_user_from_membership
(
project
,
membership
)
}
context
'reporter level access'
do
let
(
:feature
)
{
MergeRequest
}
where
(
:project_level
,
:feature_access_level
,
:membership
,
:expected_count
)
do
permission_table_for_reporter_feature_access
end
with_them
do
it
"respects visibility"
do
update_feature_access_level
(
project
,
feature_access_level
)
expected_objects
=
expected_count
==
1
?
[
project
]
:
[]
expect
(
described_class
.
filter_by_feature_visibility
(
feature
,
user
)
).
to
eq
(
expected_objects
)
end
end
end
end
describe
'#pages_available?'
do
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
...
...
spec/support/helpers/project_helpers.rb
0 → 100644
View file @
9adcdaab
# frozen_string_literal: true
module
ProjectHelpers
# @params target [Project] membership target
# @params membership [Symbol] accepts the membership levels :guest, :reporter...
# and phony levels :non_member and :anonymous
def
create_user_from_membership
(
target
,
membership
)
case
membership
when
:anonymous
nil
when
:non_member
create
(
:user
,
name:
membership
)
else
create
(
:user
,
name:
membership
).
tap
{
|
u
|
target
.
add_user
(
u
,
membership
)
}
end
end
def
update_feature_access_level
(
project
,
access_level
)
project
.
update!
(
repository_access_level:
access_level
,
merge_requests_access_level:
access_level
,
builds_access_level:
access_level
)
end
end
spec/support/helpers/search_results_helpers.rb
0 → 100644
View file @
9adcdaab
# frozen_string_literal: true
module
SearchResultHelpers
# @param target [Symbol] search target, e.g. "merge_requests", "blobs"
def
expect_search_results
(
users
,
target
,
expected_count:
nil
,
expected_objects:
nil
)
# TODO: https://gitlab.com/gitlab-org/gitlab/issues/32645
return
if
expected_count
&&
expected_count
>
0
users
=
Array
(
users
)
target
=
target
.
to_s
users
.
each
do
|
user
|
user_name
=
user
&
.
name
||
'anonymous user'
results
=
yield
(
user
)
objects
=
results
.
objects
(
target
)
if
expected_count
actual_count
=
results
.
public_send
(
"
#{
target
}
_count"
)
expect
(
actual_count
).
to
eq
(
expected_count
),
"expected count to be
#{
expected_count
}
for
#{
user_name
}
, got
#{
actual_count
}
"
end
if
expected_objects
if
expected_objects
.
empty?
expect
(
objects
.
empty?
).
to
eq
(
true
)
else
expect
(
objects
).
to
contain_exactly
(
*
expected_objects
)
end
end
end
end
end
spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
0 → 100644
View file @
9adcdaab
# frozen_string_literal: true
RSpec
.
shared_context
'ProjectPolicyTable context'
do
using
RSpec
::
Parameterized
::
TableSyntax
# rubocop:disable Metrics/AbcSize
def
permission_table_for_reporter_feature_access
:public
|
:enabled
|
:reporter
|
1
:public
|
:enabled
|
:guest
|
1
:public
|
:enabled
|
:non_member
|
1
:public
|
:enabled
|
:anonymous
|
1
:public
|
:private
|
:reporter
|
1
:public
|
:private
|
:guest
|
0
:public
|
:private
|
:non_member
|
0
:public
|
:private
|
:anonymous
|
0
:public
|
:disabled
|
:reporter
|
0
:public
|
:disabled
|
:guest
|
0
:public
|
:disabled
|
:non_member
|
0
:public
|
:disabled
|
:anonymous
|
0
:internal
|
:enabled
|
:reporter
|
1
:internal
|
:enabled
|
:guest
|
1
:internal
|
:enabled
|
:non_member
|
1
:internal
|
:enabled
|
:anonymous
|
0
:internal
|
:private
|
:reporter
|
1
:internal
|
:private
|
:guest
|
0
:internal
|
:private
|
:non_member
|
0
:internal
|
:private
|
:anonymous
|
0
:internal
|
:disabled
|
:reporter
|
0
:internal
|
:disabled
|
:guest
|
0
:internal
|
:disabled
|
:non_member
|
0
:internal
|
:disabled
|
:anonymous
|
0
:private
|
:enabled
|
:reporter
|
1
:private
|
:enabled
|
:guest
|
1
:private
|
:enabled
|
:non_member
|
0
:private
|
:enabled
|
:anonymous
|
0
:private
|
:private
|
:reporter
|
1
:private
|
:private
|
:guest
|
0
:private
|
:private
|
:non_member
|
0
:private
|
:private
|
:anonymous
|
0
:private
|
:disabled
|
:reporter
|
0
:private
|
:disabled
|
:guest
|
0
:private
|
:disabled
|
:non_member
|
0
:private
|
:disabled
|
:anonymous
|
0
end
def
permission_table_for_guest_feature_access
:public
|
:enabled
|
:reporter
|
1
:public
|
:enabled
|
:guest
|
1
:public
|
:enabled
|
:non_member
|
1
:public
|
:enabled
|
:anonymous
|
1
:public
|
:private
|
:reporter
|
1
:public
|
:private
|
:guest
|
1
:public
|
:private
|
:non_member
|
0
:public
|
:private
|
:anonymous
|
0
:public
|
:disabled
|
:reporter
|
0
:public
|
:disabled
|
:guest
|
0
:public
|
:disabled
|
:non_member
|
0
:public
|
:disabled
|
:anonymous
|
0
:internal
|
:enabled
|
:reporter
|
1
:internal
|
:enabled
|
:guest
|
1
:internal
|
:enabled
|
:non_member
|
1
:internal
|
:enabled
|
:anonymous
|
0
:internal
|
:private
|
:reporter
|
1
:internal
|
:private
|
:guest
|
1
:internal
|
:private
|
:non_member
|
0
:internal
|
:private
|
:anonymous
|
0
:internal
|
:disabled
|
:reporter
|
0
:internal
|
:disabled
|
:guest
|
0
:internal
|
:disabled
|
:non_member
|
0
:internal
|
:disabled
|
:anonymous
|
0
:private
|
:enabled
|
:reporter
|
1
:private
|
:enabled
|
:guest
|
1
:private
|
:enabled
|
:non_member
|
0
:private
|
:enabled
|
:anonymous
|
0
:private
|
:private
|
:reporter
|
1
:private
|
:private
|
:guest
|
1
:private
|
:private
|
:non_member
|
0
:private
|
:private
|
:anonymous
|
0
:private
|
:disabled
|
:reporter
|
0
:private
|
:disabled
|
:guest
|
0
:private
|
:disabled
|
:non_member
|
0
:private
|
:disabled
|
:anonymous
|
0
end
def
permission_table_for_project_access
:public
|
:reporter
|
1
:public
|
:guest
|
1
:public
|
:non_member
|
1
:public
|
:anonymous
|
1
:internal
|
:reporter
|
1
:internal
|
:guest
|
1
:internal
|
:non_member
|
1
:internal
|
:anonymous
|
0
:private
|
:reporter
|
1
:private
|
:guest
|
1
:private
|
:non_member
|
0
:private
|
:anonymous
|
0
end
# rubocop:enable Metrics/AbcSize
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