mirror of
https://github.com/harness/drone.git
synced 2025-05-18 09:59:57 +08:00
fix: [CODE-3288]: Revert "Block any push that contains commits not committed by the user (#3512)" (#3532)
* Revert "feat: [CODE-3288]: Block any push that contains commits not committed by the user (#3512)"
This reverts commit 53000fe59d
.
This commit is contained in:
parent
53000fe59d
commit
8e08be96fe
@ -117,11 +117,11 @@ func (c *Controller) getRepoCheckAccess(
|
|||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBaseSHAForRefUpdate returns the commit sha to which the new sha of the reference
|
// GetBaseSHAForScanningChanges returns the commit sha to which the new sha of the reference
|
||||||
// should be compared against when looking for incoming changes.
|
// should be compared against when scanning incoming changes.
|
||||||
// NOTE: If no such a sha exists, then (sha.None, false, nil) is returned.
|
// NOTE: If no such a sha exists, then (sha.None, false, nil) is returned.
|
||||||
// This will happen in case the default branch doesn't exist yet.
|
// This will happen in case the default branch doesn't exist yet.
|
||||||
func GetBaseSHAForRefUpdate(
|
func GetBaseSHAForScanningChanges(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
rgit RestrictedGIT,
|
rgit RestrictedGIT,
|
||||||
repo *types.RepositoryCore,
|
repo *types.RepositoryCore,
|
||||||
|
@ -93,14 +93,6 @@ func (c *Controller) PreReceive(
|
|||||||
return hook.Output{}, fmt.Errorf("failed to find inner principal with id %d: %w", in.PrincipalID, err)
|
return hook.Output{}, fmt.Errorf("failed to find inner principal with id %d: %w", in.PrincipalID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.userCommiterMatchCheck(ctx, rgit, repo, in, principal.Email, &output)
|
|
||||||
if output.Error != nil {
|
|
||||||
return output, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return hook.Output{}, fmt.Errorf("failed to check user commiter match: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dummySession := &auth.Session{Principal: *principal, Metadata: nil}
|
dummySession := &auth.Session{Principal: *principal, Metadata: nil}
|
||||||
|
|
||||||
err = c.checkProtectionRules(ctx, dummySession, repo, refUpdates, &output)
|
err = c.checkProtectionRules(ctx, dummySession, repo, refUpdates, &output)
|
||||||
|
@ -102,7 +102,7 @@ func scanSecretsInternal(ctx context.Context,
|
|||||||
//nolint:nestif
|
//nolint:nestif
|
||||||
if refUpdate.Old.IsNil() {
|
if refUpdate.Old.IsNil() {
|
||||||
if baseRevFallBack == nil {
|
if baseRevFallBack == nil {
|
||||||
fallbackSHA, fallbackAvailable, err := GetBaseSHAForRefUpdate(
|
fallbackSHA, fallbackAvailable, err := GetBaseSHAForScanningChanges(
|
||||||
ctx,
|
ctx,
|
||||||
rgit,
|
rgit,
|
||||||
repo,
|
repo,
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
// Copyright 2023 Harness, Inc.
|
|
||||||
//
|
|
||||||
// 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 githook
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/app/api/usererror"
|
|
||||||
"github.com/harness/gitness/app/services/settings"
|
|
||||||
"github.com/harness/gitness/git"
|
|
||||||
"github.com/harness/gitness/git/hook"
|
|
||||||
"github.com/harness/gitness/git/sha"
|
|
||||||
"github.com/harness/gitness/types"
|
|
||||||
|
|
||||||
"github.com/gotidy/ptr"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Controller) userCommiterMatchCheck(
|
|
||||||
ctx context.Context,
|
|
||||||
rgit RestrictedGIT,
|
|
||||||
repo *types.RepositoryCore,
|
|
||||||
in types.GithookPreReceiveInput,
|
|
||||||
principalEmail string,
|
|
||||||
output *hook.Output,
|
|
||||||
) error {
|
|
||||||
userCommiterMatch, err := settings.RepoGet(
|
|
||||||
ctx,
|
|
||||||
c.settings,
|
|
||||||
repo.ID,
|
|
||||||
settings.KeyUserCommiterMatch,
|
|
||||||
settings.DefaultUserCommiterMatch,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to check settings for user commiter match: %w", err)
|
|
||||||
}
|
|
||||||
if !userCommiterMatch {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidShaEmailMap := make(map[string]string)
|
|
||||||
|
|
||||||
// block any push that contains commits not committed by the user
|
|
||||||
for _, refUpdate := range in.RefUpdates {
|
|
||||||
baseSHA, fallbackAvailable, err := GetBaseSHAForRefUpdate(
|
|
||||||
ctx,
|
|
||||||
rgit,
|
|
||||||
repo,
|
|
||||||
in.Environment,
|
|
||||||
in.RefUpdates,
|
|
||||||
refUpdate,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get fallback sha: %w", err)
|
|
||||||
}
|
|
||||||
// the default branch doesn't exist yet
|
|
||||||
if !fallbackAvailable {
|
|
||||||
baseSHA = sha.None
|
|
||||||
}
|
|
||||||
|
|
||||||
shaEmailMap, err := c.git.GetBranchCommiterEmails(ctx, &git.GetBranchCommitterEmailsParams{
|
|
||||||
ReadParams: git.ReadParams{
|
|
||||||
RepoUID: repo.GitUID,
|
|
||||||
AlternateObjectDirs: in.Environment.AlternateObjectDirs,
|
|
||||||
},
|
|
||||||
BaseSHA: baseSHA,
|
|
||||||
RevSHA: refUpdate.New,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get commiter emails for %s: %w", refUpdate.Ref, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for sha, email := range shaEmailMap {
|
|
||||||
if email != principalEmail {
|
|
||||||
invalidShaEmailMap[sha] = email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(invalidShaEmailMap) > 0 {
|
|
||||||
output.Error = ptr.String(usererror.ErrCommiterUserMismatch.Error())
|
|
||||||
printUserCommiterMismatch(output, invalidShaEmailMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -137,25 +137,6 @@ func printOversizeFiles(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printUserCommiterMismatch(output *hook.Output, shaEmailMap map[string]string) {
|
|
||||||
output.Messages = append(
|
|
||||||
output.Messages,
|
|
||||||
colorScanHeader.Sprintf(
|
|
||||||
"Push contains commits where committer is not an authenticated user:",
|
|
||||||
),
|
|
||||||
"", // add empty line for making it visually more consumable
|
|
||||||
)
|
|
||||||
|
|
||||||
for sha, email := range shaEmailMap {
|
|
||||||
output.Messages = append(
|
|
||||||
output.Messages,
|
|
||||||
fmt.Sprintf(" %s", sha),
|
|
||||||
fmt.Sprintf(" Commiter: %s", email),
|
|
||||||
"", // add empty line for making it visually more consumable
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func singularOrPlural(noun string, plural bool) string {
|
func singularOrPlural(noun string, plural bool) string {
|
||||||
if plural {
|
if plural {
|
||||||
return noun + "s"
|
return noun + "s"
|
||||||
|
@ -22,26 +22,23 @@ import (
|
|||||||
|
|
||||||
// GeneralSettings represent the general repository settings as exposed externally.
|
// GeneralSettings represent the general repository settings as exposed externally.
|
||||||
type GeneralSettings struct {
|
type GeneralSettings struct {
|
||||||
FileSizeLimit *int64 `json:"file_size_limit" yaml:"file_size_limit"`
|
FileSizeLimit *int64 `json:"file_size_limit" yaml:"file_size_limit"`
|
||||||
UserCommiterMatch *bool `json:"user_commiter_match" yaml:"user_commiter_match"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDefaultGeneralSettings() *GeneralSettings {
|
func GetDefaultGeneralSettings() *GeneralSettings {
|
||||||
return &GeneralSettings{
|
return &GeneralSettings{
|
||||||
FileSizeLimit: ptr.Int64(settings.DefaultFileSizeLimit),
|
FileSizeLimit: ptr.Int64(settings.DefaultFileSizeLimit),
|
||||||
UserCommiterMatch: ptr.Bool(settings.DefaultUserCommiterMatch),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetGeneralSettingsMappings(s *GeneralSettings) []settings.SettingHandler {
|
func GetGeneralSettingsMappings(s *GeneralSettings) []settings.SettingHandler {
|
||||||
return []settings.SettingHandler{
|
return []settings.SettingHandler{
|
||||||
settings.Mapping(settings.KeyFileSizeLimit, s.FileSizeLimit),
|
settings.Mapping(settings.KeyFileSizeLimit, s.FileSizeLimit),
|
||||||
settings.Mapping(settings.KeyUserCommiterMatch, s.UserCommiterMatch),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetGeneralSettingsAsKeyValues(s *GeneralSettings) []settings.KeyValue {
|
func GetGeneralSettingsAsKeyValues(s *GeneralSettings) []settings.KeyValue {
|
||||||
kvs := make([]settings.KeyValue, 0, 2)
|
kvs := make([]settings.KeyValue, 0, 1)
|
||||||
|
|
||||||
if s.FileSizeLimit != nil {
|
if s.FileSizeLimit != nil {
|
||||||
kvs = append(kvs, settings.KeyValue{
|
kvs = append(kvs, settings.KeyValue{
|
||||||
@ -49,13 +46,5 @@ func GetGeneralSettingsAsKeyValues(s *GeneralSettings) []settings.KeyValue {
|
|||||||
Value: s.FileSizeLimit,
|
Value: s.FileSizeLimit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.UserCommiterMatch != nil {
|
|
||||||
kvs = append(kvs, settings.KeyValue{
|
|
||||||
Key: settings.KeyUserCommiterMatch,
|
|
||||||
Value: s.UserCommiterMatch,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return kvs
|
return kvs
|
||||||
}
|
}
|
||||||
|
@ -64,13 +64,6 @@ var (
|
|||||||
ErrSpaceWithChildsCantBeDeleted = New(http.StatusBadRequest,
|
ErrSpaceWithChildsCantBeDeleted = New(http.StatusBadRequest,
|
||||||
"Space can't be deleted as it still contains child resources")
|
"Space can't be deleted as it still contains child resources")
|
||||||
|
|
||||||
// ErrCommiterUserMismatch is returned if the commiter's email
|
|
||||||
// is not the same as authenticated user's email.
|
|
||||||
ErrCommiterUserMismatch = New(
|
|
||||||
http.StatusForbidden,
|
|
||||||
"Committer verification failed: authenticated user and committer must match",
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrDefaultBranchCantBeDeleted is returned if the user tries to delete the default branch of a repository.
|
// ErrDefaultBranchCantBeDeleted is returned if the user tries to delete the default branch of a repository.
|
||||||
ErrDefaultBranchCantBeDeleted = New(http.StatusBadRequest, "The default branch of a repository can't be deleted")
|
ErrDefaultBranchCantBeDeleted = New(http.StatusBadRequest, "The default branch of a repository can't be deleted")
|
||||||
|
|
||||||
|
@ -24,6 +24,4 @@ var (
|
|||||||
DefaultFileSizeLimit = int64(1e+8) // 100 MB
|
DefaultFileSizeLimit = int64(1e+8) // 100 MB
|
||||||
KeyInstallID Key = "install_id"
|
KeyInstallID Key = "install_id"
|
||||||
DefaultInstallID = string("")
|
DefaultInstallID = string("")
|
||||||
KeyUserCommiterMatch Key = "user_commiter_match"
|
|
||||||
DefaultUserCommiterMatch = false
|
|
||||||
)
|
)
|
||||||
|
@ -589,44 +589,6 @@ func (g *Git) GetCommits(
|
|||||||
return getCommits(ctx, repoPath, refs)
|
return getCommits(ctx, repoPath, refs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Git) GetBranchCommiterEmails(
|
|
||||||
ctx context.Context,
|
|
||||||
repoPath string,
|
|
||||||
baseSHA sha.SHA,
|
|
||||||
revSHA sha.SHA,
|
|
||||||
alternateObjDirs []string,
|
|
||||||
) (map[string]string, error) {
|
|
||||||
cmd := command.New(
|
|
||||||
"log",
|
|
||||||
command.WithFlag("--pretty=format:%H %ce"),
|
|
||||||
)
|
|
||||||
if baseSHA.IsEmpty() {
|
|
||||||
cmd.Add(command.WithArg(revSHA.String()))
|
|
||||||
} else {
|
|
||||||
cmd.Add(command.WithArg(baseSHA.String() + ".." + revSHA.String()))
|
|
||||||
}
|
|
||||||
if len(alternateObjDirs) > 0 {
|
|
||||||
cmd.Add(command.WithAlternateObjectDirs(alternateObjDirs...))
|
|
||||||
}
|
|
||||||
|
|
||||||
output := &bytes.Buffer{}
|
|
||||||
err := cmd.Run(ctx, command.WithDir(repoPath), command.WithStdout(output))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to run git to get commit data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(output)
|
|
||||||
|
|
||||||
shaEmailMap := make(map[string]string)
|
|
||||||
for scanner.Scan() {
|
|
||||||
// scanned line follows pattern "[commit sha] [commiter's email]"
|
|
||||||
shaCommiterSlice := strings.Split(scanner.Text(), " ")
|
|
||||||
shaEmailMap[shaCommiterSlice[0]] = shaCommiterSlice[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return shaEmailMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCommitDivergences returns the count of the diverging commits for all branch pairs.
|
// GetCommitDivergences returns the count of the diverging commits for all branch pairs.
|
||||||
// IMPORTANT: If a maxCount is provided it limits the overal count of diverging commits
|
// IMPORTANT: If a maxCount is provided it limits the overal count of diverging commits
|
||||||
// (maxCount 10 could lead to (0, 10) while it's actually (2, 12)).
|
// (maxCount 10 could lead to (0, 10) while it's actually (2, 12)).
|
||||||
|
@ -43,12 +43,6 @@ type GetCommitParams struct {
|
|||||||
IgnoreWhitespace bool
|
IgnoreWhitespace bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetBranchCommitterEmailsParams struct {
|
|
||||||
ReadParams
|
|
||||||
BaseSHA sha.SHA
|
|
||||||
RevSHA sha.SHA
|
|
||||||
}
|
|
||||||
|
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
SHA sha.SHA `json:"sha"`
|
SHA sha.SHA `json:"sha"`
|
||||||
ParentSHAs []sha.SHA `json:"parent_shas,omitempty"`
|
ParentSHAs []sha.SHA `json:"parent_shas,omitempty"`
|
||||||
@ -105,17 +99,6 @@ func (s *Service) GetCommit(ctx context.Context, params *GetCommitParams) (*GetC
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetBranchCommiterEmails(
|
|
||||||
ctx context.Context,
|
|
||||||
params *GetBranchCommitterEmailsParams,
|
|
||||||
) (map[string]string, error) {
|
|
||||||
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
||||||
|
|
||||||
return s.git.GetBranchCommiterEmails(
|
|
||||||
ctx, repoPath, params.BaseSHA, params.RevSHA, params.AlternateObjectDirs,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListCommitsParams struct {
|
type ListCommitsParams struct {
|
||||||
ReadParams
|
ReadParams
|
||||||
// GitREF is a git reference (branch / tag / commit SHA)
|
// GitREF is a git reference (branch / tag / commit SHA)
|
||||||
|
@ -65,10 +65,6 @@ type Interface interface {
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
params *FindOversizeFilesParams,
|
params *FindOversizeFilesParams,
|
||||||
) (*FindOversizeFilesOutput, error)
|
) (*FindOversizeFilesOutput, error)
|
||||||
GetBranchCommiterEmails(
|
|
||||||
ctx context.Context,
|
|
||||||
params *GetBranchCommitterEmailsParams,
|
|
||||||
) (map[string]string, error)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Git Cli Service
|
* Git Cli Service
|
||||||
|
Loading…
Reference in New Issue
Block a user