From 5bb7cef08b47352bf245e950d0a6bca3cd5d4ee2 Mon Sep 17 00:00:00 2001
From: qwerty287 <80460567+qwerty287@users.noreply.github.com>
Date: Tue, 26 Nov 2024 15:27:05 +0200
Subject: [PATCH] Allow to set custom trusted clone plugins (#4352)
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Thomas Anderson <127358482+zc-devs@users.noreply.github.com>
Co-authored-by: Anbraten <6918444+anbraten@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
---
cmd/server/openapi/docs.go | 14 +++++--
docs/docs/20-usage/75-project-settings.md | 9 ++--
pipeline/frontend/yaml/compiler/compiler.go | 5 +--
pipeline/frontend/yaml/compiler/option.go | 7 ----
server/api/repo.go | 5 +--
server/model/repo.go | 4 +-
server/pipeline/stepbuilder/stepBuilder.go | 3 +-
.../020_remove_repo_netrc_only_trusted.go | 36 ++++++++++++++++
server/store/datastore/migration/migration.go | 1 +
web/src/assets/locales/en.json | 4 +-
web/src/lib/api/types/repo.ts | 4 +-
web/src/views/repo/settings/General.vue | 42 ++++++++++++++++---
12 files changed, 97 insertions(+), 37 deletions(-)
create mode 100644 server/store/datastore/migration/020_remove_repo_netrc_only_trusted.go
diff --git a/cmd/server/openapi/docs.go b/cmd/server/openapi/docs.go
index 645933163..ba2940d67 100644
--- a/cmd/server/openapi/docs.go
+++ b/cmd/server/openapi/docs.go
@@ -5070,8 +5070,11 @@ const docTemplate = `{
"name": {
"type": "string"
},
- "netrc_only_trusted": {
- "type": "boolean"
+ "netrc_trusted": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
},
"org_id": {
"type": "integer"
@@ -5124,8 +5127,11 @@ const docTemplate = `{
"description": "TODO: deprecated in favor of RequireApproval =\u003e Remove in next major release",
"type": "boolean"
},
- "netrc_only_trusted": {
- "type": "boolean"
+ "netrc_trusted": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
},
"require_approval": {
"type": "string"
diff --git a/docs/docs/20-usage/75-project-settings.md b/docs/docs/20-usage/75-project-settings.md
index c15bba2ec..b87b3011d 100644
--- a/docs/docs/20-usage/75-project-settings.md
+++ b/docs/docs/20-usage/75-project-settings.md
@@ -39,16 +39,13 @@ Only server admins can set this option. If you are not a server admin this optio
:::
-## Only inject Git credentials into trusted clone plugins
+## Custom trusted clone plugins
The clone step may require Git credentials (e.g. for private repos) which are injected via `netrc`.
-By default, they are only injected into trusted clone plugins listed in the env var `WOODPECKER_PLUGINS_TRUSTED_CLONE`.
-If this option is disabled, the Git credentials are injected into every clone plugin, regardless of whether it is trusted or not.
+They are only injected into trusted plugins listed in the env var `WOODPECKER_PLUGINS_TRUSTED_CLONE` or in this repo setting.
-:::note
-This option has no effect on steps other than the clone step.
-:::
+This allows you to use a trusted plugin for in the clone section or as a step to pull or push using your git credentials.
## Project visibility
diff --git a/pipeline/frontend/yaml/compiler/compiler.go b/pipeline/frontend/yaml/compiler/compiler.go
index be2b59cbc..a4c394e92 100644
--- a/pipeline/frontend/yaml/compiler/compiler.go
+++ b/pipeline/frontend/yaml/compiler/compiler.go
@@ -98,7 +98,6 @@ type Compiler struct {
defaultClonePlugin string
trustedClonePlugins []string
securityTrustedPipeline bool
- netrcOnlyTrusted bool
}
// New creates a new Compiler with options.
@@ -196,7 +195,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.securityTrustedPipeline || (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
}
@@ -252,7 +251,7 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
return nil, err
}
- // inject netrc if it's a trusted repo or a trusted clone-plugin
+ // only inject netrc if it's a trusted repo or a trusted plugin
if c.securityTrustedPipeline || (container.IsPlugin() && container.IsTrustedCloneImage(c.trustedClonePlugins)) {
for k, v := range c.cloneEnv {
step.Environment[k] = v
diff --git a/pipeline/frontend/yaml/compiler/option.go b/pipeline/frontend/yaml/compiler/option.go
index 3787bbd82..77e24c4ce 100644
--- a/pipeline/frontend/yaml/compiler/option.go
+++ b/pipeline/frontend/yaml/compiler/option.go
@@ -176,13 +176,6 @@ func WithTrustedSecurity(trusted bool) Option {
}
}
-// WithNetrcOnlyTrusted configures the compiler with the netrcOnlyTrusted repo option.
-func WithNetrcOnlyTrusted(only bool) Option {
- return func(compiler *Compiler) {
- compiler.netrcOnlyTrusted = only
- }
-}
-
type ProxyOptions struct {
NoProxy string
HTTPProxy string
diff --git a/server/api/repo.go b/server/api/repo.go
index 10388edc4..4072dcb45 100644
--- a/server/api/repo.go
+++ b/server/api/repo.go
@@ -94,7 +94,6 @@ func PostRepo(c *gin.Context) {
repo.RequireApproval = model.RequireApprovalForks
repo.AllowPull = true
repo.AllowDeploy = false
- repo.NetrcOnlyTrusted = true
repo.CancelPreviousPipelineEvents = server.Config.Pipeline.DefaultCancelPreviousPipelineEvents
}
repo.IsActive = true
@@ -275,8 +274,8 @@ func PatchRepo(c *gin.Context) {
if in.CancelPreviousPipelineEvents != nil {
repo.CancelPreviousPipelineEvents = *in.CancelPreviousPipelineEvents
}
- if in.NetrcOnlyTrusted != nil {
- repo.NetrcOnlyTrusted = *in.NetrcOnlyTrusted
+ if in.NetrcTrusted != nil {
+ repo.NetrcTrustedPlugins = *in.NetrcTrusted
}
if in.Visibility != nil {
switch *in.Visibility {
diff --git a/server/model/repo.go b/server/model/repo.go
index d12966679..b833ce407 100644
--- a/server/model/repo.go
+++ b/server/model/repo.go
@@ -71,7 +71,7 @@ type Repo struct {
Hash string `json:"-" xorm:"varchar(500) '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'"`
+ NetrcTrustedPlugins []string `json:"netrc_trusted" xorm:"json 'netrc_trusted'"`
} // @name Repo
// TableName return database table name for xorm.
@@ -137,7 +137,7 @@ type RepoPatch struct {
AllowPull *bool `json:"allow_pr,omitempty"`
AllowDeploy *bool `json:"allow_deploy,omitempty"`
CancelPreviousPipelineEvents *[]WebhookEvent `json:"cancel_previous_pipeline_events"`
- NetrcOnlyTrusted *bool `json:"netrc_only_trusted"`
+ NetrcTrusted *[]string `json:"netrc_trusted"`
Trusted *TrustedConfigurationPatch `json:"trusted"`
} // @name RepoPatch
diff --git a/server/pipeline/stepbuilder/stepBuilder.go b/server/pipeline/stepbuilder/stepBuilder.go
index c628fe83c..8145bf9e4 100644
--- a/server/pipeline/stepbuilder/stepBuilder.go
+++ b/server/pipeline/stepbuilder/stepBuilder.go
@@ -290,7 +290,7 @@ func (b *StepBuilder) toInternalRepresentation(parsed *yaml_types.Workflow, envi
b.Repo.IsSCMPrivate || server.Config.Pipeline.AuthenticatePublicRepos,
),
compiler.WithDefaultClonePlugin(server.Config.Pipeline.DefaultClonePlugin),
- compiler.WithTrustedClonePlugins(server.Config.Pipeline.TrustedClonePlugins),
+ compiler.WithTrustedClonePlugins(append(b.Repo.NetrcTrustedPlugins, server.Config.Pipeline.TrustedClonePlugins...)),
compiler.WithRegistry(registries...),
compiler.WithSecret(secrets...),
compiler.WithPrefix(
@@ -304,7 +304,6 @@ func (b *StepBuilder) toInternalRepresentation(parsed *yaml_types.Workflow, envi
compiler.WithWorkspaceFromURL(compiler.DefaultWorkspaceBase, b.Repo.ForgeURL),
compiler.WithMetadata(metadata),
compiler.WithTrustedSecurity(b.Repo.Trusted.Security),
- compiler.WithNetrcOnlyTrusted(b.Repo.NetrcOnlyTrusted),
).Compile(parsed)
}
diff --git a/server/store/datastore/migration/020_remove_repo_netrc_only_trusted.go b/server/store/datastore/migration/020_remove_repo_netrc_only_trusted.go
new file mode 100644
index 000000000..f93c61bc5
--- /dev/null
+++ b/server/store/datastore/migration/020_remove_repo_netrc_only_trusted.go
@@ -0,0 +1,36 @@
+// Copyright 2024 Woodpecker Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package migration
+
+import (
+ "src.techknowlogick.com/xormigrate"
+ "xorm.io/xorm"
+)
+
+var removeRepoNetrcOnlyTrusted = xormigrate.Migration{
+ ID: "remove-repo-netrc-only-trusted",
+ MigrateSession: func(sess *xorm.Session) (err error) {
+ type repos struct {
+ NetrcOnlyTrusted string `xorm:"netrc_only_trusted"`
+ }
+
+ // ensure columns to drop exist
+ if err := sess.Sync(new(repos)); err != nil {
+ return err
+ }
+
+ return dropTableColumns(sess, "repos", "netrc_only_trusted")
+ },
+}
diff --git a/server/store/datastore/migration/migration.go b/server/store/datastore/migration/migration.go
index 611beb30e..9fde10f54 100644
--- a/server/store/datastore/migration/migration.go
+++ b/server/store/datastore/migration/migration.go
@@ -48,6 +48,7 @@ var migrationTasks = []*xormigrate.Migration{
&splitTrusted,
&correctPotentialCorruptOrgsUsersRelation,
&gatedToRequireApproval,
+ &removeRepoNetrcOnlyTrusted,
}
var allBeans = []any{
diff --git a/web/src/assets/locales/en.json b/web/src/assets/locales/en.json
index 8b4624e97..cba931e00 100644
--- a/web/src/assets/locales/en.json
+++ b/web/src/assets/locales/en.json
@@ -104,8 +104,8 @@
"desc": "Permit 'deployment' runs for successful pipelines. All users with with push permissions can trigger these, so use with caution."
},
"netrc_only_trusted": {
- "netrc_only_trusted": "Only inject git credentials into trusted clone plugins",
- "desc": "When enabled, git credentials are accessible only to trusted clone plugins specified in WOODPECKER_PLUGINS_TRUSTED_CLONE. Otherwise, custom clone plugins can use git credentials. This setting has no affect on non-clone steps."
+ "netrc_only_trusted": "Custom trusted clone plugins",
+ "desc": "Plugins listed here will get access to netrc credentials that can be used to clone repositories from the forge or push to it."
},
"trusted": {
"trusted": "Trusted",
diff --git a/web/src/lib/api/types/repo.ts b/web/src/lib/api/types/repo.ts
index 3062279c0..18698aaae 100644
--- a/web/src/lib/api/types/repo.ts
+++ b/web/src/lib/api/types/repo.ts
@@ -76,7 +76,7 @@ export interface Repo {
// Events that will cancel running pipelines before starting a new one
cancel_previous_pipeline_events: string[];
- netrc_only_trusted: boolean;
+ netrc_trusted: string[];
}
/* eslint-disable no-unused-vars */
@@ -104,7 +104,7 @@ export type RepoSettings = Pick<
| 'allow_pr'
| 'allow_deploy'
| 'cancel_previous_pipeline_events'
- | 'netrc_only_trusted'
+ | 'netrc_trusted'
>;
export interface RepoPermissions {
diff --git a/web/src/views/repo/settings/General.vue b/web/src/views/repo/settings/General.vue
index a03cf0050..1430028d0 100644
--- a/web/src/views/repo/settings/General.vue
+++ b/web/src/views/repo/settings/General.vue
@@ -15,11 +15,25 @@
:label="$t('repo.settings.general.allow_deploy.allow')"
:description="$t('repo.settings.general.allow_deploy.desc')"
/>
-
+
+
+
+ {{ $t('repo.settings.general.netrc_only_trusted.desc') }}
+
+
i !== image);
+}