mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 11:51:02 +00:00
provides a way to white-list plugins at a global config level
This commit is contained in:
parent
f3c06a8fc3
commit
8c655d600d
7 changed files with 139 additions and 31 deletions
|
@ -20,7 +20,8 @@ type Context struct {
|
|||
Keys *common.Keypair `json:"keys"`
|
||||
Netrc *common.Netrc `json:"netrc"`
|
||||
Yaml []byte `json:"yaml"`
|
||||
Env []string `json:"env"`
|
||||
Env []string `json:"environment"`
|
||||
Plugins []string `json:"plugins"`
|
||||
|
||||
Conf *common.Config `json:"-"`
|
||||
infos []*dockerclient.ContainerInfo
|
||||
|
@ -29,12 +30,19 @@ type Context struct {
|
|||
|
||||
func setup(c *Context) error {
|
||||
var err error
|
||||
var opts = parser.DefaultOpts
|
||||
var opts = parser.Opts{
|
||||
Network: true,
|
||||
Privileged: true,
|
||||
Volumes: true,
|
||||
Whitelist: c.Plugins,
|
||||
}
|
||||
|
||||
// if repository is trusted the build may specify
|
||||
// custom volumes, networking and run in trusted mode.
|
||||
if c.Repo.Trusted {
|
||||
opts = &parser.Opts{Network: true, Privileged: true, Volumes: true}
|
||||
opts.Network = true
|
||||
opts.Privileged = true
|
||||
opts.Volumes = true
|
||||
}
|
||||
|
||||
// inject the matrix parameters into the yaml
|
||||
|
|
|
@ -15,7 +15,8 @@ type Work struct {
|
|||
Keys *common.Keypair `json:"keypair"`
|
||||
Netrc *common.Netrc `json:"netrc"`
|
||||
Yaml []byte `json:"yaml"`
|
||||
Env []string `json:"env"`
|
||||
Env []string `json:"environment"`
|
||||
Plugins []string `json:"plugins"`
|
||||
}
|
||||
|
||||
// represents a worker that has connected
|
||||
|
|
|
@ -119,6 +119,7 @@ func (r *Runner) Run(w *queue.Work) error {
|
|||
Yaml: w.Yaml,
|
||||
Build: task,
|
||||
Env: w.Env,
|
||||
Plugins: w.Plugins,
|
||||
}
|
||||
in, err := json.Marshal(work)
|
||||
if err != nil {
|
||||
|
|
|
@ -58,7 +58,8 @@ type work struct {
|
|||
Keys *common.Keypair `json:"keys"`
|
||||
Netrc *common.Netrc `json:"netrc"`
|
||||
Yaml []byte `json:"yaml"`
|
||||
Env []string `json:"env"`
|
||||
Env []string `json:"environment"`
|
||||
Plugins []string `json:"plugins"`
|
||||
}
|
||||
|
||||
type worker struct {
|
||||
|
|
|
@ -2,6 +2,7 @@ package parser
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
|
@ -103,3 +104,42 @@ func expectTrustedNotify(c *common.Config) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LintPlugins(c *common.Config, opts *Opts) error {
|
||||
if len(opts.Whitelist) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var images []string
|
||||
images = append(images, c.Setup.Image)
|
||||
images = append(images, c.Clone.Image)
|
||||
c.Clone.Image = imageName(c.Clone.Image)
|
||||
for _, step := range c.Publish {
|
||||
images = append(images, step.Image)
|
||||
}
|
||||
for _, step := range c.Deploy {
|
||||
images = append(images, step.Image)
|
||||
}
|
||||
for _, step := range c.Notify {
|
||||
images = append(images, step.Image)
|
||||
}
|
||||
|
||||
for _, image := range images {
|
||||
match := false
|
||||
for _, pattern := range opts.Whitelist {
|
||||
if pattern == image {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
ok, err := filepath.Match(pattern, image)
|
||||
if ok && err == nil {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return fmt.Errorf("Cannot use un-trusted image %s", image)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -90,3 +90,58 @@ func Test_Linter(t *testing.T) {
|
|||
|
||||
})
|
||||
}
|
||||
|
||||
func Test_LintPlugins(t *testing.T) {
|
||||
|
||||
g := goblin.Goblin(t)
|
||||
g.Describe("Plugin Linter", func() {
|
||||
|
||||
g.It("Should fail un-trusted plugin", func() {
|
||||
c := &common.Config{
|
||||
Setup: &common.Step{Image: "foo/baz"},
|
||||
Clone: &common.Step{Image: "foo/bar"},
|
||||
Notify: map[string]*common.Step{},
|
||||
Deploy: map[string]*common.Step{},
|
||||
Publish: map[string]*common.Step{},
|
||||
}
|
||||
o := &Opts{Whitelist: []string{"plugins/*"}}
|
||||
g.Assert(LintPlugins(c, o) != nil).IsTrue()
|
||||
})
|
||||
|
||||
g.It("Should pass when empty whitelist", func() {
|
||||
c := &common.Config{
|
||||
Setup: &common.Step{Image: "foo/baz"},
|
||||
Clone: &common.Step{Image: "foo/bar"},
|
||||
Notify: map[string]*common.Step{},
|
||||
Deploy: map[string]*common.Step{},
|
||||
Publish: map[string]*common.Step{},
|
||||
}
|
||||
o := &Opts{Whitelist: []string{}}
|
||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
||||
})
|
||||
|
||||
g.It("Should pass wildcard", func() {
|
||||
c := &common.Config{
|
||||
Setup: &common.Step{Image: "plugins/drone-setup"},
|
||||
Clone: &common.Step{Image: "plugins/drone-build"},
|
||||
Notify: map[string]*common.Step{},
|
||||
Deploy: map[string]*common.Step{},
|
||||
Publish: map[string]*common.Step{},
|
||||
}
|
||||
o := &Opts{Whitelist: []string{"plugins/*"}}
|
||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
||||
})
|
||||
|
||||
g.It("Should pass itemized", func() {
|
||||
c := &common.Config{
|
||||
Setup: &common.Step{Image: "plugins/drone-setup"},
|
||||
Clone: &common.Step{Image: "plugins/drone-build"},
|
||||
Notify: map[string]*common.Step{},
|
||||
Deploy: map[string]*common.Step{},
|
||||
Publish: map[string]*common.Step{},
|
||||
}
|
||||
o := &Opts{Whitelist: []string{"plugins/drone-setup", "plugins/drone-build"}}
|
||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ type Opts struct {
|
|||
Volumes bool
|
||||
Network bool
|
||||
Privileged bool
|
||||
Whitelist []string
|
||||
}
|
||||
|
||||
var DefaultOpts = &Opts{
|
||||
Volumes: false,
|
||||
Network: false,
|
||||
Privileged: false,
|
||||
Whitelist: []string{"plugins/*"},
|
||||
}
|
||||
|
||||
// Parse parses a build matrix and returns
|
||||
|
|
Loading…
Reference in a new issue