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 Non-Exclusive Behaviour of identity_group_policies #495

Merged
merged 2 commits into from
Aug 9, 2019
Merged
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
34 changes: 20 additions & 14 deletions vault/resource_identity_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,23 +249,29 @@ func identityGroupIDPath(id string) string {
return fmt.Sprintf("%s/id/%s", identityGroupPath, id)
}

func readIdentityGroupPolicies(client *api.Client, groupId string) ([]interface{}, error) {
var presentPolicies []interface{}
if resp, err := readIdentityGroup(client, groupId); err != nil {
return nil, fmt.Errorf("error reading IdentityGroup policies %q: %s", groupId, err)
} else {
presentPolicies = resp.Data["policies"].([]interface{})
func readIdentityGroupPolicies(client *api.Client, groupID string) ([]interface{}, error) {
resp, err := readIdentityGroup(client, groupID)
if err != nil {
return nil, err
}
if resp == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice catch here that the response can be nil.

return nil, fmt.Errorf("error IdentityGroup %s does not exist", groupID)
}
return presentPolicies, nil

if v, ok := resp.Data["policies"]; ok && v != nil {
return v.([]interface{}), nil
}
return make([]interface{}, 0), nil
}

func readIdentityGroup(client *api.Client, groupId string) (*api.Secret, error) {
path := identityGroupIDPath(groupId)
log.Printf("[DEBUG] Reading IdentityGroup %s from %q", groupId, path)
// This function may return `nil` for the IdentityGroup if it does not exist
func readIdentityGroup(client *api.Client, groupID string) (*api.Secret, error) {
tyrannosaurus-becks marked this conversation as resolved.
Show resolved Hide resolved
path := identityGroupIDPath(groupID)
log.Printf("[DEBUG] Reading IdentityGroup %s from %q", groupID, path)

if resp, err := client.Logical().Read(path); err != nil {
return resp, fmt.Errorf("failed reading IdentityGroup %s from %s", groupId, path)
} else {
return resp, nil
resp, err := client.Logical().Read(path)
if err != nil {
return resp, fmt.Errorf("failed reading IdentityGroup %s from %s", groupID, path)
}
return resp, nil
}
150 changes: 57 additions & 93 deletions vault/resource_identity_group_policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ import (

func identityGroupPoliciesResource() *schema.Resource {
return &schema.Resource{
Create: identityGroupPoliciesCreate,
Create: identityGroupPoliciesUpdate,
Update: identityGroupPoliciesUpdate,
Read: identityGroupPoliciesRead,
Delete: identityGroupPoliciesDelete,
Exists: identityGroupPoliciesExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"policies": {
Expand Down Expand Up @@ -51,74 +47,41 @@ func identityGroupPoliciesResource() *schema.Resource {
},
}
}
func identityGroupPoliciesUpdateFields(d *schema.ResourceData, data map[string]interface{}, presentPolicies []interface{}) error {
o, n := d.GetChange("policies")
if d.Get("exclusive").(bool) {
data["policies"] = n.(*schema.Set).List()
} else {
data["policies"] = identityGroupPoliciesDetermineNew(presentPolicies, o.(*schema.Set).List(), n.(*schema.Set).List())
}
return nil
}

func identityGroupPoliciesCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)

groupId := d.Get("group_id").(string)

path := identityGroupPath

vaultMutexKV.Lock(path)
defer vaultMutexKV.Unlock(path)

data := map[string]interface{}{
"id": groupId,
}

if err := identityGroupPoliciesUpdateFields(d, data, []interface{}{}); err != nil {
return fmt.Errorf("error writing IdentityGroupPolicies to %q: %s", groupId, err)
}

_, err := client.Logical().Write(path, data)

if err != nil {
return fmt.Errorf("error writing IdentityGroupPolicies to %q: %s", groupId, err)
}
log.Printf("[DEBUG] Wrote IdentityGroupPolicies %q", groupId)

d.SetId(d.Get("group_id").(string))

return identityGroupPoliciesRead(d, meta)
}

func identityGroupPoliciesUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
id := d.Id()
id := d.Get("group_id").(string)

log.Printf("[DEBUG] Updating IdentityGroupPolicies %q", id)
path := identityGroupIDPath(id)

vaultMutexKV.Lock(path)
defer vaultMutexKV.Unlock(path)

presentPolicies, err := readIdentityGroupPolicies(client, id)
if err != nil {
return fmt.Errorf("error updating IdentityGroupPolicies %q - %s: %s", id, d.Get("policies"), err)
}

data := map[string]interface{}{}
data := make(map[string]interface{})
policies := d.Get("policies").(*schema.Set).List()

if err := identityGroupPoliciesUpdateFields(d, data, presentPolicies); err != nil {
return fmt.Errorf("error updating IdentityGroupPolicies %q: %s", id, err)
if d.Get("exclusive").(bool) {
data["policies"] = policies
} else {
apiPolicies, err := readIdentityGroupPolicies(client, id)
if err != nil {
return err
}
for _, policy := range policies {
apiPolicies = util.SliceAppendIfMissing(apiPolicies, policy)
}
data["policies"] = apiPolicies
}

_, err = client.Logical().Write(path, data)

_, err := client.Logical().Write(path, data)
if err != nil {
return fmt.Errorf("error updating IdentityGroupPolicies %q: %s", id, err)
}
log.Printf("[DEBUG] Updated IdentityGroupPolicies %q", id)

d.SetId(id)

return identityGroupPoliciesRead(d, meta)
}

Expand All @@ -128,11 +91,7 @@ func identityGroupPoliciesRead(d *schema.ResourceData, meta interface{}) error {

resp, err := readIdentityGroup(client, id)
if err != nil {
// We need to check if the secret_id has expired
if util.IsExpiredTokenErr(err) {
tyrannosaurus-becks marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
return fmt.Errorf("error reading IdentityGroupPolicies %q: %s", id, err)
return err
}
log.Printf("[DEBUG] Read IdentityGroupPolicies %s", id)
if resp == nil {
Expand All @@ -141,51 +100,56 @@ func identityGroupPoliciesRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

for responseKey, stateKey := range map[string]string{
"policies": "policies",
"id": "group_id",
"name": "group_name",
} {
if err := d.Set(stateKey, resp.Data[responseKey]); err != nil {
return fmt.Errorf("error setting state key \"%s\" on IdentityGroupPolicies %q: %s", stateKey, id, err)
d.Set("group_id", id)
d.Set("group_name", resp.Data["name"])

if d.Get("exclusive").(bool) {
d.Set("policies", resp.Data["policies"])
} else {
userPolicies := d.Get("policies").(*schema.Set).List()
newPolicies := make([]string, 0)
apiPolicies := resp.Data["policies"].([]interface{})

for _, policy := range userPolicies {
if found, _ := util.SliceHasElement(apiPolicies, policy); found {
newPolicies = append(newPolicies, policy.(string))
}
}
d.Set("policies", newPolicies)
}
return nil
}

func identityGroupPoliciesDelete(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("policies", []string{}); err != nil {
return fmt.Errorf("failed setting policy to empty set: %s", err)
}
return identityGroupPoliciesUpdate(d, meta)
}

func identityGroupPoliciesExists(d *schema.ResourceData, meta interface{}) (bool, error) {
client := meta.(*api.Client)
id := d.Id()
id := d.Get("group_id").(string)

resp, err := readIdentityGroup(client, id)
if err != nil {
return true, fmt.Errorf("error checking if IdentityGroupPolicies %q exists: %s", id, err)
}
log.Printf("[DEBUG] Checked if IdentityGroupPolicies %q exists", id)
log.Printf("[DEBUG] Deleting IdentityGroupPolicies %q", id)
path := identityGroupIDPath(id)

return resp != nil, nil
}
vaultMutexKV.Lock(path)
defer vaultMutexKV.Unlock(path)

func identityGroupPoliciesDetermineNew(presentPolicies, oldStatePolicies, newStatePolicies []interface{}) []string {
policies := schema.NewSet(schema.HashString, presentPolicies)
data := make(map[string]interface{})

for _, policy := range oldStatePolicies {
policies.Remove(policy)
}
for _, policy := range newStatePolicies {
policies.Add(policy)
if d.Get("exclusive").(bool) {
data["policies"] = make([]string, 0)
} else {
apiPolicies, err := readIdentityGroupPolicies(client, id)
if err != nil {
return err
}
for _, policy := range d.Get("policies").(*schema.Set).List() {
apiPolicies = util.SliceRemoveIfPresent(apiPolicies, policy)
}
data["policies"] = apiPolicies
}

var ret []string
for _, policy := range policies.List() {
ret = append(ret, policy.(string))
_, err := client.Logical().Write(path, data)
if err != nil {
return fmt.Errorf("error updating IdentityGroupPolicies %q: %s", id, err)
}
return ret
log.Printf("[DEBUG] Updated IdentityGroupPolicies %q", id)

return nil
}
Loading