Skip to content

Commit

Permalink
Support setting namespace per resource (#1305)
Browse files Browse the repository at this point in the history
This change adds support for configuring namespaces at the resource or data source level.

All namespace directives are applied relative to the provider's configured namespace. This new approach allows for namespace'd resources to be created without having to pass a namespace specific provider, although that method is still fully supported.
  • Loading branch information
benashz authored Jun 1, 2022
1 parent 646087e commit 6813aee
Show file tree
Hide file tree
Showing 373 changed files with 4,328 additions and 1,467 deletions.
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ $ cd $GOPATH/src/github.com/hashicorp/terraform-provider-vault
$ make build
```

Using the provider
----------------------

Developing the Provider
---------------------------

Expand Down Expand Up @@ -94,3 +91,35 @@ If you wish to run specific tests, use the `TESTARGS` environment variable:
```sh
TESTARGS="--run DataSourceAWSAccessCredentials" make testacc
```

Using a local development build
----------------------

It's possible to use a local build of the Vault provider with Terraform directly.
This is useful when testing the provider outside the acceptance test framework.

Configure Terraform to use the development build of the provider.

> **warning**: backup your `~/.terraformrc` before running this command:
```shell
cat > ~/.terraformrc <<HERE
provider_installation {
dev_overrides {
"hashicorp/vault" = "$HOME/.terraform.d/plugins"
}
# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
HERE
```

Then execute the `dev` make target from the project root.
```shell
make dev
```
Now Terraform is set up to use the `dev` provider build instead of the provider
from the HashiCorp registry.
60 changes: 60 additions & 0 deletions eval/namespace-enhancements/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
### Public Evaluation: Enhanced Vault namespace support

This directory contains sample Terraform code which demonstrates an enhanced way
of provisioning resources under Vault namespaces. It assumes the following:

- Terraform is installed
- The provider development requirements are satisfied *see the top level README.md for more info*
- Root access to a Vault Enterprise server

#### Setup Terraform to use a local build of the Vault provider

> **warning**: backup your `~/.terraformrc` before running this command:
```shell
cat > ~/.terraformrc <<HERE
provider_installation {
dev_overrides {
"hashicorp/vault" = "$HOME/.terraform.d/plugins"
}
# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
HERE
```

Then execute the `dev` make target from the project root.
```shell
make dev
```

Now Terraform is set up to use the `dev` provider build instead of the provider
from the HashiCorp registry.

#### The basic example

Provision a generic KV secret in multiple namespaces using a single `provider{}` block.

Ensure that the `VAULT_TOKEN` and `VAULT_ADDR` environment variables are properly set,
or an alternative auth method is configured.

*from the repo root*:

Apply the example
```shell
pushd eval/namespace-enhancements/examples/basic/.
terraform init
terraform apply
terraform output -json
popd
```

Destroy the example
```shell
pushd eval/namespace-enhancements/examples/basic/.
terraform destroy
popd
```
35 changes: 35 additions & 0 deletions eval/namespace-enhancements/examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# single provider block
provider "vault" {}

locals {
# provide namespaces as a set
namespaces = toset(var.namespaces)
}

resource "vault_namespace" "demo" {
# leverage the for_each meta-argument
for_each = local.namespaces
path = each.key
}

resource "vault_mount" "demo" {
for_each = local.namespaces
namespace = vault_namespace.demo[each.key].path
path = "secretsv1"
type = "kv"
options = {
version = "1"
}
}

resource "vault_generic_secret" "demo" {
for_each = local.namespaces
# Support namespace at the level of the resource and data source
namespace = vault_mount.demo[each.key].namespace
path = "${vault_mount.demo[each.key].path}/secret"
data_json = jsonencode(
{
"baz" = "qux"
}
)
}
8 changes: 8 additions & 0 deletions eval/namespace-enhancements/examples/basic/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
output "mount_path" {
value = values(vault_mount.demo)[*].path
}

output "secret_data" {
sensitive = true
value = values(vault_generic_secret.demo)[*].data
}
7 changes: 7 additions & 0 deletions eval/namespace-enhancements/examples/basic/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "namespaces" {
default = [
"ns-1",
"ns-2",
"ns-3",
]
}
8 changes: 6 additions & 2 deletions generated/datasources/transform/decode/role_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/util"
"github.com/hashicorp/vault/api"
)

const roleNameEndpoint = "/transform/decode/{role_name}"
Expand Down Expand Up @@ -73,7 +74,10 @@ func RoleNameDataSource() *schema.Resource {
}

func readRoleNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
path := d.Get("path").(string)
vaultPath := util.ParsePath(path, roleNameEndpoint, d)
log.Printf("[DEBUG] Writing %q", vaultPath)
Expand Down
8 changes: 6 additions & 2 deletions generated/datasources/transform/encode/role_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/util"
"github.com/hashicorp/vault/api"
)

const roleNameEndpoint = "/transform/encode/{role_name}"
Expand Down Expand Up @@ -73,7 +74,10 @@ func RoleNameDataSource() *schema.Resource {
}

func readRoleNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
path := d.Get("path").(string)
vaultPath := util.ParsePath(path, roleNameEndpoint, d)
log.Printf("[DEBUG] Writing %q", vaultPath)
Expand Down
29 changes: 23 additions & 6 deletions generated/resources/transform/alphabet/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/util"
"github.com/hashicorp/vault/api"
)

const nameEndpoint = "/transform/alphabet/{name}"
Expand Down Expand Up @@ -50,8 +51,12 @@ func NameResource() *schema.Resource {
Schema: fields,
}
}

func createNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
path := d.Get("path").(string)
vaultPath := util.ParsePath(path, nameEndpoint, d)
log.Printf("[DEBUG] Creating %q", vaultPath)
Expand All @@ -72,7 +77,10 @@ func createNameResource(d *schema.ResourceData, meta interface{}) error {
}

func readNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Reading %q", vaultPath)

Expand Down Expand Up @@ -104,7 +112,10 @@ func readNameResource(d *schema.ResourceData, meta interface{}) error {
}

func updateNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Updating %q", vaultPath)

Expand All @@ -120,7 +131,10 @@ func updateNameResource(d *schema.ResourceData, meta interface{}) error {
}

func deleteNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Deleting %q", vaultPath)

Expand All @@ -136,7 +150,10 @@ func deleteNameResource(d *schema.ResourceData, meta interface{}) error {
}

func resourceNameExists(d *schema.ResourceData, meta interface{}) (bool, error) {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return false, e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Checking if %q exists", vaultPath)

Expand Down
4 changes: 2 additions & 2 deletions generated/resources/transform/alphabet/name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
sdk_schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/vault/api"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/schema"
"github.com/hashicorp/terraform-provider-vault/testutil"
"github.com/hashicorp/terraform-provider-vault/vault"
Expand Down Expand Up @@ -58,7 +58,7 @@ func TestAlphabetName(t *testing.T) {
}

func destroy(s *terraform.State) error {
client := nameTestProvider.SchemaProvider().Meta().(*api.Client)
client := nameTestProvider.SchemaProvider().Meta().(*provider.ProviderMeta).GetClient()

for _, rs := range s.RootModule().Resources {
if rs.Type != "vault_transform_alphabet_name" {
Expand Down
29 changes: 23 additions & 6 deletions generated/resources/transform/role/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/util"
"github.com/hashicorp/vault/api"
)

const nameEndpoint = "/transform/role/{name}"
Expand Down Expand Up @@ -51,8 +52,12 @@ func NameResource() *schema.Resource {
Schema: fields,
}
}

func createNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
path := d.Get("path").(string)
vaultPath := util.ParsePath(path, nameEndpoint, d)
log.Printf("[DEBUG] Creating %q", vaultPath)
Expand All @@ -73,7 +78,10 @@ func createNameResource(d *schema.ResourceData, meta interface{}) error {
}

func readNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Reading %q", vaultPath)

Expand Down Expand Up @@ -105,7 +113,10 @@ func readNameResource(d *schema.ResourceData, meta interface{}) error {
}

func updateNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Updating %q", vaultPath)

Expand All @@ -121,7 +132,10 @@ func updateNameResource(d *schema.ResourceData, meta interface{}) error {
}

func deleteNameResource(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Deleting %q", vaultPath)

Expand All @@ -137,7 +151,10 @@ func deleteNameResource(d *schema.ResourceData, meta interface{}) error {
}

func resourceNameExists(d *schema.ResourceData, meta interface{}) (bool, error) {
client := meta.(*api.Client)
client, e := provider.GetClient(d, meta)
if e != nil {
return false, e
}
vaultPath := d.Id()
log.Printf("[DEBUG] Checking if %q exists", vaultPath)

Expand Down
4 changes: 2 additions & 2 deletions generated/resources/transform/role/name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
sdk_schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/vault/api"

"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/schema"
"github.com/hashicorp/terraform-provider-vault/testutil"
"github.com/hashicorp/terraform-provider-vault/vault"
Expand Down Expand Up @@ -61,7 +61,7 @@ func TestRoleName(t *testing.T) {
}

func destroy(s *terraform.State) error {
client := nameTestProvider.SchemaProvider().Meta().(*api.Client)
client := nameTestProvider.SchemaProvider().Meta().(*provider.ProviderMeta).GetClient()

for _, rs := range s.RootModule().Resources {
if rs.Type != "vault_transform_role_name" {
Expand Down
Loading

0 comments on commit 6813aee

Please sign in to comment.