mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-09-12 23:52:00 +00:00
Split repo trusted setting (#4025)
This commit is contained in:
@@ -166,6 +166,9 @@ CI_REPO_PRIVATE=false
|
||||
CI_REPO_REMOTE_ID=4
|
||||
CI_REPO_SCM=git
|
||||
CI_REPO_TRUSTED=false
|
||||
CI_REPO_TRUSTED_NETWORK=false
|
||||
CI_REPO_TRUSTED_VOLUMES=false
|
||||
CI_REPO_TRUSTED_SECURITY=false
|
||||
CI_REPO_URL=http://1.2.3.4:3000/test/woodpecker-test
|
||||
CI_STEP_NAME=
|
||||
CI_STEP_NUMBER=0
|
||||
|
@@ -51,18 +51,22 @@ func (m *Metadata) Environ() map[string]string {
|
||||
prevSourceBranch, prevTargetBranch := getSourceTargetBranches(m.Prev.Commit.Refspec)
|
||||
|
||||
params := map[string]string{
|
||||
"CI": m.Sys.Name,
|
||||
"CI_REPO": path.Join(m.Repo.Owner, m.Repo.Name),
|
||||
"CI_REPO_NAME": m.Repo.Name,
|
||||
"CI_REPO_OWNER": m.Repo.Owner,
|
||||
"CI_REPO_REMOTE_ID": m.Repo.RemoteID,
|
||||
"CI_REPO_SCM": m.Repo.SCM,
|
||||
"CI_REPO_URL": m.Repo.ForgeURL,
|
||||
"CI_REPO_CLONE_URL": m.Repo.CloneURL,
|
||||
"CI_REPO_CLONE_SSH_URL": m.Repo.CloneSSHURL,
|
||||
"CI_REPO_DEFAULT_BRANCH": m.Repo.Branch,
|
||||
"CI_REPO_PRIVATE": strconv.FormatBool(m.Repo.Private),
|
||||
"CI_REPO_TRUSTED": strconv.FormatBool(m.Repo.Trusted),
|
||||
"CI": m.Sys.Name,
|
||||
"CI_REPO": path.Join(m.Repo.Owner, m.Repo.Name),
|
||||
"CI_REPO_NAME": m.Repo.Name,
|
||||
"CI_REPO_OWNER": m.Repo.Owner,
|
||||
"CI_REPO_REMOTE_ID": m.Repo.RemoteID,
|
||||
"CI_REPO_SCM": m.Repo.SCM,
|
||||
"CI_REPO_URL": m.Repo.ForgeURL,
|
||||
"CI_REPO_CLONE_URL": m.Repo.CloneURL,
|
||||
"CI_REPO_CLONE_SSH_URL": m.Repo.CloneSSHURL,
|
||||
"CI_REPO_DEFAULT_BRANCH": m.Repo.Branch,
|
||||
"CI_REPO_PRIVATE": strconv.FormatBool(m.Repo.Private),
|
||||
"CI_REPO_TRUSTED_NETWORK": strconv.FormatBool(m.Repo.Trusted.Network),
|
||||
"CI_REPO_TRUSTED_VOLUMES": strconv.FormatBool(m.Repo.Trusted.Volumes),
|
||||
"CI_REPO_TRUSTED_SECURITY": strconv.FormatBool(m.Repo.Trusted.Security),
|
||||
// Deprecated remove in 4.x
|
||||
"CI_REPO_TRUSTED": strconv.FormatBool(m.Repo.Trusted.Security && m.Repo.Trusted.Network && m.Repo.Trusted.Volumes),
|
||||
|
||||
"CI_COMMIT_SHA": m.Curr.Commit.Sha,
|
||||
"CI_COMMIT_REF": m.Curr.Commit.Ref,
|
||||
|
@@ -29,17 +29,17 @@ type (
|
||||
|
||||
// Repo defines runtime metadata for a repository.
|
||||
Repo struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
RemoteID string `json:"remote_id,omitempty"`
|
||||
ForgeURL string `json:"forge_url,omitempty"`
|
||||
SCM string `json:"scm,omitempty"`
|
||||
CloneURL string `json:"clone_url,omitempty"`
|
||||
CloneSSHURL string `json:"clone_url_ssh,omitempty"`
|
||||
Private bool `json:"private,omitempty"`
|
||||
Branch string `json:"default_branch,omitempty"`
|
||||
Trusted bool `json:"trusted,omitempty"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
RemoteID string `json:"remote_id,omitempty"`
|
||||
ForgeURL string `json:"forge_url,omitempty"`
|
||||
SCM string `json:"scm,omitempty"`
|
||||
CloneURL string `json:"clone_url,omitempty"`
|
||||
CloneSSHURL string `json:"clone_url_ssh,omitempty"`
|
||||
Private bool `json:"private,omitempty"`
|
||||
Branch string `json:"default_branch,omitempty"`
|
||||
Trusted TrustedConfiguration `json:"trusted,omitempty"`
|
||||
}
|
||||
|
||||
// Pipeline defines runtime metadata for a pipeline.
|
||||
@@ -113,4 +113,10 @@ type (
|
||||
// URL returns the root url of a configured forge
|
||||
URL() string
|
||||
}
|
||||
|
||||
TrustedConfiguration struct {
|
||||
Network bool `json:"network,omitempty"`
|
||||
Volumes bool `json:"volumes,omitempty"`
|
||||
Security bool `json:"security,omitempty"`
|
||||
}
|
||||
)
|
||||
|
@@ -83,22 +83,22 @@ func (s *Secret) Match(event string) bool {
|
||||
|
||||
// Compiler compiles the yaml.
|
||||
type Compiler struct {
|
||||
local bool
|
||||
escalated []string
|
||||
prefix string
|
||||
volumes []string
|
||||
networks []string
|
||||
env map[string]string
|
||||
cloneEnv map[string]string
|
||||
workspaceBase string
|
||||
workspacePath string
|
||||
metadata metadata.Metadata
|
||||
registries []Registry
|
||||
secrets map[string]Secret
|
||||
defaultClonePlugin string
|
||||
trustedClonePlugins []string
|
||||
trustedPipeline bool
|
||||
netrcOnlyTrusted bool
|
||||
local bool
|
||||
escalated []string
|
||||
prefix string
|
||||
volumes []string
|
||||
networks []string
|
||||
env map[string]string
|
||||
cloneEnv map[string]string
|
||||
workspaceBase string
|
||||
workspacePath string
|
||||
metadata metadata.Metadata
|
||||
registries []Registry
|
||||
secrets map[string]Secret
|
||||
defaultClonePlugin string
|
||||
trustedClonePlugins []string
|
||||
securityTrustedPipeline bool
|
||||
netrcOnlyTrusted bool
|
||||
}
|
||||
|
||||
// New creates a new Compiler with options.
|
||||
@@ -196,7 +196,7 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
|
||||
}
|
||||
|
||||
// only inject netrc if it's a trusted repo or a trusted plugin
|
||||
if !c.netrcOnlyTrusted || c.trustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage(c.trustedClonePlugins)) {
|
||||
if !c.netrcOnlyTrusted || c.securityTrustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage(c.trustedClonePlugins)) {
|
||||
for k, v := range c.cloneEnv {
|
||||
step.Environment[k] = v
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
|
||||
}
|
||||
|
||||
// inject netrc if it's a trusted repo or a trusted clone-plugin
|
||||
if c.trustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage(c.trustedClonePlugins)) {
|
||||
if c.securityTrustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage(c.trustedClonePlugins)) {
|
||||
for k, v := range c.cloneEnv {
|
||||
step.Environment[k] = v
|
||||
}
|
||||
|
@@ -169,10 +169,10 @@ func WithTrustedClonePlugins(images []string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithTrusted configures the compiler with the trusted repo option.
|
||||
func WithTrusted(trusted bool) Option {
|
||||
// WithTrustedSecurity configures the compiler with the trusted repo option.
|
||||
func WithTrustedSecurity(trusted bool) Option {
|
||||
return func(compiler *Compiler) {
|
||||
compiler.trustedPipeline = trusted
|
||||
compiler.securityTrustedPipeline = trusted
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,11 +30,17 @@ import (
|
||||
|
||||
// A Linter lints a pipeline configuration.
|
||||
type Linter struct {
|
||||
trusted bool
|
||||
trusted TrustedConfiguration
|
||||
privilegedPlugins *[]string
|
||||
trustedClonePlugins *[]string
|
||||
}
|
||||
|
||||
type TrustedConfiguration struct {
|
||||
Network bool
|
||||
Volumes bool
|
||||
Security bool
|
||||
}
|
||||
|
||||
// New creates a new Linter with options.
|
||||
func New(opts ...Option) *Linter {
|
||||
linter := new(Linter)
|
||||
@@ -143,10 +149,8 @@ func (l *Linter) lintContainers(config *WorkflowConfig, area string) error {
|
||||
if err := l.lintImage(config, container, area); err != nil {
|
||||
linterErr = multierr.Append(linterErr, err)
|
||||
}
|
||||
if !l.trusted {
|
||||
if err := l.lintTrusted(config, container, area); err != nil {
|
||||
linterErr = multierr.Append(linterErr, err)
|
||||
}
|
||||
if err := l.lintTrusted(config, container, area); err != nil {
|
||||
linterErr = multierr.Append(linterErr, err)
|
||||
}
|
||||
if err := l.lintSettings(config, container, area); err != nil {
|
||||
linterErr = multierr.Append(linterErr, err)
|
||||
@@ -204,29 +208,35 @@ func (l *Linter) lintSettings(config *WorkflowConfig, c *types.Container, field
|
||||
func (l *Linter) lintTrusted(config *WorkflowConfig, c *types.Container, area string) error {
|
||||
yamlPath := fmt.Sprintf("%s.%s", area, c.Name)
|
||||
errors := []string{}
|
||||
if c.Privileged {
|
||||
errors = append(errors, "Insufficient privileges to use privileged mode")
|
||||
if !l.trusted.Security {
|
||||
if c.Privileged {
|
||||
errors = append(errors, "Insufficient privileges to use privileged mode")
|
||||
}
|
||||
}
|
||||
if len(c.DNS) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use custom dns")
|
||||
if !l.trusted.Network {
|
||||
if len(c.DNS) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use custom dns")
|
||||
}
|
||||
if len(c.DNSSearch) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use dns_search")
|
||||
}
|
||||
if len(c.ExtraHosts) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use extra_hosts")
|
||||
}
|
||||
if len(c.NetworkMode) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use network_mode")
|
||||
}
|
||||
}
|
||||
if len(c.DNSSearch) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use dns_search")
|
||||
}
|
||||
if len(c.Devices) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use devices")
|
||||
}
|
||||
if len(c.ExtraHosts) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use extra_hosts")
|
||||
}
|
||||
if len(c.NetworkMode) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use network_mode")
|
||||
}
|
||||
if len(c.Volumes.Volumes) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use volumes")
|
||||
}
|
||||
if len(c.Tmpfs) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use tmpfs")
|
||||
if !l.trusted.Volumes {
|
||||
if len(c.Devices) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use devices")
|
||||
}
|
||||
if len(c.Volumes.Volumes) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use volumes")
|
||||
}
|
||||
if len(c.Tmpfs) != 0 {
|
||||
errors = append(errors, "Insufficient privileges to use tmpfs")
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
|
@@ -94,7 +94,11 @@ steps:
|
||||
conf, err := yaml.ParseString(testd.Data)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, linter.New(linter.WithTrusted(true)).Lint([]*linter.WorkflowConfig{{
|
||||
assert.NoError(t, linter.New(linter.WithTrusted(linter.TrustedConfiguration{
|
||||
Network: true,
|
||||
Volumes: true,
|
||||
Security: true,
|
||||
})).Lint([]*linter.WorkflowConfig{{
|
||||
File: testd.Title,
|
||||
RawConfig: testd.Data,
|
||||
Workflow: conf,
|
||||
|
@@ -18,7 +18,7 @@ package linter
|
||||
type Option func(*Linter)
|
||||
|
||||
// WithTrusted adds the trusted option to the linter.
|
||||
func WithTrusted(trusted bool) Option {
|
||||
func WithTrusted(trusted TrustedConfiguration) Option {
|
||||
return func(linter *Linter) {
|
||||
linter.trusted = trusted
|
||||
}
|
||||
|
Reference in New Issue
Block a user