github.com/minio/console@v1.3.0/api/admin_idp.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  //
    17  
    18  package api
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"time"
    24  
    25  	"github.com/go-openapi/runtime/middleware"
    26  	"github.com/minio/console/api/operations"
    27  	"github.com/minio/console/api/operations/idp"
    28  	"github.com/minio/console/models"
    29  	"github.com/minio/madmin-go/v3"
    30  )
    31  
    32  var errInvalidIDPType = fmt.Errorf("IDP type must be one of %v", madmin.ValidIDPConfigTypes)
    33  
    34  func registerIDPHandlers(api *operations.ConsoleAPI) {
    35  	api.IdpCreateConfigurationHandler = idp.CreateConfigurationHandlerFunc(func(params idp.CreateConfigurationParams, session *models.Principal) middleware.Responder {
    36  		response, err := createIDPConfigurationResponse(session, params)
    37  		if err != nil {
    38  			return idp.NewCreateConfigurationDefault(err.Code).WithPayload(err.APIError)
    39  		}
    40  		return idp.NewCreateConfigurationCreated().WithPayload(response)
    41  	})
    42  	api.IdpUpdateConfigurationHandler = idp.UpdateConfigurationHandlerFunc(func(params idp.UpdateConfigurationParams, session *models.Principal) middleware.Responder {
    43  		response, err := updateIDPConfigurationResponse(session, params)
    44  		if err != nil {
    45  			return idp.NewUpdateConfigurationDefault(err.Code).WithPayload(err.APIError)
    46  		}
    47  		return idp.NewUpdateConfigurationOK().WithPayload(response)
    48  	})
    49  	api.IdpListConfigurationsHandler = idp.ListConfigurationsHandlerFunc(func(params idp.ListConfigurationsParams, session *models.Principal) middleware.Responder {
    50  		response, err := listIDPConfigurationsResponse(session, params)
    51  		if err != nil {
    52  			return idp.NewListConfigurationsDefault(err.Code).WithPayload(err.APIError)
    53  		}
    54  		return idp.NewListConfigurationsOK().WithPayload(response)
    55  	})
    56  	api.IdpDeleteConfigurationHandler = idp.DeleteConfigurationHandlerFunc(func(params idp.DeleteConfigurationParams, session *models.Principal) middleware.Responder {
    57  		response, err := deleteIDPConfigurationResponse(session, params)
    58  		if err != nil {
    59  			return idp.NewDeleteConfigurationDefault(err.Code).WithPayload(err.APIError)
    60  		}
    61  		return idp.NewDeleteConfigurationOK().WithPayload(response)
    62  	})
    63  	api.IdpGetConfigurationHandler = idp.GetConfigurationHandlerFunc(func(params idp.GetConfigurationParams, session *models.Principal) middleware.Responder {
    64  		response, err := getIDPConfigurationsResponse(session, params)
    65  		if err != nil {
    66  			return idp.NewGetConfigurationDefault(err.Code).WithPayload(err.APIError)
    67  		}
    68  		return idp.NewGetConfigurationOK().WithPayload(response)
    69  	})
    70  	api.IdpGetLDAPEntitiesHandler = idp.GetLDAPEntitiesHandlerFunc(func(params idp.GetLDAPEntitiesParams, session *models.Principal) middleware.Responder {
    71  		response, err := getLDAPEntitiesResponse(session, params)
    72  		if err != nil {
    73  			return idp.NewGetLDAPEntitiesDefault(err.Code).WithPayload(err.APIError)
    74  		}
    75  		return idp.NewGetLDAPEntitiesOK().WithPayload(response)
    76  	})
    77  }
    78  
    79  func createIDPConfigurationResponse(session *models.Principal, params idp.CreateConfigurationParams) (*models.SetIDPResponse, *CodedAPIError) {
    80  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
    81  	defer cancel()
    82  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
    83  	if err != nil {
    84  		return nil, ErrorWithContext(ctx, err)
    85  	}
    86  	restart, err := createOrUpdateIDPConfig(ctx, params.Type, params.Body.Name, params.Body.Input, false, AdminClient{Client: mAdmin})
    87  	if err != nil {
    88  		return nil, ErrorWithContext(ctx, err)
    89  	}
    90  	return &models.SetIDPResponse{Restart: restart}, nil
    91  }
    92  
    93  func updateIDPConfigurationResponse(session *models.Principal, params idp.UpdateConfigurationParams) (*models.SetIDPResponse, *CodedAPIError) {
    94  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
    95  	defer cancel()
    96  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
    97  	if err != nil {
    98  		return nil, ErrorWithContext(ctx, err)
    99  	}
   100  	restart, err := createOrUpdateIDPConfig(ctx, params.Type, params.Name, params.Body.Input, true, AdminClient{Client: mAdmin})
   101  	if err != nil {
   102  		return nil, ErrorWithContext(ctx, err)
   103  	}
   104  	return &models.SetIDPResponse{Restart: restart}, nil
   105  }
   106  
   107  func createOrUpdateIDPConfig(ctx context.Context, idpType, name, input string, update bool, client MinioAdmin) (bool, error) {
   108  	if !madmin.ValidIDPConfigTypes.Contains(idpType) {
   109  		return false, errInvalidIDPType
   110  	}
   111  	restart, err := client.addOrUpdateIDPConfig(ctx, idpType, name, input, update)
   112  	if err != nil {
   113  		return false, err
   114  	}
   115  	return restart, nil
   116  }
   117  
   118  func listIDPConfigurationsResponse(session *models.Principal, params idp.ListConfigurationsParams) (*models.IdpListConfigurationsResponse, *CodedAPIError) {
   119  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   120  	defer cancel()
   121  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   122  	if err != nil {
   123  		return nil, ErrorWithContext(ctx, err)
   124  	}
   125  	results, err := listIDPConfigurations(ctx, params.Type, AdminClient{Client: mAdmin})
   126  	if err != nil {
   127  		return nil, ErrorWithContext(ctx, err)
   128  	}
   129  	return &models.IdpListConfigurationsResponse{Results: results}, nil
   130  }
   131  
   132  func listIDPConfigurations(ctx context.Context, idpType string, client MinioAdmin) ([]*models.IdpServerConfiguration, error) {
   133  	if !madmin.ValidIDPConfigTypes.Contains(idpType) {
   134  		return nil, errInvalidIDPType
   135  	}
   136  	results, err := client.listIDPConfig(ctx, idpType)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	return parseIDPConfigurations(results), nil
   141  }
   142  
   143  func parseIDPConfigurations(configs []madmin.IDPListItem) (serverConfigs []*models.IdpServerConfiguration) {
   144  	for _, c := range configs {
   145  		serverConfigs = append(serverConfigs, &models.IdpServerConfiguration{
   146  			Name:    c.Name,
   147  			Enabled: c.Enabled,
   148  			Type:    c.Type,
   149  		})
   150  	}
   151  	return serverConfigs
   152  }
   153  
   154  func deleteIDPConfigurationResponse(session *models.Principal, params idp.DeleteConfigurationParams) (*models.SetIDPResponse, *CodedAPIError) {
   155  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   156  	defer cancel()
   157  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   158  	if err != nil {
   159  		return nil, ErrorWithContext(ctx, err)
   160  	}
   161  	restart, err := deleteIDPConfig(ctx, params.Type, params.Name, AdminClient{Client: mAdmin})
   162  	if err != nil {
   163  		return nil, ErrorWithContext(ctx, err)
   164  	}
   165  	return &models.SetIDPResponse{Restart: restart}, nil
   166  }
   167  
   168  func deleteIDPConfig(ctx context.Context, idpType, name string, client MinioAdmin) (bool, error) {
   169  	if !madmin.ValidIDPConfigTypes.Contains(idpType) {
   170  		return false, errInvalidIDPType
   171  	}
   172  	restart, err := client.deleteIDPConfig(ctx, idpType, name)
   173  	if err != nil {
   174  		return false, err
   175  	}
   176  	return restart, nil
   177  }
   178  
   179  func getIDPConfigurationsResponse(session *models.Principal, params idp.GetConfigurationParams) (*models.IdpServerConfiguration, *CodedAPIError) {
   180  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   181  	defer cancel()
   182  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   183  	if err != nil {
   184  		return nil, ErrorWithContext(ctx, err)
   185  	}
   186  	result, err := getIDPConfiguration(ctx, params.Type, params.Name, AdminClient{Client: mAdmin})
   187  	if err != nil {
   188  		return nil, ErrorWithContext(ctx, err)
   189  	}
   190  	return result, nil
   191  }
   192  
   193  func getIDPConfiguration(ctx context.Context, idpType, name string, client MinioAdmin) (*models.IdpServerConfiguration, error) {
   194  	if !madmin.ValidIDPConfigTypes.Contains(idpType) {
   195  		return nil, errInvalidIDPType
   196  	}
   197  	config, err := client.getIDPConfig(ctx, idpType, name)
   198  	if err != nil {
   199  		return nil, err
   200  	}
   201  
   202  	return &models.IdpServerConfiguration{
   203  		Name: config.Name,
   204  		Type: config.Type,
   205  		Info: parseIDPConfigurationsInfo(config.Info),
   206  	}, nil
   207  }
   208  
   209  func parseIDPConfigurationsInfo(infoList []madmin.IDPCfgInfo) (results []*models.IdpServerConfigurationInfo) {
   210  	for _, info := range infoList {
   211  		results = append(results, &models.IdpServerConfigurationInfo{
   212  			Key:   info.Key,
   213  			Value: info.Value,
   214  			IsCfg: info.IsCfg,
   215  			IsEnv: info.IsEnv,
   216  		})
   217  	}
   218  	return results
   219  }
   220  
   221  func getLDAPEntitiesResponse(session *models.Principal, params idp.GetLDAPEntitiesParams) (*models.LdapEntities, *CodedAPIError) {
   222  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   223  	defer cancel()
   224  	mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   225  	if err != nil {
   226  		return nil, ErrorWithContext(ctx, err)
   227  	}
   228  
   229  	result, err := getEntitiesResult(ctx, AdminClient{Client: mAdmin}, params.Body.Users, params.Body.Groups, params.Body.Policies)
   230  	if err != nil {
   231  		return nil, ErrorWithContext(ctx, err)
   232  	}
   233  
   234  	return result, nil
   235  }
   236  
   237  func getEntitiesResult(ctx context.Context, client MinioAdmin, users, groups, policies []string) (*models.LdapEntities, error) {
   238  	entities, err := client.getLDAPPolicyEntities(ctx, madmin.PolicyEntitiesQuery{
   239  		Users:  users,
   240  		Groups: groups,
   241  		Policy: policies,
   242  	})
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	var result models.LdapEntities
   248  
   249  	var usersEntity []*models.LdapUserPolicyEntity
   250  	var groupsEntity []*models.LdapGroupPolicyEntity
   251  	var policiesEntity []*models.LdapPolicyEntity
   252  
   253  	result.Timestamp = entities.Timestamp.Format(time.RFC3339)
   254  
   255  	for _, userMapping := range entities.UserMappings {
   256  		mapItem := models.LdapUserPolicyEntity{
   257  			User:     userMapping.User,
   258  			Policies: userMapping.Policies,
   259  		}
   260  
   261  		usersEntity = append(usersEntity, &mapItem)
   262  	}
   263  
   264  	result.Users = usersEntity
   265  
   266  	for _, groupsMapping := range entities.GroupMappings {
   267  		mapItem := models.LdapGroupPolicyEntity{
   268  			Group:    groupsMapping.Group,
   269  			Policies: groupsMapping.Policies,
   270  		}
   271  
   272  		groupsEntity = append(groupsEntity, &mapItem)
   273  	}
   274  
   275  	result.Groups = groupsEntity
   276  
   277  	for _, policyMapping := range entities.PolicyMappings {
   278  		mapItem := models.LdapPolicyEntity{
   279  			Policy: policyMapping.Policy,
   280  			Users:  policyMapping.Users,
   281  			Groups: policyMapping.Groups,
   282  		}
   283  
   284  		policiesEntity = append(policiesEntity, &mapItem)
   285  	}
   286  
   287  	result.Policies = policiesEntity
   288  
   289  	return &result, nil
   290  }