Skip to content
This repository was archived by the owner on Aug 7, 2025. It is now read-only.

Commit 12c7392

Browse files
authored
Merge pull request #18 from rundeck-plugins/enh/acl-updates
Authorization updates for rundeck 3.3.8
2 parents b00e457 + 401d1f0 commit 12c7392

File tree

5 files changed

+164
-96
lines changed

5 files changed

+164
-96
lines changed

rundeck-execution-mode-timer/grails-app/controllers/com/rundeck/plugin/EditProjectController.groovy

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package com.rundeck.plugin
22

3-
import com.dtolabs.rundeck.core.authorization.AuthorizationUtil
3+
import com.dtolabs.rundeck.core.authorization.AuthContextProcessor
44
import com.dtolabs.rundeck.core.common.IRundeckProject
55
import grails.converters.JSON
66
import groovy.time.TimeCategory
77
import groovy.time.TimeDuration
8+
import org.rundeck.core.auth.AuthConstants
89

910
import javax.servlet.http.HttpServletResponse
1011

1112
class EditProjectController {
1213

13-
static final String ACTION_ADMIN = "admin"
14-
static final String RES_TYPE_SYSTEM = "system"
15-
1614
static allowedMethods = [
1715
getExecutionLater: 'GET',
1816
apiProjectDisableLater: 'POST',
@@ -21,17 +19,18 @@ class EditProjectController {
2119
]
2220

2321
def frameworkService
22+
AuthContextProcessor rundeckAuthContextProcessor
2423
def updateModeProjectService
2524
def apiService
2625

2726
def boolean requireAuth(String project) {
2827

2928
def authContext =
30-
frameworkService.getAuthContextForSubjectAndProject(session.subject, project)
31-
if (!frameworkService.authorizeApplicationResource(
32-
authContext,
33-
AuthorizationUtil.resourceType(RES_TYPE_SYSTEM),
34-
ACTION_ADMIN
29+
rundeckAuthContextProcessor.getAuthContextForSubjectAndProject(session.subject, project)
30+
if (!rundeckAuthContextProcessor.authorizeApplicationResource(
31+
authContext,
32+
rundeckAuthContextProcessor.authResourceForProject(project),
33+
AuthConstants.ACTION_ADMIN
3534
)) {
3635
request.errorCode = 'request.error.unauthorized.message'
3736
request.errorArgs = ['Calendar (admin)', 'Server']

rundeck-execution-mode-timer/grails-app/controllers/com/rundeck/plugin/ExecutionModeController.groovy

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package com.rundeck.plugin
22

3+
import com.dtolabs.rundeck.core.authorization.AuthContextProcessor
34
import com.dtolabs.rundeck.core.authorization.AuthorizationUtil
45
import com.dtolabs.rundeck.core.authorization.UserAndRolesAuthContext
6+
import com.dtolabs.rundeck.core.cluster.ClusterInfoService
57
import grails.converters.JSON
68
import groovy.time.TimeCategory
79
import groovy.time.TimeDuration
10+
import org.rundeck.core.auth.AuthConstants
811

912
import javax.servlet.http.HttpServletResponse
1013

1114

1215
class ExecutionModeController {
13-
static final String ACTION_ADMIN = "admin"
14-
static final String RES_TYPE_SYSTEM = "system"
1516

1617
static allowedMethods = [
1718
getExecutionLater: 'GET',
@@ -22,22 +23,23 @@ class ExecutionModeController {
2223
]
2324

2425
def executionModeService
25-
def frameworkService
26+
ClusterInfoService clusterInfoService
27+
AuthContextProcessor rundeckAuthContextProcessor
2628
def apiService
2729

2830
private boolean authorizeSystemAdmin() {
2931

30-
UserAndRolesAuthContext authContext = frameworkService.getAuthContextForSubject(session.subject)
31-
if (!frameworkService.authorizeApplicationResource(
32-
authContext,
33-
AuthorizationUtil.resourceType('system'),
34-
ACTION_ADMIN
32+
UserAndRolesAuthContext authContext = rundeckAuthContextProcessor.getAuthContextForSubject(session.subject)
33+
if (!rundeckAuthContextProcessor.authorizeApplicationResource(
34+
authContext,
35+
AuthConstants.RESOURCE_TYPE_SYSTEM,
36+
AuthConstants.ACTION_ADMIN
3537
)) {
3638
request.errorCode = 'request.error.unauthorized.message'
3739
request.errorArgs = [
3840
'Calendar (admin)',
3941
'Server',
40-
frameworkService.getServerUUID()]
42+
clusterInfoService.getServerUUID()]
4143
response.status = HttpServletResponse.SC_FORBIDDEN
4244
request.titleCode = 'request.error.unauthorized.title'
4345

rundeck-execution-mode-timer/src/test/groovy/com/rundeck/plugin/EditProjectControllerSpec.groovy

Lines changed: 79 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.rundeck.plugin
22

3-
3+
import com.dtolabs.rundeck.core.authorization.AuthContextProcessor
44
import com.dtolabs.rundeck.core.common.IRundeckProject
55
import grails.testing.web.controllers.ControllerUnitTest
6+
import org.rundeck.core.auth.AuthConstants
67
import spock.lang.Specification
8+
import spock.lang.Unroll
9+
710
import javax.security.auth.Subject
811
import com.dtolabs.rundeck.core.authentication.Group
912
import com.dtolabs.rundeck.core.authentication.Username
@@ -25,7 +28,14 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
2528
controller.updateModeProjectService = Mock(UpdateModeProjectService){
2629
getScheduleExecutionLater(_,_)>>[executions:[active:false]]
2730
}
28-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: true)
31+
controller.frameworkService = new MockFrameworkService()
32+
33+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
34+
1 * getAuthContextForSubjectAndProject(_, projectName)>>Mock(UserAndRolesAuthContext)
35+
1 * authResourceForProject(projectName)>>[:]
36+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
37+
0*_(*_)
38+
}
2939

3040
when:
3141
controller.getExecutionLater(projectName)
@@ -45,7 +55,14 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
4555
controller.updateModeProjectService = Mock(UpdateModeProjectService){
4656
getProjectModeChangeStatus(_, _)>> [active:false]
4757
}
48-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: true)
58+
controller.frameworkService = new MockFrameworkService()
59+
60+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
61+
1 * getAuthContextForSubjectAndProject(_, projectName)>>Mock(UserAndRolesAuthContext)
62+
1 * authResourceForProject(projectName)>>[:]
63+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
64+
0*_(*_)
65+
}
4966

5067
when:
5168
controller.getNextExecutionChangeStatus(projectName)
@@ -63,7 +80,14 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
6380
def "test api apiProjectEnableLater auth"(){
6481
given:
6582
String project = "TestProject"
66-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: false)
83+
controller.frameworkService = new MockFrameworkService()
84+
85+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
86+
1 * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
87+
1 * authResourceForProject(project)>>[:]
88+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> false
89+
0*_(*_)
90+
}
6791
controller.apiService = new MockApiService(requireVersion: true)
6892
controller.updateModeProjectService = Mock(UpdateModeProjectService)
6993

@@ -80,7 +104,13 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
80104
def "test api apiProjectDisableLater auth"(){
81105
given:
82106
String project = "TestProject"
83-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: false)
107+
controller.frameworkService = new MockFrameworkService()
108+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
109+
1 * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
110+
1 * authResourceForProject(project)>>[:]
111+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> false
112+
0*_(*_)
113+
}
84114
controller.apiService = new MockApiService(requireVersion: true)
85115
controller.updateModeProjectService = Mock(UpdateModeProjectService)
86116

@@ -94,10 +124,18 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
94124
response.status == 403
95125
}
96126

127+
@Unroll
97128
def "test api apiProjectEnableLater method"(){
98129
given:
99130
String project = "TestProject"
100-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: true)
131+
controller.frameworkService = new MockFrameworkService()
132+
133+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
134+
invocations * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
135+
invocations * authResourceForProject(project)>>[:]
136+
invocations * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
137+
0*_(*_)
138+
}
101139
controller.apiService = new MockApiService(requireVersion: true)
102140
controller.updateModeProjectService = Mock(UpdateModeProjectService)
103141

@@ -112,18 +150,26 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
112150
response.status == statusCode
113151

114152
where:
115-
method | statusCode
116-
'POST' | 400
117-
'GET' | 405
118-
'PUT' | 405
119-
'DELETE' | 405
153+
method | statusCode | invocations
154+
'POST' | 400 | 1
155+
'GET' | 405 | 0
156+
'PUT' | 405 | 0
157+
'DELETE' | 405 | 0
120158

121159
}
122160

161+
@Unroll
123162
def "test api apiProjectDisableLater method"(){
124163
given:
125164
String project = "TestProject"
126-
controller.frameworkService = new MockFrameworkService(authorizeApplicationResource: true)
165+
controller.frameworkService = new MockFrameworkService()
166+
167+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
168+
invocations * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
169+
invocations * authResourceForProject(project)>>[:]
170+
invocations * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
171+
0*_(*_)
172+
}
127173
controller.apiService = new MockApiService(requireVersion: true)
128174
controller.updateModeProjectService = Mock(UpdateModeProjectService)
129175

@@ -138,11 +184,11 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
138184
response.status == statusCode
139185

140186
where:
141-
method | statusCode
142-
'POST' | 400
143-
'GET' | 405
144-
'PUT' | 405
145-
'DELETE' | 405
187+
method | statusCode | invocations
188+
'POST' | 400 | 1
189+
'GET' | 405 | 0
190+
'PUT' | 405 | 0
191+
'DELETE' | 405 | 0
146192

147193
}
148194

@@ -157,7 +203,14 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
157203
getProjectProperties() >> properties
158204
}
159205

