mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-09-29 15:01:59 +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
|
@ -13,14 +13,15 @@ import (
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
// Links *common.Link
|
// Links *common.Link
|
||||||
Clone *common.Clone `json:"clone"`
|
Clone *common.Clone `json:"clone"`
|
||||||
Repo *common.Repo `json:"repo"`
|
Repo *common.Repo `json:"repo"`
|
||||||
Commit *common.Commit `json:"commit"`
|
Commit *common.Commit `json:"commit"`
|
||||||
Build *common.Build `json:"build"`
|
Build *common.Build `json:"build"`
|
||||||
Keys *common.Keypair `json:"keys"`
|
Keys *common.Keypair `json:"keys"`
|
||||||
Netrc *common.Netrc `json:"netrc"`
|
Netrc *common.Netrc `json:"netrc"`
|
||||||
Yaml []byte `json:"yaml"`
|
Yaml []byte `json:"yaml"`
|
||||||
Env []string `json:"env"`
|
Env []string `json:"environment"`
|
||||||
|
Plugins []string `json:"plugins"`
|
||||||
|
|
||||||
Conf *common.Config `json:"-"`
|
Conf *common.Config `json:"-"`
|
||||||
infos []*dockerclient.ContainerInfo
|
infos []*dockerclient.ContainerInfo
|
||||||
|
@ -29,12 +30,19 @@ type Context struct {
|
||||||
|
|
||||||
func setup(c *Context) error {
|
func setup(c *Context) error {
|
||||||
var err 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
|
// if repository is trusted the build may specify
|
||||||
// custom volumes, networking and run in trusted mode.
|
// custom volumes, networking and run in trusted mode.
|
||||||
if c.Repo.Trusted {
|
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
|
// inject the matrix parameters into the yaml
|
||||||
|
|
|
@ -9,13 +9,14 @@ import (
|
||||||
// Work represents an item for work to be
|
// Work represents an item for work to be
|
||||||
// processed by a worker.
|
// processed by a worker.
|
||||||
type Work struct {
|
type Work struct {
|
||||||
User *common.User `json:"user"`
|
User *common.User `json:"user"`
|
||||||
Repo *common.Repo `json:"repo"`
|
Repo *common.Repo `json:"repo"`
|
||||||
Commit *common.Commit `json:"commit"`
|
Commit *common.Commit `json:"commit"`
|
||||||
Keys *common.Keypair `json:"keypair"`
|
Keys *common.Keypair `json:"keypair"`
|
||||||
Netrc *common.Netrc `json:"netrc"`
|
Netrc *common.Netrc `json:"netrc"`
|
||||||
Yaml []byte `json:"yaml"`
|
Yaml []byte `json:"yaml"`
|
||||||
Env []string `json:"env"`
|
Env []string `json:"environment"`
|
||||||
|
Plugins []string `json:"plugins"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// represents a worker that has connected
|
// represents a worker that has connected
|
||||||
|
|
|
@ -112,13 +112,14 @@ func (r *Runner) Run(w *queue.Work) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
work := &work{
|
work := &work{
|
||||||
Repo: w.Repo,
|
Repo: w.Repo,
|
||||||
Commit: w.Commit,
|
Commit: w.Commit,
|
||||||
Keys: w.Keys,
|
Keys: w.Keys,
|
||||||
Netrc: w.Netrc,
|
Netrc: w.Netrc,
|
||||||
Yaml: w.Yaml,
|
Yaml: w.Yaml,
|
||||||
Build: task,
|
Build: task,
|
||||||
Env: w.Env,
|
Env: w.Env,
|
||||||
|
Plugins: w.Plugins,
|
||||||
}
|
}
|
||||||
in, err := json.Marshal(work)
|
in, err := json.Marshal(work)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -52,13 +52,14 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type work struct {
|
type work struct {
|
||||||
Repo *common.Repo `json:"repo"`
|
Repo *common.Repo `json:"repo"`
|
||||||
Commit *common.Commit `json:"commit"`
|
Commit *common.Commit `json:"commit"`
|
||||||
Build *common.Build `json:"build"`
|
Build *common.Build `json:"build"`
|
||||||
Keys *common.Keypair `json:"keys"`
|
Keys *common.Keypair `json:"keys"`
|
||||||
Netrc *common.Netrc `json:"netrc"`
|
Netrc *common.Netrc `json:"netrc"`
|
||||||
Yaml []byte `json:"yaml"`
|
Yaml []byte `json:"yaml"`
|
||||||
Env []string `json:"env"`
|
Env []string `json:"environment"`
|
||||||
|
Plugins []string `json:"plugins"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
common "github.com/drone/drone/pkg/types"
|
||||||
|
@ -103,3 +104,42 @@ func expectTrustedNotify(c *common.Config) error {
|
||||||
}
|
}
|
||||||
return nil
|
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
|
Volumes bool
|
||||||
Network bool
|
Network bool
|
||||||
Privileged bool
|
Privileged bool
|
||||||
|
Whitelist []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultOpts = &Opts{
|
var DefaultOpts = &Opts{
|
||||||
Volumes: false,
|
Volumes: false,
|
||||||
Network: false,
|
Network: false,
|
||||||
Privileged: false,
|
Privileged: false,
|
||||||
|
Whitelist: []string{"plugins/*"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses a build matrix and returns
|
// Parse parses a build matrix and returns
|
||||||
|
|
Loading…
Reference in a new issue