Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panic while importing namespaces in TFVP #1818

Merged
merged 2 commits into from
Apr 13, 2023

Conversation

vinay-gopalan
Copy link
Contributor

@vinay-gopalan vinay-gopalan commented Apr 11, 2023

This PR adds a nil check in the code that performs namespace imports. The code checks the TF state to ensure a namespace is not already set to state, however it does not account for the case where the state attributes are nil. This case occurs when a user would like to perform a terraform import command before any plan or apply runs (terraform.tfstate file does not necessarily exist)

The panic was reproduced with the following steps:

  • Create a namespace on a running Vault server
  • Enable a secrets/auth engine of your choice within that namespace
  • Setup a TF config file with a vault_mount resource that has the same path as your engine in the 2nd step
  • Set the TERRAFORM_VAULT_NAMESPACE_IMPORT env variable to the value of the created namespace
  • Run terraform import vault_mount.<your_mount> <your_path>

Without employing the fix, a panic is generated. With the fix, the import executes successfully.

@vinay-gopalan vinay-gopalan requested review from a team and jasonodonnell April 11, 2023 22:07
@vinay-gopalan
Copy link
Contributor Author

Writing a dynamic test for this scenario is a bit difficult with the current TF SDK. A dynamic acceptance test would require the test code to set up a secret/auth engine mount within Vault without running a plan or apply, which currently does not seem possible in the SDK. I was able to test the fix manually with the steps mentioned in the PR description with different cases for the TF state, and can dig into more dynamic tests using the SDK in the future if they are a possibility.

Copy link
Contributor

@fairclothjm fairclothjm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just left a few thoughts on possible improvements

@fairclothjm
Copy link
Contributor

@vinay-gopalan RE: writing a test for this scenario

I wonder if we could make use of the Vault API client (provider.GetClient) to set up a secret/auth engine mount within Vault? I think that should allow us to bypass the plan/apply in the SDK?

@vinay-gopalan
Copy link
Contributor Author

@vinay-gopalan RE: writing a test for this scenario

I wonder if we could make use of the Vault API client (provider.GetClient) to set up a secret/auth engine mount within Vault? I think that should allow us to bypass the plan/apply in the SDK?

@fairclothjm good question! I actually tried something very similar to what you were pointing at, and it doesn't look like the SDK allows an Import step to be the first step in a testcase 🤔

func TestAccProvider_ImportNamespace(t *testing.T) {
	// need to short circuit the test
	// in case these are unset
	testutil.TestEntPreCheck(t)
	testutil.SkipTestEnvUnset(t, consts.EnvVarVaultNamespaceImport)

	mountPath := acctest.RandomWithPrefix("tf-pki-mount")
	resourceName := "vault_mount.pki"
	ns := os.Getenv(consts.EnvVarVaultNamespaceImport)

	// create mount in namespace for the test
	client := testProvider.Meta().(*provider.ProviderMeta).GetClient()
	client.SetNamespace(ns)
	err := client.Sys().Mount(mountPath, &api.MountInput{
		Type:        "pki",
		Description: "Mount for testing namespace imports",
	})
	if err != nil {
		t.Fatalf(fmt.Sprintf("error mounting pki engine; err=%s", err))
	}

	resource.Test(t, resource.TestCase{
		Providers: testProviders,
		Steps: []resource.TestStep{
			testutil.GetImportTestStep(resourceName, false, nil),
		},
	})
}

func testNamespaceImportConfig(path string) string {
	return fmt.Sprintf(`
resource "vault_mount" "pki" {
  path    = "%s"
  type    = "pki"
}
`, path)
}

Error returned because no such resource exists in the state (state non-existent):

Resource specified by ResourceName couldn't be found: vault_mount.pki

The test above also requires some prior set up to the Vault server (setting up the namespaces etc.) before it can be run, which might make it more of a local-only test. I'll dig into it a bit more to see if I can find a better solution, but for now we might have to resort to manual testing

@fairclothjm
Copy link
Contributor

@vinay-gopalan I found ExternalProviders and it seems like that should allow us to do an import step as the first step. But I couldn't get it to work so maybe I am misunderstanding that field.

I agree that manual tests should be ok for now since this will likely take a bit of work to figure out. (If it is even possible at all)

@vinay-gopalan vinay-gopalan added this to the 3.15.0 milestone Apr 13, 2023
@vinay-gopalan vinay-gopalan merged commit ce2c32e into main Apr 13, 2023
@vinay-gopalan vinay-gopalan deleted the VAULT-15234/fix-ns-import-panic branch April 13, 2023 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants