woodpecker/engine/compiler/builtin/validate.go
2016-04-16 00:51:05 -07:00

105 lines
2.8 KiB
Go

package builtin
import (
"fmt"
"path/filepath"
"github.com/drone/drone/engine/compiler/parse"
)
type validateOp struct {
visitor
plugins []string
trusted bool
}
// NewValidateOp returns a linter that checks container configuration.
func NewValidateOp(trusted bool, plugins []string) Visitor {
return &validateOp{
trusted: trusted,
plugins: plugins,
}
}
func (v *validateOp) VisitContainer(node *parse.ContainerNode) error {
switch node.NodeType {
case parse.NodePlugin, parse.NodeCache, parse.NodeClone:
if err := v.validatePlugins(node); err != nil {
return err
}
}
if node.NodeType == parse.NodePlugin {
if err := v.validatePluginConfig(node); err != nil {
return err
}
}
return v.validateConfig(node)
}
// validate the plugin image and return an error if the plugin
// image does not match the whitelist.
func (v *validateOp) validatePlugins(node *parse.ContainerNode) error {
match := false
for _, pattern := range v.plugins {
ok, err := filepath.Match(pattern, node.Container.Image)
if ok && err == nil {
match = true
break
}
}
if !match {
return fmt.Errorf(
"Plugin %s is not in the whitelist",
node.Container.Image,
)
}
return nil
}
// validate the plugin command and entrypoint and return an error
// the user attempts to set or override these values.
func (v *validateOp) validatePluginConfig(node *parse.ContainerNode) error {
if len(node.Container.Entrypoint) != 0 {
return fmt.Errorf("Cannot set plugin Entrypoint")
}
if len(node.Container.Command) != 0 {
return fmt.Errorf("Cannot set plugin Command")
}
return nil
}
// validate the container configuration and return an error if
// restricted configurations are used.
func (v *validateOp) validateConfig(node *parse.ContainerNode) error {
if v.trusted {
return nil
}
if node.Container.Privileged {
return fmt.Errorf("Insufficient privileges to use privileged mode")
}
if len(node.Container.DNS) != 0 {
return fmt.Errorf("Insufficient privileges to use custom dns")
}
if len(node.Container.DNSSearch) != 0 {
return fmt.Errorf("Insufficient privileges to use dns_search")
}
if len(node.Container.Devices) != 0 {
return fmt.Errorf("Insufficient privileges to use devices")
}
if len(node.Container.ExtraHosts) != 0 {
return fmt.Errorf("Insufficient privileges to use extra_hosts")
}
if len(node.Container.Network) != 0 {
return fmt.Errorf("Insufficient privileges to override the network")
}
if node.Container.OomKillDisable {
return fmt.Errorf("Insufficient privileges to disable oom_kill")
}
if len(node.Container.Volumes) != 0 && node.Type() != parse.NodeCache {
return fmt.Errorf("Insufficient privileges to use volumes")
}
if len(node.Container.VolumesFrom) != 0 {
return fmt.Errorf("Insufficient privileges to use volumes_from")
}
return nil
}