Skip to content

Commit 5222a16

Browse files
committed
Merge branch 'main' into refactor-embed-gzip
2 parents 5ef3413 + d5893ee commit 5222a16

File tree

27 files changed

+1056
-287
lines changed

27 files changed

+1056
-287
lines changed

CHANGELOG.md

Lines changed: 423 additions & 0 deletions
Large diffs are not rendered by default.

custom/conf/app.example.ini

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,17 +1186,24 @@ LEVEL = Info
11861186
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11871187
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11881188
;;
1189-
;; GPG key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey
1189+
;; GPG or SSH key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey
1190+
;; Depending on the value of SIGNING_FORMAT this is either:
1191+
;; - openpgp: the GPG key ID
1192+
;; - ssh: the path to the ssh public key "/path/to/key.pub": where "/path/to/key" is the private key, use ssh-keygen -t ed25519 to generate a new key pair without password
11901193
;; run in the context of the RUN_USER
11911194
;; Switch to none to stop signing completely
11921195
;SIGNING_KEY = default
11931196
;;
1194-
;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer.
1197+
;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer and the signing format.
11951198
;; These should match a publicized name and email address for the key. (When SIGNING_KEY is default these are set to
1196-
;; the results of git config --get user.name and git config --get user.email respectively and can only be overridden
1199+
;; the results of git config --get user.name, git config --get user.email and git config --default openpgp --get gpg.format respectively and can only be overridden
11971200
;; by setting the SIGNING_KEY ID to the correct ID.)
11981201
;SIGNING_NAME =
11991202
;SIGNING_EMAIL =
1203+
;; SIGNING_FORMAT can be one of:
1204+
;; - openpgp (default): use GPG to sign commits
1205+
;; - ssh: use SSH to sign commits
1206+
;SIGNING_FORMAT = openpgp
12001207
;;
12011208
;; Sets the default trust model for repositories. Options are: collaborator, committer, collaboratorcommitter
12021209
;DEFAULT_TRUST_MODEL = collaborator
@@ -1223,6 +1230,13 @@ LEVEL = Info
12231230
;; - commitssigned: require that all the commits in the head branch are signed.
12241231
;; - approved: only sign when merging an approved pr to a protected branch
12251232
;MERGES = pubkey, twofa, basesigned, commitssigned
1233+
;;
1234+
;; Determines which additional ssh keys are trusted for all signed commits regardless of the user
1235+
;; This is useful for ssh signing key rotation.
1236+
;; Exposes the provided SIGNING_NAME and SIGNING_EMAIL as the signer, regardless of the SIGNING_FORMAT value.
1237+
;; Multiple keys should be comma separated.
1238+
;; E.g."ssh-<algorithm> <key>". or "ssh-<algorithm> <key1>, ssh-<algorithm> <key2>".
1239+
;TRUSTED_SSH_KEYS =
12261240

12271241
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12281242
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

modules/git/command.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Command struct {
4747
globalArgsLength int
4848
brokenArgs []string
4949
cmd *exec.Cmd // for debug purpose only
50+
configArgs []string
5051
}
5152

5253
func logArgSanitize(arg string) string {
@@ -196,6 +197,16 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
196197
return c
197198
}
198199

200+
func (c *Command) AddConfig(key, value string) *Command {
201+
kv := key + "=" + value
202+
if !isSafeArgumentValue(kv) {
203+
c.brokenArgs = append(c.brokenArgs, key)
204+
} else {
205+
c.configArgs = append(c.configArgs, "-c", kv)
206+
}
207+
return c
208+
}
209+
199210
// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
200211
// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead
201212
func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
@@ -321,7 +332,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
321332

322333
startTime := time.Now()
323334

