From a464b052cc95221c0f01cfe30b75e76aaa6ba052 Mon Sep 17 00:00:00 2001 From: Malhar Vora Date: Sat, 29 Jul 2017 07:33:20 +0000 Subject: [PATCH 1/2] Add automated cli test for user management --- cli/main/cli_test.go | 126 ++++++++++++++++++++++++++++++++ cli/main/config.yaml | 50 +++++++++++++ cli/main/test-user1-private.pem | 27 +++++++ cli/main/test-user1-public.pem | 9 +++ 4 files changed, 212 insertions(+) create mode 100644 cli/main/cli_test.go create mode 100755 cli/main/config.yaml create mode 100644 cli/main/test-user1-private.pem create mode 100644 cli/main/test-user1-public.pem diff --git a/cli/main/cli_test.go b/cli/main/cli_test.go new file mode 100644 index 0000000..8b137c7 --- /dev/null +++ b/cli/main/cli_test.go @@ -0,0 +1,126 @@ +package main + +import ( + "bytes" + "os" + "os/exec" + "path" + "strings" + "testing" + "time" +) + +type userData struct { + Username string + PrivateKeyFile string + PublicKeyFile string + Token string +} + +// Testuser data +var testUserData = userData{"user1", "test-user1-private.pem", "test-user1-public.pem", ""} + +// Root user data +var rootData = userData{"root", "test-root-init-private.pem", "", ""} + +// Return top level directory of project +func getProjectRootPath() string { + var currentWorkingDirectory, _ = os.Getwd() + var projectRootPath = path.Join(currentWorkingDirectory, "..", "..") + return projectRootPath +} + +// Get server executable path +func getServerExecutablePath() string { + projectRootPath := getProjectRootPath() + serverExecutableDir := path.Join(projectRootPath, "dist") + serverExecutableFilename := "vsmd" + serverExecutablePath := path.Join(serverExecutableDir, serverExecutableFilename) + return serverExecutablePath +} + +// Main function for test. Used here as an alternate for +// setup() and teardown() phase +func TestMain(m *testing.M) { + serverExecutablePath := getServerExecutablePath() + cmd := exec.Command(serverExecutablePath) + cmd.Start() + time.Sleep(time.Second * 3) + v := m.Run() + cmd.Process.Kill() + os.Exit(v) +} + +func getOutput(command string) (string, error) { + projectRootPath := getProjectRootPath() + cliExecutableName := "vsm-cli" + cliExecutablePath := path.Join(projectRootPath, "dist", cliExecutableName) + cmd := exec.Command(cliExecutablePath, strings.Split(command, " ")...) + output, err := cmd.CombinedOutput() + return bytes.NewBuffer(output).String(), err +} + +// Test login using pre-created root account +func TestRootLogin(t *testing.T) { + + projectRootPath := getProjectRootPath() + certFileName := "test-root-init-private.pem" + certFilePath := path.Join(projectRootPath, "certs", certFileName) + command := "login root" + " " + certFilePath + output, _ := getOutput(command) + + check1 := strings.Contains(output, "Login successful") + check2 := strings.Contains(output, "Token:") + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } else { + index := strings.Index(output, "Token:") + rootData.Token = strings.Trim(output[index+7:], "\n") + } +} + +// Test user creation +func TestUserCreate(t *testing.T) { + + command := "--token " + rootData.Token + " users create " + testUserData.Username + " " + testUserData.PublicKeyFile + output, _ := getOutput(command) + + check1 := strings.Contains(output, "User created successfully") + check2 := strings.Contains(output, "Id: "+testUserData.Username) + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } +} + +// Test user data retrieval +func TestUserGet(t *testing.T) { + command := "--token " + rootData.Token + " users get " + testUserData.Username + output, _ := getOutput(command) + + check1 := strings.Contains(output, "\"username\": \""+testUserData.Username+"\"") + check2 := strings.Contains(output, "\"credentials\"") + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } +} + +// Test user deletion +func TestUserDelete(t *testing.T) { + command := "--token " + rootData.Token + " users delete " + testUserData.Username + output, _ := getOutput(command) + + check1 := strings.Contains(output, "User deleted successfully") + + if check1 == false { + t.Fail() + } +} diff --git a/cli/main/config.yaml b/cli/main/config.yaml new file mode 100755 index 0000000..2800410 --- /dev/null +++ b/cli/main/config.yaml @@ -0,0 +1,50 @@ +# Server +server: + + # Listeners + http: + enabled: true + port: 8080 + https: + enabled: true + port: 8443 + + # Root server certificate, also used to sign certificates when the server acts as a Certificate Authority + caCert: ../../certs/test-root-cert.pem + + # Private key corresponding to root server certificate + caKey: ../../certs/test-root-key.pem + + # Certificate used by the server in SSL handshake. Must be signed by key in caKey + serverCert: ../../certs/test-server-cert.pem + + # Private key of serverCert + serverKey: ../../certs/test-server-key.pem + + # Public key to create user "root" during server initialization + rootInitPubKey: ../../certs/test-root-init-public.pem + + # Private key of user "root". Recommended to remove from server when moving from testing to production. + rootInitPriKey: ../../certs/test-root-init-private.pem + +# Data Store - this is where encrypted secrets are stored +dataStore: + type: InMemoryDataStore + connectionString: + +# Virtual Key Store - manages keys' storage and retrieval +virtualKeyStore: + # Number of key stores + keyStoreCount: 3 + + # Minimum number of key stores required to create and retrieve keys + keyStoreThreshold: 2 + + # Key stores that will keep the actual keys + keyStores: + - type: InMemoryKeyStore + connectionString: + - type: InMemoryKeyStore + connectionString: + - type: InMemoryKeyStore + connectionString: diff --git a/cli/main/test-user1-private.pem b/cli/main/test-user1-private.pem new file mode 100644 index 0000000..27b558b --- /dev/null +++ b/cli/main/test-user1-private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAstoxxNcJTHSmBpvNNNQCk5oM4uzxZ+c8SN4Bpy7bXQbp5s1g +cjYvKMoU1+dKDh/l6fFboUZ4PU22EdjecwAiEYpYWeweLlN3jbooTFQjcvmR7sAG +gieNb5J8BsYCQesyYVFezbwI4gjJcHdZoIhWCVlnbuMwFjbA9qK0nxtVFIcxH9Hd +JCqLQ2FMUsleh51WvkbWNoG1cGJD26kLipGHeXXLiIzmOzSJ3VXn33EJMK0KBU+t +Z4Pa6sqcIZFQs1E00gre1UAj6ckKCeC+NBmWLnTcpABAM6f4YqP7xzK1U2aNCuwv +njTvwCcK12h1iQrc/BnQzChaUirQNf3cTQBW6wIDAQABAoIBAHDIVSAKdgund1at +gu6wTtujBkNHJUffMk3E6YfybVQxWug3VH1RG9X98LzhVfqoNMScdaqylHob+hcx +Cb29NL6Y3fP+iF2wNrDB1k2jtSL4rATBRJlotbDIz7s5vAyzcvaZaE4WKAfZgKWS +LYukzZRhs27iht1LM82TdpDqnHEvbWXHX54pU8YK5Yb0G8J4dPNp9/7vmVV6ahD1 +BF1OL/6icSvLOqa908yMzw3lSiTQjPEm/RTPYDt3CMCftYnmXw9k2y1n1wPQxGPT +w6W/aoWfG6eOF3woK7b3FXtmEUgcruyxX5IGEstVodk4W6arVQlHrxF6zmqB4tHQ +fzpHmUkCgYEA2p761AKu5x/rICiKSaYCHwo8T/NwcMZFi15EiZ/+naKlX94JkHVk +ZQYdfrTeD2z6I87JkM01cP40+2l3/u8DZQOPMRGPKpYKBnZvPTWCB5nl+H+AJM2M +wTu5W7K3IxGSaE7Pf8fmjtkZseG6YY4UXHdddMjkPjPZT2evJ50c1G8CgYEA0W6K ++JHQeBGOLDP/se7Xtd+lCZeU3MnatwT4l1W6pKEMpQm9Ejpj+nr7A24BWusV2HHH +5uwoVf9YkTqTsmdE9DA1QZUEAjGPYIO272CVFwH3uaNVlnahESKzBU64T3LItU5M +5AxP313sAfC3iBoqKOZU8kJgWegXAajUKn7Su0UCgYEA14noF8AxelMguErf1C6k +Zr/rqJOFJtqD1Bzzi5A/MmEZlIPPgCoM+gDmcXaWfDTgBQ+p8GYxKx6lU72u/Zve +B+hTc3gxYzYb2jVIBNvNP/s+HRpvV1mETTq5y6tOHXgElWwl7YBDUlC+oX7AB9BR +SLyyWiJ5zM3HkR7TNEYVF2cCgYBNbui1BPymGB+P2l30xNE+roTPqhrhE0TpnE3p +bkoG6oDJWHNulOY4S1YZq4eWvQqjr1Xw3GoBedqeP6EyOhp1iol2SQllYjuXvLtb +gEM/cXvNSEWxzwS4WDMGiFd/EHqDBoNJYf/6HzjOctj42muyGY9Yzw/ezgALngdr ++t4hXQKBgQCTLW2NQjmH3Zc8skNRxb36kI/K6Jp1nfi3rW0XIXC/9LRZwdfQNe2L +Ebo6YdroBivFXymLeCeK5o0feO6fCI3itsl5Wws5hLOzij2fdNaqDcpxGtge8Bzv +ZUHyDHAysQA/6wu7hVOrXaLm7t27WpfV5/32ElJYVTI4sq+J+zsfcQ== +-----END RSA PRIVATE KEY----- diff --git a/cli/main/test-user1-public.pem b/cli/main/test-user1-public.pem new file mode 100644 index 0000000..3131bf4 --- /dev/null +++ b/cli/main/test-user1-public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAstoxxNcJTHSmBpvNNNQC +k5oM4uzxZ+c8SN4Bpy7bXQbp5s1gcjYvKMoU1+dKDh/l6fFboUZ4PU22EdjecwAi +EYpYWeweLlN3jbooTFQjcvmR7sAGgieNb5J8BsYCQesyYVFezbwI4gjJcHdZoIhW +CVlnbuMwFjbA9qK0nxtVFIcxH9HdJCqLQ2FMUsleh51WvkbWNoG1cGJD26kLipGH +eXXLiIzmOzSJ3VXn33EJMK0KBU+tZ4Pa6sqcIZFQs1E00gre1UAj6ckKCeC+NBmW +LnTcpABAM6f4YqP7xzK1U2aNCuwvnjTvwCcK12h1iQrc/BnQzChaUirQNf3cTQBW +6wIDAQAB +-----END PUBLIC KEY----- From 8b2d2c4b53d821baab81e5b22d88915d3581c10e Mon Sep 17 00:00:00 2001 From: Malhar Vora Date: Sat, 29 Jul 2017 07:33:20 +0000 Subject: [PATCH 2/2] Add automated cli test for user management - Add base framework for automated CLI testing - Add tests for user management CLI commands Signed-off-by: Malhar Vora --- cli/main/cli_test.go | 126 ++++++++++++++++++++++++++++++++ cli/main/config.yaml | 50 +++++++++++++ cli/main/test-user1-private.pem | 27 +++++++ cli/main/test-user1-public.pem | 9 +++ 4 files changed, 212 insertions(+) create mode 100644 cli/main/cli_test.go create mode 100755 cli/main/config.yaml create mode 100644 cli/main/test-user1-private.pem create mode 100644 cli/main/test-user1-public.pem diff --git a/cli/main/cli_test.go b/cli/main/cli_test.go new file mode 100644 index 0000000..8b137c7 --- /dev/null +++ b/cli/main/cli_test.go @@ -0,0 +1,126 @@ +package main + +import ( + "bytes" + "os" + "os/exec" + "path" + "strings" + "testing" + "time" +) + +type userData struct { + Username string + PrivateKeyFile string + PublicKeyFile string + Token string +} + +// Testuser data +var testUserData = userData{"user1", "test-user1-private.pem", "test-user1-public.pem", ""} + +// Root user data +var rootData = userData{"root", "test-root-init-private.pem", "", ""} + +// Return top level directory of project +func getProjectRootPath() string { + var currentWorkingDirectory, _ = os.Getwd() + var projectRootPath = path.Join(currentWorkingDirectory, "..", "..") + return projectRootPath +} + +// Get server executable path +func getServerExecutablePath() string { + projectRootPath := getProjectRootPath() + serverExecutableDir := path.Join(projectRootPath, "dist") + serverExecutableFilename := "vsmd" + serverExecutablePath := path.Join(serverExecutableDir, serverExecutableFilename) + return serverExecutablePath +} + +// Main function for test. Used here as an alternate for +// setup() and teardown() phase +func TestMain(m *testing.M) { + serverExecutablePath := getServerExecutablePath() + cmd := exec.Command(serverExecutablePath) + cmd.Start() + time.Sleep(time.Second * 3) + v := m.Run() + cmd.Process.Kill() + os.Exit(v) +} + +func getOutput(command string) (string, error) { + projectRootPath := getProjectRootPath() + cliExecutableName := "vsm-cli" + cliExecutablePath := path.Join(projectRootPath, "dist", cliExecutableName) + cmd := exec.Command(cliExecutablePath, strings.Split(command, " ")...) + output, err := cmd.CombinedOutput() + return bytes.NewBuffer(output).String(), err +} + +// Test login using pre-created root account +func TestRootLogin(t *testing.T) { + + projectRootPath := getProjectRootPath() + certFileName := "test-root-init-private.pem" + certFilePath := path.Join(projectRootPath, "certs", certFileName) + command := "login root" + " " + certFilePath + output, _ := getOutput(command) + + check1 := strings.Contains(output, "Login successful") + check2 := strings.Contains(output, "Token:") + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } else { + index := strings.Index(output, "Token:") + rootData.Token = strings.Trim(output[index+7:], "\n") + } +} + +// Test user creation +func TestUserCreate(t *testing.T) { + + command := "--token " + rootData.Token + " users create " + testUserData.Username + " " + testUserData.PublicKeyFile + output, _ := getOutput(command) + + check1 := strings.Contains(output, "User created successfully") + check2 := strings.Contains(output, "Id: "+testUserData.Username) + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } +} + +// Test user data retrieval +func TestUserGet(t *testing.T) { + command := "--token " + rootData.Token + " users get " + testUserData.Username + output, _ := getOutput(command) + + check1 := strings.Contains(output, "\"username\": \""+testUserData.Username+"\"") + check2 := strings.Contains(output, "\"credentials\"") + + finalCheck := check1 && check2 + + if finalCheck == false { + t.Fail() + } +} + +// Test user deletion +func TestUserDelete(t *testing.T) { + command := "--token " + rootData.Token + " users delete " + testUserData.Username + output, _ := getOutput(command) + + check1 := strings.Contains(output, "User deleted successfully") + + if check1 == false { + t.Fail() + } +} diff --git a/cli/main/config.yaml b/cli/main/config.yaml new file mode 100755 index 0000000..2800410 --- /dev/null +++ b/cli/main/config.yaml @@ -0,0 +1,50 @@ +# Server +server: + + # Listeners + http: + enabled: true + port: 8080 + https: + enabled: true + port: 8443 + + # Root server certificate, also used to sign certificates when the server acts as a Certificate Authority + caCert: ../../certs/test-root-cert.pem + + # Private key corresponding to root server certificate + caKey: ../../certs/test-root-key.pem + + # Certificate used by the server in SSL handshake. Must be signed by key in caKey + serverCert: ../../certs/test-server-cert.pem + + # Private key of serverCert + serverKey: ../../certs/test-server-key.pem + + # Public key to create user "root" during server initialization + rootInitPubKey: ../../certs/test-root-init-public.pem + + # Private key of user "root". Recommended to remove from server when moving from testing to production. + rootInitPriKey: ../../certs/test-root-init-private.pem + +# Data Store - this is where encrypted secrets are stored +dataStore: + type: InMemoryDataStore + connectionString: + +# Virtual Key Store - manages keys' storage and retrieval +virtualKeyStore: + # Number of key stores + keyStoreCount: 3 + + # Minimum number of key stores required to create and retrieve keys + keyStoreThreshold: 2 + + # Key stores that will keep the actual keys + keyStores: + - type: InMemoryKeyStore + connectionString: + - type: InMemoryKeyStore + connectionString: + - type: InMemoryKeyStore + connectionString: diff --git a/cli/main/test-user1-private.pem b/cli/main/test-user1-private.pem new file mode 100644 index 0000000..27b558b --- /dev/null +++ b/cli/main/test-user1-private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAstoxxNcJTHSmBpvNNNQCk5oM4uzxZ+c8SN4Bpy7bXQbp5s1g +cjYvKMoU1+dKDh/l6fFboUZ4PU22EdjecwAiEYpYWeweLlN3jbooTFQjcvmR7sAG +gieNb5J8BsYCQesyYVFezbwI4gjJcHdZoIhWCVlnbuMwFjbA9qK0nxtVFIcxH9Hd +JCqLQ2FMUsleh51WvkbWNoG1cGJD26kLipGHeXXLiIzmOzSJ3VXn33EJMK0KBU+t +Z4Pa6sqcIZFQs1E00gre1UAj6ckKCeC+NBmWLnTcpABAM6f4YqP7xzK1U2aNCuwv +njTvwCcK12h1iQrc/BnQzChaUirQNf3cTQBW6wIDAQABAoIBAHDIVSAKdgund1at +gu6wTtujBkNHJUffMk3E6YfybVQxWug3VH1RG9X98LzhVfqoNMScdaqylHob+hcx +Cb29NL6Y3fP+iF2wNrDB1k2jtSL4rATBRJlotbDIz7s5vAyzcvaZaE4WKAfZgKWS +LYukzZRhs27iht1LM82TdpDqnHEvbWXHX54pU8YK5Yb0G8J4dPNp9/7vmVV6ahD1 +BF1OL/6icSvLOqa908yMzw3lSiTQjPEm/RTPYDt3CMCftYnmXw9k2y1n1wPQxGPT +w6W/aoWfG6eOF3woK7b3FXtmEUgcruyxX5IGEstVodk4W6arVQlHrxF6zmqB4tHQ +fzpHmUkCgYEA2p761AKu5x/rICiKSaYCHwo8T/NwcMZFi15EiZ/+naKlX94JkHVk +ZQYdfrTeD2z6I87JkM01cP40+2l3/u8DZQOPMRGPKpYKBnZvPTWCB5nl+H+AJM2M +wTu5W7K3IxGSaE7Pf8fmjtkZseG6YY4UXHdddMjkPjPZT2evJ50c1G8CgYEA0W6K ++JHQeBGOLDP/se7Xtd+lCZeU3MnatwT4l1W6pKEMpQm9Ejpj+nr7A24BWusV2HHH +5uwoVf9YkTqTsmdE9DA1QZUEAjGPYIO272CVFwH3uaNVlnahESKzBU64T3LItU5M +5AxP313sAfC3iBoqKOZU8kJgWegXAajUKn7Su0UCgYEA14noF8AxelMguErf1C6k +Zr/rqJOFJtqD1Bzzi5A/MmEZlIPPgCoM+gDmcXaWfDTgBQ+p8GYxKx6lU72u/Zve +B+hTc3gxYzYb2jVIBNvNP/s+HRpvV1mETTq5y6tOHXgElWwl7YBDUlC+oX7AB9BR +SLyyWiJ5zM3HkR7TNEYVF2cCgYBNbui1BPymGB+P2l30xNE+roTPqhrhE0TpnE3p +bkoG6oDJWHNulOY4S1YZq4eWvQqjr1Xw3GoBedqeP6EyOhp1iol2SQllYjuXvLtb +gEM/cXvNSEWxzwS4WDMGiFd/EHqDBoNJYf/6HzjOctj42muyGY9Yzw/ezgALngdr ++t4hXQKBgQCTLW2NQjmH3Zc8skNRxb36kI/K6Jp1nfi3rW0XIXC/9LRZwdfQNe2L +Ebo6YdroBivFXymLeCeK5o0feO6fCI3itsl5Wws5hLOzij2fdNaqDcpxGtge8Bzv +ZUHyDHAysQA/6wu7hVOrXaLm7t27WpfV5/32ElJYVTI4sq+J+zsfcQ== +-----END RSA PRIVATE KEY----- diff --git a/cli/main/test-user1-public.pem b/cli/main/test-user1-public.pem new file mode 100644 index 0000000..3131bf4 --- /dev/null +++ b/cli/main/test-user1-public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAstoxxNcJTHSmBpvNNNQC +k5oM4uzxZ+c8SN4Bpy7bXQbp5s1gcjYvKMoU1+dKDh/l6fFboUZ4PU22EdjecwAi +EYpYWeweLlN3jbooTFQjcvmR7sAGgieNb5J8BsYCQesyYVFezbwI4gjJcHdZoIhW +CVlnbuMwFjbA9qK0nxtVFIcxH9HdJCqLQ2FMUsleh51WvkbWNoG1cGJD26kLipGH +eXXLiIzmOzSJ3VXn33EJMK0KBU+tZ4Pa6sqcIZFQs1E00gre1UAj6ckKCeC+NBmW +LnTcpABAM6f4YqP7xzK1U2aNCuwvnjTvwCcK12h1iQrc/BnQzChaUirQNf3cTQBW +6wIDAQAB +-----END PUBLIC KEY-----