From 7de8c4ee70866a34839015bb3bf9f7cc3d0d39c6 Mon Sep 17 00:00:00 2001 From: Shubhendu Date: Thu, 5 Sep 2024 16:25:30 +0530 Subject: [PATCH] Added structs for IAM import response (#302) Signed-off-by: Shubhendu Ram Tripathi --- iam-migrate.go | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/iam-migrate.go b/iam-migrate.go index 2a175e4..1e51e99 100644 --- a/iam-migrate.go +++ b/iam-migrate.go @@ -21,10 +21,88 @@ package madmin import ( "context" + "encoding/json" "io" "net/http" ) +// ImportIAMResult - represents the structure iam import response +type ImportIAMResult struct { + // Skipped entries while import + // This could be due to groups, policies etc missing for + // impoprted entries. We dont fail hard in this case and + // skip those entries + Skipped IAMEntities `json:"skipped,omitempty"` + + // Removed entries - this mostly happens for policies + // where empty might be getting imported and that's invalid + Removed IAMEntities `json:"removed,omitempty"` + + // Newly added entries + Added IAMEntities `json:"added,omitmepty"` + + // Failed entries while import. This would have details of + // failed entities with respective errors + Failed IAMErrEntities `json:"failed,omitmpty"` +} + +// IAMEntities - represents different IAM entities +type IAMEntities struct { + // List of policy names + Policies []string `json:"policies,omitmepty"` + // List of user names + Users []string `json:"users,omitmepty"` + // List of group names + Groups []string `json:"groups,omitempty"` + // List of Service Account names + ServiceAccounts []string `json:"serviceAccounts,omitempty"` + // List of user policies, each entry in map represents list of policies + // applicable to the user + UserPolicies []map[string][]string `json:"userPolicies,omitempty"` + // List of group policies, each entry in map represents list of policies + // applicable to the group + GroupPolicies []map[string][]string `json:"groupPolicies,omitempty"` + // List of STS policies, each entry in map represents list of policies + // applicable to the STS + STSPolicies []map[string][]string `json:"stsPolicies,omitempty"` +} + +// IAMErrEntities - represents errored out IAM entries while import with error +type IAMErrEntities struct { + // List of errored out policies with errors + Policies []IAMErrEntity `json:"policies,omitempty"` + // List of errored out users with errors + Users []IAMErrEntity `json:"users,omitempty"` + // List of errored out groups with errors + Groups []IAMErrEntity `json:"groups,omitempty"` + // List of errored out service accounts with errors + ServiceAccounts []IAMErrEntity `json:"serviceAccounts,omitempty"` + // List of errored out user policies with errors + UserPolicies []IAMErrPolicyEntity `json:"userPolicies,omitempty"` + // List of errored out group policies with errors + GroupPolicies []IAMErrPolicyEntity `json:"groupPolicies,omitempty"` + // List of errored out STS policies with errors + STSPolicies []IAMErrPolicyEntity `json:"stsPolicies,omitempty"` +} + +// IAMErrEntity - represents errored out IAM entity +type IAMErrEntity struct { + // Name of the errored IAM entity + Name string `json:"name,omitempty"` + // Actual error + Error error `json:"error,omitempty"` +} + +// IAMErrPolicyEntity - represents errored out IAM policies +type IAMErrPolicyEntity struct { + // Name of entity (user, group, STS) + Name string `json:"name,omitempty"` + // List of policies + Policies []string `json:"policies,omitempty"` + // Actual error + Error error `json:"error,omitempty"` +} + // ExportIAM makes an admin call to export IAM data func (adm *AdminClient) ExportIAM(ctx context.Context) (io.ReadCloser, error) { path := adminAPIPrefix + "/export-iam" @@ -67,5 +145,41 @@ func (adm *AdminClient) ImportIAM(ctx context.Context, contentReader io.ReadClos if resp.StatusCode != http.StatusOK { return httpRespToErrorResponse(resp) } + return nil } + +// ImportIAMV2 makes an admin call to setup IAM from imported content +func (adm *AdminClient) ImportIAMV2(ctx context.Context, contentReader io.ReadCloser) (iamr ImportIAMResult, err error) { + content, err := io.ReadAll(contentReader) + if err != nil { + return iamr, err + } + + path := adminAPIPrefix + "/import-iam-v2" + resp, err := adm.executeMethod(ctx, + http.MethodPut, requestData{ + relPath: path, + content: content, + }, + ) + defer closeResponse(resp) + if err != nil { + return iamr, err + } + + if resp.StatusCode != http.StatusOK { + return iamr, httpRespToErrorResponse(resp) + } + + b, err := io.ReadAll(resp.Body) + if err != nil { + return iamr, err + } + + if err = json.Unmarshal(b, &iamr); err != nil { + return iamr, err + } + + return iamr, nil +}