324-
cmd := exec.CommandContext(ctx, c.prog, c.args...)
335+
cmd := exec.CommandContext(ctx, c.prog, append(c.configArgs, c.args...)...)
325336
c.cmd = cmd // for debug purpose only
326337
if opts.Env == nil {
327338
cmd.Env = os.Environ()

modules/git/key.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
7+
const (
8+
SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli
9+
SigningKeyFormatSSH = "ssh"
10+
)
11+
12+
type SigningKey struct {
13+
KeyID string
14+
Format string
15+
}

modules/git/repo.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type GPGSettings struct {
2828
Email string
2929
Name string
3030
PublicKeyContent string
31+
Format string
3132
}
3233

3334
const prettyLogFormat = `--pretty=format:%H`

modules/git/repo_gpg.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@ package git
66

77
import (
88
"fmt"
9+
"os"
910
"strings"
1011

1112
"code.gitea.io/gitea/modules/process"
1213
)
1314

1415
// LoadPublicKeyContent will load the key from gpg
1516
func (gpgSettings *GPGSettings) LoadPublicKeyContent() error {
17+
if gpgSettings.Format == SigningKeyFormatSSH {
18+
content, err := os.ReadFile(gpgSettings.KeyID)
19+
if err != nil {
20+
return fmt.Errorf("unable to read SSH public key file: %s, %w", gpgSettings.KeyID, err)
21+
}
22+
gpgSettings.PublicKeyContent = string(content)
23+
return nil
24+
}
1625
content, stderr, err := process.GetManager().Exec(
1726
"gpg -a --export",
1827
"gpg", "-a", "--export", gpgSettings.KeyID)
@@ -44,6 +53,9 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings,
4453
signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
4554
gpgSettings.KeyID = strings.TrimSpace(signingKey)
4655

56+
format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
57+
gpgSettings.Format = strings.TrimSpace(format)
58+
4759
defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
4860
gpgSettings.Email = strings.TrimSpace(defaultEmail)
4961

modules/git/repo_tree.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
type CommitTreeOpts struct {
1616
Parents []string
1717
Message string
18-
KeyID string
18+
Key *SigningKey
1919
NoGPGSign bool
2020
AlwaysSign bool
2121
}
@@ -43,8 +43,13 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
4343
_, _ = messageBytes.WriteString(opts.Message)
4444
_, _ = messageBytes.WriteString("\n")
4545

46-
if opts.KeyID != "" || opts.AlwaysSign {
47-
cmd.AddOptionFormat("-S%s", opts.KeyID)
46+
if opts.Key != nil {
47+
if opts.Key.Format != "" {
48+
cmd.AddConfig("gpg.format", opts.Key.Format)
49+
}
50+
cmd.AddOptionFormat("-S%s", opts.Key.KeyID)
51+
} else if opts.AlwaysSign {
52+
cmd.AddOptionFormat("-S")
4853
}
4954

5055
if opts.NoGPGSign {

modules/setting/repository.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,13 @@ var (
100100
SigningKey string
101101
SigningName string
102102
SigningEmail string
103+
SigningFormat string
103104
InitialCommit []string
104105
CRUDActions []string `ini:"CRUD_ACTIONS"`
105106
Merges []string
106107
Wiki []string
107108
DefaultTrustModel string
109+
TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"`
108110
} `ini:"repository.signing"`
109111
}{
110112
DetectedCharsetsOrder: []string{
@@ -242,20 +244,24 @@ var (
242244
SigningKey string
243245
SigningName string
244246
SigningEmail string
247+
SigningFormat string
245248
InitialCommit []string
246249
CRUDActions []string `ini:"CRUD_ACTIONS"`
247250
Merges []string
248251
Wiki []string
249252
DefaultTrustModel string
253+
TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"`
250254
}{
251255
SigningKey: "default",
252256
SigningName: "",
253257
SigningEmail: "",
258+
SigningFormat: "openpgp", // git.SigningKeyFormatOpenPGP
254259
InitialCommit: []string{"always"},
255260
CRUDActions: []string{"pubkey", "twofa", "parentsigned"},
256261
Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"},
257262
Wiki: []string{"never"},
258263
DefaultTrustModel: "collaborator",
264+
TrustedSSHKeys: []string{},
259265
},
260266
}
261267
RepoRootPath string

0 commit comments

Comments
 (0)