Skip to content

Commit

Permalink
Validate aclpolicy in system/acl API uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
gschueler committed Jul 31, 2015
1 parent 8ac7569 commit c5d6d9d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
Expand Up @@ -3,6 +3,7 @@ package rundeck.controllers
import com.dtolabs.rundeck.app.support.PluginConfigParams
import com.dtolabs.rundeck.app.support.StoreFilterCommand
import com.dtolabs.rundeck.core.authorization.AuthContext
import com.dtolabs.rundeck.core.authorization.Validation
import com.dtolabs.rundeck.core.common.IRundeckProject
import com.dtolabs.rundeck.core.common.ProviderService
import com.dtolabs.rundeck.core.execution.service.ExecutionServiceException
Expand All @@ -21,6 +22,7 @@ import rundeck.services.ApiService
import rundeck.services.AuthorizationService
import rundeck.services.PasswordFieldsService

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.util.regex.Pattern
import java.util.regex.PatternSyntaxException
Expand Down Expand Up @@ -63,6 +65,7 @@ class FrameworkController extends ControllerBase {
def metricService
def ApiService apiService
def configStorageService
def AuthorizationService authorizationService
// the delete, save and update actions only
// accept POST requests
def static allowedMethods = [
Expand Down Expand Up @@ -2104,6 +2107,26 @@ class FrameworkController extends ControllerBase {
])
}

//validate input
Validation validation = authorizationService.validateYamlPolicy(params.path, text)
if(!validation.valid){
response.status==HttpServletResponse.SC_BAD_REQUEST
return withFormat{
def j={
render(contentType:'application/json'){
return apiService.renderJsonAclpolicyValidation(validation,delegate)
}
}
xml{
render(contentType: 'application/xml'){
return apiService.renderXmlAclpolicyValidation(validation,delegate)
}
}
json j
'*' j
}
}

configStorageService.writeFileResource(storagePath,new ByteArrayInputStream(text.bytes),[:])

if(respFormat in ['yaml','text']){
Expand Down
Expand Up @@ -7,7 +7,6 @@ import com.dtolabs.rundeck.app.support.StoreFilterCommand
import com.dtolabs.rundeck.core.authorization.AuthContext
import com.dtolabs.rundeck.core.authorization.AuthorizationUtil
import com.dtolabs.rundeck.core.authorization.Validation
import com.dtolabs.rundeck.core.authorization.providers.YamlProvider
import com.dtolabs.rundeck.core.common.Framework
import com.dtolabs.rundeck.core.common.IRundeckProject
import com.dtolabs.rundeck.core.execution.service.FileCopierService
Expand All @@ -29,6 +28,7 @@ import rundeck.codecs.JobsXMLCodec
import rundeck.codecs.JobsYAMLCodec
import rundeck.filters.ApiRequestFilters
import rundeck.services.ApiService
import rundeck.services.AuthorizationService
import rundeck.services.ExecutionService
import rundeck.services.FrameworkService
import rundeck.services.LogFileStorageService
Expand All @@ -55,6 +55,7 @@ class MenuController extends ControllerBase{
def configurationService
def quartzScheduler
def ApiService apiService
def AuthorizationService authorizationService
static allowedMethods = [
deleteJobfilter:'POST',
storeJobfilter:'POST',
Expand Down Expand Up @@ -616,7 +617,7 @@ class MenuController extends ControllerBase{
def fwkConfigDir=frameworkService.rundeckFramework.getConfigDir()
def list=fwkConfigDir.listFiles().grep{it.name=~/\.aclpolicy$/}.sort()
Map<File,Validation> validation=list.collectEntries{
[it,YamlProvider.validate(YamlProvider.sourceFromFile(it))]
[it,authorizationService.validateYamlPolicy(it)]
}

[rundeckFramework: frameworkService.rundeckFramework,fwkConfigDir:fwkConfigDir, aclFileList: list, validations: validation]
Expand Down
23 changes: 23 additions & 0 deletions rundeckapp/grails-app/services/rundeck/services/ApiService.groovy
@@ -1,5 +1,6 @@
package rundeck.services

import com.dtolabs.rundeck.core.authorization.Validation
import grails.converters.JSON
import grails.web.JSONBuilder
import groovy.xml.MarkupBuilder
Expand Down Expand Up @@ -611,6 +612,28 @@ class ApiService {
path.lastIndexOf('/')>=0?path.substring(path.lastIndexOf('/') + 1):path
}

public void renderJsonAclpolicyValidation(Validation validation, builder){
builder.valid = validation.valid
if(!validation.valid) {
builder.'policies' = builder.array {
def d=delegate
validation.errors.keySet().sort().each { ident ->
builder.'element'(policy: ident, errors: validation.errors[ident])
}
}
}
}
public void renderXmlAclpolicyValidation(Validation validation, builder){
builder.'validation'(valid:validation.valid){
validation.errors?.keySet().sort().each{ident->
policy(id:ident){
validation.errors[ident].each{
delegate.error(it)
}
}
}
}
}
/**
* Render execution document for api response
*/
Expand Down
Expand Up @@ -8,6 +8,7 @@ import com.dtolabs.rundeck.core.authorization.AclRuleSetSource
import com.dtolabs.rundeck.core.authorization.AclsUtil
import com.dtolabs.rundeck.core.authorization.Authorization
import com.dtolabs.rundeck.core.authorization.RuleEvaluator
import com.dtolabs.rundeck.core.authorization.Validation
import com.dtolabs.rundeck.core.authorization.providers.*
import com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
Expand Down Expand Up @@ -71,6 +72,13 @@ class AuthorizationService implements InitializingBean{
}
}

public Validation validateYamlPolicy(String ident, String text){
YamlProvider.validate(YamlProvider.sourceFromString(ident,text,new Date()))
}

public Validation validateYamlPolicy(File file){
YamlProvider.validate(YamlProvider.sourceFromFile(file))
}

private Policies getStoredPolicies() {
//TODO: cache
Expand Down

0 comments on commit c5d6d9d

Please sign in to comment.