mirror of https://github.com/harness/drone.git
[SSH] Minor Server Changes (#2088)
parent
7899ebd3a3
commit
90680e24f7
|
@ -5,6 +5,8 @@ web/dist
|
|||
release
|
||||
.idea
|
||||
coverage.out
|
||||
*.rsa
|
||||
*.rsa.pub
|
||||
|
||||
# ignore any executables we build
|
||||
/gitness
|
|
@ -15,11 +15,9 @@ release
|
|||
coverage.out
|
||||
gitness.session.sql
|
||||
web/cypress/node_modules
|
||||
*.rsa
|
||||
*.rsa.pub
|
||||
node_modules/
|
||||
|
||||
# ignore any executables we build
|
||||
/gitness
|
||||
|
||||
node_modules/
|
||||
|
||||
ssh/gitness.rsa
|
||||
ssh/gitness.rsa.pub
|
|
@ -75,12 +75,8 @@ var (
|
|||
"hmac-sha2-256",
|
||||
"hmac-sha2-512",
|
||||
}
|
||||
defaultServerKeys = []string{"ssh/gitness.rsa"}
|
||||
KeepAliveMsg = "keepalive@openssh.com"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrHostKeysAreRequired = errors.New("host keys are required")
|
||||
defaultServerKeyPath = "ssh/gitness.rsa"
|
||||
KeepAliveMsg = "keepalive@openssh.com"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
@ -96,7 +92,7 @@ type Server struct {
|
|||
KeyExchanges []string
|
||||
MACs []string
|
||||
HostKeys []string
|
||||
KeepAliveInterval int
|
||||
KeepAliveInterval time.Duration
|
||||
|
||||
Verifier publickey.Service
|
||||
RepoCtrl *repo.Controller
|
||||
|
@ -119,10 +115,6 @@ func (s *Server) sanitize() error {
|
|||
s.MACs = defaultMACs
|
||||
}
|
||||
|
||||
if len(s.HostKeys) == 0 {
|
||||
s.HostKeys = defaultServerKeys
|
||||
}
|
||||
|
||||
if s.KeepAliveInterval == 0 {
|
||||
s.KeepAliveInterval = 5000
|
||||
}
|
||||
|
@ -169,34 +161,22 @@ func (s *Server) ListenAndServe() error {
|
|||
}
|
||||
|
||||
func (s *Server) setupHostKeys() error {
|
||||
if len(s.HostKeys) == 0 {
|
||||
return ErrHostKeysAreRequired
|
||||
}
|
||||
keys := make([]string, 0, len(s.HostKeys))
|
||||
// check if file exists and append to slice keys
|
||||
for _, key := range s.HostKeys {
|
||||
_, err := os.Stat(key)
|
||||
if err != nil {
|
||||
log.Err(err).Msgf("unable to check if %s exists", key)
|
||||
continue
|
||||
return fmt.Errorf("failed to read provided host key %q: %w", key, err)
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
// if there is no keys found then create one from HostKeys field
|
||||
if len(keys) == 0 {
|
||||
fullpath := s.HostKeys[0]
|
||||
filePath := filepath.Dir(fullpath)
|
||||
|
||||
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create dir %s: %w", filePath, err)
|
||||
}
|
||||
|
||||
err := GenerateKeyPair(fullpath)
|
||||
log.Debug().Msg("no host key provided - setup default key if it doesn't exist yet")
|
||||
err := createKeyIfNotExists(defaultServerKeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate private key: %w", err)
|
||||
return fmt.Errorf("failed to setup default key %q: %w", defaultServerKeyPath, err)
|
||||
}
|
||||
keys = append(keys, fullpath)
|
||||
keys = append(keys, defaultServerKeyPath)
|
||||
}
|
||||
|
||||
// set keys to internal ssh server
|
||||
|
@ -206,6 +186,7 @@ func (s *Server) setupHostKeys() error {
|
|||
log.Err(err).Msg("failed to set host key to ssh server")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -268,7 +249,7 @@ func (s *Server) sessionHandler(session ssh.Session) {
|
|||
|
||||
// set keep alive connection
|
||||
if s.KeepAliveInterval > 0 {
|
||||
go s.sendKeepAliveMsg(ctx, session)
|
||||
go sendKeepAliveMsg(ctx, session, s.KeepAliveInterval)
|
||||
}
|
||||
|
||||
err = s.RepoCtrl.GitServicePack(
|
||||
|
@ -302,8 +283,8 @@ func (s *Server) sessionHandler(session ssh.Session) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Server) sendKeepAliveMsg(ctx context.Context, session ssh.Session) {
|
||||
ticker := time.NewTicker(time.Duration(s.KeepAliveInterval))
|
||||
func sendKeepAliveMsg(ctx context.Context, session ssh.Session, interval time.Duration) {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
log.Ctx(ctx).Debug().Str("remote_addr", session.RemoteAddr().String()).Msgf("sendKeepAliveMsg")
|
||||
|
||||
|
@ -312,8 +293,11 @@ func (s *Server) sendKeepAliveMsg(ctx context.Context, session ssh.Session) {
|
|||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
log.Ctx(ctx).Debug().Msg("connection: sendKeepAliveMsg: send keepalive message to a client")
|
||||
_, _ = session.SendRequest(KeepAliveMsg, true, nil)
|
||||
log.Ctx(ctx).Debug().Msg("send keepalive message to ssh client")
|
||||
_, err := session.SendRequest(KeepAliveMsg, true, nil)
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Debug().Err(err).Msg("failed to send keepalive message to ssh client")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,8 +316,12 @@ func (s *Server) publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
|||
}
|
||||
|
||||
principal, err := s.Verifier.ValidateKey(ctx, key, enum.PublicKeyUsageAuth)
|
||||
if errors.IsNotFound(err) {
|
||||
log.Debug().Err(err).Msg("public key is unknown")
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to validate public key")
|
||||
log.Warn().Err(err).Msg("failed to validate public key")
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -365,6 +353,31 @@ func sshConnectionFailed(conn net.Conn, err error) {
|
|||
log.Err(err).Msgf("failed connection from %s with error: %v", conn.RemoteAddr(), err)
|
||||
}
|
||||
|
||||
func createKeyIfNotExists(path string) error {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
// if the path already exists there's nothing we have to do
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to check for for existence of key: %w", err)
|
||||
}
|
||||
|
||||
log.Debug().Msgf("generate new key at %q", path)
|
||||
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create dir %q for key: %w", dir, err)
|
||||
}
|
||||
|
||||
err = GenerateKeyPair(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate key pair: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateKeyPair make a pair of public and private keys for SSH access.
|
||||
func GenerateKeyPair(keyPath string) error {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
|
|
|
@ -138,7 +138,7 @@ type Config struct {
|
|||
}
|
||||
|
||||
SSH struct {
|
||||
Enable bool `envconfig:"GITNESS_SSH_ENABLE" default:"true"`
|
||||
Enable bool `envconfig:"GITNESS_SSH_ENABLE" default:"false"`
|
||||
Host string `envconfig:"GITNESS_SSH_HOST"`
|
||||
Port int `envconfig:"GITNESS_SSH_PORT" default:"22"`
|
||||
// DefaultUser holds value for generating urls {user}@host:path and force check
|
||||
|
@ -152,7 +152,7 @@ type Config struct {
|
|||
TrustedUserCAKeys []string `envconfig:"GITNESS_SSH_TRUSTED_USER_CA_KEYS"`
|
||||
TrustedUserCAKeysFile string `envconfig:"GITNESS_SSH_TRUSTED_USER_CA_KEYS_FILENAME"`
|
||||
TrustedUserCAKeysParsed []gossh.PublicKey
|
||||
KeepAliveInterval int `envconfig:"GITNESS_SSH_KEEP_ALIVE_INTERVAL" default:"5000"`
|
||||
KeepAliveInterval time.Duration `envconfig:"GITNESS_SSH_KEEP_ALIVE_INTERVAL" default:"5s"`
|
||||
}
|
||||
|
||||
// CI defines configuration related to build executions.
|
||||
|
|
Loading…
Reference in New Issue