160-
MockFrameworkService mockFrameworkService = new MockFrameworkService(authorizeApplicationResource: true)
206+
MockFrameworkService mockFrameworkService = new MockFrameworkService()
207+
208+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
209+
1 * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
210+
1 * authResourceForProject(project)>>[:]
211+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
212+
0*_(*_)
213+
}
161214
mockFrameworkService.setRundeckProject(rundeckProject)
162215

163216
controller.frameworkService = mockFrameworkService
@@ -203,7 +256,14 @@ class EditProjectControllerSpec extends Specification implements ControllerUnitT
203256
getProjectProperties() >> properties
204257
}
205258

206-
MockFrameworkService mockFrameworkService = new MockFrameworkService(authorizeApplicationResource: true)
259+
MockFrameworkService mockFrameworkService = new MockFrameworkService()
260+
261+
controller.rundeckAuthContextProcessor = Mock(AuthContextProcessor){
262+
1 * getAuthContextForSubjectAndProject(_, project)>>Mock(UserAndRolesAuthContext)
263+
1 * authResourceForProject(project)>>[:]
264+
1 * authorizeApplicationResource(_, _, AuthConstants.ACTION_ADMIN) >> true
265+
0*_(*_)
266+
}
207267
mockFrameworkService.setRundeckProject(rundeckProject)
208268

