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

Use new semantic version checking for Consul secrets backend logic #1593

Merged
merged 16 commits into from
Sep 7, 2022
Merged
Changes from 3 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
110 changes: 55 additions & 55 deletions vault/resource_consul_secret_backend_role.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package vault

import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-provider-vault/internal/semver"
"log"
"regexp"
"strings"
Expand All @@ -19,13 +22,12 @@ var (

func consulSecretBackendRoleResource() *schema.Resource {
return &schema.Resource{
Create: consulSecretBackendRoleWrite,
Read: ReadWrapper(consulSecretBackendRoleRead),
Update: consulSecretBackendRoleWrite,
Delete: consulSecretBackendRoleDelete,
Exists: consulSecretBackendRoleExists,
CreateContext: consulSecretBackendRoleWrite,
ReadContext: ReadContextWrapper(consulSecretBackendRoleRead),
UpdateContext: consulSecretBackendRoleWrite,
DeleteContext: consulSecretBackendRoleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -138,21 +140,23 @@ func consulSecretBackendRoleGetBackend(d *schema.ResourceData) string {
}
}

func consulSecretBackendRoleWrite(d *schema.ResourceData, meta interface{}) error {
func consulSecretBackendRoleWrite(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return e
return diag.FromErr(e)
}

name := d.Get("name").(string)

backend := consulSecretBackendRoleGetBackend(d)
if backend == "" {
return fmt.Errorf("No backend specified for Consul secret backend role %s", name)
return diag.Errorf("No backend specified for Consul secret backend role %s", name)
}

path := consulSecretBackendRolePath(backend, name)

// This loads either the consul_policies or policies field, depending on which the
// user provided, and then stores it under the appropriate key in the data.
var policies []interface{}
if v, ok := d.GetOk("policies"); ok {
policies = v.([]interface{})
Expand All @@ -165,13 +169,22 @@ func consulSecretBackendRoleWrite(d *schema.ResourceData, meta interface{}) erro
nodeIdentities := d.Get("node_identities").(*schema.Set).List()

data := map[string]interface{}{
"policies": policies,
"consul_policies": policies,
"consul_roles": roles,
"service_identities": serviceIdentities,
"node_identities": nodeIdentities,
}

useAPIVer2, _, err := semver.GreaterThanOrEqual(ctx, client, consts.VaultVersion11)
if err != nil {
return diag.FromErr(err)
}

if useAPIVer2 {
data["consul_policies"] = policies
} else {
data["policies"] = policies
}

params := []string{
"max_ttl",
"ttl",
Expand All @@ -189,17 +202,17 @@ func consulSecretBackendRoleWrite(d *schema.ResourceData, meta interface{}) erro
log.Printf("[DEBUG] Configuring Consul secrets backend role at %q", path)

if _, err := client.Logical().Write(path, data); err != nil {
return fmt.Errorf("error writing role configuration for %q: %s", path, err)
return diag.Errorf("error writing role configuration for %q: %s", path, err)
}

d.SetId(path)
return consulSecretBackendRoleRead(d, meta)
return consulSecretBackendRoleRead(ctx, d, meta)
}

func consulSecretBackendRoleRead(d *schema.ResourceData, meta interface{}) error {
func consulSecretBackendRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return e
return diag.FromErr(e)
}

upgradeOldID(d)
Expand All @@ -209,30 +222,30 @@ func consulSecretBackendRoleRead(d *schema.ResourceData, meta interface{}) error
if err != nil {
log.Printf("[WARN] Removing consul role %q because its ID is invalid", path)
d.SetId("")
return fmt.Errorf("invalid role ID %q: %s", path, err)
return diag.Errorf("invalid role ID %q: %s", path, err)
}

backend, err := consulSecretBackendRoleBackendFromPath(path)
if err != nil {
log.Printf("[WARN] Removing consul role %q because its ID is invalid", path)
d.SetId("")
return fmt.Errorf("invalid role ID %q: %s", path, err)
return diag.Errorf("invalid role ID %q: %s", path, err)
}

log.Printf("[DEBUG] Reading Consul secrets backend role at %q", path)

secret, err := client.Logical().Read(path)
if err != nil {
return fmt.Errorf("error reading role configuration for %q: %s", path, err)
return diag.Errorf("error reading role configuration for %q: %s", path, err)
}

if secret == nil {
return fmt.Errorf("resource not found")
return diag.Errorf("resource not found")
}

data := secret.Data
if err := d.Set("name", name); err != nil {
return err
return diag.FromErr(err)
}
var pathKey string
if _, ok := d.GetOk(consts.FieldPath); ok {
Expand All @@ -241,7 +254,7 @@ func consulSecretBackendRoleRead(d *schema.ResourceData, meta interface{}) error
pathKey = "backend"
}
if err := d.Set(pathKey, backend); err != nil {
return err
return diag.FromErr(err)
}

// map request params to schema fields
Expand All @@ -257,17 +270,24 @@ func consulSecretBackendRoleRead(d *schema.ResourceData, meta interface{}) error
"node_identities": "node_identities",
}

_, hasLegacyPolicies := data["policies"]
if hasLegacyPolicies {
params["policies"] = "policies"
if _, ok := d.GetOk("consul_policies"); ok {
params["policies"] = "consul_policies"
}
// Check whether Vault will return consul_policies or policies based on its version.
useAPIVer2, _, err := semver.GreaterThanOrEqual(ctx, client, consts.VaultVersion11)
if err != nil {
return diag.FromErr(err)
}

// Return either policies or consul_policies depending on the following criteria:
// * Vault version < 1.11: Always use policies
// * Vault version >= 1.11: Default consul_policies; use policies if the user specified it
policyField := "consul_policies"
if _, ok := d.GetOk("policies"); ok || !useAPIVer2 {
policyField = "policies"
}

if useAPIVer2 {
params["consul_policies"] = policyField
} else {
params["consul_policies"] = "consul_policies"
if _, ok := d.GetOk("policies"); ok {
params["consul_policies"] = "policies"
}
params["policies"] = policyField
}

for k, v := range params {
Expand All @@ -283,50 +303,30 @@ func consulSecretBackendRoleRead(d *schema.ResourceData, meta interface{}) error
}
}
if err := d.Set(v, val); err != nil {
return err
return diag.FromErr(err)
}
}

return nil
}

func consulSecretBackendRoleDelete(d *schema.ResourceData, meta interface{}) error {
func consulSecretBackendRoleDelete(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return e
return diag.FromErr(e)
}

path := d.Id()

log.Printf("[DEBUG] Deleting Consul backend role at %q", path)

if _, err := client.Logical().Delete(path); err != nil {
return fmt.Errorf("error deleting Consul backend role at %q: %s", path, err)
return diag.Errorf("error deleting Consul backend role at %q: %s", path, err)
}
log.Printf("[DEBUG] Deleted Consul backend role at %q", path)
return nil
}

func consulSecretBackendRoleExists(d *schema.ResourceData, meta interface{}) (bool, error) {
client, e := provider.GetClient(d, meta)
if e != nil {
return false, e
}

upgradeOldID(d)

path := d.Id()

log.Printf("[DEBUG] Checking Consul secrets backend role at %q", path)

secret, err := client.Logical().Read(path)
if err != nil {
return false, fmt.Errorf("error reading role configuration for %q: %s", path, err)
}

return secret != nil, nil
}

func upgradeOldID(d *schema.ResourceData) {
// Upgrade old "{backend},{name}" ID format
id := d.Id()
Expand Down