mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Allow Protected Branches to Whitelist Deploy Keys (#8483)
Add an option to protected branches to add writing deploy keys to the whitelist for pushing. Please note this is technically a breaking change: previously if the owner of a repository was on the whitelist then any writing deploy key was effectively on the whitelist. This option will now need to be set if that is desired. Closes #8472 Details: * Allow Protected Branches to Whitelist Deploy Keys * Add migration * Ensure that IsDeployKey is set to false on the http pushes * add not null default false
This commit is contained in:
		@@ -66,6 +66,7 @@ func runHookPreReceive(c *cli.Context) error {
 | 
			
		||||
	reponame := os.Getenv(models.EnvRepoName)
 | 
			
		||||
	userID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
 | 
			
		||||
	prID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchPRID), 10, 64)
 | 
			
		||||
	isDeployKey, _ := strconv.ParseBool(os.Getenv(models.EnvIsDeployKey))
 | 
			
		||||
 | 
			
		||||
	buf := bytes.NewBuffer(nil)
 | 
			
		||||
	scanner := bufio.NewScanner(os.Stdin)
 | 
			
		||||
@@ -98,6 +99,7 @@ func runHookPreReceive(c *cli.Context) error {
 | 
			
		||||
				GitObjectDirectory:              os.Getenv(private.GitObjectDirectory),
 | 
			
		||||
				GitQuarantinePath:               os.Getenv(private.GitQuarantinePath),
 | 
			
		||||
				ProtectedBranchID:               prID,
 | 
			
		||||
				IsDeployKey:                     isDeployKey,
 | 
			
		||||
			})
 | 
			
		||||
			switch statusCode {
 | 
			
		||||
			case http.StatusInternalServerError:
 | 
			
		||||
 
 | 
			
		||||
@@ -191,6 +191,8 @@ func runServ(c *cli.Context) error {
 | 
			
		||||
	os.Setenv(models.EnvPusherID, strconv.FormatInt(results.UserID, 10))
 | 
			
		||||
	os.Setenv(models.ProtectedBranchRepoID, strconv.FormatInt(results.RepoID, 10))
 | 
			
		||||
	os.Setenv(models.ProtectedBranchPRID, fmt.Sprintf("%d", 0))
 | 
			
		||||
	os.Setenv(models.EnvIsDeployKey, fmt.Sprintf("%t", results.IsDeployKey))
 | 
			
		||||
	os.Setenv(models.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
 | 
			
		||||
 | 
			
		||||
	//LFS token authentication
 | 
			
		||||
	if verb == lfsAuthenticateVerb {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ type ProtectedBranch struct {
 | 
			
		||||
	WhitelistUserIDs          []int64            `xorm:"JSON TEXT"`
 | 
			
		||||
	WhitelistTeamIDs          []int64            `xorm:"JSON TEXT"`
 | 
			
		||||
	EnableMergeWhitelist      bool               `xorm:"NOT NULL DEFAULT false"`
 | 
			
		||||
	WhitelistDeployKeys       bool               `xorm:"NOT NULL DEFAULT false"`
 | 
			
		||||
	MergeWhitelistUserIDs     []int64            `xorm:"JSON TEXT"`
 | 
			
		||||
	MergeWhitelistTeamIDs     []int64            `xorm:"JSON TEXT"`
 | 
			
		||||
	EnableStatusCheck         bool               `xorm:"NOT NULL DEFAULT false"`
 | 
			
		||||
 
 | 
			
		||||
@@ -260,6 +260,8 @@ var migrations = []Migration{
 | 
			
		||||
	NewMigration("change length of some external login users columns", changeSomeColumnsLengthOfExternalLoginUser),
 | 
			
		||||
	// v102 -> v103
 | 
			
		||||
	NewMigration("update migration repositories' service type", dropColumnHeadUserNameOnPullRequest),
 | 
			
		||||
	// v103 -> v104
 | 
			
		||||
	NewMigration("Add WhitelistDeployKeys to protected branch", addWhitelistDeployKeysToBranches),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Migrate database to current version
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								models/migrations/v103.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								models/migrations/v103.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package migrations
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"xorm.io/xorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func addWhitelistDeployKeysToBranches(x *xorm.Engine) error {
 | 
			
		||||
	type ProtectedBranch struct {
 | 
			
		||||
		ID                  int64
 | 
			
		||||
		WhitelistDeployKeys bool `xorm:"NOT NULL DEFAULT false"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return x.Sync2(new(ProtectedBranch))
 | 
			
		||||
}
 | 
			
		||||
@@ -22,6 +22,8 @@ const (
 | 
			
		||||
	EnvPusherName   = "GITEA_PUSHER_NAME"
 | 
			
		||||
	EnvPusherEmail  = "GITEA_PUSHER_EMAIL"
 | 
			
		||||
	EnvPusherID     = "GITEA_PUSHER_ID"
 | 
			
		||||
	EnvKeyID        = "GITEA_KEY_ID"
 | 
			
		||||
	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CommitToPushCommit transforms a git.Commit to PushCommit type.
 | 
			
		||||
 
 | 
			
		||||
@@ -152,6 +152,7 @@ type ProtectBranchForm struct {
 | 
			
		||||
	EnableWhitelist         bool
 | 
			
		||||
	WhitelistUsers          string
 | 
			
		||||
	WhitelistTeams          string
 | 
			
		||||
	WhitelistDeployKeys     bool
 | 
			
		||||
	EnableMergeWhitelist    bool
 | 
			
		||||
	MergeWhitelistUsers     string
 | 
			
		||||
	MergeWhitelistTeams     string
 | 
			
		||||
 
 | 
			
		||||
@@ -31,11 +31,12 @@ type HookOptions struct {
 | 
			
		||||
	GitAlternativeObjectDirectories string
 | 
			
		||||
	GitQuarantinePath               string
 | 
			
		||||
	ProtectedBranchID               int64
 | 
			
		||||
	IsDeployKey                     bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookPreReceive check whether the provided commits are allowed
 | 
			
		||||
func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string) {
 | 
			
		||||
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&gitObjectDirectory=%s&gitAlternativeObjectDirectories=%s&gitQuarantinePath=%s&prID=%d",
 | 
			
		||||
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&gitObjectDirectory=%s&gitAlternativeObjectDirectories=%s&gitQuarantinePath=%s&prID=%d&isDeployKey=%t",
 | 
			
		||||
		url.PathEscape(ownerName),
 | 
			
		||||
		url.PathEscape(repoName),
 | 
			
		||||
		url.QueryEscape(opts.OldCommitID),
 | 
			
		||||
@@ -46,6 +47,7 @@ func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string)
 | 
			
		||||
		url.QueryEscape(opts.GitAlternativeObjectDirectories),
 | 
			
		||||
		url.QueryEscape(opts.GitQuarantinePath),
 | 
			
		||||
		opts.ProtectedBranchID,
 | 
			
		||||
		opts.IsDeployKey,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	resp, err := newInternalRequest(reqURL, "GET").Response()
 | 
			
		||||
 
 | 
			
		||||
@@ -1334,6 +1334,7 @@ settings.protect_this_branch = Enable Branch Protection
 | 
			
		||||
settings.protect_this_branch_desc = Prevent deletion and disable any Git pushing to the branch.
 | 
			
		||||
settings.protect_whitelist_committers = Enable Push Whitelist
 | 
			
		||||
settings.protect_whitelist_committers_desc = Allow whitelisted users or teams to push to this branch (but not force push).
 | 
			
		||||
settings.protect_whitelist_deploy_keys = Whitelist deploy keys with write access to push
 | 
			
		||||
settings.protect_whitelist_users = Whitelisted users for pushing:
 | 
			
		||||
settings.protect_whitelist_search_users = Search users…
 | 
			
		||||
settings.protect_whitelist_teams = Whitelisted teams for pushing:
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ func HookPreReceive(ctx *macaron.Context) {
 | 
			
		||||
	gitAlternativeObjectDirectories := ctx.QueryTrim("gitAlternativeObjectDirectories")
 | 
			
		||||
	gitQuarantinePath := ctx.QueryTrim("gitQuarantinePath")
 | 
			
		||||
	prID := ctx.QueryInt64("prID")
 | 
			
		||||
	isDeployKey := ctx.QueryBool("isDeployKey")
 | 
			
		||||
 | 
			
		||||
	branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
 | 
			
		||||
	repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
 | 
			
		||||
@@ -95,7 +96,12 @@ func HookPreReceive(ctx *macaron.Context) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		canPush := protectBranch.CanUserPush(userID)
 | 
			
		||||
		canPush := false
 | 
			
		||||
		if isDeployKey {
 | 
			
		||||
			canPush = protectBranch.WhitelistDeployKeys
 | 
			
		||||
		} else {
 | 
			
		||||
			canPush = protectBranch.CanUserPush(userID)
 | 
			
		||||
		}
 | 
			
		||||
		if !canPush && prID > 0 {
 | 
			
		||||
			pr, err := models.GetPullRequestByID(prID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -263,6 +263,7 @@ func HTTP(ctx *context.Context) {
 | 
			
		||||
			models.EnvPusherName + "=" + authUser.Name,
 | 
			
		||||
			models.EnvPusherID + fmt.Sprintf("=%d", authUser.ID),
 | 
			
		||||
			models.ProtectedBranchRepoID + fmt.Sprintf("=%d", repo.ID),
 | 
			
		||||
			models.EnvIsDeployKey + "=false",
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !authUser.KeepEmailPrivate {
 | 
			
		||||
 
 | 
			
		||||
@@ -213,6 +213,7 @@ func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm)
 | 
			
		||||
 | 
			
		||||
		protectBranch.EnableStatusCheck = f.EnableStatusCheck
 | 
			
		||||
		protectBranch.StatusCheckContexts = f.StatusCheckContexts
 | 
			
		||||
		protectBranch.WhitelistDeployKeys = f.WhitelistDeployKeys
 | 
			
		||||
 | 
			
		||||
		protectBranch.RequiredApprovals = f.RequiredApprovals
 | 
			
		||||
		if strings.TrimSpace(f.ApprovalsWhitelistUsers) != "" {
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,13 @@
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
						<br>
 | 
			
		||||
						<div class="whitelist field">
 | 
			
		||||
							<div class="ui checkbox">
 | 
			
		||||
								<input type="checkbox" name="whitelist_deploy_keys" {{if .Branch.WhitelistDeployKeys}}checked{{end}}>
 | 
			
		||||
								<label for="whitelist_deploy_keys">{{.i18n.Tr "repo.settings.protect_whitelist_deploy_keys"}}</label>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					<div class="field">
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user