mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-09-19 15:56:03 +00:00
Add unit test for SSH user creation on nodes
This commit is contained in:
parent
ed071d389c
commit
c9982b979c
@ -3,6 +3,7 @@ package pubapi
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
@ -16,6 +17,9 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
@ -28,6 +32,14 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
peer1 := peer.Peer{PublicIP: "192.0.2.11:2000", VPNIP: "192.0.2.21", VPNPubKey: []byte{1, 2, 3}}
|
peer1 := peer.Peer{PublicIP: "192.0.2.11:2000", VPNIP: "192.0.2.21", VPNPubKey: []byte{1, 2, 3}}
|
||||||
peer2 := peer.Peer{PublicIP: "192.0.2.12:2000", VPNIP: "192.0.2.22", VPNPubKey: []byte{2, 3, 4}}
|
peer2 := peer.Peer{PublicIP: "192.0.2.12:2000", VPNIP: "192.0.2.22", VPNPubKey: []byte{2, 3, 4}}
|
||||||
|
sshUser1 := &ssh.UserKey{
|
||||||
|
Username: "test-user-1",
|
||||||
|
PublicKey: "ssh-rsa abcdefg",
|
||||||
|
}
|
||||||
|
sshUser2 := &ssh.UserKey{
|
||||||
|
Username: "test-user-2",
|
||||||
|
PublicKey: "ssh-ed25519 hijklmn",
|
||||||
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
initialPeers []peer.Peer
|
initialPeers []peer.Peer
|
||||||
@ -38,6 +50,7 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
messageSequenceOverride []string
|
messageSequenceOverride []string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantState state.State
|
wantState state.State
|
||||||
|
sshKeys []*ssh.UserKey
|
||||||
}{
|
}{
|
||||||
"basic": {
|
"basic": {
|
||||||
initialPeers: []peer.Peer{peer1},
|
initialPeers: []peer.Peer{peer1},
|
||||||
@ -45,6 +58,13 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
state: state.AcceptingInit,
|
state: state.AcceptingInit,
|
||||||
wantState: state.NodeWaitingForClusterJoin,
|
wantState: state.NodeWaitingForClusterJoin,
|
||||||
},
|
},
|
||||||
|
"basic with SSH users": {
|
||||||
|
initialPeers: []peer.Peer{peer1},
|
||||||
|
updatedPeers: []peer.Peer{peer2},
|
||||||
|
state: state.AcceptingInit,
|
||||||
|
wantState: state.NodeWaitingForClusterJoin,
|
||||||
|
sshKeys: []*ssh.UserKey{sshUser1, sshUser2},
|
||||||
|
},
|
||||||
"already activated": {
|
"already activated": {
|
||||||
initialPeers: []peer.Peer{peer1},
|
initialPeers: []peer.Peer{peer1},
|
||||||
updatedPeers: []peer.Peer{peer2},
|
updatedPeers: []peer.Peer{peer2},
|
||||||
@ -127,7 +147,9 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger := zaptest.NewLogger(t)
|
logger := zaptest.NewLogger(t)
|
||||||
cor := &fakeCore{state: tc.state, vpnPubKey: vpnPubKey, setVPNIPErr: tc.setVPNIPErr}
|
fs := afero.NewMemMapFs()
|
||||||
|
linuxUserManager := user.NewLinuxUserManagerFake(fs)
|
||||||
|
cor := &fakeCore{state: tc.state, vpnPubKey: vpnPubKey, setVPNIPErr: tc.setVPNIPErr, linuxUserManager: linuxUserManager}
|
||||||
netDialer := testdialer.NewBufconnDialer()
|
netDialer := testdialer.NewBufconnDialer()
|
||||||
dialer := grpcutil.NewDialer(fakeValidator{}, netDialer)
|
dialer := grpcutil.NewDialer(fakeValidator{}, netDialer)
|
||||||
|
|
||||||
@ -147,7 +169,7 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
go pubserver.Serve(netDialer.GetListener(net.JoinHostPort(nodeIP, endpointAVPNPort)))
|
go pubserver.Serve(netDialer.GetListener(net.JoinHostPort(nodeIP, endpointAVPNPort)))
|
||||||
defer pubserver.GracefulStop()
|
defer pubserver.GracefulStop()
|
||||||
|
|
||||||
_, nodeVPNPubKey, err := activateNode(require, netDialer, messageSequence, nodeIP, "9000", nodeVPNIP, peer.ToPubProto(tc.initialPeers), ownerID, clusterID, stateDiskKey)
|
_, nodeVPNPubKey, err := activateNode(require, netDialer, messageSequence, nodeIP, "9000", nodeVPNIP, peer.ToPubProto(tc.initialPeers), ownerID, clusterID, stateDiskKey, ssh.ToProtoSlice(tc.sshKeys))
|
||||||
assert.Equal(tc.wantState, cor.state)
|
assert.Equal(tc.wantState, cor.state)
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
@ -171,6 +193,25 @@ func TestActivateAsNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.Equal(tc.initialPeers, cor.updatedPeers[0])
|
assert.Equal(tc.initialPeers, cor.updatedPeers[0])
|
||||||
assert.Equal([]role.Role{role.Node}, cor.persistNodeStateRoles)
|
assert.Equal([]role.Role{role.Node}, cor.persistNodeStateRoles)
|
||||||
|
|
||||||
|
// Test SSH user & key creation. Both cases: "supposed to add" and "not supposed to add"
|
||||||
|
// This slightly differs from a real environment (e.g. missing /home) but should be fine in the stub context with a virtual file system
|
||||||
|
if tc.sshKeys != nil {
|
||||||
|
passwd := user.Passwd{}
|
||||||
|
entries, err := passwd.Parse(fs)
|
||||||
|
require.NoError(err)
|
||||||
|
for _, singleEntry := range entries {
|
||||||
|
username := singleEntry.Gecos
|
||||||
|
_, err := fs.Stat(fmt.Sprintf("/home/%s/.ssh/authorized_keys.d/ssh-keys", username))
|
||||||
|
assert.NoError(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passwd := user.Passwd{}
|
||||||
|
_, err := passwd.Parse(fs)
|
||||||
|
assert.EqualError(err, "open /etc/passwd: file does not exist")
|
||||||
|
_, err = fs.Stat("/home")
|
||||||
|
assert.EqualError(err, "open /home: file does not exist")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +367,7 @@ func TestJoinCluster(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func activateNode(require *require.Assertions, dialer netDialer, messageSequence []string, nodeIP, bindPort, nodeVPNIP string, peers []*pubproto.Peer, ownerID, clusterID, stateDiskKey []byte) (string, []byte, error) {
|
func activateNode(require *require.Assertions, dialer netDialer, messageSequence []string, nodeIP, bindPort, nodeVPNIP string, peers []*pubproto.Peer, ownerID, clusterID, stateDiskKey []byte, sshUserKeys []*pubproto.SSHUserKey) (string, []byte, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
conn, err := dialGRPC(ctx, dialer, net.JoinHostPort(nodeIP, bindPort))
|
conn, err := dialGRPC(ctx, dialer, net.JoinHostPort(nodeIP, bindPort))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
@ -344,10 +385,11 @@ func activateNode(require *require.Assertions, dialer netDialer, messageSequence
|
|||||||
err = stream.Send(&pubproto.ActivateAsNodeRequest{
|
err = stream.Send(&pubproto.ActivateAsNodeRequest{
|
||||||
Request: &pubproto.ActivateAsNodeRequest_InitialRequest{
|
Request: &pubproto.ActivateAsNodeRequest_InitialRequest{
|
||||||
InitialRequest: &pubproto.ActivateAsNodeInitialRequest{
|
InitialRequest: &pubproto.ActivateAsNodeInitialRequest{
|
||||||
NodeVpnIp: nodeVPNIP,
|
NodeVpnIp: nodeVPNIP,
|
||||||
Peers: peers,
|
Peers: peers,
|
||||||
OwnerId: ownerID,
|
OwnerId: ownerID,
|
||||||
ClusterId: clusterID,
|
ClusterId: clusterID,
|
||||||
|
SshUserKeys: sshUserKeys,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user