Skip to content

Commit

Permalink
Refactor SSH init code, fix directory creation for TrustedUserCAKeys …
Browse files Browse the repository at this point in the history
…file (go-gitea#20299)

* Refactor SSH init code, fix directory creation for TrustedUserCAKeys file

* Update modules/ssh/init.go

Co-authored-by: zeripath <[email protected]>

* fix lint copyright

* Update modules/ssh/init.go

Co-authored-by: zeripath <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
  • Loading branch information
3 people committed Jul 10, 2022
1 parent 317c565 commit b15bf30
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 29 deletions.
21 changes: 4 additions & 17 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,16 +843,17 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
SSH.StartBuiltinServer = false
}

trustedUserCaKeys := sec.Key("SSH_TRUSTED_USER_CA_KEYS").Strings(",")
for _, caKey := range trustedUserCaKeys {
SSH.TrustedUserCAKeysFile = sec.Key("SSH_TRUSTED_USER_CA_KEYS_FILENAME").MustString(filepath.Join(SSH.RootPath, "gitea-trusted-user-ca-keys.pem"))

for _, caKey := range SSH.TrustedUserCAKeys {
pubKey, _, _, _, err := gossh.ParseAuthorizedKey([]byte(caKey))
if err != nil {
log.Fatal("Failed to parse TrustedUserCaKeys: %s %v", caKey, err)
}

SSH.TrustedUserCAKeysParsed = append(SSH.TrustedUserCAKeysParsed, pubKey)
}
if len(trustedUserCaKeys) > 0 {
if len(SSH.TrustedUserCAKeys) > 0 {
// Set the default as email,username otherwise we can leave it empty
sec.Key("SSH_AUTHORIZED_PRINCIPALS_ALLOW").MustString("username,email")
} else {
Expand All @@ -861,20 +862,6 @@ func loadFromConf(allowEmpty bool, extraConfig string) {

SSH.AuthorizedPrincipalsAllow, SSH.AuthorizedPrincipalsEnabled = parseAuthorizedPrincipalsAllow(sec.Key("SSH_AUTHORIZED_PRINCIPALS_ALLOW").Strings(","))

if !SSH.Disabled && !SSH.StartBuiltinServer {
if err = os.MkdirAll(SSH.KeyTestPath, 0o644); err != nil {
log.Fatal("Failed to create '%s': %v", SSH.KeyTestPath, err)
}

if len(trustedUserCaKeys) > 0 && SSH.AuthorizedPrincipalsEnabled {
fname := sec.Key("SSH_TRUSTED_USER_CA_KEYS_FILENAME").MustString(filepath.Join(SSH.RootPath, "gitea-trusted-user-ca-keys.pem"))
if err := os.WriteFile(fname,
[]byte(strings.Join(trustedUserCaKeys, "\n")), 0o600); err != nil {
log.Fatal("Failed to create '%s': %v", fname, err)
}
}
}

SSH.MinimumKeySizeCheck = sec.Key("MINIMUM_KEY_SIZE_CHECK").MustBool(SSH.MinimumKeySizeCheck)
minimumKeySizes := Cfg.Section("ssh.minimum_key_sizes").Keys()
for _, key := range minimumKeySizes {
Expand Down
55 changes: 55 additions & 0 deletions modules/ssh/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package ssh

import (
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

func Init() error {
if setting.SSH.Disabled {
return nil
}

if setting.SSH.StartBuiltinServer {
Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
log.Info("SSH server started on %s. Cipher list (%v), key exchange algorithms (%v), MACs (%v)",
net.JoinHostPort(setting.SSH.ListenHost, strconv.Itoa(setting.SSH.ListenPort)),
setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs,
)
return nil
}

builtinUnused()

// FIXME: why 0o644 for a directory .....
if err := os.MkdirAll(setting.SSH.KeyTestPath, 0o644); err != nil {
return fmt.Errorf("failed to create directory %q for ssh key test: %w", setting.SSH.KeyTestPath, err)
}

if len(setting.SSH.TrustedUserCAKeys) > 0 && setting.SSH.AuthorizedPrincipalsEnabled {
caKeysFileName := setting.SSH.TrustedUserCAKeysFile
caKeysFileDir := filepath.Dir(caKeysFileName)

err := os.MkdirAll(caKeysFileDir, 0o700) // SSH.RootPath by default (That is `~/.ssh` in most cases)
if err != nil {
return fmt.Errorf("failed to create directory %q for ssh trusted ca keys: %w", caKeysFileDir, err)
}

if err := os.WriteFile(caKeysFileName, []byte(strings.Join(setting.SSH.TrustedUserCAKeys, "\n")), 0o600); err != nil {
return fmt.Errorf("failed to write ssh trusted ca keys to %q: %w", caKeysFileName, err)
}
}

return nil
}
4 changes: 2 additions & 2 deletions modules/ssh/ssh_graceful.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func listen(server *ssh.Server) {
log.Info("SSH Listener: %s Closed", server.Addr)
}

// Unused informs our cleanup routine that we will not be using a ssh port
func Unused() {
// builtinUnused informs our cleanup routine that we will not be using a ssh port
func builtinUnused() {
graceful.GetManager().InformCleanup()
}
12 changes: 2 additions & 10 deletions routers/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ package routers

import (
"context"
"net"
"reflect"
"runtime"
"strconv"

"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
Expand Down Expand Up @@ -158,14 +156,8 @@ func GlobalInitInstalled(ctx context.Context) {

mustInitCtx(ctx, syncAppPathForGit)

if setting.SSH.StartBuiltinServer {
ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
log.Info("SSH server started on %s. Cipher list (%v), key exchange algorithms (%v), MACs (%v)",
net.JoinHostPort(setting.SSH.ListenHost, strconv.Itoa(setting.SSH.ListenPort)),
setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
} else {
ssh.Unused()
}
mustInit(ssh.Init)

auth.Init()
svg.Init()
}
Expand Down

0 comments on commit b15bf30

Please sign in to comment.