Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
FIY695
jenkins
提交
581eb9ce
J
jenkins
项目概览
FIY695
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
581eb9ce
编写于
9月 04, 2015
作者:
V
Valentina Armenise
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[SECURITY-186] check user permissions when calling QUEUE API
上级
9fd92363
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
174 addition
and
11 deletion
+174
-11
core/src/main/java/hudson/model/Queue.java
core/src/main/java/hudson/model/Queue.java
+99
-9
test/src/test/java/hudson/model/QueueTest.java
test/src/test/java/hudson/model/QueueTest.java
+75
-2
未找到文件。
core/src/main/java/hudson/model/Queue.java
浏览文件 @
581eb9ce
...
@@ -109,6 +109,7 @@ import jenkins.security.QueueItemAuthenticatorConfiguration;
...
@@ -109,6 +109,7 @@ import jenkins.security.QueueItemAuthenticatorConfiguration;
import
jenkins.util.AtmostOneTaskExecutor
;
import
jenkins.util.AtmostOneTaskExecutor
;
import
org.acegisecurity.AccessDeniedException
;
import
org.acegisecurity.AccessDeniedException
;
import
org.acegisecurity.Authentication
;
import
org.acegisecurity.Authentication
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponses
;
import
org.kohsuke.stapler.HttpResponses
;
import
org.kohsuke.stapler.export.Exported
;
import
org.kohsuke.stapler.export.Exported
;
...
@@ -694,15 +695,68 @@ public class Queue extends ResourceController implements Saveable {
...
@@ -694,15 +695,68 @@ public class Queue extends ResourceController implements Saveable {
*/
*/
@Exported
(
inline
=
true
)
@Exported
(
inline
=
true
)
public
synchronized
Item
[]
getItems
()
{
public
synchronized
Item
[]
getItems
()
{
Item
[]
r
=
new
Item
[
waitingList
.
size
()
+
blockedProjects
.
size
()
+
buildables
.
size
()
+
pendings
.
size
()];
List
<
Item
>
r
=
new
ArrayList
<
Item
>();
waitingList
.
toArray
(
r
);
int
idx
=
waitingList
.
size
();
for
(
WaitingItem
p
:
waitingList
)
{
for
(
BlockedItem
p
:
blockedProjects
.
values
())
r
=
filterItemListBasedOnPermissions
(
r
,
p
);
r
[
idx
++]
=
p
;
}
for
(
BuildableItem
p
:
reverse
(
buildables
.
values
()))
for
(
BlockedItem
p
:
blockedProjects
.
values
()){
r
[
idx
++]
=
p
;
r
=
filterItemListBasedOnPermissions
(
r
,
p
);
for
(
BuildableItem
p
:
reverse
(
pendings
.
values
()))
}
r
[
idx
++]
=
p
;
for
(
BuildableItem
p
:
reverse
(
buildables
.
values
()))
{
r
=
filterItemListBasedOnPermissions
(
r
,
p
);
}
for
(
BuildableItem
p
:
reverse
(
pendings
.
values
()))
{
r
=
filterItemListBasedOnPermissions
(
r
,
p
);
}
Item
[]
items
=
new
Item
[
r
.
size
()];
r
.
toArray
(
items
);
return
items
;
}
private
List
<
Item
>
filterItemListBasedOnPermissions
(
List
<
Item
>
r
,
Item
t
)
{
if
(
t
.
task
instanceof
hudson
.
model
.
Item
)
{
if
(((
hudson
.
model
.
Item
)
t
.
task
).
hasPermission
(
hudson
.
model
.
Item
.
READ
))
{
r
.
add
(
t
);
}
}
return
r
;
}
/**
* Returns an array of Item for which it is only visible the name of the task.
*
* Generally speaking the array is sorted such that the items that are most likely built sooner are
* at the end.
*/
@Restricted
(
NoExternalUse
.
class
)
@Exported
(
inline
=
true
)
public
synchronized
StubItem
[]
getDiscoverableItems
()
{
List
<
StubItem
>
r
=
new
ArrayList
<
StubItem
>();
for
(
WaitingItem
p
:
waitingList
)
{
r
=
filterDiscoverableItemListBasedOnPermissions
(
r
,
p
);
}
for
(
BlockedItem
p
:
blockedProjects
.
values
()){
r
=
filterDiscoverableItemListBasedOnPermissions
(
r
,
p
);
}
for
(
BuildableItem
p
:
reverse
(
buildables
.
values
()))
{
r
=
filterDiscoverableItemListBasedOnPermissions
(
r
,
p
);
}
for
(
BuildableItem
p
:
reverse
(
pendings
.
values
()))
{
r
=
filterDiscoverableItemListBasedOnPermissions
(
r
,
p
);
}
StubItem
[]
items
=
new
StubItem
[
r
.
size
()];
r
.
toArray
(
items
);
return
items
;
}
private
List
<
StubItem
>
filterDiscoverableItemListBasedOnPermissions
(
List
<
StubItem
>
r
,
Item
t
)
{
if
(
t
.
task
instanceof
hudson
.
model
.
Item
)
{
if
(!((
hudson
.
model
.
Item
)
t
.
task
).
hasPermission
(
hudson
.
model
.
Item
.
READ
)
&&
((
hudson
.
model
.
Item
)
t
.
task
).
hasPermission
(
hudson
.
model
.
Item
.
DISCOVER
))
{
r
.
add
(
new
StubItem
(
new
StubTask
(
t
.
task
)));
}
}
return
r
;
return
r
;
}
}
...
@@ -1581,6 +1635,42 @@ public class Queue extends ResourceController implements Saveable {
...
@@ -1581,6 +1635,42 @@ public class Queue extends ResourceController implements Saveable {
}
}
}
}
/**
* A Stub class for {@link Task} which exposes only the name of the Task to be displayed when the user
* has DISCOVERY permissions only.
*/
@Restricted
(
NoExternalUse
.
class
)
@ExportedBean
(
defaultVisibility
=
999
)
public
static
class
StubTask
{
private
String
name
;
public
StubTask
(
@Nonnull
Queue
.
Task
base
)
{
this
.
name
=
base
.
getName
();
}
@Exported
public
String
getName
()
{
return
name
;
}
}
/**
* A Stub class for {@link Item} which exposes only the name of the Task to be displayed when the user
* has DISCOVERY permissions only.
*/
@Restricted
(
NoExternalUse
.
class
)
@ExportedBean
(
defaultVisibility
=
999
)
public
class
StubItem
{
@Exported
public
StubTask
task
;
public
StubItem
(
StubTask
task
)
{
this
.
task
=
task
;
}
}
/**
/**
* An optional interface for actions on Queue.Item.
* An optional interface for actions on Queue.Item.
...
...
test/src/test/java/hudson/model/QueueTest.java
浏览文件 @
581eb9ce
...
@@ -23,9 +23,12 @@
...
@@ -23,9 +23,12 @@
*/
*/
package
hudson.model
;
package
hudson.model
;
import
com.gargoylesoftware.htmlunit.html.DomElement
;
import
com.gargoylesoftware.htmlunit.html.DomNode
;
import
com.gargoylesoftware.htmlunit.html.HtmlFileInput
;
import
com.gargoylesoftware.htmlunit.html.HtmlFileInput
;
import
com.gargoylesoftware.htmlunit.html.HtmlForm
;
import
com.gargoylesoftware.htmlunit.html.HtmlForm
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
com.gargoylesoftware.htmlunit.xml.XmlPage
;
import
hudson.Launcher
;
import
hudson.Launcher
;
import
hudson.matrix.AxisList
;
import
hudson.matrix.AxisList
;
import
hudson.matrix.LabelAxis
;
import
hudson.matrix.LabelAxis
;
...
@@ -39,11 +42,16 @@ import hudson.model.Queue.BlockedItem;
...
@@ -39,11 +42,16 @@ import hudson.model.Queue.BlockedItem;
import
hudson.model.Queue.Executable
;
import
hudson.model.Queue.Executable
;
import
hudson.model.Queue.WaitingItem
;
import
hudson.model.Queue.WaitingItem
;
import
hudson.model.queue.AbstractQueueTask
;
import
hudson.model.queue.AbstractQueueTask
;
import
hudson.model.queue.CauseOfBlockage
;
import
hudson.model.queue.QueueTaskDispatcher
;
import
hudson.model.queue.QueueTaskFuture
;
import
hudson.model.queue.QueueTaskFuture
;
import
hudson.model.queue.ScheduleResult
;
import
hudson.model.queue.ScheduleResult
;
import
hudson.model.queue.SubTask
;
import
hudson.model.queue.SubTask
;
import
hudson.security.ACL
;
import
hudson.security.ACL
;
import
hudson.security.AuthorizationMatrixProperty
;
import
hudson.security.GlobalMatrixAuthorizationStrategy
;
import
hudson.security.GlobalMatrixAuthorizationStrategy
;
import
hudson.security.Permission
;
import
hudson.security.ProjectMatrixAuthorizationStrategy
;
import
hudson.security.SparseACL
;
import
hudson.security.SparseACL
;
import
hudson.slaves.DumbSlave
;
import
hudson.slaves.DumbSlave
;
import
hudson.slaves.DummyCloudImpl
;
import
hudson.slaves.DummyCloudImpl
;
...
@@ -58,7 +66,10 @@ import java.io.IOException;
...
@@ -58,7 +66,10 @@ import java.io.IOException;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.CancellationException
;
import
java.util.concurrent.CancellationException
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
...
@@ -84,7 +95,9 @@ import org.jvnet.hudson.test.Bug;
...
@@ -84,7 +95,9 @@ import org.jvnet.hudson.test.Bug;
import
org.jvnet.hudson.test.HudsonTestCase
;
import
org.jvnet.hudson.test.HudsonTestCase
;
import
org.jvnet.hudson.test.MockQueueItemAuthenticator
;
import
org.jvnet.hudson.test.MockQueueItemAuthenticator
;
import
org.jvnet.hudson.test.SequenceLock
;
import
org.jvnet.hudson.test.SequenceLock
;
import
org.jvnet.hudson.test.SleepBuilder
;
import
org.jvnet.hudson.test.TestBuilder
;
import
org.jvnet.hudson.test.TestBuilder
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.mortbay.jetty.Server
;
import
org.mortbay.jetty.Server
;
import
org.mortbay.jetty.bio.SocketConnector
;
import
org.mortbay.jetty.bio.SocketConnector
;
import
org.mortbay.jetty.servlet.ServletHandler
;
import
org.mortbay.jetty.servlet.ServletHandler
;
...
@@ -413,11 +426,11 @@ public class QueueTest extends HudsonTestCase {
...
@@ -413,11 +426,11 @@ public class QueueTest extends HudsonTestCase {
FreeStyleBuild
b
=
v
.
waitForStart
();
FreeStyleBuild
b
=
v
.
waitForStart
();
assertEquals
(
1
,
b
.
getNumber
());
assertEquals
(
1
,
b
.
getNumber
());
assertTrue
(
b
.
isBuilding
());
assertTrue
(
b
.
isBuilding
());
assertSame
(
p
,
b
.
getProject
());
assertSame
(
p
,
b
.
getProject
());
ev
.
signal
();
// let the build complete
ev
.
signal
();
// let the build complete
FreeStyleBuild
b2
=
assertBuildStatusSuccess
(
v
);
FreeStyleBuild
b2
=
assertBuildStatusSuccess
(
v
);
assertSame
(
b
,
b2
);
assertSame
(
b
,
b2
);
}
}
@Inject
@Inject
...
@@ -579,4 +592,64 @@ public class QueueTest extends HudsonTestCase {
...
@@ -579,4 +592,64 @@ public class QueueTest extends HudsonTestCase {
}
catch
(
CancellationException
e
)
{
}
catch
(
CancellationException
e
)
{
}
}
}
}
public
void
testQueueApiOutputShouldBeFilteredByUserPermission
()
throws
Exception
{
jenkins
.
setSecurityRealm
(
createDummySecurityRealm
());
ProjectMatrixAuthorizationStrategy
str
=
new
ProjectMatrixAuthorizationStrategy
();
str
.
add
(
Jenkins
.
READ
,
"bob"
);
str
.
add
(
Jenkins
.
READ
,
"alice"
);
str
.
add
(
Jenkins
.
READ
,
"james"
);
jenkins
.
setAuthorizationStrategy
(
str
);
FreeStyleProject
project
=
createFreeStyleProject
(
"project"
);
Map
<
Permission
,
Set
<
String
>>
permissions
=
new
HashMap
<
Permission
,
Set
<
String
>>();
permissions
.
put
(
Item
.
READ
,
Collections
.
singleton
(
"bob"
));
permissions
.
put
(
Item
.
DISCOVER
,
Collections
.
singleton
(
"james"
));
AuthorizationMatrixProperty
prop1
=
new
AuthorizationMatrixProperty
(
permissions
);
project
.
addProperty
(
prop1
);
project
.
getBuildersList
().
add
(
new
SleepBuilder
(
10
));
project
.
scheduleBuild2
(
0
);
WebClient
webClient
=
new
WebClient
();
webClient
.
login
(
"bob"
,
"bob"
);
XmlPage
p
=
webClient
.
goToXml
(
"/queue/api/xml"
);
//bob has permission on the project and will be able to see it in the queue together with information such as the URL and the name.
for
(
DomNode
element:
p
.
getFirstChild
().
getFirstChild
().
getChildNodes
()){
if
(
element
.
getNodeName
().
equals
(
"task"
)){
assertEquals
(((
DomElement
)
element
).
getElementsByTagName
(
"name"
).
size
(),
1
);
assertEquals
(((
DomElement
)
element
).
getElementsByTagName
(
"name"
).
item
(
0
).
getFirstChild
().
toString
(),
"project"
);
assertEquals
(((
DomElement
)
element
).
getElementsByTagName
(
"url"
).
size
(),
1
);
}
}
WebClient
webClient2
=
new
WebClient
();
webClient2
.
login
(
"alice"
);
XmlPage
p2
=
webClient2
.
goToXml
(
"/queue/api/xml"
);
//alice does not have permission on the project and will not see it in the queue.
assertEquals
(
"<queue></queue>"
,
p2
.
getContent
());
WebClient
webClient3
=
new
WebClient
();
webClient3
.
login
(
"james"
);
XmlPage
p3
=
webClient3
.
goToXml
(
"/queue/api/xml"
);
//james has DISCOVER permission on the project and will only be able to see the task name.
assertEquals
(
"<queue><discoverableItem><task><name>project</name></task></discoverableItem></queue>"
,
p3
.
getContent
());
}
//we force the project not to be executed so that it stays in the queue
@TestExtension
(
"testQueueApiOutputShouldBeFilteredByUserPermission"
)
public
static
class
MyQueueTaskDispatcher
extends
QueueTaskDispatcher
{
@Override
public
CauseOfBlockage
canTake
(
Node
node
,
Queue
.
BuildableItem
item
)
{
return
new
CauseOfBlockage
()
{
@Override
public
String
getShortDescription
()
{
return
"blocked by canTake"
;
}
};
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录