Allow caller to specify new line for SSH public key.
The default behavior of the various builders that create SSH key pairs appears to be to add a trailing new line. This will be the default behavior, but at least it can be customized if desired.
This commit is contained in:
parent
ad075ffac3
commit
6824806e6f
|
@ -4,6 +4,7 @@ package common
|
|||
// Perhaps through 'helper/ssh'?
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
|
@ -35,6 +36,29 @@ func (o sshKeyPairType) String() string {
|
|||
return string(o)
|
||||
}
|
||||
|
||||
const (
|
||||
// unixNewLine is a unix new line.
|
||||
unixNewLine newLineOption = "\n"
|
||||
|
||||
// windowsNewLine is a Windows new line.
|
||||
windowsNewLine newLineOption = "\r\n"
|
||||
|
||||
// noNewLine will not append a new line.
|
||||
noNewLine newLineOption = ""
|
||||
)
|
||||
|
||||
// newLineOption specifies the type of new line to append to a string.
|
||||
// See the 'const' block for choices.
|
||||
type newLineOption string
|
||||
|
||||
func (o newLineOption) String() string {
|
||||
return string(o)
|
||||
}
|
||||
|
||||
func (o newLineOption) Bytes() []byte {
|
||||
return []byte(o)
|
||||
}
|
||||
|
||||
// sshKeyPairBuilder builds SSH key pairs.
|
||||
type sshKeyPairBuilder interface {
|
||||
// SetType sets the key pair type.
|
||||
|
@ -99,9 +123,9 @@ type sshKeyPair interface {
|
|||
PrivateKeyPemBlock() []byte
|
||||
|
||||
// PublicKeyAuthorizedKeysFormat returns a slice of bytes
|
||||
// representing the public key in OpenSSH authorized_keys
|
||||
// format with a trailing new line.
|
||||
PublicKeyAuthorizedKeysFormat() []byte
|
||||
// representing the public key in OpenSSH authorized_keys format
|
||||
// with the specified new line.
|
||||
PublicKeyAuthorizedKeysFormat(newLineOption) []byte
|
||||
}
|
||||
|
||||
type defaultSshKeyPair struct {
|
||||
|
@ -148,8 +172,26 @@ func (o defaultSshKeyPair) PrivateKeyPemBlock() []byte {
|
|||
})
|
||||
}
|
||||
|
||||
func (o defaultSshKeyPair) PublicKeyAuthorizedKeysFormat() []byte {
|
||||
return ssh.MarshalAuthorizedKey(o.publicKey)
|
||||
func (o defaultSshKeyPair) PublicKeyAuthorizedKeysFormat(nl newLineOption) []byte {
|
||||
result := ssh.MarshalAuthorizedKey(o.publicKey)
|
||||
|
||||
switch nl {
|
||||
case noNewLine:
|
||||
result = bytes.TrimSuffix(result, unixNewLine.Bytes())
|
||||
case windowsNewLine:
|
||||
result = bytes.TrimSuffix(result, unixNewLine.Bytes())
|
||||
result = append(result, nl.Bytes()...)
|
||||
case unixNewLine:
|
||||
fallthrough
|
||||
default:
|
||||
// This is how all the other "SSH key pair" code works in
|
||||
// the different builders.
|
||||
if !bytes.HasSuffix(result, unixNewLine.Bytes()) {
|
||||
result = append(result, unixNewLine.Bytes()...)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// newEcdsaSshKeyPair returns a new ECDSA SSH key pair for the given bits
|
||||
|
|
|
@ -45,7 +45,12 @@ func (o expected) matches(kp sshKeyPair) error {
|
|||
expDescription + "' - got '" + kp.Description() + "'")
|
||||
}
|
||||
|
||||
err := verifySshKeyPair(kp)
|
||||
err := verifyPublickeyAuthorizedKeysFormat(kp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = verifySshKeyPair(kp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -121,3 +126,39 @@ func verifySshKeyPair(kp sshKeyPair) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyPublickeyAuthorizedKeysFormat(kp sshKeyPair) error {
|
||||
newLines := []newLineOption{
|
||||
unixNewLine,
|
||||
noNewLine,
|
||||
windowsNewLine,
|
||||
}
|
||||
|
||||
for _, nl := range newLines {
|
||||
publicKeyAk := kp.PublicKeyAuthorizedKeysFormat(nl)
|
||||
|
||||
if len(publicKeyAk) < 2 {
|
||||
return errors.New("expected public key in authorized keys format to be at least 2 bytes")
|
||||
}
|
||||
|
||||
switch nl {
|
||||
case noNewLine:
|
||||
if publicKeyAk[len(publicKeyAk) - 1] == '\n' {
|
||||
return errors.New("public key in authorized keys format has trailing new line when none was specified")
|
||||
}
|
||||
case unixNewLine:
|
||||
if publicKeyAk[len(publicKeyAk) - 1] != '\n' {
|
||||
return errors.New("public key in authorized keys format does not have unix new line when unix was specified")
|
||||
}
|
||||
if string(publicKeyAk[len(publicKeyAk) - 2:]) == windowsNewLine.String() {
|
||||
return errors.New("public key in authorized keys format has windows new line when unix was specified")
|
||||
}
|
||||
case windowsNewLine:
|
||||
if string(publicKeyAk[len(publicKeyAk) - 2:]) != windowsNewLine.String() {
|
||||
return errors.New("public key in authorized keys format does not have windows new line when windows was specified")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue