Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
gitlab-foss
提交
bad08fbe
G
gitlab-foss
项目概览
李少辉-开发者
/
gitlab-foss
通知
15
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
gitlab-foss
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bad08fbe
编写于
5月 16, 2017
作者:
M
Michael Kozono
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move CI access logic into GitAccess
上级
b3874294
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
198 addition
and
57 deletion
+198
-57
app/controllers/concerns/lfs_request.rb
app/controllers/concerns/lfs_request.rb
+4
-0
app/controllers/projects/git_http_client_controller.rb
app/controllers/projects/git_http_client_controller.rb
+1
-19
app/controllers/projects/git_http_controller.rb
app/controllers/projects/git_http_controller.rb
+10
-6
lib/gitlab/git_access.rb
lib/gitlab/git_access.rb
+17
-3
spec/lib/gitlab/git_access_spec.rb
spec/lib/gitlab/git_access_spec.rb
+127
-1
spec/requests/git_http_spec.rb
spec/requests/git_http_spec.rb
+33
-25
spec/support/git_http_helpers.rb
spec/support/git_http_helpers.rb
+6
-3
未找到文件。
app/controllers/concerns/lfs_request.rb
浏览文件 @
bad08fbe
...
...
@@ -106,4 +106,8 @@ module LfsRequest
def
objects
@objects
||=
(
params
[
:objects
]
||
[]).
to_a
end
def
has_authentication_ability?
(
capability
)
(
authentication_abilities
||
[]).
include?
(
capability
)
end
end
app/controllers/projects/git_http_client_controller.rb
浏览文件 @
bad08fbe
...
...
@@ -128,28 +128,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController
@authentication_result
=
Gitlab
::
Auth
.
find_for_git_client
(
login
,
password
,
project:
project
,
ip:
request
.
ip
)
return
false
unless
@authentication_result
.
success?
if
download_request?
authentication_has_download_access?
else
authentication_has_upload_access?
end
@authentication_result
.
success?
end
def
ci?
authentication_result
.
ci?
(
project
)
end
def
authentication_has_download_access?
has_authentication_ability?
(
:download_code
)
||
has_authentication_ability?
(
:build_download_code
)
end
def
authentication_has_upload_access?
has_authentication_ability?
(
:push_code
)
end
def
has_authentication_ability?
(
capability
)
(
authentication_abilities
||
[]).
include?
(
capability
)
end
end
app/controllers/projects/git_http_controller.rb
浏览文件 @
bad08fbe
...
...
@@ -67,20 +67,24 @@ class Projects::GitHttpController < Projects::GitHttpClientController
end
def
render_denied
if
user
&&
can?
(
user
,
:read_project
,
project
)
render
plain:
access_check
.
message
,
status: :
forbidden
if
access_check
.
message
==
Gitlab
::
GitAccess
::
ERROR_MESSAGES
[
:project_not_found
]
render
plain:
access_check
.
message
,
status: :
not_found
else
# Do not leak information about project existence
render_not_found
render
plain:
access_check
.
message
,
status: :forbidden
end
end
def
upload_pack_allowed?
access_check
.
allowed?
||
ci?
access_check
.
allowed?
end
def
access
@access
||=
access_klass
.
new
(
user
,
project
,
'http'
,
authentication_abilities:
authentication_abilities
)
@access
||=
access_klass
.
new
(
access_actor
,
project
,
'http'
,
authentication_abilities:
authentication_abilities
)
end
def
access_actor
return
user
if
user
return
:ci
if
ci?
end
def
access_check
...
...
lib/gitlab/git_access.rb
浏览文件 @
bad08fbe
...
...
@@ -63,6 +63,11 @@ module Gitlab
authentication_abilities
.
include?
(
:build_download_code
)
&&
user_access
.
can_do_action?
(
:build_download_code
)
end
# Allow generic CI (build without a user) for backwards compatibility
def
ci_can_download_code?
authentication_abilities
.
include?
(
:build_download_code
)
&&
ci?
end
def
protocol_allowed?
Gitlab
::
ProtocolAccess
.
allowed?
(
protocol
)
end
...
...
@@ -115,6 +120,7 @@ module Gitlab
return
if
deploy_key?
passed
=
user_can_download_code?
||
ci_can_download_code?
||
build_can_download_code?
||
guest_can_download_code?
...
...
@@ -184,11 +190,17 @@ module Gitlab
actor
.
is_a?
(
DeployKey
)
end
def
ci?
actor
==
:ci
end
def
can_read_project?
if
deploy_key
if
deploy_key
?
deploy_key
.
has_access_to?
(
project
)
elsif
user
user
.
can?
(
:read_project
,
project
)
elsif
ci?
true
# allow CI (build without a user) for backwards compatibility
end
||
Guest
.
can?
(
:read_project
,
project
)
end
...
...
@@ -213,10 +225,12 @@ module Gitlab
case
actor
when
User
actor
when
DeployKey
nil
when
Key
actor
.
user
when
DeployKey
nil
when
:ci
nil
end
end
...
...
spec/lib/gitlab/git_access_spec.rb
浏览文件 @
bad08fbe
require
'spec_helper'
describe
Gitlab
::
GitAccess
,
lib:
true
do
let
(
:pull_access_check
)
{
access
.
check
(
'git-upload-pack'
,
'_any'
)
}
let
(
:push_access_check
)
{
access
.
check
(
'git-receive-pack'
,
'_any'
)
}
let
(
:access
)
{
Gitlab
::
GitAccess
.
new
(
actor
,
project
,
protocol
,
authentication_abilities:
authentication_abilities
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -51,7 +53,123 @@ describe Gitlab::GitAccess, lib: true do
end
end
describe
'#check with commands disabled'
do
describe
'#check_project_accessibility!'
do
context
'when the project exists'
do
context
'when actor exists'
do
context
'when actor is a DeployKey'
do
let
(
:deploy_key
)
{
create
(
:deploy_key
,
user:
user
,
can_push:
true
)
}
let
(
:actor
)
{
deploy_key
}
context
'when the DeployKey has access to the project'
do
before
{
deploy_key
.
projects
<<
project
}
it
'allows pull access'
do
expect
(
pull_access_check
.
allowed?
).
to
be_truthy
end
it
'allows push access'
do
expect
(
push_access_check
.
allowed?
).
to
be_truthy
end
end
context
'when the Deploykey does not have access to the project'
do
it
'blocks pulls with "not found"'
do
expect
(
pull_access_check
.
allowed?
).
to
be_falsey
expect
(
pull_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
it
'blocks pushes with "not found"'
do
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
end
end
context
'when actor is a User'
do
context
'when the User can read the project'
do
before
{
project
.
team
<<
[
user
,
:master
]
}
it
'allows pull access'
do
expect
(
pull_access_check
.
allowed?
).
to
be_truthy
end
it
'allows push access'
do
expect
(
push_access_check
.
allowed?
).
to
be_truthy
end
end
context
'when the User cannot read the project'
do
it
'blocks pulls with "not found"'
do
expect
(
pull_access_check
.
allowed?
).
to
be_falsey
expect
(
pull_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
it
'blocks pushes with "not found"'
do
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
end
end
# For backwards compatibility
context
'when actor is :ci'
do
let
(
:actor
)
{
:ci
}
let
(
:authentication_abilities
)
{
build_authentication_abilities
}
it
'allows pull access'
do
expect
(
pull_access_check
.
allowed?
).
to
be_truthy
end
it
'does not block pushes with "not found"'
do
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'You are not allowed to upload code for this project.'
)
end
end
end
context
'when actor is nil'
do
let
(
:actor
)
{
nil
}
context
'when guests can read the project'
do
let
(
:project
)
{
create
(
:project
,
:repository
,
:public
)
}
it
'allows pull access'
do
expect
(
pull_access_check
.
allowed?
).
to
be_truthy
end
it
'does not block pushes with "not found"'
do
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'You are not allowed to upload code for this project.'
)
end
end
context
'when guests cannot read the project'
do
it
'blocks pulls with "not found"'
do
expect
(
pull_access_check
.
allowed?
).
to
be_falsey
expect
(
pull_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
it
'blocks pushes with "not found"'
do
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
end
end
end
context
'when the project is nil'
do
let
(
:project
)
{
nil
}
it
'blocks any command with "not found"'
do
expect
(
pull_access_check
.
allowed?
).
to
be_falsey
expect
(
pull_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
expect
(
push_access_check
.
allowed?
).
to
be_falsey
expect
(
push_access_check
.
message
).
to
eq
(
'The project you were looking for could not be found.'
)
end
end
end
describe
'#check_command_disabled!'
do
before
{
project
.
team
<<
[
user
,
:master
]
}
context
'over http'
do
...
...
@@ -219,6 +337,14 @@ describe Gitlab::GitAccess, lib: true do
end
end
end
describe
'generic CI (build without a user)'
do
let
(
:actor
)
{
:ci
}
context
'pull code'
do
it
{
expect
(
subject
).
to
be_allowed
}
end
end
end
end
...
...
spec/requests/git_http_spec.rb
浏览文件 @
bad08fbe
...
...
@@ -489,29 +489,41 @@ describe 'Git HTTP requests', lib: true do
end
context
"when a gitlab ci token is provided"
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:build
)
{
create
(
:ci_build
,
:running
)
}
let
(
:project
)
{
build
.
project
}
let
(
:other_project
)
{
create
(
:empty_project
)
}
before
do
build
.
update!
(
project:
project
)
# can't associate it on factory create
end
context
'when build created by system is authenticated'
do
let
(
:path
)
{
"
#{
project
.
path_with_namespace
}
.git"
}
let
(
:env
)
{
{
user:
'gitlab-ci-token'
,
password:
build
.
token
}
}
it_behaves_like
'pulls are allowed'
# TODO Verify this is desired behavior
it
"rejects pushes with 401 Unauthorized (no project existence information leak)"
do
# A non-401 here is not an information leak since the system is
# "authenticated" as CI using the correct token. It does not have
# push access, so pushes should be rejected as forbidden, and giving
# a reason is fine.
#
# We know for sure it is not an information leak since pulls using
# the build token must be allowed.
it
"rejects pushes with 403 Forbidden"
do
push_get
(
path
,
env
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
expect
(
response
).
to
have_http_status
(
:forbidden
)
expect
(
response
.
body
).
to
eq
(
git_access_error
(
:upload
))
end
# TODO Verify this is desired behavior. Should be 403 Forbidden?
# We are "authenticated" as CI using a valid token here. But we are
# not authorized to see any other project, so return "not found".
it
"rejects pulls for other project with 404 Not Found"
do
clone_get
(
"
#{
other_project
.
path_with_namespace
}
.git"
,
env
)
expect
(
response
).
to
have_http_status
(
:not_found
)
expect
(
response
.
body
).
to
eq
(
'TODO: What should this be?'
)
expect
(
response
.
body
).
to
eq
(
git_access_error
(
:project_not_found
)
)
end
end
...
...
@@ -522,31 +534,27 @@ describe 'Git HTTP requests', lib: true do
end
shared_examples
'can download code only'
do
it
'downloads get status 200'
do
allow_any_instance_of
(
Repository
).
to
receive
(
:exists?
).
and_return
(
true
)
clone_get
"
#{
project
.
path_with_namespace
}
.git"
,
user:
'gitlab-ci-token'
,
password:
build
.
token
let
(
:path
)
{
"
#{
project
.
path_with_namespace
}
.git"
}
let
(
:env
)
{
{
user:
'gitlab-ci-token'
,
password:
build
.
token
}
}
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
.
content_type
.
to_s
).
to
eq
(
Gitlab
::
Workhorse
::
INTERNAL_API_CONTENT_TYPE
)
end
it
'downloads from non-existing repository and gets 403'
do
allow_any_instance_of
(
Repository
).
to
receive
(
:exists?
).
and_return
(
false
)
it_behaves_like
'pulls are allowed'
clone_get
"
#{
project
.
path_with_namespace
}
.git"
,
user:
'gitlab-ci-token'
,
password:
build
.
token
context
'when the repo does not exist'
do
let
(
:project
)
{
create
(
:empty_project
)
}
it
'rejects pulls with 403 Forbidden'
do
clone_get
path
,
env
expect
(
response
).
to
have_http_status
(
:forbidden
)
expect
(
response
).
to
have_http_status
(
:forbidden
)
expect
(
response
.
body
).
to
eq
(
git_access_error
(
:no_repo
))
end
end
it
'
uploads get status 403
'
do
push_get
"
#{
project
.
path_with_namespace
}
.git"
,
user:
'gitlab-ci-token'
,
password:
build
.
token
it
'
rejects pushes with 403 Forbidden
'
do
push_get
path
,
env
expect
(
response
).
to
have_http_status
(
:unauthorized
)
expect
(
response
).
to
have_http_status
(
:forbidden
)
expect
(
response
.
body
).
to
eq
(
git_access_error
(
:upload
))
end
end
...
...
spec/support/git_http_helpers.rb
浏览文件 @
bad08fbe
...
...
@@ -52,14 +52,17 @@ module GitHttpHelpers
end
def
git_access_error
(
error_key
)
Gitlab
::
GitAccess
::
ERROR_MESSAGES
[
error_key
]
message
=
Gitlab
::
GitAccess
::
ERROR_MESSAGES
[
error_key
]
message
||
raise
(
"GitAccess error message key '
#{
error_key
}
' not found"
)
end
def
git_access_wiki_error
(
error_key
)
Gitlab
::
GitAccessWiki
::
ERROR_MESSAGES
[
error_key
]
message
=
Gitlab
::
GitAccessWiki
::
ERROR_MESSAGES
[
error_key
]
message
||
raise
(
"GitAccessWiki error message key '
#{
error_key
}
' not found"
)
end
def
change_access_error
(
error_key
)
Gitlab
::
Checks
::
ChangeAccess
::
ERROR_MESSAGES
[
error_key
]
message
=
Gitlab
::
Checks
::
ChangeAccess
::
ERROR_MESSAGES
[
error_key
]
message
||
raise
(
"ChangeAccess error message key '
#{
error_key
}
' not found"
)
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录