Skip to content

Commit

Permalink
Fix erroneous persistent diff in the vault_token resource. (hashicorp…
Browse files Browse the repository at this point in the history
…#1622)

The vault_token resource would produce a persistent diff for the
renewable and policies fields.

- factor out more constants
- clean up extraneous bits in consts.go
  • Loading branch information
benashz authored and marcboudreau committed Nov 6, 2022
1 parent 4828743 commit 482cc19
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 133 deletions.
26 changes: 16 additions & 10 deletions internal/consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,16 +156,22 @@ const (
FieldAuthMethodTypes = "auth_method_types"
FieldIdentityGroupIDs = "identity_group_ids"
FieldIdentityEntityIDs = "identity_entity_ids"
/*
auth_method_accessors ([]string: []) - Array of auth mount accessor IDs. If present, only auth methods corresponding to the given accessors are checked during login.
auth_method_types ([]string: []) - Array of auth method types. If present, only auth methods corresponding to the given types are checked during login.
identity_group_ids ([]string: []) - Array of identity group IDs. If present, only entities belonging to one of the given groups are checked during login. Note that these IDs can be from the current namespace or a child namespace.
identity_entity_ids ([]string: []) - Array of identity entity IDs. If present, only entities with the given IDs are checked during login. Note that these IDs can be from the current namespace or a child namespace.
*/
FieldWrappingAccessor = "wrapping_accessor"
FieldRoleName = "role_name"
FieldPolicies = "policies"
FieldNoParent = "no_parent"
FieldNoDefaultPolicy = "no_default_policy"
FieldRenewable = "renewable"
FieldExplicitMaxTTL = "explicit_max_ttl"
FieldWrappingTTL = "wrapping_ttl"
FieldDisplayName = "display_name"
FieldNumUses = "num_uses"
FieldRenewMinLease = "renew_min_lease"
FieldRenewIncrement = "renew_increment"
FieldLeaseStarted = "lease_started"
FieldClientToken = "client_token"
FieldWrappedToken = "wrapped_token"
FieldOrphan = "orphan"

/*
common environment variables
Expand Down
113 changes: 55 additions & 58 deletions vault/resource_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

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

func tokenResource() *schema.Resource {
Expand All @@ -25,14 +26,14 @@ func tokenResource() *schema.Resource {
},

Schema: map[string]*schema.Schema{
"role_name": {
consts.FieldRoleName: {
Type: schema.TypeString,
Required: false,
Optional: true,
ForceNew: true,
Description: "The token role name.",
},
"policies": {
consts.FieldPolicies: {
Type: schema.TypeSet,
Required: false,
Optional: true,
Expand All @@ -42,77 +43,77 @@ func tokenResource() *schema.Resource {
},
Description: "List of policies.",
},
"no_parent": {
consts.FieldNoParent: {
Type: schema.TypeBool,
Required: false,
Optional: true,
ForceNew: true,
Computed: true,
Description: "Flag to create a token without parent.",
},
"no_default_policy": {
consts.FieldNoDefaultPolicy: {
Type: schema.TypeBool,
Required: false,
Optional: true,
ForceNew: true,
Description: "Flag to disable the default policy.",
},
"renewable": {
consts.FieldRenewable: {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Computed: true,
Description: "Flag to allow the token to be renewed",
},
"ttl": {
consts.FieldTTL: {
Type: schema.TypeString,
Required: false,
Optional: true,
ForceNew: true,
Description: "The TTL period of the token.",
},
"explicit_max_ttl": {
consts.FieldExplicitMaxTTL: {
Type: schema.TypeString,
Required: false,
Optional: true,
ForceNew: true,
Description: "The explicit max TTL of the token.",
},
"wrapping_ttl": {
consts.FieldWrappingTTL: {
Type: schema.TypeString,
Required: false,
Optional: true,
Description: "The TTL period of the wrapped token.",
},
"display_name": {
consts.FieldDisplayName: {
Type: schema.TypeString,
Required: false,
Optional: true,
ForceNew: true,
Default: "token",
Default: consts.FieldToken,
Description: "The display name of the token.",
},
"num_uses": {
consts.FieldNumUses: {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Computed: true,
Description: "The number of allowed uses of the token.",
},
"period": {
consts.FieldPeriod: {
Type: schema.TypeString,
Required: false,
Optional: true,
ForceNew: true,
Description: "The period of the token.",
},
"renew_min_lease": {
consts.FieldRenewMinLease: {
Type: schema.TypeInt,
Required: false,
Optional: true,
Description: "The minimum lease to renew token.",
},
"renew_increment": {
consts.FieldRenewIncrement: {
Type: schema.TypeInt,
Required: false,
Optional: true,
Expand All @@ -123,24 +124,24 @@ func tokenResource() *schema.Resource {
Computed: true,
Description: "The token lease duration.",
},
"lease_started": {
consts.FieldLeaseStarted: {
Type: schema.TypeString,
Computed: true,
Description: "The token lease started on.",
},
"client_token": {
consts.FieldClientToken: {
Type: schema.TypeString,
Computed: true,
Description: "The client token.",
Sensitive: true,
},
"wrapped_token": {
consts.FieldWrappedToken: {
Type: schema.TypeString,
Computed: true,
Description: "The client wrapped token.",
Sensitive: true,
},
"wrapping_accessor": {
consts.FieldWrappingAccessor: {
Type: schema.TypeString,
Computed: true,
Description: "The client wrapping accessor.",
Expand Down Expand Up @@ -168,62 +169,58 @@ func tokenCreate(d *schema.ResourceData, meta interface{}) error {
var err error
var wrapped bool

role := d.Get("role_name").(string)

iPolicies := d.Get("policies").(*schema.Set).List()
policies := make([]string, 0, len(iPolicies))
for _, iPolicy := range iPolicies {
policies = append(policies, iPolicy.(string))
}
role := d.Get(consts.FieldRoleName).(string)

createRequest := &api.TokenCreateRequest{}

if len(policies) > 0 {
createRequest.Policies = policies
if v, ok := d.GetOk(consts.FieldPolicies); ok && v != nil {
createRequest.Policies = util.TerraformSetToStringArray(v)
}

if v, ok := d.GetOk("ttl"); ok {
if v, ok := d.GetOk(consts.FieldTTL); ok {
createRequest.TTL = v.(string)
}

if v, ok := d.GetOk("explicit_max_ttl"); ok {
if v, ok := d.GetOk(consts.FieldExplicitMaxTTL); ok {
createRequest.ExplicitMaxTTL = v.(string)
}

if v, ok := d.GetOk("period"); ok {
if v, ok := d.GetOk(consts.FieldPeriod); ok {
createRequest.Period = v.(string)
}

if v, ok := d.GetOk("no_parent"); ok {
if v, ok := d.GetOk(consts.FieldNoParent); ok {
createRequest.NoParent = v.(bool)
}

if v, ok := d.GetOk("no_default_policy"); ok {
if v, ok := d.GetOk(consts.FieldNoDefaultPolicy); ok {
createRequest.NoDefaultPolicy = v.(bool)
}

if v, ok := d.GetOk("display_name"); ok {
if v, ok := d.GetOk(consts.FieldDisplayName); ok {
createRequest.DisplayName = v.(string)
}

if v, ok := d.GetOk("num_uses"); ok {
if v, ok := d.GetOk(consts.FieldNumUses); ok {
createRequest.NumUses = v.(int)
}

if v, ok := d.GetOk("renewable"); ok {
renewable := v.(bool)
if v, ok := d.GetOkExists(consts.FieldRenewable); ok {
renewable, ok := v.(bool)
if !ok {
return fmt.Errorf("unexpected type %T for %q", d.Get(consts.FieldRenewable), consts.FieldRenewable)
}
createRequest.Renewable = &renewable
}

if v, ok := d.GetOk("metadata"); ok {
if v, ok := d.GetOk(consts.FieldMetadata); ok {
d := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
d[k] = val.(string)
}
createRequest.Metadata = d
}

if v, ok := d.GetOk("wrapping_ttl"); ok {
if v, ok := d.GetOk(consts.FieldWrappingTTL); ok {
wrappingTTL := v.(string)

client, err = client.Clone()
Expand Down Expand Up @@ -272,10 +269,10 @@ func tokenCreate(d *schema.ResourceData, meta interface{}) error {
}

if wrapped {
d.Set("wrapped_token", resp.WrapInfo.Token)
d.Set("wrapping_accessor", resp.WrapInfo.Accessor)
d.Set(consts.FieldWrappedToken, resp.WrapInfo.Token)
d.Set(consts.FieldWrappingAccessor, resp.WrapInfo.Accessor)
} else {
d.Set("client_token", resp.Auth.ClientToken)
d.Set(consts.FieldClientToken, resp.Auth.ClientToken)
}

d.SetId(accessor)
Expand All @@ -289,7 +286,7 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
return e
}

id := d.Get("client_token").(string)
id := d.Get(consts.FieldClientToken).(string)
accessor := d.Id()

log.Printf("[DEBUG] Reading token accessor %q", accessor)
Expand All @@ -302,7 +299,7 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {

log.Printf("[DEBUG] Read token accessor %q", accessor)

iPolicies := resp.Data["policies"].([]interface{})
iPolicies := resp.Data[consts.FieldPolicies].([]interface{})
policies := make([]string, 0, len(iPolicies))
for _, iPolicy := range iPolicies {
if iPolicy == "default" {
Expand All @@ -312,11 +309,11 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
policies = append(policies, iPolicy.(string))
}

d.Set("policies", policies)
d.Set("no_parent", resp.Data["orphan"])
d.Set("renewable", resp.Data["renewable"])
d.Set("display_name", strings.TrimPrefix(resp.Data["display_name"].(string), "token-"))
d.Set("num_uses", resp.Data["num_uses"])
d.Set(consts.FieldPolicies, policies)
d.Set(consts.FieldNoParent, resp.Data[consts.FieldOrphan])
d.Set(consts.FieldRenewable, resp.Data[consts.FieldRenewable])
d.Set(consts.FieldDisplayName, strings.TrimPrefix(resp.Data[consts.FieldDisplayName].(string), "token-"))
d.Set(consts.FieldNumUses, resp.Data[consts.FieldNumUses])

issueTimeStr, ok := resp.Data["issue_time"].(string)
if !ok {
Expand All @@ -327,7 +324,7 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
if err != nil {
return fmt.Errorf("error parsing issue_time: %s, please format string like '2006-01-02T15:04:05.999999999Z07:00'", err)
}
d.Set("lease_started", issueTime.Format(time.RFC3339))
d.Set(consts.FieldLeaseStarted, issueTime.Format(time.RFC3339))

expireTimeStr, ok := resp.Data["expire_time"].(string)
if !ok {
Expand All @@ -340,9 +337,9 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set(consts.FieldLeaseDuration, int(expireTime.Sub(issueTime).Seconds()))

d.Set("metadata", resp.Data["meta"])
d.Set(consts.FieldMetadata, resp.Data["meta"])

if d.Get("renewable").(bool) && tokenCheckLease(d) {
if d.Get(consts.FieldRenewable).(bool) && tokenCheckLease(d) {
if id == "" {
log.Printf("[DEBUG] Lease for token access %q cannot be renewed as it's been encrypted.", accessor)
return nil
Expand All @@ -352,7 +349,7 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {

increment := d.Get(consts.FieldLeaseDuration).(int)

if v, ok := d.GetOk("renew_increment"); ok {
if v, ok := d.GetOk(consts.FieldRenewIncrement); ok {
increment = v.(int)
}

Expand All @@ -365,9 +362,9 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {

log.Printf("[DEBUG] Lease for token accessor %q renewed, new lease duration %d", id, renewed.Auth.LeaseDuration)

d.Set(consts.FieldLeaseDuration, renewed.Data["lease_duration"])
d.Set("lease_started", time.Now().Format(time.RFC3339))
d.Set("client_token", renewed.Auth.ClientToken)
d.Set(consts.FieldLeaseDuration, renewed.Data[consts.FieldLeaseDuration])
d.Set(consts.FieldLeaseStarted, time.Now().Format(time.RFC3339))
d.Set(consts.FieldClientToken, renewed.Auth.ClientToken)

d.SetId(renewed.Auth.Accessor)
}
Expand Down Expand Up @@ -417,7 +414,7 @@ func tokenExists(d *schema.ResourceData, meta interface{}) (bool, error) {
func tokenCheckLease(d *schema.ResourceData) bool {
accessor := d.Id()

startedStr := d.Get("lease_started").(string)
startedStr := d.Get(consts.FieldLeaseStarted).(string)
if startedStr == "" {
return false
}
Expand All @@ -440,7 +437,7 @@ func tokenCheckLease(d *schema.ResourceData) bool {
return false
}

if v, ok := d.GetOk("renew_min_lease"); ok {
if v, ok := d.GetOk(consts.FieldRenewMinLease); ok {
renewMinLease := v.(int)
if renewMinLease <= 0 {
return false
Expand Down
Loading

0 comments on commit 482cc19

Please sign in to comment.