2022-03-22 11:03:15 -04:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/base64"
|
|
|
|
"errors"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/edgelesssys/constellation/cli/azure"
|
|
|
|
"github.com/edgelesssys/constellation/cli/ec2"
|
|
|
|
"github.com/edgelesssys/constellation/cli/gcp"
|
2022-05-02 04:54:54 -04:00
|
|
|
"github.com/edgelesssys/constellation/cli/qemu"
|
2022-04-06 04:36:58 -04:00
|
|
|
"github.com/edgelesssys/constellation/internal/constants"
|
2022-05-16 11:32:00 -04:00
|
|
|
"github.com/edgelesssys/constellation/internal/file"
|
2022-03-22 11:03:15 -04:00
|
|
|
"github.com/edgelesssys/constellation/internal/state"
|
2022-04-12 08:20:46 -04:00
|
|
|
wgquick "github.com/nmiculinic/wg-quick-go"
|
2022-03-22 11:03:15 -04:00
|
|
|
"github.com/spf13/afero"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestInitArgumentValidation(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
cmd := newInitCmd()
|
|
|
|
assert.NoError(cmd.ValidateArgs(nil))
|
|
|
|
assert.Error(cmd.ValidateArgs([]string{"something"}))
|
|
|
|
assert.Error(cmd.ValidateArgs([]string{"sth", "sth"}))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInitialize(t *testing.T) {
|
|
|
|
testKey := base64.StdEncoding.EncodeToString([]byte("32bytesWireGuardKeyForTheTesting"))
|
|
|
|
testGcpState := state.ConstellationState{
|
2022-04-19 11:02:02 -04:00
|
|
|
CloudProvider: "GCP",
|
2022-03-22 11:03:15 -04:00
|
|
|
GCPNodes: gcp.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-0": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
"id-1": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
GCPCoordinators: gcp.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-c": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
testAzureState := state.ConstellationState{
|
|
|
|
CloudProvider: "Azure",
|
|
|
|
AzureNodes: azure.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-0": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
"id-1": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
AzureCoordinators: azure.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-c": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
AzureResourceGroup: "test",
|
|
|
|
}
|
2022-05-02 04:54:54 -04:00
|
|
|
testQemuState := state.ConstellationState{
|
|
|
|
CloudProvider: "QEMU",
|
|
|
|
QEMUNodes: qemu.Instances{
|
|
|
|
"id-0": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
"id-1": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
},
|
|
|
|
QEMUCoordinators: qemu.Instances{
|
|
|
|
"id-c": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
},
|
|
|
|
}
|
2022-03-22 11:03:15 -04:00
|
|
|
testActivationResps := []fakeActivationRespMessage{
|
|
|
|
{log: "testlog1"},
|
|
|
|
{log: "testlog2"},
|
|
|
|
{
|
|
|
|
kubeconfig: "kubeconfig",
|
2022-03-29 05:38:14 -04:00
|
|
|
clientVpnIp: "192.0.2.2",
|
2022-03-28 02:58:56 -04:00
|
|
|
coordinatorVpnKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
ownerID: "ownerID",
|
|
|
|
clusterID: "clusterID",
|
|
|
|
},
|
|
|
|
{log: "testlog3"},
|
|
|
|
}
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
|
|
|
|
testCases := map[string]struct {
|
|
|
|
existingState state.ConstellationState
|
|
|
|
client protoClient
|
|
|
|
serviceAccountCreator stubServiceAccountCreator
|
|
|
|
waiter statusWaiter
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey string
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler vpnHandler
|
|
|
|
initVPN bool
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"initialize some gcp instances": {
|
|
|
|
existingState: testGcpState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
|
|
|
privKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"initialize some azure instances": {
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
|
|
|
privKey: testKey,
|
|
|
|
},
|
2022-05-02 04:54:54 -04:00
|
|
|
"initialize some qemu instances": {
|
|
|
|
existingState: testQemuState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
vpnHandler: &stubVPNHandler{},
|
|
|
|
privKey: testKey,
|
|
|
|
},
|
2022-04-12 08:20:46 -04:00
|
|
|
"initialize vpn": {
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
|
|
|
initVPN: true,
|
|
|
|
privKey: testKey,
|
|
|
|
},
|
|
|
|
"invalid initialize vpn": {
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
vpnHandler: &stubVPNHandler{applyErr: someErr},
|
|
|
|
initVPN: true,
|
|
|
|
privKey: testKey,
|
|
|
|
wantErr: true,
|
2022-04-12 08:20:46 -04:00
|
|
|
},
|
|
|
|
"invalid create vpn config": {
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
vpnHandler: &stubVPNHandler{createErr: someErr},
|
|
|
|
initVPN: true,
|
|
|
|
privKey: testKey,
|
|
|
|
wantErr: true,
|
2022-04-12 08:20:46 -04:00
|
|
|
},
|
|
|
|
"invalid write vpn config": {
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &fakeProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
vpnHandler: &stubVPNHandler{marshalErr: someErr},
|
|
|
|
initVPN: true,
|
|
|
|
privKey: testKey,
|
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"no state exists": {
|
|
|
|
existingState: state.ConstellationState{},
|
|
|
|
client: &stubProtoClient{},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"no instances to pick one": {
|
|
|
|
existingState: state.ConstellationState{
|
|
|
|
EC2Instances: ec2.Instances{},
|
|
|
|
EC2SecurityGroup: "sg-test",
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
client: &stubProtoClient{},
|
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
privKey: testKey,
|
|
|
|
vpnHandler: &stubVPNHandler{},
|
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"public key to short": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: base64.StdEncoding.EncodeToString([]byte("tooShortKey")),
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"public key to long": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: base64.StdEncoding.EncodeToString([]byte("thisWireguardKeyIsToLongAndHasTooManyBytes")),
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"public key not base64": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: "this is not base64 encoded",
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail Connect": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{connectErr: someErr},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail Activate": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{activateErr: someErr},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient WriteLogStream": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{writeLogStreamErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient getKubeconfig": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{getKubeconfigErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient getCoordinatorVpnKey": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{getCoordinatorVpnKeyErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient getClientVpnIp": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{getClientVpnIpErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient getOwnerID": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{getOwnerIDErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail respClient getClusterID": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
2022-03-22 11:03:15 -04:00
|
|
|
client: &stubProtoClient{respClient: &stubActivationRespClient{getClusterIDErr: someErr}},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail to wait for required status": {
|
|
|
|
existingState: testGcpState,
|
|
|
|
client: &stubProtoClient{},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{waitForAllErr: someErr},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"fail to create service account": {
|
2022-04-19 11:02:02 -04:00
|
|
|
existingState: testGcpState,
|
|
|
|
client: &stubProtoClient{},
|
|
|
|
serviceAccountCreator: stubServiceAccountCreator{createErr: someErr},
|
|
|
|
waiter: &stubStatusWaiter{},
|
|
|
|
privKey: testKey,
|
|
|
|
vpnHandler: &stubVPNHandler{},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
cmd := newInitCmd()
|
|
|
|
var out bytes.Buffer
|
|
|
|
cmd.SetOut(&out)
|
|
|
|
var errOut bytes.Buffer
|
|
|
|
cmd.SetErr(&errOut)
|
2022-05-13 05:56:43 -04:00
|
|
|
cmd.Flags().String("config", "", "") // register persisten flag manually
|
2022-03-22 11:03:15 -04:00
|
|
|
fs := afero.NewMemMapFs()
|
|
|
|
fileHandler := file.NewHandler(fs)
|
2022-04-06 04:36:58 -04:00
|
|
|
require.NoError(fileHandler.WriteJSON(constants.StateFilename, tc.existingState, file.OptNone))
|
2022-03-22 11:03:15 -04:00
|
|
|
|
|
|
|
// Write key file to filesystem and set path in flag.
|
2022-03-28 02:58:56 -04:00
|
|
|
require.NoError(afero.Afero{Fs: fs}.WriteFile("privK", []byte(tc.privKey), 0o600))
|
|
|
|
require.NoError(cmd.Flags().Set("privatekey", "privK"))
|
2022-04-12 08:20:46 -04:00
|
|
|
if tc.initVPN {
|
|
|
|
require.NoError(cmd.Flags().Set("wg-autoconfig", "true"))
|
|
|
|
}
|
|
|
|
|
2022-03-22 11:03:15 -04:00
|
|
|
ctx := context.Background()
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-04-13 09:01:02 -04:00
|
|
|
err := initialize(ctx, cmd, tc.client, &tc.serviceAccountCreator, fileHandler, tc.waiter, tc.vpnHandler)
|
2022-03-22 11:03:15 -04:00
|
|
|
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
} else {
|
|
|
|
require.NoError(err)
|
2022-04-12 08:20:46 -04:00
|
|
|
assert.Equal(tc.initVPN, tc.vpnHandler.(*stubVPNHandler).configured)
|
2022-03-29 05:38:14 -04:00
|
|
|
assert.Contains(out.String(), "192.0.2.2")
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Contains(out.String(), "ownerID")
|
|
|
|
assert.Contains(out.String(), "clusterID")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWriteOutput(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
result := activationResult{
|
|
|
|
clientVpnIP: "foo-qq",
|
|
|
|
coordinatorPubKey: "bar-qq",
|
|
|
|
coordinatorPubIP: "baz-qq",
|
|
|
|
kubeconfig: "foo-bar-baz-qq",
|
|
|
|
}
|
|
|
|
var out bytes.Buffer
|
|
|
|
testFs := afero.NewMemMapFs()
|
|
|
|
fileHandler := file.NewHandler(testFs)
|
|
|
|
|
2022-04-06 04:36:58 -04:00
|
|
|
err := result.writeOutput(&out, fileHandler)
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.NoError(err)
|
|
|
|
assert.Contains(out.String(), result.clientVpnIP)
|
|
|
|
assert.Contains(out.String(), result.coordinatorPubIP)
|
|
|
|
assert.Contains(out.String(), result.coordinatorPubKey)
|
|
|
|
|
|
|
|
afs := afero.Afero{Fs: testFs}
|
2022-04-06 04:36:58 -04:00
|
|
|
adminConf, err := afs.ReadFile(constants.AdminConfFilename)
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.NoError(err)
|
|
|
|
assert.Equal(result.kubeconfig, string(adminConf))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIpsToEndpoints(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ips := []string{"192.0.2.1", "192.0.2.2", "192.0.2.3"}
|
|
|
|
port := "8080"
|
|
|
|
endpoints := ipsToEndpoints(ips, port)
|
|
|
|
assert.Equal([]string{"192.0.2.1:8080", "192.0.2.2:8080", "192.0.2.3:8080"}, endpoints)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInitCompletion(t *testing.T) {
|
|
|
|
testCases := map[string]struct {
|
2022-04-26 10:54:05 -04:00
|
|
|
args []string
|
|
|
|
toComplete string
|
|
|
|
wantResult []string
|
|
|
|
wantShellCD cobra.ShellCompDirective
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"first arg": {
|
2022-04-26 10:54:05 -04:00
|
|
|
args: []string{},
|
|
|
|
toComplete: "hello",
|
|
|
|
wantResult: []string{},
|
|
|
|
wantShellCD: cobra.ShellCompDirectiveDefault,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"secnod arg": {
|
2022-04-26 10:54:05 -04:00
|
|
|
args: []string{"23"},
|
|
|
|
toComplete: "/test/h",
|
|
|
|
wantResult: []string{},
|
|
|
|
wantShellCD: cobra.ShellCompDirectiveError,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"third arg": {
|
2022-04-26 10:54:05 -04:00
|
|
|
args: []string{"./file", "sth"},
|
|
|
|
toComplete: "./file",
|
|
|
|
wantResult: []string{},
|
|
|
|
wantShellCD: cobra.ShellCompDirectiveError,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
cmd := &cobra.Command{}
|
|
|
|
result, shellCD := initCompletion(cmd, tc.args, tc.toComplete)
|
2022-04-26 10:54:05 -04:00
|
|
|
assert.Equal(tc.wantResult, result)
|
|
|
|
assert.Equal(tc.wantShellCD, shellCD)
|
2022-03-22 11:03:15 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-28 02:58:56 -04:00
|
|
|
func TestReadOrGenerateVPNKey(t *testing.T) {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
2022-03-28 02:58:56 -04:00
|
|
|
testKey := []byte(base64.StdEncoding.EncodeToString([]byte("32bytesWireGuardKeyForTheTesting")))
|
2022-03-22 11:03:15 -04:00
|
|
|
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
2022-04-13 03:15:27 -04:00
|
|
|
require.NoError(fileHandler.Write("testKey", testKey, file.OptNone))
|
2022-03-22 11:03:15 -04:00
|
|
|
|
2022-03-28 02:58:56 -04:00
|
|
|
privK, pubK, err := readOrGenerateVPNKey(fileHandler, "testKey")
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.NoError(err)
|
2022-03-28 02:58:56 -04:00
|
|
|
assert.Equal(testKey, privK)
|
|
|
|
assert.NotEmpty(pubK)
|
2022-03-22 11:03:15 -04:00
|
|
|
|
|
|
|
// no path provided
|
2022-03-28 02:58:56 -04:00
|
|
|
privK, pubK, err = readOrGenerateVPNKey(fileHandler, "")
|
|
|
|
assert.NoError(err)
|
|
|
|
assert.NotEmpty(privK)
|
|
|
|
assert.NotEmpty(pubK)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadOrGeneratedMasterSecret(t *testing.T) {
|
|
|
|
testCases := map[string]struct {
|
|
|
|
filename string
|
|
|
|
filecontent string
|
|
|
|
createFile bool
|
|
|
|
fs func() afero.Fs
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"file with secret exists": {
|
|
|
|
filename: "someSecret",
|
|
|
|
filecontent: base64.StdEncoding.EncodeToString([]byte("ConstellationSecret")),
|
|
|
|
createFile: true,
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: false,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"no file given": {
|
|
|
|
filename: "",
|
|
|
|
filecontent: "",
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: false,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"file does not exist": {
|
|
|
|
filename: "nonExistingSecret",
|
|
|
|
filecontent: "",
|
|
|
|
createFile: false,
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"file is empty": {
|
|
|
|
filename: "emptySecret",
|
|
|
|
filecontent: "",
|
|
|
|
createFile: true,
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"secret too short": {
|
|
|
|
filename: "shortSecret",
|
|
|
|
filecontent: base64.StdEncoding.EncodeToString([]byte("short")),
|
|
|
|
createFile: true,
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"secret not encoded": {
|
|
|
|
filename: "unencodedSecret",
|
|
|
|
filecontent: "Constellation",
|
|
|
|
createFile: true,
|
|
|
|
fs: afero.NewMemMapFs,
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"file not writeable": {
|
|
|
|
filename: "",
|
|
|
|
filecontent: "",
|
|
|
|
createFile: false,
|
|
|
|
fs: func() afero.Fs { return afero.NewReadOnlyFs(afero.NewMemMapFs()) },
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
fileHandler := file.NewHandler(tc.fs())
|
|
|
|
|
|
|
|
if tc.createFile {
|
2022-04-13 03:15:27 -04:00
|
|
|
require.NoError(fileHandler.Write(tc.filename, []byte(tc.filecontent), file.OptNone))
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var out bytes.Buffer
|
2022-04-06 04:36:58 -04:00
|
|
|
secret, err := readOrGeneratedMasterSecret(&out, fileHandler, tc.filename)
|
2022-03-22 11:03:15 -04:00
|
|
|
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
} else {
|
|
|
|
assert.NoError(err)
|
|
|
|
|
|
|
|
if tc.filename == "" {
|
2022-04-06 04:36:58 -04:00
|
|
|
require.Contains(out.String(), constants.MasterSecretFilename)
|
2022-03-22 11:03:15 -04:00
|
|
|
filename := strings.Split(out.String(), "./")
|
|
|
|
tc.filename = strings.Trim(filename[1], "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
content, err := fileHandler.Read(tc.filename)
|
|
|
|
require.NoError(err)
|
|
|
|
assert.Equal(content, []byte(base64.StdEncoding.EncodeToString(secret)))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAutoscaleFlag(t *testing.T) {
|
|
|
|
testKey := base64.StdEncoding.EncodeToString([]byte("32bytesWireGuardKeyForTheTesting"))
|
|
|
|
testGcpState := state.ConstellationState{
|
2022-04-19 11:02:02 -04:00
|
|
|
CloudProvider: "gcp",
|
2022-03-22 11:03:15 -04:00
|
|
|
GCPNodes: gcp.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-0": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
"id-1": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
GCPCoordinators: gcp.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-c": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
testAzureState := state.ConstellationState{
|
2022-04-19 11:02:02 -04:00
|
|
|
CloudProvider: "azure",
|
2022-03-22 11:03:15 -04:00
|
|
|
AzureNodes: azure.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-0": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
|
|
|
"id-1": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
AzureCoordinators: azure.Instances{
|
2022-04-13 09:01:02 -04:00
|
|
|
"id-c": {PrivateIP: "192.0.2.1", PublicIP: "192.0.2.1"},
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
AzureResourceGroup: "test",
|
|
|
|
}
|
|
|
|
testActivationResps := []fakeActivationRespMessage{
|
|
|
|
{log: "testlog1"},
|
|
|
|
{log: "testlog2"},
|
|
|
|
{
|
|
|
|
kubeconfig: "kubeconfig",
|
2022-03-29 05:38:14 -04:00
|
|
|
clientVpnIp: "192.0.2.2",
|
2022-03-28 02:58:56 -04:00
|
|
|
coordinatorVpnKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
ownerID: "ownerID",
|
|
|
|
clusterID: "clusterID",
|
|
|
|
},
|
|
|
|
{log: "testlog3"},
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := map[string]struct {
|
|
|
|
autoscaleFlag bool
|
|
|
|
existingState state.ConstellationState
|
|
|
|
client *stubProtoClient
|
|
|
|
serviceAccountCreator stubServiceAccountCreator
|
|
|
|
waiter statusWaiter
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey string
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"initialize some gcp instances without autoscale flag": {
|
|
|
|
autoscaleFlag: false,
|
|
|
|
existingState: testGcpState,
|
|
|
|
client: &stubProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"initialize some azure instances without autoscale flag": {
|
|
|
|
autoscaleFlag: false,
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &stubProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"initialize some gcp instances with autoscale flag": {
|
|
|
|
autoscaleFlag: true,
|
|
|
|
existingState: testGcpState,
|
|
|
|
client: &stubProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"initialize some azure instances with autoscale flag": {
|
|
|
|
autoscaleFlag: true,
|
|
|
|
existingState: testAzureState,
|
|
|
|
client: &stubProtoClient{
|
|
|
|
respClient: &fakeActivationRespClient{responses: testActivationResps},
|
|
|
|
},
|
2022-04-13 09:01:02 -04:00
|
|
|
waiter: &stubStatusWaiter{},
|
2022-03-28 02:58:56 -04:00
|
|
|
privKey: testKey,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
cmd := newInitCmd()
|
|
|
|
var out bytes.Buffer
|
|
|
|
cmd.SetOut(&out)
|
|
|
|
var errOut bytes.Buffer
|
|
|
|
cmd.SetErr(&errOut)
|
2022-05-13 05:56:43 -04:00
|
|
|
cmd.Flags().String("config", "", "") // register persisten flag manually
|
2022-03-22 11:03:15 -04:00
|
|
|
fs := afero.NewMemMapFs()
|
|
|
|
fileHandler := file.NewHandler(fs)
|
2022-04-12 08:20:46 -04:00
|
|
|
vpnHandler := stubVPNHandler{}
|
2022-04-06 04:36:58 -04:00
|
|
|
require.NoError(fileHandler.WriteJSON(constants.StateFilename, tc.existingState, file.OptNone))
|
2022-03-22 11:03:15 -04:00
|
|
|
|
|
|
|
// Write key file to filesystem and set path in flag.
|
2022-03-28 02:58:56 -04:00
|
|
|
require.NoError(afero.Afero{Fs: fs}.WriteFile("privK", []byte(tc.privKey), 0o600))
|
|
|
|
require.NoError(cmd.Flags().Set("privatekey", "privK"))
|
2022-03-22 11:03:15 -04:00
|
|
|
|
|
|
|
require.NoError(cmd.Flags().Set("autoscale", strconv.FormatBool(tc.autoscaleFlag)))
|
|
|
|
ctx := context.Background()
|
|
|
|
|
2022-04-13 09:01:02 -04:00
|
|
|
require.NoError(initialize(ctx, cmd, tc.client, &tc.serviceAccountCreator, fileHandler, tc.waiter, &vpnHandler))
|
2022-03-22 11:03:15 -04:00
|
|
|
if tc.autoscaleFlag {
|
|
|
|
assert.Len(tc.client.activateAutoscalingNodeGroups, 1)
|
|
|
|
} else {
|
|
|
|
assert.Len(tc.client.activateAutoscalingNodeGroups, 0)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-03-29 05:38:14 -04:00
|
|
|
|
|
|
|
func TestWriteWGQuickFile(t *testing.T) {
|
|
|
|
testCases := map[string]struct {
|
2022-04-12 08:20:46 -04:00
|
|
|
fileHandler file.Handler
|
|
|
|
vpnHandler *stubVPNHandler
|
|
|
|
vpnConfig *wgquick.Config
|
|
|
|
wantErr bool
|
2022-03-29 05:38:14 -04:00
|
|
|
}{
|
|
|
|
"write wg quick file": {
|
2022-04-12 08:20:46 -04:00
|
|
|
fileHandler: file.NewHandler(afero.NewMemMapFs()),
|
|
|
|
vpnHandler: &stubVPNHandler{marshalRes: "config"},
|
|
|
|
},
|
|
|
|
"marshal failed": {
|
|
|
|
fileHandler: file.NewHandler(afero.NewMemMapFs()),
|
|
|
|
vpnHandler: &stubVPNHandler{marshalErr: errors.New("some err")},
|
|
|
|
wantErr: true,
|
2022-03-29 05:38:14 -04:00
|
|
|
},
|
|
|
|
"write fails": {
|
2022-04-12 08:20:46 -04:00
|
|
|
fileHandler: file.NewHandler(afero.NewReadOnlyFs(afero.NewMemMapFs())),
|
|
|
|
vpnHandler: &stubVPNHandler{marshalRes: "config"},
|
|
|
|
wantErr: true,
|
2022-03-29 05:38:14 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
2022-04-06 04:36:58 -04:00
|
|
|
err := writeWGQuickFile(tc.fileHandler, tc.vpnHandler, tc.vpnConfig)
|
2022-03-29 05:38:14 -04:00
|
|
|
|
|
|
|
if tc.wantErr {
|
|
|
|
assert.Error(err)
|
|
|
|
} else {
|
|
|
|
assert.NoError(err)
|
2022-04-06 04:36:58 -04:00
|
|
|
file, err := tc.fileHandler.Read(constants.WGQuickConfigFilename)
|
2022-03-29 05:38:14 -04:00
|
|
|
assert.NoError(err)
|
2022-04-12 08:20:46 -04:00
|
|
|
assert.Contains(string(file), tc.vpnHandler.marshalRes)
|
2022-03-29 05:38:14 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|