Add some ssh related tests.
This commit is contained in:
parent
8890c8edd7
commit
325d77fce9
6 changed files with 204 additions and 12 deletions
6
Gopkg.lock
generated
6
Gopkg.lock
generated
|
@ -262,8 +262,8 @@
|
|||
revision = "de77670473b5492f5d0bce155b5c01534c2d13f7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:c26dc5debe7fa23c636a116c336aa033f8d7be0d3464d7b363f4b3355dcccf4f"
|
||||
branch = "ssh-login"
|
||||
digest = "1:a78bee6074ef87c752657e5641cdcdba87d77544804d6c868689228340de7739"
|
||||
name = "github.com/smallstep/cli"
|
||||
packages = [
|
||||
"command",
|
||||
|
@ -285,7 +285,7 @@
|
|||
"utils",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "eeecaac062cb548ee2ab7c7563bc3c2f2160f019"
|
||||
revision = "98e63ae8527b8cfbe0090163f6ce55a455698435"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
|
@ -35,7 +35,7 @@ ignored = ["github.com/Masterminds/semver/v3"]
|
|||
name = "github.com/go-chi/chi"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
branch = "ssh-login"
|
||||
name = "github.com/smallstep/cli"
|
||||
|
||||
[[constraint]]
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"crypto/x509"
|
||||
|
||||
"github.com/smallstep/certificates/db"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type MockAuthDB struct {
|
||||
|
@ -14,6 +15,8 @@ type MockAuthDB struct {
|
|||
revoke func(rci *db.RevokedCertificateInfo) error
|
||||
storeCertificate func(crt *x509.Certificate) error
|
||||
useToken func(id, tok string) (bool, error)
|
||||
isSSHHost func(principal string) (bool, error)
|
||||
storeSSHCertificate func(crt *ssh.Certificate) error
|
||||
shutdown func() error
|
||||
}
|
||||
|
||||
|
@ -58,6 +61,20 @@ func (m *MockAuthDB) StoreCertificate(crt *x509.Certificate) error {
|
|||
return m.err
|
||||
}
|
||||
|
||||
func (m *MockAuthDB) IsSSHHost(principal string) (bool, error) {
|
||||
if m.isSSHHost != nil {
|
||||
return m.isSSHHost(principal)
|
||||
}
|
||||
return m.ret1.(bool), m.err
|
||||
}
|
||||
|
||||
func (m *MockAuthDB) StoreSSHCertificate(crt *ssh.Certificate) error {
|
||||
if m.storeSSHCertificate != nil {
|
||||
return m.storeSSHCertificate(crt)
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *MockAuthDB) Shutdown() error {
|
||||
if m.shutdown != nil {
|
||||
return m.shutdown()
|
||||
|
|
|
@ -4,12 +4,15 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/smallstep/assert"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/templates"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
|
@ -253,3 +256,167 @@ func TestAuthority_SignSSHAddUser(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthority_GetSSHRoots(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
user, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
|
||||
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
host, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
|
||||
type fields struct {
|
||||
sshCAUserCerts []ssh.PublicKey
|
||||
sshCAHostCerts []ssh.PublicKey
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want *SSHKeys
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{[]ssh.PublicKey{user}, []ssh.PublicKey{host}}, &SSHKeys{UserKeys: []ssh.PublicKey{user}, HostKeys: []ssh.PublicKey{host}}, false},
|
||||
{"nil", fields{}, &SSHKeys{}, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := testAuthority(t)
|
||||
a.sshCAUserCerts = tt.fields.sshCAUserCerts
|
||||
a.sshCAHostCerts = tt.fields.sshCAHostCerts
|
||||
|
||||
got, err := a.GetSSHRoots()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Authority.GetSSHRoots() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Authority.GetSSHRoots() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthority_GetSSHFederation(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
user, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
|
||||
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
host, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
|
||||
type fields struct {
|
||||
sshCAUserFederatedCerts []ssh.PublicKey
|
||||
sshCAHostFederatedCerts []ssh.PublicKey
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want *SSHKeys
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{[]ssh.PublicKey{user}, []ssh.PublicKey{host}}, &SSHKeys{UserKeys: []ssh.PublicKey{user}, HostKeys: []ssh.PublicKey{host}}, false},
|
||||
{"nil", fields{}, &SSHKeys{}, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := testAuthority(t)
|
||||
a.sshCAUserFederatedCerts = tt.fields.sshCAUserFederatedCerts
|
||||
a.sshCAHostFederatedCerts = tt.fields.sshCAHostFederatedCerts
|
||||
|
||||
got, err := a.GetSSHFederation()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Authority.GetSSHFederation() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Authority.GetSSHFederation() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthority_GetSSHConfig(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
user, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
userSigner, err := ssh.NewSignerFromSigner(key)
|
||||
assert.FatalError(t, err)
|
||||
userB64 := base64.StdEncoding.EncodeToString(user.Marshal())
|
||||
|
||||
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
assert.FatalError(t, err)
|
||||
host, err := ssh.NewPublicKey(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
hostSigner, err := ssh.NewSignerFromSigner(key)
|
||||
assert.FatalError(t, err)
|
||||
hostB64 := base64.StdEncoding.EncodeToString(host.Marshal())
|
||||
|
||||
tmplConfig := &templates.Templates{
|
||||
SSH: &templates.SSHTemplates{
|
||||
User: []templates.Template{
|
||||
{Name: "known_host.tpl", Type: templates.File, TemplatePath: "./testdata/templates/known_hosts.tpl", Path: "ssh/known_host", Comment: "#"},
|
||||
},
|
||||
Host: []templates.Template{
|
||||
{Name: "ca.tpl", Type: templates.File, TemplatePath: "./testdata/templates/ca.tpl", Path: "/etc/ssh/ca.pub", Comment: "#"},
|
||||
},
|
||||
},
|
||||
Data: map[string]interface{}{
|
||||
"Step": &templates.Step{
|
||||
SSH: templates.StepSSH{
|
||||
UserKey: user,
|
||||
HostKey: host,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
userOutput := []templates.Output{
|
||||
{Name: "known_host.tpl", Type: templates.File, Comment: "#", Path: "ssh/known_host", Content: []byte(fmt.Sprintf("@cert-authority * %s %s", host.Type(), hostB64))},
|
||||
}
|
||||
hostOutput := []templates.Output{
|
||||
{Name: "ca.tpl", Type: templates.File, Comment: "#", Path: "/etc/ssh/ca.pub", Content: []byte(user.Type() + " " + userB64)},
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
templates *templates.Templates
|
||||
userSigner ssh.Signer
|
||||
hostSigner ssh.Signer
|
||||
}
|
||||
type args struct {
|
||||
typ string
|
||||
data map[string]string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want []templates.Output
|
||||
wantErr bool
|
||||
}{
|
||||
{"user", fields{tmplConfig, userSigner, hostSigner}, args{"user", nil}, userOutput, false},
|
||||
{"host", fields{tmplConfig, userSigner, hostSigner}, args{"host", nil}, hostOutput, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := testAuthority(t)
|
||||
a.config.Templates = tt.fields.templates
|
||||
a.sshCAUserCertSignKey = tt.fields.userSigner
|
||||
a.sshCAHostCertSignKey = tt.fields.hostSigner
|
||||
|
||||
got, err := a.GetSSHConfig(tt.args.typ, tt.args.data)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Authority.GetSSHConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Authority.GetSSHConfig() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
4
authority/testdata/templates/ca.tpl
vendored
Normal file
4
authority/testdata/templates/ca.tpl
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{{.Step.SSH.UserKey.Type}} {{.Step.SSH.UserKey.Marshal | toString | b64enc}}
|
||||
{{- range .Step.SSH.UserFederatedKeys}}
|
||||
{{.Type}} {{.Marshal | toString | b64enc}}
|
||||
{{- end}}
|
4
authority/testdata/templates/known_hosts.tpl
vendored
Normal file
4
authority/testdata/templates/known_hosts.tpl
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
@cert-authority * {{.Step.SSH.HostKey.Type}} {{.Step.SSH.HostKey.Marshal | toString | b64enc}}
|
||||
{{- range .Step.SSH.HostFederatedKeys}}
|
||||
@cert-authority * {{.Type}} {{.Marshal | toString | b64enc}}
|
||||
{{- end}}
|
Loading…
Reference in a new issue