Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Protected Branches to Whitelist Deploy Keys #8483

Merged
2 changes: 2 additions & 0 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
zeripath marked this conversation as resolved.
Show resolved Hide resolved

buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin)
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions cmd/serv.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions models/branches.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ type ProtectedBranch struct {
BranchName string `xorm:"UNIQUE(s)"`
CanPush bool `xorm:"NOT NULL DEFAULT false"`
EnableWhitelist bool
WhitelistUserIDs []int64 `xorm:"JSON TEXT"`
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
EnableMergeWhitelist bool `xorm:"NOT NULL DEFAULT false"`
WhitelistUserIDs []int64 `xorm:"JSON TEXT"`
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
EnableMergeWhitelist bool `xorm:"NOT NULL DEFAULT false"`
WhitelistDeployKeys bool
MergeWhitelistUserIDs []int64 `xorm:"JSON TEXT"`
MergeWhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
EnableStatusCheck bool `xorm:"NOT NULL DEFAULT false"`
Expand Down
2 changes: 2 additions & 0 deletions models/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions modules/auth/repo_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ type ProtectBranchForm struct {
EnableWhitelist bool
WhitelistUsers string
WhitelistTeams string
WhitelistDeployKeys bool
EnableMergeWhitelist bool
MergeWhitelistUsers string
MergeWhitelistTeams string
Expand Down
4 changes: 3 additions & 1 deletion modules/private/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,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:
Expand Down
8 changes: 7 additions & 1 deletion routers/private/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions routers/repo/setting_protected_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) != "" {
Expand Down
7 changes: 7 additions & 0 deletions templates/repo/settings/protected_branch.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down