209269
controller.frameworkService = mockFrameworkService
@@ -245,14 +305,9 @@ class MockFrameworkService{
245305
String serverUUID
246306
IRundeckProject rundeckProject
247307

248-
boolean authorizeApplicationResource = true
249-
boolean authorizeApplicationResourceNonAdmin = false
250308
def projectList
251309
String frameworkNodeName
252310
Map frameworkPropertiesMap = [:]
253-
def getAuthContextForSubjectAndProject(Object a, Object b){
254-
return new SubjectAuthContext(null, null)
255-
}
256311

257312
Map frameworkProjectsTestData = [:]
258313

@@ -263,35 +318,6 @@ class MockFrameworkService{
263318
frameworkProjectsTestData[name]
264319
}
265320

266-
UserAndRolesAuthContext getAuthContextForUserAndRolesAndProject(String user, Collection roles, String project) {
267-
def sub = new Subject()
268-
sub.principals = [
269-
new Username(user),
270-
new Group("expect:" + project)
271-
] + roles.collect {
272-
new Group(it)
273-
}
274-
return new SubjectAuthContext(sub, null)
275-
}
276-
def getAuthContextForSubject(Object a){
277-
return new SubjectAuthContext(null, null)
278-
}
279-
280-
def authorizeProjectResources(Object a, Object b, Object c, Object d){
281-
return []
282-
}
283-
def authorizeApplicationResource(Object a, Object b, Object c){
284-
return authorizeApplicationResource
285-
}
286-
287-
def authorizeApplicationResourceAny(Object a, Object b, Object c){
288-
return authorizeApplicationResource || authorizeApplicationResourceNonAdmin
289-
}
290-
291-
def authorizeProjectJobAny(Object a, Object b, Object c, Object d){
292-
return authorizeApplicationResource
293-
}
294-
295321
IRundeckProject getRundeckProject() {
296322
return rundeckProject
297323
}

0 commit comments

Comments
 (0)