mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-06-05 08:58:50 +00:00
Only inject netrc to trusted clone plugins (#1352)
Co-authored-by: qwerty287 <ndev@web.de> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
7870c29f5f
commit
e28b43ab19
11 changed files with 68 additions and 8 deletions
|
@ -48,6 +48,7 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/server/router/middleware"
|
||||
"github.com/woodpecker-ci/woodpecker/server/store"
|
||||
"github.com/woodpecker-ci/woodpecker/server/web"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/constant"
|
||||
"github.com/woodpecker-ci/woodpecker/version"
|
||||
// "github.com/woodpecker-ci/woodpecker/server/plugins/encryption"
|
||||
// encryptedStore "github.com/woodpecker-ci/woodpecker/server/plugins/encryption/wrapper/store"
|
||||
|
@ -313,6 +314,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store, f forge.Forge) {
|
|||
|
||||
// Cloning
|
||||
server.Config.Pipeline.DefaultCloneImage = c.String("default-clone-image")
|
||||
constant.TrustedCloneImages = append(constant.TrustedCloneImages, server.Config.Pipeline.DefaultCloneImage)
|
||||
|
||||
// Execution
|
||||
_events := c.StringSlice("default-cancel-previous-pipeline-events")
|
||||
|
|
|
@ -81,6 +81,8 @@ type Compiler struct {
|
|||
cacher Cacher
|
||||
reslimit ResourceLimit
|
||||
defaultCloneImage string
|
||||
trustedPipeline bool
|
||||
netrcOnlyTrusted bool
|
||||
}
|
||||
|
||||
// New creates a new Compiler with options.
|
||||
|
@ -146,12 +148,13 @@ func (c *Compiler) Compile(conf *yaml.Config) (*backend.Config, error) {
|
|||
c.path = conf.Workspace.Path
|
||||
}
|
||||
|
||||
cloneImage := constant.DefaultCloneImage
|
||||
if len(c.defaultCloneImage) > 0 {
|
||||
cloneImage = c.defaultCloneImage
|
||||
}
|
||||
|
||||
// add default clone step
|
||||
if !c.local && len(conf.Clone.Containers) == 0 && !conf.SkipClone {
|
||||
cloneImage := constant.DefaultCloneImage
|
||||
if len(c.defaultCloneImage) > 0 {
|
||||
cloneImage = c.defaultCloneImage
|
||||
}
|
||||
cloneSettings := map[string]interface{}{"depth": "0"}
|
||||
if c.metadata.Curr.Event == frontend.EventTag {
|
||||
cloneSettings["tags"] = "true"
|
||||
|
@ -185,9 +188,14 @@ func (c *Compiler) Compile(conf *yaml.Config) (*backend.Config, error) {
|
|||
|
||||
name := fmt.Sprintf("%s_clone_%d", c.prefix, i)
|
||||
step := c.createProcess(name, container, defaultCloneName)
|
||||
for k, v := range c.cloneEnv {
|
||||
step.Environment[k] = v
|
||||
|
||||
// only inject netrc if it's a trusted repo or a trusted plugin
|
||||
if !c.netrcOnlyTrusted || c.trustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage()) {
|
||||
for k, v := range c.cloneEnv {
|
||||
step.Environment[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
stage.Steps = append(stage.Steps, step)
|
||||
|
||||
config.Stages = append(config.Stages, stage)
|
||||
|
|
|
@ -219,6 +219,20 @@ func WithDefaultCloneImage(cloneImage string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithTrusted configures the compiler with the trusted repo option
|
||||
func WithTrusted(trusted bool) Option {
|
||||
return func(compiler *Compiler) {
|
||||
compiler.trustedPipeline = trusted
|
||||
}
|
||||
}
|
||||
|
||||
// WithNetrcOnlyTrusted configures the compiler with the netrcOnlyTrusted repo option
|
||||
func WithNetrcOnlyTrusted(only bool) Option {
|
||||
return func(compiler *Compiler) {
|
||||
compiler.netrcOnlyTrusted = only
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(bradrydzewski) consider an alternate approach to
|
||||
// WithProxy where the proxy strings are passed directly
|
||||
// to the function as named parameters.
|
||||
|
|
|
@ -3,10 +3,12 @@ package yaml
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/pipeline/frontend/yaml/constraint"
|
||||
"github.com/woodpecker-ci/woodpecker/pipeline/frontend/yaml/types"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/constant"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -114,3 +116,7 @@ func (c *Containers) UnmarshalYAML(value *yaml.Node) error {
|
|||
func (c *Container) IsPlugin() bool {
|
||||
return len(c.Commands) == 0
|
||||
}
|
||||
|
||||
func (c *Container) IsTrustedCloneImage() bool {
|
||||
return c.IsPlugin() && slices.Contains(constant.TrustedCloneImages, c.Image)
|
||||
}
|
||||
|
|
|
@ -287,6 +287,8 @@ func (b *StepBuilder) toInternalRepresentation(parsed *yaml.Config, environ map[
|
|||
compiler.WithProxy(),
|
||||
compiler.WithWorkspaceFromURL("/woodpecker", b.Repo.Link),
|
||||
compiler.WithMetadata(metadata),
|
||||
compiler.WithTrusted(b.Repo.IsTrusted),
|
||||
compiler.WithNetrcOnlyTrusted(b.Repo.NetrcOnlyTrusted),
|
||||
).Compile(parsed)
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ func PostRepo(c *gin.Context) {
|
|||
repo.IsActive = true
|
||||
repo.UserID = user.ID
|
||||
repo.AllowPull = true
|
||||
repo.NetrcOnlyTrusted = true
|
||||
repo.CancelPreviousPipelineEvents = server.Config.Pipeline.DefaultCancelPreviousPipelineEvents
|
||||
|
||||
if repo.Visibility == "" {
|
||||
|
@ -147,6 +148,9 @@ func PatchRepo(c *gin.Context) {
|
|||
if in.CancelPreviousPipelineEvents != nil {
|
||||
repo.CancelPreviousPipelineEvents = *in.CancelPreviousPipelineEvents
|
||||
}
|
||||
if in.NetrcOnlyTrusted != nil {
|
||||
repo.NetrcOnlyTrusted = *in.NetrcOnlyTrusted
|
||||
}
|
||||
if in.Visibility != nil {
|
||||
switch *in.Visibility {
|
||||
case string(model.VisibilityInternal), string(model.VisibilityPrivate), string(model.VisibilityPublic):
|
||||
|
|
|
@ -48,6 +48,7 @@ type Repo struct {
|
|||
Hash string `json:"-" xorm:"varchar(500) 'repo_hash'"`
|
||||
Perm *Perm `json:"-" xorm:"-"`
|
||||
CancelPreviousPipelineEvents []WebhookEvent `json:"cancel_previous_pipeline_events" xorm:"json 'cancel_previous_pipeline_events'"`
|
||||
NetrcOnlyTrusted bool `json:"netrc_only_trusted" xorm:"NOT NULL DEFAULT true 'netrc_only_trusted'"`
|
||||
}
|
||||
|
||||
// TableName return database table name for xorm
|
||||
|
@ -108,6 +109,7 @@ type RepoPatch struct {
|
|||
Visibility *string `json:"visibility,omitempty"`
|
||||
AllowPull *bool `json:"allow_pr,omitempty"`
|
||||
CancelPreviousPipelineEvents *[]WebhookEvent `json:"cancel_previous_pipeline_events"`
|
||||
NetrcOnlyTrusted *bool `json:"netrc_only_trusted"`
|
||||
}
|
||||
|
||||
type ForgeRemoteID string
|
||||
|
|
|
@ -35,3 +35,7 @@ const (
|
|||
// DefaultCloneImage can be changed by 'WOODPECKER_DEFAULT_CLONE_IMAGE' at runtime
|
||||
DefaultCloneImage = "docker.io/woodpeckerci/plugin-git:2.0.3"
|
||||
)
|
||||
|
||||
var TrustedCloneImages = []string{
|
||||
DefaultCloneImage,
|
||||
}
|
||||
|
|
|
@ -92,7 +92,11 @@
|
|||
"protected": "Protected",
|
||||
"desc": "Every pipeline needs to be approved before being executed."
|
||||
},
|
||||
"trusted": {
|
||||
"netrc_only_trusted": {
|
||||
"netrc_only_trusted": "Only inject netrc credentials into trusted containers",
|
||||
"desc": "Only inject netrc credentials into trusted containers (recommended)."
|
||||
},
|
||||
"trusted": {
|
||||
"trusted": "Trusted",
|
||||
"desc": "Underlying pipeline containers get access to escalated capabilities like mounting volumes."
|
||||
},
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
:label="$t('repo.settings.general.protected.protected')"
|
||||
:description="$t('repo.settings.general.protected.desc')"
|
||||
/>
|
||||
<Checkbox
|
||||
v-model="repoSettings.netrc_only_trusted"
|
||||
:label="$t('repo.settings.general.netrc_only_trusted.netrc_only_trusted')"
|
||||
:description="$t('repo.settings.general.netrc_only_trusted.desc')"
|
||||
/>
|
||||
<Checkbox
|
||||
v-if="user?.admin"
|
||||
v-model="repoSettings.trusted"
|
||||
|
@ -130,6 +135,7 @@ export default defineComponent({
|
|||
trusted: repo.value.trusted,
|
||||
allow_pr: repo.value.allow_pr,
|
||||
cancel_previous_pipeline_events: repo.value.cancel_previous_pipeline_events || [],
|
||||
netrc_only_trusted: repo.value.netrc_only_trusted,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ export type Repo = {
|
|||
|
||||
// Events that will cancel running pipelines before starting a new one
|
||||
cancel_previous_pipeline_events: string[];
|
||||
netrc_only_trusted: boolean;
|
||||
};
|
||||
|
||||
export enum RepoVisibility {
|
||||
|
@ -67,7 +68,14 @@ export enum RepoVisibility {
|
|||
|
||||
export type RepoSettings = Pick<
|
||||
Repo,
|
||||
'config_file' | 'timeout' | 'visibility' | 'trusted' | 'gated' | 'allow_pr' | 'cancel_previous_pipeline_events'
|
||||
| 'config_file'
|
||||
| 'timeout'
|
||||
| 'visibility'
|
||||
| 'trusted'
|
||||
| 'gated'
|
||||
| 'allow_pr'
|
||||
| 'cancel_previous_pipeline_events'
|
||||
| 'netrc_only_trusted'
|
||||
>;
|
||||
|
||||
export type RepoPermissions = {
|
||||
|
|
Loading…
Reference in a new issue