diff --git a/weed/iamapi/iamapi_management_handlers.go b/weed/iamapi/iamapi_management_handlers.go index 5449a5d9f..a8babd24e 100644 --- a/weed/iamapi/iamapi_management_handlers.go +++ b/weed/iamapi/iamapi_management_handlers.go @@ -544,6 +544,14 @@ func (iama *IamApiServer) DeletePolicy(s3cfg *iam_pb.S3ApiConfiguration, values } } + // Reject deletion if the policy is attached to any group + if groupName, attached := isPolicyAttachedToAnyGroup(s3cfg, policyName); attached { + return resp, &IamError{ + Code: iam.ErrCodeDeleteConflictException, + Error: fmt.Errorf("policy %s is still attached to group %s", policyName, groupName), + } + } + delete(policies.Policies, policyName) if err := iama.s3ApiConfig.PutPolicies(&policies); err != nil { return resp, &IamError{Code: iam.ErrCodeServiceFailureException, Error: err} diff --git a/weed/s3api/s3api_embedded_iam.go b/weed/s3api/s3api_embedded_iam.go index 8ea95b666..f6ee985e5 100644 --- a/weed/s3api/s3api_embedded_iam.go +++ b/weed/s3api/s3api_embedded_iam.go @@ -510,6 +510,25 @@ func (e *EmbeddedIamApi) DeletePolicy(ctx context.Context, values url.Values) (* } } } + // Check if policy is attached to any group + groupNames, err := e.credentialManager.ListGroups(ctx) + if err != nil { + return resp, &iamError{Code: iam.ErrCodeServiceFailureException, Error: err} + } + for _, gn := range groupNames { + g, err := e.credentialManager.GetGroup(ctx, gn) + if err != nil { + continue + } + for _, pn := range g.PolicyNames { + if pn == policyName { + return resp, &iamError{ + Code: iam.ErrCodeDeleteConflictException, + Error: fmt.Errorf("policy %s is attached to group %s", policyName, gn), + } + } + } + } if err := e.credentialManager.DeletePolicy(ctx, policyName); err != nil { return resp, &iamError{Code: iam.ErrCodeServiceFailureException, Error: err} } @@ -1630,8 +1649,10 @@ func (e *EmbeddedIamApi) ListAttachedGroupPolicies(s3cfg *iam_pb.S3ApiConfigurat if g.Name == groupName { for _, policyName := range g.PolicyNames { pn := policyName + policyArn := fmt.Sprintf("arn:aws:iam:::policy/%s", policyName) resp.ListAttachedGroupPoliciesResult.AttachedPolicies = append(resp.ListAttachedGroupPoliciesResult.AttachedPolicies, &iam.AttachedPolicy{ PolicyName: &pn, + PolicyArn: &policyArn, }) } return resp, nil