Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
249 changes: 249 additions & 0 deletions service/federations/saml/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"net/http"
"net/url"

Expand Down Expand Up @@ -82,6 +83,34 @@ func (s *Service) Get(ctx context.Context, federationID string) (*GetResponse, e
return &federation, nil
}

// Exists checks that Federation with federationID exists.
func (s *Service) Exists(ctx context.Context, federationID string) (bool, error) {
if federationID == "" {
return false, iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}

path, err := url.JoinPath(apiVersion, "federations", "saml", federationID)
if err != nil {
return false, iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

_, err = s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: nil,
Method: http.MethodHead,
Path: path,
})
if err != nil {
if errors.Is(err, iamerrors.ErrFederationNotFound) {
return false, nil
}

//nolint:wrapcheck // DoRequest already wraps the error.
return false, err
}

return true, nil
}

// Create creates a new Federation.
func (s *Service) Create(ctx context.Context, input CreateRequest) (*CreateResponse, error) {
if input.Name == "" {
Expand Down Expand Up @@ -189,3 +218,223 @@ func (s *Service) Delete(ctx context.Context, federationID string) error {

return nil
}

func (s *Service) getFederationResource(
ctx context.Context, federationID string, segments []string, output interface{},
) error {
if federationID == "" {
return iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}

pathSegments := append([]string{apiVersion, "federations", "saml", federationID}, segments...)

path, err := url.JoinPath(pathSegments[0], pathSegments[1:]...)
if err != nil {
return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

response, err := s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: nil,
Method: http.MethodGet,
Path: path,
})
if err != nil {
//nolint:wrapcheck // DoRequest already wraps the error.
return err
}

err = client.UnmarshalJSON(response, output)
if err != nil {
return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

return nil
}

// Preview returns preview information of Federation using federationID or alias.
func (s *Service) Preview(ctx context.Context, federationID string) (*FederationPreview, error) {
var preview FederationPreview
err := s.getFederationResource(ctx, federationID, []string{"preview"}, &preview)
if err != nil {
return nil, err
}

return &preview, nil
}

// GetGroupMappings returns a list of mappings for the Federation.
func (s *Service) GetGroupMappings(ctx context.Context, federationID string) (*GroupMappingsResponse, error) {
var mappings GroupMappingsResponse
err := s.getFederationResource(ctx, federationID, []string{"group-mappings"}, &mappings)
if err != nil {
return nil, err
}

return &mappings, nil
}

// UpdateGroupMappings updates mappings for the Federation.
func (s *Service) UpdateGroupMappings(
ctx context.Context, federationID string, input GroupMappingsRequest,
) (*GroupMappingsResponse, error) {
if federationID == "" {
return nil, iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}

path, err := url.JoinPath(apiVersion, "federations", "saml", federationID, "group-mappings")
if err != nil {
return nil, iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

body, err := json.Marshal(input)
if err != nil {
return nil, iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

response, err := s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: bytes.NewReader(body),
Method: http.MethodPut,
Path: path,
})
if err != nil {
//nolint:wrapcheck // DoRequest already wraps the error.
return nil, err
}

var mappings GroupMappingsResponse
err = client.UnmarshalJSON(response, &mappings)
if err != nil {
return nil, iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

return &mappings, nil
}

// AddExternalGroupMapping creates mapping between internal and external group.
func (s *Service) AddExternalGroupMapping(
Comment thread
icerzack marked this conversation as resolved.
Outdated
ctx context.Context, federationID, groupID, externalGroupID string,
) error {
if federationID == "" {
return iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}
if groupID == "" {
return iamerrors.Error{Err: iamerrors.ErrGroupIDRequired, Desc: "No groupID was provided."}
}
if externalGroupID == "" {
return iamerrors.Error{Err: iamerrors.ErrInputDataRequired, Desc: "No externalGroupID was provided."}
}

path, err := url.JoinPath(
apiVersion,
"federations",
"saml",
federationID,
"group-mappings",
groupID,
"external-groups",
externalGroupID,
)
if err != nil {
return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

_, err = s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: nil,
Method: http.MethodPut,
Path: path,
})
if err != nil {
//nolint:wrapcheck // DoRequest already wraps the error.
return err
}

return nil
}

// DeleteExternalGroupMapping deletes mapping between internal and external group.
func (s *Service) DeleteExternalGroupMapping(
ctx context.Context, federationID, groupID, externalGroupID string,
) error {
if federationID == "" {
return iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}
if groupID == "" {
return iamerrors.Error{Err: iamerrors.ErrGroupIDRequired, Desc: "No groupID was provided."}
}
if externalGroupID == "" {
return iamerrors.Error{Err: iamerrors.ErrInputDataRequired, Desc: "No externalGroupID was provided."}
}

path, err := url.JoinPath(
apiVersion,
"federations",
"saml",
federationID,
"group-mappings",
groupID,
"external-groups",
externalGroupID,
)
if err != nil {
return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

_, err = s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: nil,
Method: http.MethodDelete,
Path: path,
})
if err != nil {
//nolint:wrapcheck // DoRequest already wraps the error.
return err
}

return nil
}

// ExternalGroupMappingExists checks that internal and external groups are mapped.
func (s *Service) ExternalGroupMappingExists(
ctx context.Context, federationID, groupID, externalGroupID string,
) (bool, error) {
if federationID == "" {
return false, iamerrors.Error{Err: iamerrors.ErrFederationIDRequired, Desc: "No federationID was provided."}
}
if groupID == "" {
return false, iamerrors.Error{Err: iamerrors.ErrGroupIDRequired, Desc: "No groupID was provided."}
}
if externalGroupID == "" {
return false, iamerrors.Error{Err: iamerrors.ErrInputDataRequired, Desc: "No externalGroupID was provided."}
}

path, err := url.JoinPath(
apiVersion,
"federations",
"saml",
federationID,
"group-mappings",
groupID,
"external-groups",
externalGroupID,
)
if err != nil {
return false, iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()}
}

_, err = s.baseClient.DoRequest(ctx, client.DoRequestInput{
Body: nil,
Method: http.MethodHead,
Path: path,
})
if err != nil {
if errors.Is(err, iamerrors.ErrFederationNotFound) ||
errors.Is(err, iamerrors.ErrGroupNotFound) ||
errors.Is(err, iamerrors.ErrUserOrGroupNotFound) {
return false, nil
}

//nolint:wrapcheck // DoRequest already wraps the error.
return false, err
}

return true, nil
}
Loading
Loading