feat: update gitea vendor
runner nix smoke / nix label and flake smoke (push) Failing after 1m28s

This commit is contained in:
2026-09-26 21:18:24 +00:00
parent c439c1b948
commit d9b2a4e787
3538 changed files with 116131 additions and 44340 deletions
+3 -3
View File
@@ -11,9 +11,9 @@ import (
"strconv"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
)
func Init() error {
+56 -64
View File
@@ -6,9 +6,6 @@ package ssh
import (
"bytes"
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"io"
@@ -22,12 +19,12 @@ import (
"sync"
"syscall"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
asymkey_model "gitea.dev/models/asymkey"
"gitea.dev/modules/generate"
"gitea.dev/modules/graceful"
"gitea.dev/modules/log"
"gitea.dev/modules/process"
"gitea.dev/modules/setting"
"github.com/gliderlabs/ssh"
gossh "golang.org/x/crypto/ssh"
@@ -59,7 +56,7 @@ func getExitStatusFromError(err error) int {
return 0
}
exitErr, ok := err.(*exec.ExitError)
exitErr, ok := errors.AsType[*exec.ExitError](err)
if !ok {
return 1
}
@@ -155,7 +152,6 @@ func sessionHandler(session ssh.Session) {
process.SetSysProcAttribute(cmd)
wg := &sync.WaitGroup{}
wg.Add(2)
if err = cmd.Start(); err != nil {
log.Error("SSH: Start: %v", err)
@@ -169,21 +165,19 @@ func sessionHandler(session ssh.Session) {
}
}()
go func() {
defer wg.Done()
wg.Go(func() {
defer stdout.Close()
if _, err := io.Copy(session, stdout); err != nil {
log.Error("Failed to write stdout to session. %s", err)
}
}()
})
go func() {
defer wg.Done()
wg.Go(func() {
defer stderr.Close()
if _, err := io.Copy(session.Stderr(), stderr); err != nil {
log.Error("Failed to write stderr to session. %s", err)
}
}()
})
// Ensure all the output has been written before we wait on the command
// to exit.
@@ -325,7 +319,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
}
// sshConnectionFailed logs a failed connection
// - this mainly exists to give a nice function name in logging
// - this mainly exists to give a nice function name in logging
func sshConnectionFailed(conn net.Conn, err error) {
// Log the underlying error with a specific message
log.Warn("Failed connection from %s with error: %v", conn.RemoteAddr(), err)
@@ -354,40 +348,37 @@ func Listen(host string, port int, ciphers, keyExchanges, macs []string) {
},
}
keys := make([]string, 0, len(setting.SSH.ServerHostKeys))
hostKeyFiles := make([]string, 0, len(setting.SSH.ServerHostKeys))
for _, key := range setting.SSH.ServerHostKeys {
isExist, err := util.IsExist(key)
_, err := os.Stat(key)
if err != nil {
log.Fatal("Unable to check if %s exists. Error: %v", setting.SSH.ServerHostKeys, err)
}
if isExist {
keys = append(keys, key)
if !errors.Is(err, os.ErrNotExist) {
log.Fatal("Unable to check if %s exists. Error: %v", setting.SSH.ServerHostKeys, err)
}
continue
}
hostKeyFiles = append(hostKeyFiles, key)
}
if len(keys) == 0 {
filePath := filepath.Dir(setting.SSH.ServerHostKeys[0])
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
log.Error("Failed to create dir %s: %v", filePath, err)
if len(hostKeyFiles) == 0 {
hostKeyDir := filepath.Dir(setting.SSH.ServerHostKeys[0])
err := os.MkdirAll(hostKeyDir, os.ModePerm)
if err != nil {
log.Error("Failed to create dir %s: %v", hostKeyDir, err)
}
err := GenKeyPair(setting.SSH.ServerHostKeys[0])
hostKeyFiles, err = InitDefaultHostKeys(hostKeyDir)
if err != nil {
log.Fatal("Failed to generate private key: %v", err)
}
log.Trace("New private key is generated: %s", setting.SSH.ServerHostKeys[0])
keys = append(keys, setting.SSH.ServerHostKeys[0])
}
for _, key := range keys {
log.Info("Adding SSH host key: %s", key)
err := srv.SetOption(ssh.HostKeyFile(key))
for _, keyFile := range hostKeyFiles {
log.Info("Adding SSH host key: %s", keyFile)
err := srv.SetOption(ssh.HostKeyFile(keyFile))
if err != nil {
log.Error("Failed to set Host Key. %s", err)
}
}
go func() {
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Service: Built-in SSH server", process.SystemProcessType, true)
defer finished()
@@ -398,43 +389,44 @@ func Listen(host string, port int, ciphers, keyExchanges, macs []string) {
// GenKeyPair make a pair of public and private keys for SSH access.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded
func GenKeyPair(keyPath string) error {
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
func GenKeyPair(keyPath string, keyType generate.SSHKeyType, bits int) error {
publicKey, privateKeyPEM, err := generate.NewSSHKey(keyType, bits)
if err != nil {
return err
}
privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
f, err := os.OpenFile(keyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
return err
}
defer func() {
if err = f.Close(); err != nil {
log.Error("Close: %v", err)
}
}()
if err := pem.Encode(f, privateKeyPEM); err != nil {
return err
}
// generate public key
pub, err := gossh.NewPublicKey(&privateKey.PublicKey)
public := gossh.MarshalAuthorizedKey(publicKey)
privateKeyBuf := &bytes.Buffer{}
err = pem.Encode(privateKeyBuf, privateKeyPEM)
if err != nil {
return err
}
public := gossh.MarshalAuthorizedKey(pub)
p, err := os.OpenFile(keyPath+".pub", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
err = os.WriteFile(keyPath, privateKeyBuf.Bytes(), 0o600)
if err != nil {
return err
}
defer func() {
if err = p.Close(); err != nil {
log.Error("Close: %v", err)
return os.WriteFile(keyPath+".pub", public, 0o644)
}
// InitDefaultHostKeys mirrors how ssh-keygen -A operates
// it runs checks if public and private keys are already defined and creates new ones if not present
// key naming does not follow the OpenSSH convention due to existing settings being gitea.{KeyType} so generation follows gitea convention
func InitDefaultHostKeys(path string) (keyFiles []string, _ error) {
var errs []error
keyTypes := []generate.SSHKeyType{generate.SSHKeyRSA, generate.SSHKeyECDSA, generate.SSHKeyED25519}
for _, keyType := range keyTypes {
keyPath := filepath.Join(path, "gitea."+string(keyType))
_, errStatPriv := os.Stat(keyPath)
if errStatPriv != nil {
err := GenKeyPair(keyPath, keyType, 0)
if err != nil {
errs = append(errs, err)
continue
}
}
}()
_, err = p.Write(public)
return err
keyFiles = append(keyFiles, keyPath)
}
return keyFiles, errors.Join(errs...)
}
@@ -4,9 +4,9 @@
package ssh
import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"gitea.dev/modules/graceful"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"github.com/gliderlabs/ssh"
)
@@ -20,7 +20,7 @@ func listen(server *ssh.Server) {
if err != nil {
select {
case <-graceful.GetManager().IsShutdown():
log.Critical("Failed to start SSH server: %v", err)
log.Error("Failed to start SSH server: %v", err)
default:
log.Fatal("Failed to start SSH server: %v", err)
}
@@ -0,0 +1,124 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package ssh
import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"os"
"path/filepath"
"testing"
"gitea.dev/modules/generate"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
gossh "golang.org/x/crypto/ssh"
)
func TestGenKeyPair(t *testing.T) {
testCases := []struct {
keyType generate.SSHKeyType
expectedType any
}{
{
keyType: generate.SSHKeyRSA,
expectedType: &rsa.PrivateKey{},
},
{
keyType: generate.SSHKeyED25519,
expectedType: &ed25519.PrivateKey{},
},
{
keyType: generate.SSHKeyECDSA,
expectedType: &ecdsa.PrivateKey{},
},
}
tmpDir := t.TempDir()
for _, tc := range testCases {
name := "gitea." + string(tc.keyType)
fn := filepath.Join(tmpDir, name)
t.Run("Generate "+name, func(t *testing.T) {
require.NoError(t, GenKeyPair(fn, tc.keyType, 0))
bytes, err := os.ReadFile(fn)
require.NoError(t, err)
privateKey, err := gossh.ParseRawPrivateKey(bytes)
require.NoError(t, err)
assert.IsType(t, tc.expectedType, privateKey)
})
}
t.Run("Generate unknown key type", func(t *testing.T) {
err := GenKeyPair(t.TempDir()+"gitea.badkey", "badkey", 0)
require.Error(t, err)
})
}
func TestInitKeys(t *testing.T) {
tempDir := t.TempDir()
keyTypes := []string{"rsa", "ecdsa", "ed25519"}
for _, keyType := range keyTypes {
privKeyPath := filepath.Join(tempDir, "gitea."+keyType)
pubKeyPath := filepath.Join(tempDir, "gitea."+keyType+".pub")
assert.NoFileExists(t, privKeyPath)
assert.NoFileExists(t, pubKeyPath)
}
// Test basic creation
keyFiles, err := InitDefaultHostKeys(tempDir)
require.NoError(t, err)
assert.Len(t, keyFiles, len(keyTypes))
// Record file contents so regeneration can be detected
content := map[string][]byte{}
for _, keyType := range keyTypes {
privKeyPath := filepath.Join(tempDir, "gitea."+keyType)
pubKeyPath := filepath.Join(tempDir, "gitea."+keyType+".pub")
data, err := os.ReadFile(privKeyPath)
require.NoError(t, err)
content[privKeyPath] = data
data, err = os.ReadFile(pubKeyPath)
require.NoError(t, err)
content[pubKeyPath] = data
}
// Test recreation on missing private key and noop for missing pub key
require.NoError(t, os.Remove(filepath.Join(tempDir, "gitea.ecdsa.pub")))
require.NoError(t, os.Remove(filepath.Join(tempDir, "gitea.ed25519")))
keyFiles, err = InitDefaultHostKeys(tempDir)
require.NoError(t, err)
assert.Len(t, keyFiles, len(keyTypes))
for _, keyType := range keyTypes {
privKeyPath := filepath.Join(tempDir, "gitea."+keyType)
pubKeyPath := filepath.Join(tempDir, "gitea."+keyType+".pub")
dataPriv, err := os.ReadFile(privKeyPath)
require.NoError(t, err)
switch keyType {
case "rsa":
// No modification to RSA key
dataPub, err := os.ReadFile(pubKeyPath)
require.NoError(t, err)
assert.Equal(t, content[privKeyPath], dataPriv)
assert.Equal(t, content[pubKeyPath], dataPub)
case "ecdsa":
// ECDSA public key should be missing, private unchanged
assert.Equal(t, content[privKeyPath], dataPriv)
assert.NoFileExists(t, pubKeyPath)
case "ed25519":
// ed25519 private key was removed, so both keys regenerated
dataPub, err := os.ReadFile(pubKeyPath)
require.NoError(t, err)
assert.NotEqual(t, content[privKeyPath], dataPriv)
assert.NotEqual(t, content[pubKeyPath], dataPub)
}
}
}