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

add multiple group/user policies support #492

Merged
merged 1 commit into from
Jul 27, 2023
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
47 changes: 37 additions & 10 deletions minio/resource_minio_iam_group_policy_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/minio/madmin-go"
)

func resourceMinioIAMGroupPolicyAttachment() *schema.Resource {
Expand Down Expand Up @@ -43,10 +44,17 @@ func minioCreateGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat
var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

log.Printf("[DEBUG] Attaching policy %s to group: %s", policyName, groupName)
err := minioAdmin.SetPolicy(ctx, policyName, groupName, true)
policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return NewResourceError("unable to attach group policy", groupName+" "+policyName, err)
return err
}
if !Contains(policies, policyName) {
log.Printf("[DEBUG] Attaching policy %s to group: %s", policyName, groupName)
policies = append(policies, policyName)
err := minioAdmin.SetPolicy(ctx, strings.Join(policies, ","), groupName, true)
if err != nil {
return NewResourceError("unable to attach group policy", groupName+" "+policyName, err)
}
}

d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", groupName)))
Expand All @@ -58,19 +66,19 @@ func minioReadGroupPolicyAttachment(ctx context.Context, d *schema.ResourceData,
minioAdmin := meta.(*S3MinioClient).S3Admin

var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

groupInfo, errGroup := minioAdmin.GetGroupDescription(ctx, groupName)
if errGroup != nil {
return NewResourceError("failed to load group infos", groupName, errGroup)
policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return err
}

if groupInfo.Policy == "" {
if !Contains(policies, policyName) {
log.Printf("[WARN] No such policy by name (%s) found, removing from state", d.Id())
d.SetId("")
return nil
}

if err := d.Set("policy_name", string(groupInfo.Policy)); err != nil {
if err := d.Set("policy_name", policyName); err != nil {
return NewResourceError("failed to load group infos", groupName, err)
}

Expand All @@ -81,8 +89,19 @@ func minioDeleteGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat
minioAdmin := meta.(*S3MinioClient).S3Admin

var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return err
}

errIam := minioAdmin.SetPolicy(ctx, "", groupName, true)
newPolicies, found := Filter(policies, policyName)
if !found {
return nil
}

errIam := minioAdmin.SetPolicy(ctx, strings.Join(newPolicies, ","), groupName, true)
if errIam != nil {
return NewResourceError("unable to delete user policy", groupName, errIam)
}
Expand Down Expand Up @@ -110,3 +129,11 @@ func minioImportGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat
d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", groupName)))
return []*schema.ResourceData{d}, nil
}

func minioReadGroupPolicies(ctx context.Context, minioAdmin *madmin.AdminClient, groupName string) ([]string, diag.Diagnostics) {
groupInfo, errGroup := minioAdmin.GetGroupDescription(ctx, groupName)
if errGroup != nil {
return nil, NewResourceError("failed to load group infos", groupName, errGroup)
}
return strings.Split(groupInfo.Policy, ","), nil
}
62 changes: 46 additions & 16 deletions minio/resource_minio_iam_user_policy_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,17 @@ func minioCreateUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
var userName = d.Get("user_name").(string)
var policyName = d.Get("policy_name").(string)
minioAdmin := meta.(*S3MinioClient).S3Admin
err := minioAdmin.SetPolicy(ctx, policyName, userName, false)

policies, err := minioReadUserPolicies(ctx, minioAdmin, userName)
if err != nil {
return NewResourceError("unable to Set User policy", userName+" "+policyName, err)
return err
}
if !Contains(policies, policyName) {
policies = append(policies, policyName)
err := minioAdmin.SetPolicy(ctx, strings.Join(policies, ","), userName, false)
if err != nil {
return NewResourceError("unable to Set User policy", userName+" "+policyName, err)
}
}

d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", userName)))
Expand All @@ -56,28 +64,20 @@ func minioCreateUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
func minioReadUserPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin
var userName = d.Get("user_name").(string)
var isLDAPUser = LDAPUserDistinguishedNamePattern.MatchString(userName)

log.Printf("[DEBUG] UserPolicyAttachment: is user '%s' an LDAP user? %t", userName, isLDAPUser)
var policyName = d.Get("policy_name").(string)

userInfo, errUser := minioAdmin.GetUserInfo(ctx, userName)
policies, errUser := minioReadUserPolicies(ctx, minioAdmin, userName)
if errUser != nil {
errUserResponse, errUserIsResponse := errUser.(madmin.ErrorResponse)

log.Printf("[DEBUG] UserPolicyAttachment: got an error, errUserIsResponse=%t, errUserResponse.Code=%s", errUserIsResponse, errUserResponse.Code)

if !isLDAPUser || !errUserIsResponse || !strings.EqualFold(errUserResponse.Code, "XMinioAdminNoSuchUser") {
return NewResourceError("failed to load user Infos", userName, errUser)
}
return errUser
}

if userInfo.PolicyName == "" {
if !Contains(policies, policyName) {
log.Printf("[WARN] No such policy by name (%s) found, removing from state", d.Id())
d.SetId("")
return nil
}

if err := d.Set("policy_name", string(userInfo.PolicyName)); err != nil {
if err := d.Set("policy_name", policyName); err != nil {
return diag.FromErr(err)
}

Expand All @@ -86,9 +86,21 @@ func minioReadUserPolicyAttachment(ctx context.Context, d *schema.ResourceData,

func minioDeleteUserPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin

var userName = d.Get("user_name").(string)
var policyName = d.Get("policy_name").(string)

policies, err := minioReadUserPolicies(ctx, minioAdmin, userName)
if err != nil {
return err
}

errIam := minioAdmin.SetPolicy(ctx, "", userName, false)
newPolicies, found := Filter(policies, policyName)
if !found {
return nil
}

errIam := minioAdmin.SetPolicy(ctx, strings.Join(newPolicies, ","), userName, false)
if errIam != nil {
return NewResourceError("unable to delete user policy", userName, errIam)
}
Expand Down Expand Up @@ -116,3 +128,21 @@ func minioImportUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", userName)))
return []*schema.ResourceData{d}, nil
}

func minioReadUserPolicies(ctx context.Context, minioAdmin *madmin.AdminClient, userName string) ([]string, diag.Diagnostics) {
var isLDAPUser = LDAPUserDistinguishedNamePattern.MatchString(userName)

log.Printf("[DEBUG] UserPolicyAttachment: is user '%s' an LDAP user? %t", userName, isLDAPUser)

userInfo, errUser := minioAdmin.GetUserInfo(ctx, userName)
if errUser != nil {
errUserResponse, errUserIsResponse := errUser.(madmin.ErrorResponse)

log.Printf("[DEBUG] UserPolicyAttachment: got an error, errUserIsResponse=%t, errUserResponse.Code=%s", errUserIsResponse, errUserResponse.Code)

if !isLDAPUser || !errUserIsResponse || !strings.EqualFold(errUserResponse.Code, "XMinioAdminNoSuchUser") {
return nil, NewResourceError("failed to load user Infos", userName, errUser)
}
}
return strings.Split(userInfo.PolicyName, ","), nil
}
10 changes: 10 additions & 0 deletions minio/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ func Contains(slice []string, item string) bool {
return ok
}

func Filter(slice []string, item string) ([]string, bool) {
var out []string
for _, s := range slice {
if s != item {
out = append(out, s)
}
}
return out, len(out) != len(slice)
}

// HashcodeString hashes a string to a unique hashcode.
//
// crc32 returns a `uint32`, but for our use we need
Expand Down