Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions vault/data_source_mounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package vault

import (
"context"
"sort"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-vault/internal/provider"
)

func mountsDataSource() *schema.Resource {
return &schema.Resource{
ReadContext: provider.ReadContextWrapper(mountsDataSourceRead),
Schema: map[string]*schema.Schema{
"mounts": {
Type: schema.TypeList,
Computed: true,
Description: "Liste des mounts activés dans Vault",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"accessor": {
Type: schema.TypeString,
Computed: true,
Description: "Internal accessor for the mount.",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Human-readable description of the mount.",
},
"local": {
Type: schema.TypeBool,
Computed: true,
Description: "True if the mount is local to this Vault node.",
},
"options": {
Type: schema.TypeMap,
Computed: true,
Description: "Key-value options that configure the mount.",
Elem: &schema.Schema{Type: schema.TypeString},
},
"path": {
Type: schema.TypeString,
Computed: true,
Description: "Full path of the mount, ending with a slash (/).",
},
"seal_wrap": {
Type: schema.TypeBool,
Computed: true,
Description: "Indicates whether seal wrapping is enabled for this mount.",
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "Backend type of the mount (e.g., kv, pki).",
},
"uuid": {
Type: schema.TypeString,
Computed: true,
Description: "Unique identifier (UUID) of the mount.",
},
},
},
},
},
}
}

func mountsDataSourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, err := provider.GetClient(d, meta)
if err != nil {
return diag.FromErr(err)
}
mounts, err := client.Sys().ListMountsWithContext(ctx)
if err != nil {
return diag.FromErr(err)
}

// Extraire et trier les paths pour un ordre stable
paths := make([]string, 0, len(mounts))
for path := range mounts {
paths = append(paths, path)
}
sort.Strings(paths)

result := make([]map[string]any, 0, len(paths))
for _, path := range paths {
m := mounts[path]
result = append(result, map[string]any{
"accessor": m.Accessor,
"description": m.Description,
"local": m.Local,
"options": m.Options,
"path": path,
"seal_wrap": m.SealWrap,
"type": m.Type,
"uuid": m.UUID,
})
}

if err := d.Set("mounts", result); err != nil {
return diag.FromErr(err)
}

d.SetId("vault-mounts")
return nil
}
82 changes: 82 additions & 0 deletions vault/data_source_mounts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package vault

import (
"context"
"fmt"
"strconv"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"

"github.com/hashicorp/terraform-provider-vault/testutil"
)

func TestAccDataSourceMounts(t *testing.T) {
kvPath := acctest.RandomWithPrefix("tf-test-kv-backend")
pkiPath := acctest.RandomWithPrefix("tf-test-pki-backend")
dataName := "data.vault_mounts.test"
resource.Test(t, resource.TestCase{
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories(context.Background(), t),
PreCheck: func() {
testutil.TestAccPreCheck(t)
},
Steps: []resource.TestStep{
{
Config: testMountsDataSource(kvPath, pkiPath),
Check: resource.ComposeTestCheckFunc(
testCheckMountInList(dataName, kvPath+"/", "kv"),
testCheckMountInList(dataName, pkiPath+"/", "pki"),
),
},
},
})
}

func testMountsDataSource(kvPath, pkiPath string) string {
return fmt.Sprintf(`
resource "vault_mount" "kv" {
path = "%s"
type = "kv"
description = "KV secret engine mount"
}

resource "vault_mount" "pki" {
path = "%s"
type = "pki"
description = "PKI secret engine mount"
}


data "vault_mounts" "test" {
depends_on = [ vault_mount.kv,vault_mount.pki ]
}`, kvPath, pkiPath)
}

func testCheckMountInList(name, expectedPath, expectedType string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("resource %s not found", name)
}

countStr := rs.Primary.Attributes["mounts.#"]
count, err := strconv.Atoi(countStr)
if err != nil {
return err
}

for i := range count {
path := rs.Primary.Attributes[fmt.Sprintf("mounts.%d.path", i)]
typ := rs.Primary.Attributes[fmt.Sprintf("mounts.%d.type", i)]
if path == expectedPath && typ == expectedType {
return nil
}
}
return fmt.Errorf("mount with path %s and type %s not found", expectedPath, expectedType)
}
}
4 changes: 4 additions & 0 deletions vault/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ var (
Resource: UpdateSchemaResource(transitCMACDataSource()),
PathInventory: []string{"/transit/cmac/{name}/{url_mac_length}"},
},
"vault_mounts": {
Resource: UpdateSchemaResource(mountsDataSource()),
PathInventory: []string{"/sys/mounts"},
},
}

ResourceRegistry = map[string]*provider.Description{
Expand Down
50 changes: 50 additions & 0 deletions website/docs/d/mounts.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
layout: "vault"
page_title: "Vault: vault_mounts data source"
sidebar_current: "docs-vault-datasource-mounts"
description: |-
Lists all mounts.
---

# vault_mounts

Lists all issuers under a particular mount.

~> **Important** All data retrieved from Vault will be
written in cleartext to state file generated by Terraform, will appear in
the console output when Terraform runs, and may be included in plan files
if secrets are interpolated into any resource attributes.
Protect these artifacts accordingly. See
[the main provider documentation](../index.html)
for more details.

## Example Usage

```hcl
data "vault_mounts" "all" {}
```

## Argument Reference

The vault_mounts data source does not require any arguments. Optionally, the namespace argument can be used to target Vault Enterprise namespaces:

- `namespace` - (Optional) The namespace of the target resource.
The value should not contain leading or trailing forward slashes.
The `namespace` is always relative to the provider's configured [namespace](/docs/providers/vault/index.html#namespace).
_Available only for Vault Enterprise_.

## Attributes Reference

The following attributes are exported by the data source:

| Attribute | Type | Description |
| ------------- | ------------ | ----------------------------------------------------------------------------- |
| `mounts` | list(object) | A list of objects representing each enabled mount. Each object contains: |
| `path` | string | The full path of the mount, ending with `/`. |
| `type` | string | The type of the backend (e.g., `kv`, `pki`). |
| `description` | string | Human-readable description of the mount. |
| `options` | map(string) | Key-value map of mount options (all values are strings). |
| `accessor` | string | Internal Vault accessor for the mount. |
| `local` | bool | Boolean indicating if the mount is local to the Vault node. |
| `seal_wrap` | bool | Boolean indicating if seal wrapping is enabled. |
| `uuid` | string | Unique UUID of the mount. |
Loading