mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-02-15 02:45:14 +00:00
Merge branch 'origin/main' into 'next-release/main'
This commit is contained in:
commit
36acd25459
12 changed files with 97 additions and 37 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
},
|
||||
}
|
|
@ -48,6 +48,7 @@ var migrationTasks = []*xormigrate.Migration{
|
|||
&splitTrusted,
|
||||
&correctPotentialCorruptOrgsUsersRelation,
|
||||
&gatedToRequireApproval,
|
||||
&removeRepoNetrcOnlyTrusted,
|
||||
}
|
||||
|
||||
var allBeans = []any{
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -15,11 +15,25 @@
|
|||
:label="$t('repo.settings.general.allow_deploy.allow')"
|
||||
:description="$t('repo.settings.general.allow_deploy.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')"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
v-slot="{ id }"
|
||||
:label="$t('repo.settings.general.netrc_only_trusted.netrc_only_trusted')"
|
||||
docs-url="docs/usage/project-settings#custom-trusted-clone-plugins"
|
||||
>
|
||||
<span class="ml-1 mb-2 text-wp-text-alt-100">{{ $t('repo.settings.general.netrc_only_trusted.desc') }}</span>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div v-for="image in repoSettings.netrc_trusted" :key="image" class="flex gap-2">
|
||||
<TextField :id="id" :model-value="image" disabled />
|
||||
<Button type="button" color="gray" start-icon="trash" @click="removeImage(image)" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<TextField :id="id" v-model="newImage" @keydown.enter.prevent="addNewImage" />
|
||||
<Button type="button" color="gray" start-icon="plus" @click="addNewImage" />
|
||||
</div>
|
||||
</div>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
|
@ -178,7 +192,7 @@ function loadRepoSettings() {
|
|||
allow_pr: repo.value.allow_pr,
|
||||
allow_deploy: repo.value.allow_deploy,
|
||||
cancel_previous_pipeline_events: repo.value.cancel_previous_pipeline_events || [],
|
||||
netrc_only_trusted: repo.value.netrc_only_trusted,
|
||||
netrc_trusted: repo.value.netrc_trusted || [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -236,4 +250,20 @@ const cancelPreviousPipelineEventsOptions: CheckboxOption[] = [
|
|||
},
|
||||
{ value: WebhookEvents.Deploy, text: i18n.t('repo.pipeline.event.deploy') },
|
||||
];
|
||||
|
||||
const newImage = ref('');
|
||||
function addNewImage() {
|
||||
if (!newImage.value) {
|
||||
return;
|
||||
}
|
||||
repoSettings.value?.netrc_trusted.push(newImage.value);
|
||||
newImage.value = '';
|
||||
}
|
||||
function removeImage(image: string) {
|
||||
if (!repoSettings.value) {
|
||||
throw new Error('Unexpected: repoSettings should be set');
|
||||
}
|
||||
|
||||
repoSettings.value.netrc_trusted = repoSettings.value.netrc_trusted.filter((i) => i !== image);
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue