Files
seaweedfs/weed/iam/responses.go
T
Chris Lu f8973b3ed6 feat(iam): OIDC provider mutations + multi-client + TLS thumbprints (Phase 2b) (#9320)
* feat(iam): OIDC provider mutations + multi-client + TLS thumbprints

- Mutating IAM actions: CreateOpenIDConnectProvider,
  DeleteOpenIDConnectProvider, AddClientIDToOpenIDConnectProvider,
  RemoveClientIDFromOpenIDConnectProvider,
  UpdateOpenIDConnectProviderThumbprint, TagOpenIDConnectProvider,
  UntagOpenIDConnectProvider. Each enforces AWS-shape input bounds and
  the read-only mode rejects all mutations.
- Multiple client_ids per provider in OIDCConfig (clientIds list, plural)
  with full backward compatibility — singular clientId still works and is
  merged into the audience allowlist. Provider factory accepts both.
- AWS-compatible TLS thumbprint pinning: when OIDCConfig.Thumbprints is
  non-empty, JWKS fetches enforce that the negotiated TLS chain contains
  a certificate whose SHA-1 hex matches the allowlist. Empty list keeps
  the existing system-trust path.

* fix(iam): factor Tags.member.N parser into a helper

CreateOpenIDConnectProvider and TagOpenIDConnectProvider were both
walking the AWS Tags.member.N.Key / Tags.member.N.Value query-string
convention with copy-pasted loops. Factor into extractTags so the
parsing rules and the "no tags present" semantics live in one place.

Addresses gemini medium review on PR #9320.

* fix(iam): sentinel errors for OIDC provider not-found / already-exists

The s3api dispatcher was using strings.Contains(err.Error(), "not found")
and "already exists" to map IAM-manager errors back to AWS error codes.
Substring matching on a formatted message couples the API error code
to the exact wording of the upstream message — touching the message
silently changes the IAM API contract.

Define ErrOIDCProviderNotFound and ErrOIDCProviderAlreadyExists in the
integration package, fmt.Errorf("%w: ...") them at the four return
sites in iam_manager.go and oidc_provider_store.go, and use errors.Is
at the s3api call sites. Same control flow, no string-match fragility.

Addresses gemini medium review on PR #9320.

* fix(iam): surface non-NotFound errors from CreateOIDCProvider lookup

Previously CreateOIDCProvider only treated GetProviderByARN's success path
as "exists" and silently fell through on any error, including transient
backend failures. That hid real problems and still attempted a write.
Distinguish ErrOIDCProviderNotFound (the only "safe to create" case) from
other errors so we don't mask filer outages or partition issues.

* fix(iam): enforce 100-client-ID cap on AddClientIDToOIDCProvider

CreateOIDCProvider and the implicit update path through validateOIDC-
ProviderRecord both reject lists with more than 100 client IDs, but
AddClientIDToOIDCProvider could grow the list past that bound one
ID at a time. Refuse the add when the list is already at the cap so
the invariant holds across every mutation entry point.

* feat(iam): IAM-managed OIDC provider live view in STS service

Add a separate, mutex-guarded map of admin-managed OIDC providers on
the STS service. The map can be atomically replaced via
SetIAMManagedOIDCProvidersByIssuer; AssumeRoleWithWebIdentity lookups
consult it first and fall back to the existing static-config map, so
records persisted through the IAM API can shadow bootstrap entries
without a restart.

This is the runtime hook the IAM API and the metadata-subscribe path
will both call when the OIDCProviderStore changes (next two commits).

* feat(iam): refresh STS service runtime view after OIDC mutations

Add IAMManager.RefreshOIDCProvidersFromStore: lists every persisted
OIDCProviderRecord, builds a runtime OIDCProvider for each, and atomically
publishes the issuer-keyed map into the STS service. Each mutating IAM API
call (Create / Delete / AddClientID / RemoveClientID / UpdateThumbprints)
now triggers this refresh inline so the local instance picks up the change
without waiting for a metadata-subscribe round trip. Tag mutations skip
the refresh because tags do not affect token validation.

Refresh failures only log; the persisted write has already succeeded by
that point, so a transient list error must not surface to the API caller.
The peer-instance update path (filer metadata subscription) is added in a
follow-up commit.

* feat(iam): subscribe to OIDC provider changes on the filer

Watch /etc/iam/oidc-providers under the existing s3 metadata-subscribe
loop and call RefreshOIDCProvidersFromStore on any create / update /
delete / rename. This is the cross-instance update path: S3 server A
writes via the IAM API, the filer fans out the metadata change, and S3
servers B..N pick up the new runtime view without a restart.

Mirrors the existing onIamConfigChange / onCircuitBreakerConfigChange
pattern. The handler short-circuits when the path is unrelated, and
when no IAMManager is wired in (static-only configurations).
2026-05-05 11:26:08 -07:00

497 lines
19 KiB
Go

package iam
import (
"encoding/xml"
"github.com/aws/aws-sdk-go/service/iam"
)
// CommonResponse is embedded in IAM success response types to provide RequestId.
type CommonResponse struct {
ResponseMetadata struct {
RequestId string `xml:"RequestId"`
} `xml:"ResponseMetadata"`
}
// IAMTag mirrors AWS IAM's Tag list element with the Key/Value pair shape.
type IAMTag struct {
Key string `xml:"Key"`
Value string `xml:"Value"`
}
// OpenIDConnectProviderListEntry is one element of ListOpenIDConnectProviders.
type OpenIDConnectProviderListEntry struct {
Arn string `xml:"Arn"`
}
// ListOpenIDConnectProvidersResponse is the response for ListOpenIDConnectProviders.
type ListOpenIDConnectProvidersResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListOpenIDConnectProvidersResponse"`
ListOpenIDConnectProvidersResult struct {
OpenIDConnectProviderList []*OpenIDConnectProviderListEntry `xml:"OpenIDConnectProviderList>member"`
} `xml:"ListOpenIDConnectProvidersResult"`
CommonResponse
}
// GetOpenIDConnectProviderResponse is the response for GetOpenIDConnectProvider.
type GetOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetOpenIDConnectProviderResponse"`
GetOpenIDConnectProviderResult struct {
Url string `xml:"Url"`
ClientIDList []string `xml:"ClientIDList>member,omitempty"`
ThumbprintList []string `xml:"ThumbprintList>member,omitempty"`
Tags []*IAMTag `xml:"Tags>member,omitempty"`
CreateDate string `xml:"CreateDate,omitempty"`
} `xml:"GetOpenIDConnectProviderResult"`
CommonResponse
}
// CreateOpenIDConnectProviderResponse is the response for CreateOpenIDConnectProvider.
type CreateOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateOpenIDConnectProviderResponse"`
CreateOpenIDConnectProviderResult struct {
OpenIDConnectProviderArn string `xml:"OpenIDConnectProviderArn"`
Tags []*IAMTag `xml:"Tags>member,omitempty"`
} `xml:"CreateOpenIDConnectProviderResult"`
CommonResponse
}
// DeleteOpenIDConnectProviderResponse is the response for DeleteOpenIDConnectProvider.
type DeleteOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteOpenIDConnectProviderResponse"`
CommonResponse
}
// AddClientIDToOpenIDConnectProviderResponse is the response for AddClientIDToOpenIDConnectProvider.
type AddClientIDToOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ AddClientIDToOpenIDConnectProviderResponse"`
CommonResponse
}
// RemoveClientIDFromOpenIDConnectProviderResponse is the response for RemoveClientIDFromOpenIDConnectProvider.
type RemoveClientIDFromOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ RemoveClientIDFromOpenIDConnectProviderResponse"`
CommonResponse
}
// UpdateOpenIDConnectProviderThumbprintResponse is the response for UpdateOpenIDConnectProviderThumbprint.
type UpdateOpenIDConnectProviderThumbprintResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UpdateOpenIDConnectProviderThumbprintResponse"`
CommonResponse
}
// TagOpenIDConnectProviderResponse is the response for TagOpenIDConnectProvider.
type TagOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ TagOpenIDConnectProviderResponse"`
CommonResponse
}
// UntagOpenIDConnectProviderResponse is the response for UntagOpenIDConnectProvider.
type UntagOpenIDConnectProviderResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UntagOpenIDConnectProviderResponse"`
CommonResponse
}
// SetRequestId stores the request ID generated for the current HTTP request.
func (r *CommonResponse) SetRequestId(requestID string) {
r.ResponseMetadata.RequestId = requestID
}
// RequestIDSetter is implemented by IAM responses that can carry a RequestId.
type RequestIDSetter interface {
SetRequestId(string)
}
// ListUsersResponse is the response for ListUsers action.
type ListUsersResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUsersResponse"`
ListUsersResult struct {
Users []*iam.User `xml:"Users>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListUsersResult"`
CommonResponse
}
// ListAccessKeysResponse is the response for ListAccessKeys action.
type ListAccessKeysResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListAccessKeysResponse"`
ListAccessKeysResult struct {
AccessKeyMetadata []*iam.AccessKeyMetadata `xml:"AccessKeyMetadata>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListAccessKeysResult"`
CommonResponse
}
// DeleteAccessKeyResponse is the response for DeleteAccessKey action.
type DeleteAccessKeyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteAccessKeyResponse"`
CommonResponse
}
// CreatePolicyResponse is the response for CreatePolicy action.
type CreatePolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreatePolicyResponse"`
CreatePolicyResult struct {
Policy iam.Policy `xml:"Policy"`
} `xml:"CreatePolicyResult"`
CommonResponse
}
// DeletePolicyResponse is the response for DeletePolicy action.
type DeletePolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeletePolicyResponse"`
CommonResponse
}
// ListPoliciesResponse is the response for ListPolicies action.
type ListPoliciesResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListPoliciesResponse"`
ListPoliciesResult struct {
Policies []*iam.Policy `xml:"Policies>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListPoliciesResult"`
CommonResponse
}
// GetPolicyResponse is the response for GetPolicy action.
type GetPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetPolicyResponse"`
GetPolicyResult struct {
Policy iam.Policy `xml:"Policy"`
} `xml:"GetPolicyResult"`
CommonResponse
}
// ListPolicyVersionsResponse is the response for ListPolicyVersions action.
type ListPolicyVersionsResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListPolicyVersionsResponse"`
ListPolicyVersionsResult struct {
Versions []*iam.PolicyVersion `xml:"Versions>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListPolicyVersionsResult"`
CommonResponse
}
// GetPolicyVersionResponse is the response for GetPolicyVersion action.
type GetPolicyVersionResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetPolicyVersionResponse"`
GetPolicyVersionResult struct {
PolicyVersion iam.PolicyVersion `xml:"PolicyVersion"`
} `xml:"GetPolicyVersionResult"`
CommonResponse
}
// CreateUserResponse is the response for CreateUser action.
type CreateUserResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateUserResponse"`
CreateUserResult struct {
User iam.User `xml:"User"`
} `xml:"CreateUserResult"`
CommonResponse
}
// DeleteUserResponse is the response for DeleteUser action.
type DeleteUserResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteUserResponse"`
CommonResponse
}
// GetUserResponse is the response for GetUser action.
type GetUserResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetUserResponse"`
GetUserResult struct {
User iam.User `xml:"User"`
} `xml:"GetUserResult"`
CommonResponse
}
// UpdateUserResponse is the response for UpdateUser action.
type UpdateUserResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UpdateUserResponse"`
CommonResponse
}
// CreateAccessKeyResponse is the response for CreateAccessKey action.
type CreateAccessKeyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateAccessKeyResponse"`
CreateAccessKeyResult struct {
AccessKey iam.AccessKey `xml:"AccessKey"`
} `xml:"CreateAccessKeyResult"`
CommonResponse
}
// PutUserPolicyResponse is the response for PutUserPolicy action.
type PutUserPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ PutUserPolicyResponse"`
CommonResponse
}
// DeleteUserPolicyResponse is the response for DeleteUserPolicy action.
type DeleteUserPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteUserPolicyResponse"`
CommonResponse
}
// AttachUserPolicyResponse is the response for AttachUserPolicy action.
type AttachUserPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ AttachUserPolicyResponse"`
CommonResponse
}
// DetachUserPolicyResponse is the response for DetachUserPolicy action.
type DetachUserPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DetachUserPolicyResponse"`
CommonResponse
}
// ListAttachedUserPoliciesResponse is the response for ListAttachedUserPolicies action.
type ListAttachedUserPoliciesResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListAttachedUserPoliciesResponse"`
ListAttachedUserPoliciesResult struct {
AttachedPolicies []*iam.AttachedPolicy `xml:"AttachedPolicies>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListAttachedUserPoliciesResult"`
CommonResponse
}
// ListUserPoliciesResponse is the response for ListUserPolicies action.
type ListUserPoliciesResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUserPoliciesResponse"`
ListUserPoliciesResult struct {
PolicyNames []string `xml:"PolicyNames>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListUserPoliciesResult"`
CommonResponse
}
// GetUserPolicyResponse is the response for GetUserPolicy action.
type GetUserPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetUserPolicyResponse"`
GetUserPolicyResult struct {
UserName string `xml:"UserName"`
PolicyName string `xml:"PolicyName"`
PolicyDocument string `xml:"PolicyDocument"`
} `xml:"GetUserPolicyResult"`
CommonResponse
}
// ErrorResponse is the IAM error response format.
// AWS IAM uses a bare <RequestId> at root level for errors, not <ResponseMetadata>.
type ErrorResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ErrorResponse"`
Error struct {
iam.ErrorDetails
Type string `xml:"Type"`
} `xml:"Error"`
RequestId string `xml:"RequestId"`
}
// SetRequestId stores the request ID generated for the current HTTP request.
func (r *ErrorResponse) SetRequestId(requestID string) {
r.RequestId = requestID
}
// Error represents an IAM API error with code and underlying error.
type Error struct {
Code string
Error error
}
// Policies stores IAM policies (used for managed policy storage).
type Policies struct {
Policies map[string]interface{} `json:"policies"`
}
// SetUserStatusResponse is the response for SetUserStatus action.
// This is a SeaweedFS extension to enable/disable users without deleting them.
type SetUserStatusResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ SetUserStatusResponse"`
CommonResponse
}
// UpdateAccessKeyResponse is the response for UpdateAccessKey action.
type UpdateAccessKeyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UpdateAccessKeyResponse"`
CommonResponse
}
// ServiceAccountInfo contains service account details for API responses.
type ServiceAccountInfo struct {
ServiceAccountId string `xml:"ServiceAccountId"`
ParentUser string `xml:"ParentUser"`
Description string `xml:"Description,omitempty"`
AccessKeyId string `xml:"AccessKeyId"`
SecretAccessKey *string `xml:"SecretAccessKey,omitempty"` // Only returned in Create response
Status string `xml:"Status"`
Expiration *string `xml:"Expiration,omitempty"` // ISO 8601 format, nil = no expiration
CreateDate string `xml:"CreateDate"`
}
// CreateServiceAccountResponse is the response for CreateServiceAccount action.
type CreateServiceAccountResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateServiceAccountResponse"`
CreateServiceAccountResult struct {
ServiceAccount ServiceAccountInfo `xml:"ServiceAccount"`
} `xml:"CreateServiceAccountResult"`
CommonResponse
}
// DeleteServiceAccountResponse is the response for DeleteServiceAccount action.
type DeleteServiceAccountResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteServiceAccountResponse"`
CommonResponse
}
// ListServiceAccountsResponse is the response for ListServiceAccounts action.
type ListServiceAccountsResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListServiceAccountsResponse"`
ListServiceAccountsResult struct {
ServiceAccounts []*ServiceAccountInfo `xml:"ServiceAccounts>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListServiceAccountsResult"`
CommonResponse
}
// GetServiceAccountResponse is the response for GetServiceAccount action.
type GetServiceAccountResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetServiceAccountResponse"`
GetServiceAccountResult struct {
ServiceAccount ServiceAccountInfo `xml:"ServiceAccount"`
} `xml:"GetServiceAccountResult"`
CommonResponse
}
// UpdateServiceAccountResponse is the response for UpdateServiceAccount action.
type UpdateServiceAccountResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UpdateServiceAccountResponse"`
CommonResponse
}
// CreateGroupResponse is the response for CreateGroup action.
type CreateGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateGroupResponse"`
CreateGroupResult struct {
Group iam.Group `xml:"Group"`
} `xml:"CreateGroupResult"`
CommonResponse
}
// DeleteGroupResponse is the response for DeleteGroup action.
type DeleteGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteGroupResponse"`
CommonResponse
}
// UpdateGroupResponse is the response for UpdateGroup action.
type UpdateGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ UpdateGroupResponse"`
CommonResponse
}
// GetGroupResponse is the response for GetGroup action.
type GetGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetGroupResponse"`
GetGroupResult struct {
Group iam.Group `xml:"Group"`
Users []*iam.User `xml:"Users>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"GetGroupResult"`
CommonResponse
}
// ListGroupsResponse is the response for ListGroups action.
type ListGroupsResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListGroupsResponse"`
ListGroupsResult struct {
Groups []*iam.Group `xml:"Groups>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListGroupsResult"`
CommonResponse
}
// AddUserToGroupResponse is the response for AddUserToGroup action.
type AddUserToGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ AddUserToGroupResponse"`
CommonResponse
}
// RemoveUserFromGroupResponse is the response for RemoveUserFromGroup action.
type RemoveUserFromGroupResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ RemoveUserFromGroupResponse"`
CommonResponse
}
// AttachGroupPolicyResponse is the response for AttachGroupPolicy action.
type AttachGroupPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ AttachGroupPolicyResponse"`
CommonResponse
}
// DetachGroupPolicyResponse is the response for DetachGroupPolicy action.
type DetachGroupPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DetachGroupPolicyResponse"`
CommonResponse
}
// ListAttachedGroupPoliciesResponse is the response for ListAttachedGroupPolicies action.
type ListAttachedGroupPoliciesResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListAttachedGroupPoliciesResponse"`
ListAttachedGroupPoliciesResult struct {
AttachedPolicies []*iam.AttachedPolicy `xml:"AttachedPolicies>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListAttachedGroupPoliciesResult"`
CommonResponse
}
// PutGroupPolicyResponse is the response for PutGroupPolicy action.
type PutGroupPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ PutGroupPolicyResponse"`
CommonResponse
}
// GetGroupPolicyResponse is the response for GetGroupPolicy action.
type GetGroupPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetGroupPolicyResponse"`
GetGroupPolicyResult struct {
GroupName string `xml:"GroupName"`
PolicyName string `xml:"PolicyName"`
PolicyDocument string `xml:"PolicyDocument"`
} `xml:"GetGroupPolicyResult"`
CommonResponse
}
// DeleteGroupPolicyResponse is the response for DeleteGroupPolicy action.
type DeleteGroupPolicyResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteGroupPolicyResponse"`
CommonResponse
}
// ListGroupPoliciesResponse is the response for ListGroupPolicies action.
type ListGroupPoliciesResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListGroupPoliciesResponse"`
ListGroupPoliciesResult struct {
PolicyNames []string `xml:"PolicyNames>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListGroupPoliciesResult"`
CommonResponse
}
// ListGroupsForUserResponse is the response for ListGroupsForUser action.
type ListGroupsForUserResponse struct {
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListGroupsForUserResponse"`
ListGroupsForUserResult struct {
Groups []*iam.Group `xml:"Groups>member"`
IsTruncated bool `xml:"IsTruncated"`
Marker string `xml:"Marker,omitempty"`
} `xml:"ListGroupsForUserResult"`
CommonResponse
}