diff --git a/test/vault_cluster_autounseal_test.go b/test/vault_cluster_autounseal_test.go new file mode 100644 index 00000000..6378645b --- /dev/null +++ b/test/vault_cluster_autounseal_test.go @@ -0,0 +1,99 @@ +package test + +import ( + "fmt" + "testing" + "time" + + "github.com/gruntwork-io/terratest/modules/aws" + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/random" + "github.com/gruntwork-io/terratest/modules/retry" + "github.com/gruntwork-io/terratest/modules/ssh" + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/gruntwork-io/terratest/modules/test-structure" +) + +// This is the alias of a KMS key we have previously created that lives in the +// AWS account where our CI tests run. We have one with the same alias in +// every region. This key is necessary for the test of an Enterprise Vault feature +// called auto unseal. If you wish to run test this locally, replace this with +// the alias of an KMS key you already have on the AWS account you use for running +// your tests or create a new one. Beware that creating an AWS KMS key costs money. +const AUTO_UNSEAL_KMS_KEY_ALIAS = "dedicated-test-key" + +const VAULT_AUTO_UNSEAL_AUTH_PATH = "examples/vault-auto-unseal" +const VAR_VAULT_AUTO_UNSEAL_KMS_KEY_ALIAS = "auto_unseal_kms_key_alias" + +// Test the Vault auto unseal example by: +// +// 1. Copying the code in this repo to a temp folder so tests on the Terraform code can run in parallel without the +// state files overwriting each other. +// 2. Building the AMI in the vault-consul-ami example with the given build name +// 3. Deploying a cluster of 1 vault server using the example Terraform code +// 4. Sshing into vault node to initialize the server and check that it booted unsealed +// 5. Increasing the the cluster size to 3 and check that new nodes are unsealed when they boot and join the cluster +func runVaultAutoUnsealTest(t *testing.T, amiId string, awsRegion string, sshUserName string) { + examplesDir := test_structure.CopyTerraformFolderToTemp(t, REPO_ROOT, VAULT_AUTO_UNSEAL_AUTH_PATH) + + defer test_structure.RunTestStage(t, "teardown", func() { + teardownResources(t, examplesDir) + }) + + defer test_structure.RunTestStage(t, "log", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, examplesDir) + keyPair := test_structure.LoadEc2KeyPair(t, examplesDir) + + getVaultLogs(t, "vaultAutoUnseal", terraformOptions, amiId, awsRegion, sshUserName, keyPair) + }) + + test_structure.RunTestStage(t, "deploy", func() { + uniqueId := random.UniqueId() + terraformVars := map[string]interface{}{ + VAR_VAULT_AUTO_UNSEAL_KMS_KEY_ALIAS: AUTO_UNSEAL_KMS_KEY_ALIAS, + VAR_VAULT_CLUSTER_SIZE: 1, + } + deployCluster(t, amiId, awsRegion, examplesDir, uniqueId, terraformVars) + }) + + test_structure.RunTestStage(t, "validate", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, examplesDir) + keyPair := test_structure.LoadEc2KeyPair(t, examplesDir) + + testAutoUnseal(t, OUTPUT_VAULT_CLUSTER_ASG_NAME, sshUserName, terraformOptions, awsRegion, keyPair) + }) +} + +func testAutoUnseal(t *testing.T, asgNameOutputVar string, sshUserName string, terraformOptions *terraform.Options, awsRegion string, keyPair *aws.Ec2Keypair) { + asgName := terraform.OutputRequired(t, terraformOptions, asgNameOutputVar) + nodeIpAddresses := getIpAddressesOfAsgInstances(t, asgName, awsRegion) + logger.Logf(t, fmt.Sprintf("IP ADDRESS OF INSTANCE %s", nodeIpAddresses[0])) + initialCluster := VaultCluster{ + Leader: ssh.Host{ + Hostname: nodeIpAddresses[0], + SshUserName: sshUserName, + SshKeyPair: keyPair.KeyPair, + }, + } + + establishConnectionToCluster(t, initialCluster) + waitForVaultToBoot(t, initialCluster) + + retry.DoWithRetry(t, "Initializing the cluster", 10, 10*time.Second, func() (string, error) { + return ssh.CheckSshCommandE(t, initialCluster.Leader, "vault operator init") + }) + assertStatus(t, initialCluster.Leader, Leader) + + logger.Logf(t, "Increasing the cluster size and running 'terraform apply' again") + terraformOptions.Vars[VAR_VAULT_CLUSTER_SIZE] = 3 + terraform.Apply(t, terraformOptions) + + logger.Logf(t, "The cluster now should be bigger and the new nodes should boot unsealed (on standby mode already)") + newCluster := findVaultClusterNodes(t, asgNameOutputVar, sshUserName, terraformOptions, awsRegion, keyPair) + establishConnectionToCluster(t, newCluster) + for _, node := range newCluster.Nodes() { + if node.Hostname != initialCluster.Leader.Hostname { + assertStatus(t, node, Standby) + } + } +} diff --git a/test/vault_cluster_enterprise_test.go b/test/vault_cluster_enterprise_test.go index e3511564..4b2ca281 100644 --- a/test/vault_cluster_enterprise_test.go +++ b/test/vault_cluster_enterprise_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/gruntwork-io/terratest/modules/aws" - "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/retry" "github.com/gruntwork-io/terratest/modules/ssh" @@ -16,17 +15,6 @@ import ( "github.com/gruntwork-io/terratest/modules/test-structure" ) -// This is the alias of a KMS key we have previously created that lives in the -// AWS account where our CI tests run. We have one with the same alias in -// every region. This key is necessary for the test of an Enterprise Vault feature -// called auto unseal. If you wish to run test this locally, replace this with -// the alias of an KMS key you already have on the AWS account you use for running -// your tests or create a new one. Beware that creating an AWS KMS key costs money. -const AUTO_UNSEAL_KMS_KEY_ALIAS = "dedicated-test-key" - -const VAULT_AUTO_UNSEAL_AUTH_PATH = "examples/vault-auto-unseal" -const VAR_VAULT_AUTO_UNSEAL_KMS_KEY_ALIAS = "auto_unseal_kms_key_alias" - // To test this on circle ci you need a url set as an environment variable, VAULT_AMI_TEMPLATE_VAR_DOWNLOAD_URL // which you would also have to set locally if you want to run this test locally. // The reason is to prevent the actual url from being visible on code and logs @@ -38,45 +26,6 @@ func getUrlFromEnv(t *testing.T) string { return url } -// Test the Vault auto unseal example by: -// -// 1. Copying the code in this repo to a temp folder so tests on the Terraform code can run in parallel without the -// state files overwriting each other. -// 2. Building the AMI in the vault-consul-ami example with the given build name -// 3. Deploying a cluster of 1 vault server using the example Terraform code -// 4. Sshing into vault node to initialize the server and check that it booted unsealed -// 5. Increasing the the cluster size to 3 and check that new nodes are unsealed when they boot and join the cluster -func runVaultAutoUnsealTest(t *testing.T, amiId string, awsRegion string, sshUserName string) { - examplesDir := test_structure.CopyTerraformFolderToTemp(t, REPO_ROOT, VAULT_AUTO_UNSEAL_AUTH_PATH) - - defer test_structure.RunTestStage(t, "teardown", func() { - teardownResources(t, examplesDir) - }) - - defer test_structure.RunTestStage(t, "log", func() { - terraformOptions := test_structure.LoadTerraformOptions(t, examplesDir) - keyPair := test_structure.LoadEc2KeyPair(t, examplesDir) - - getVaultLogs(t, "vaultAutoUnseal", terraformOptions, amiId, awsRegion, sshUserName, keyPair) - }) - - test_structure.RunTestStage(t, "deploy", func() { - uniqueId := random.UniqueId() - terraformVars := map[string]interface{}{ - VAR_VAULT_AUTO_UNSEAL_KMS_KEY_ALIAS: AUTO_UNSEAL_KMS_KEY_ALIAS, - VAR_VAULT_CLUSTER_SIZE: 1, - } - deployCluster(t, amiId, awsRegion, examplesDir, uniqueId, terraformVars) - }) - - test_structure.RunTestStage(t, "validate", func() { - terraformOptions := test_structure.LoadTerraformOptions(t, examplesDir) - keyPair := test_structure.LoadEc2KeyPair(t, examplesDir) - - testAutoUnseal(t, OUTPUT_VAULT_CLUSTER_ASG_NAME, sshUserName, terraformOptions, awsRegion, keyPair) - }) -} - // Test the Vault enterprise cluster example by: // // 1. Copy the code in this repo to a temp folder so tests on the Terraform code can run in parallel without the @@ -115,40 +64,6 @@ func runVaultEnterpriseClusterTest(t *testing.T, amiId string, awsRegion string, }) } -func testAutoUnseal(t *testing.T, asgNameOutputVar string, sshUserName string, terraformOptions *terraform.Options, awsRegion string, keyPair *aws.Ec2Keypair) { - asgName := terraform.OutputRequired(t, terraformOptions, asgNameOutputVar) - nodeIpAddresses := getIpAddressesOfAsgInstances(t, asgName, awsRegion) - logger.Logf(t, fmt.Sprintf("IP ADDRESS OF INSTANCE %s", nodeIpAddresses[0])) - initialCluster := VaultCluster{ - Leader: ssh.Host{ - Hostname: nodeIpAddresses[0], - SshUserName: sshUserName, - SshKeyPair: keyPair.KeyPair, - }, - } - - establishConnectionToCluster(t, initialCluster) - waitForVaultToBoot(t, initialCluster) - - retry.DoWithRetry(t, "Initializing the cluster", 10, 10*time.Second, func() (string, error) { - return ssh.CheckSshCommandE(t, initialCluster.Leader, "vault operator init") - }) - assertStatus(t, initialCluster.Leader, Leader) - - logger.Logf(t, "Increasing the cluster size and running 'terraform apply' again") - terraformOptions.Vars[VAR_VAULT_CLUSTER_SIZE] = 3 - terraform.Apply(t, terraformOptions) - - logger.Logf(t, "The cluster now should be bigger and the new nodes should boot unsealed (on standby mode already)") - newCluster := findVaultClusterNodes(t, asgNameOutputVar, sshUserName, terraformOptions, awsRegion, keyPair) - establishConnectionToCluster(t, newCluster) - for _, node := range newCluster.Nodes() { - if node.Hostname != initialCluster.Leader.Hostname { - assertStatus(t, node, Standby) - } - } -} - // Check if the enterprise version of consul and vault is installed func checkEnterpriseInstall(t *testing.T, asgNameOutputVar string, sshUserName string, terratestOptions *terraform.Options, awsRegion string, keyPair *aws.Ec2Keypair) { asgName := terraform.OutputRequired(t, terratestOptions, asgNameOutputVar)