summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2020-09-19 17:44:55 +0100
committerGitHub <noreply@github.com>2020-09-20 00:44:55 +0800
commit4979f15c3f44b8e7be46ebce02e25ebd9cc74197 (patch)
tree803aa9da68170090d22d7a1235f36189d1bca9ba /modules
parent89c94e2f8e871028492d5460fd3a10794f4ced1b (diff)
downloadgitea-4979f15c3f44b8e7be46ebce02e25ebd9cc74197.tar.gz
gitea-4979f15c3f44b8e7be46ebce02e25ebd9cc74197.zip
Add configurable Trust Models (#11712)
* Add configurable Trust Models Gitea's default signature verification model differs from GitHub. GitHub uses signatures to verify that the committer is who they say they are - meaning that when GitHub makes a signed commit it must be the committer. The GitHub model prevents re-publishing of commits after revocation of a key and prevents re-signing of other people's commits to create a completely trusted repository signed by one key or a set of trusted keys. The default behaviour of Gitea in contrast is to always display the avatar and information related to a signature. This allows signatures to be decoupled from the committer. That being said, allowing arbitary users to present other peoples commits as theirs is not necessarily desired therefore we have a trust model whereby signatures from collaborators are marked trusted, signatures matching the commit line are marked untrusted and signatures that match a user in the db but not the committer line are marked unmatched. The problem with this model is that this conflicts with Github therefore we need to provide an option to allow users to choose the Github model should they wish to. Signed-off-by: Andrew Thornton <art27@cantab.net> * Adjust locale strings Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @6543 Co-authored-by: 6543 <6543@obermui.de> * Update models/gpg_key.go * Add migration for repository Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'modules')
-rw-r--r--modules/auth/repo_form.go4
-rw-r--r--modules/context/repo.go2
-rw-r--r--modules/git/repo_tree.go10
-rw-r--r--modules/repofiles/delete.go2
-rw-r--r--modules/repofiles/temp_repo.go22
-rw-r--r--modules/repofiles/update.go2
-rw-r--r--modules/repository/create.go1
-rw-r--r--modules/repository/generate.go1
-rw-r--r--modules/repository/init.go17
-rw-r--r--modules/setting/repository.go52
-rw-r--r--modules/structs/repo.go3
11 files changed, 81 insertions, 35 deletions
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 3ad57085b0..f1130f372b 100644
--- a/modules/auth/repo_form.go
+++ b/modules/auth/repo_form.go
@@ -45,6 +45,7 @@ type CreateRepoForm struct {
Webhooks bool
Avatar bool
Labels bool
+ TrustModel string
}
// Validate validates the fields
@@ -142,6 +143,9 @@ type RepoSettingForm struct {
EnableIssueDependencies bool
IsArchived bool
+ // Signing Settings
+ TrustModel string
+
// Admin settings
EnableHealthCheck bool
EnableCloseIssuesViaCommitInAnyBranch bool
diff --git a/modules/context/repo.go b/modules/context/repo.go
index 2c77361460..cb2e60d263 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -114,7 +114,7 @@ func (r *Repository) CanCommitToBranch(doer *models.User) (CanCommitToBranchResu
requireSigned = protectedBranch.RequireSignedCommits
}
- sign, keyID, err := r.Repository.SignCRUDAction(doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName)
+ sign, keyID, _, err := r.Repository.SignCRUDAction(doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName)
canCommit := r.CanEnableEditor() && userCanPush
if requireSigned {
diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go
index a662aaab4f..57896318a7 100644
--- a/modules/git/repo_tree.go
+++ b/modules/git/repo_tree.go
@@ -62,7 +62,7 @@ type CommitTreeOpts struct {
}
// CommitTree creates a commit from a given tree id for the user with provided message
-func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
+func (repo *Repository) CommitTree(author *Signature, committer *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
err := LoadGitVersion()
if err != nil {
return SHA1{}, err
@@ -72,11 +72,11 @@ func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOp
// Because this may call hooks we should pass in the environment
env := append(os.Environ(),
- "GIT_AUTHOR_NAME="+sig.Name,
- "GIT_AUTHOR_EMAIL="+sig.Email,
+ "GIT_AUTHOR_NAME="+author.Name,
+ "GIT_AUTHOR_EMAIL="+author.Email,
"GIT_AUTHOR_DATE="+commitTimeStr,
- "GIT_COMMITTER_NAME="+sig.Name,
- "GIT_COMMITTER_EMAIL="+sig.Email,
+ "GIT_COMMITTER_NAME="+committer.Name,
+ "GIT_COMMITTER_EMAIL="+committer.Email,
"GIT_COMMITTER_DATE="+commitTimeStr,
)
cmd := NewCommand("commit-tree", tree.ID.String())
diff --git a/modules/repofiles/delete.go b/modules/repofiles/delete.go
index 2ffc75e7c8..8343776c47 100644
--- a/modules/repofiles/delete.go
+++ b/modules/repofiles/delete.go
@@ -67,7 +67,7 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
}
}
if protectedBranch.RequireSignedCommits {
- _, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), opts.OldBranch)
+ _, _, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), opts.OldBranch)
if err != nil {
if !models.IsErrWontSign(err) {
return nil, err
diff --git a/modules/repofiles/temp_repo.go b/modules/repofiles/temp_repo.go
index ec671a9322..e0d6c9fcb6 100644
--- a/modules/repofiles/temp_repo.go
+++ b/modules/repofiles/temp_repo.go
@@ -204,8 +204,6 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *models
"GIT_AUTHOR_NAME="+authorSig.Name,
"GIT_AUTHOR_EMAIL="+authorSig.Email,
"GIT_AUTHOR_DATE="+authorDate.Format(time.RFC3339),
- "GIT_COMMITTER_NAME="+committerSig.Name,
- "GIT_COMMITTER_EMAIL="+committerSig.Email,
"GIT_COMMITTER_DATE="+committerDate.Format(time.RFC3339),
)
@@ -217,14 +215,32 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *models
// Determine if we should sign
if git.CheckGitVersionConstraint(">= 1.7.9") == nil {
- sign, keyID, _ := t.repo.SignCRUDAction(author, t.basePath, "HEAD")
+ sign, keyID, signer, _ := t.repo.SignCRUDAction(author, t.basePath, "HEAD")
if sign {
args = append(args, "-S"+keyID)
+ if t.repo.GetTrustModel() == models.CommitterTrustModel || t.repo.GetTrustModel() == models.CollaboratorCommitterTrustModel {
+ if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email {
+ // Add trailers
+ _, _ = messageBytes.WriteString("\n")
+ _, _ = messageBytes.WriteString("Co-Authored-By: ")
+ _, _ = messageBytes.WriteString(committerSig.String())
+ _, _ = messageBytes.WriteString("\n")
+ _, _ = messageBytes.WriteString("Co-Committed-By: ")
+ _, _ = messageBytes.WriteString(committerSig.String())
+ _, _ = messageBytes.WriteString("\n")
+ }
+ committerSig = signer
+ }
} else if git.CheckGitVersionConstraint(">= 2.0.0") == nil {
args = append(args, "--no-gpg-sign")
}
}
+ env = append(env,
+ "GIT_COMMITTER_NAME="+committerSig.Name,
+ "GIT_COMMITTER_EMAIL="+committerSig.Email,
+ )
+
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
if err := git.NewCommand(args...).RunInDirTimeoutEnvFullPipeline(env, -1, t.basePath, stdout, stderr, messageBytes); err != nil {
diff --git a/modules/repofiles/update.go b/modules/repofiles/update.go
index dcb87ec92b..f7fa5f0289 100644
--- a/modules/repofiles/update.go
+++ b/modules/repofiles/update.go
@@ -161,7 +161,7 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
}
}
if protectedBranch.RequireSignedCommits {
- _, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), opts.OldBranch)
+ _, _, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), opts.OldBranch)
if err != nil {
if !models.IsErrWontSign(err) {
return nil, err
diff --git a/modules/repository/create.go b/modules/repository/create.go
index abbec05a37..c180b9b948 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -41,6 +41,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m
CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch,
Status: opts.Status,
IsEmpty: !opts.AutoInit,
+ TrustModel: opts.TrustModel,
}
err = models.WithTx(func(ctx models.DBContext) error {
diff --git a/modules/repository/generate.go b/modules/repository/generate.go
index c5fb0af383..1314464a6e 100644
--- a/modules/repository/generate.go
+++ b/modules/repository/generate.go
@@ -243,6 +243,7 @@ func GenerateRepository(ctx models.DBContext, doer, owner *models.User, template
IsEmpty: !opts.GitContent || templateRepo.IsEmpty,
IsFsckEnabled: templateRepo.IsFsckEnabled,
TemplateID: templateRepo.ID,
+ TrustModel: templateRepo.TrustModel,
}
if err = models.CreateRepository(ctx, doer, owner, generateRepo); err != nil {
diff --git a/modules/repository/init.go b/modules/repository/init.go
index c2038e18d4..d066544a85 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -109,10 +109,10 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User, def
"GIT_AUTHOR_NAME="+sig.Name,
"GIT_AUTHOR_EMAIL="+sig.Email,
"GIT_AUTHOR_DATE="+commitTimeStr,
- "GIT_COMMITTER_NAME="+sig.Name,
- "GIT_COMMITTER_EMAIL="+sig.Email,
"GIT_COMMITTER_DATE="+commitTimeStr,
)
+ committerName := sig.Name
+ committerEmail := sig.Email
if stdout, err := git.NewCommand("add", "--all").
SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)).
@@ -132,14 +132,25 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User, def
}
if git.CheckGitVersionConstraint(">= 1.7.9") == nil {
- sign, keyID, _ := models.SignInitialCommit(tmpPath, u)
+ sign, keyID, signer, _ := models.SignInitialCommit(tmpPath, u)
if sign {
args = append(args, "-S"+keyID)
+
+ if repo.GetTrustModel() == models.CommitterTrustModel || repo.GetTrustModel() == models.CollaboratorCommitterTrustModel {
+ // need to set the committer to the KeyID owner
+ committerName = signer.Name
+ committerEmail = signer.Email
+ }
} else if git.CheckGitVersionConstraint(">= 2.0.0") == nil {
args = append(args, "--no-gpg-sign")
}
}
+ env = append(env,
+ "GIT_COMMITTER_NAME="+committerName,
+ "GIT_COMMITTER_EMAIL="+committerEmail,
+ )
+
if stdout, err := git.NewCommand(args...).
SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)).
RunInDirWithEnv(tmpPath, env); err != nil {
diff --git a/modules/setting/repository.go b/modules/setting/repository.go
index eb1501d7b8..67dd805353 100644
--- a/modules/setting/repository.go
+++ b/modules/setting/repository.go
@@ -83,13 +83,14 @@ var (
} `ini:"repository.issue"`
Signing struct {
- SigningKey string
- SigningName string
- SigningEmail string
- InitialCommit []string
- CRUDActions []string `ini:"CRUD_ACTIONS"`
- Merges []string
- Wiki []string
+ SigningKey string
+ SigningName string
+ SigningEmail string
+ InitialCommit []string
+ CRUDActions []string `ini:"CRUD_ACTIONS"`
+ Merges []string
+ Wiki []string
+ DefaultTrustModel string
} `ini:"repository.signing"`
}{
DetectedCharsetsOrder: []string{
@@ -209,21 +210,23 @@ var (
// Signing settings
Signing: struct {
- SigningKey string
- SigningName string
- SigningEmail string
- InitialCommit []string
- CRUDActions []string `ini:"CRUD_ACTIONS"`
- Merges []string
- Wiki []string
+ SigningKey string
+ SigningName string
+ SigningEmail string
+ InitialCommit []string
+ CRUDActions []string `ini:"CRUD_ACTIONS"`
+ Merges []string
+ Wiki []string
+ DefaultTrustModel string
}{
- SigningKey: "default",
- SigningName: "",
- SigningEmail: "",
- InitialCommit: []string{"always"},
- CRUDActions: []string{"pubkey", "twofa", "parentsigned"},
- Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"},
- Wiki: []string{"never"},
+ SigningKey: "default",
+ SigningName: "",
+ SigningEmail: "",
+ InitialCommit: []string{"always"},
+ CRUDActions: []string{"pubkey", "twofa", "parentsigned"},
+ Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"},
+ Wiki: []string{"never"},
+ DefaultTrustModel: "collaborator",
},
}
RepoRootPath string
@@ -268,6 +271,13 @@ func newRepository() {
log.Fatal("Failed to map Repository.PullRequest settings: %v", err)
}
+ // Handle default trustmodel settings
+ Repository.Signing.DefaultTrustModel = strings.ToLower(strings.TrimSpace(Repository.Signing.DefaultTrustModel))
+ if Repository.Signing.DefaultTrustModel == "default" {
+ Repository.Signing.DefaultTrustModel = "collaborator"
+ }
+
+ // Handle preferred charset orders
preferred := make([]string, 0, len(Repository.DetectedCharsetsOrder))
for _, charset := range Repository.DetectedCharsetsOrder {
canonicalCharset := strings.ToLower(strings.TrimSpace(charset))
diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index c57702b282..c86b19dfd0 100644
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -117,6 +117,9 @@ type CreateRepoOption struct {
Readme string `json:"readme"`
// DefaultBranch of the repository (used when initializes and in template)
DefaultBranch string `json:"default_branch" binding:"GitRefName;MaxSize(100)"`
+ // TrustModel of the repository
+ // enum: default,collaborator,committer,collaboratorcommitter
+ TrustModel string `json:"trust_model"`
}
// EditRepoOption options when editing a repository's properties