github.com/minio/console@v1.4.1/api/service_accounts_handlers.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2021 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  package api
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"errors"
    23  	"time"
    24  
    25  	"github.com/go-openapi/runtime/middleware"
    26  	"github.com/minio/console/api/operations"
    27  	saApi "github.com/minio/console/api/operations/service_account"
    28  	userApi "github.com/minio/console/api/operations/user"
    29  	"github.com/minio/console/models"
    30  	"github.com/minio/console/pkg/utils"
    31  	"github.com/minio/madmin-go/v3"
    32  	iampolicy "github.com/minio/pkg/v3/policy"
    33  )
    34  
    35  func registerServiceAccountsHandlers(api *operations.ConsoleAPI) {
    36  	// Create Service Account
    37  	api.ServiceAccountCreateServiceAccountHandler = saApi.CreateServiceAccountHandlerFunc(func(params saApi.CreateServiceAccountParams, session *models.Principal) middleware.Responder {
    38  		creds, err := getCreateServiceAccountResponse(session, params)
    39  		if err != nil {
    40  			return saApi.NewCreateServiceAccountDefault(err.Code).WithPayload(err.APIError)
    41  		}
    42  		return saApi.NewCreateServiceAccountCreated().WithPayload(creds)
    43  	})
    44  	// Create User Service Account
    45  	api.UserCreateAUserServiceAccountHandler = userApi.CreateAUserServiceAccountHandlerFunc(func(params userApi.CreateAUserServiceAccountParams, session *models.Principal) middleware.Responder {
    46  		creds, err := getCreateAUserServiceAccountResponse(session, params)
    47  		if err != nil {
    48  			return saApi.NewCreateServiceAccountDefault(err.Code).WithPayload(err.APIError)
    49  		}
    50  		return userApi.NewCreateAUserServiceAccountCreated().WithPayload(creds)
    51  	})
    52  	// Create User Service Account
    53  	api.UserCreateServiceAccountCredentialsHandler = userApi.CreateServiceAccountCredentialsHandlerFunc(func(params userApi.CreateServiceAccountCredentialsParams, session *models.Principal) middleware.Responder {
    54  		creds, err := getCreateAUserServiceAccountCredsResponse(session, params)
    55  		if err != nil {
    56  			return saApi.NewCreateServiceAccountDefault(err.Code).WithPayload(err.APIError)
    57  		}
    58  		return userApi.NewCreateServiceAccountCredentialsCreated().WithPayload(creds)
    59  	})
    60  	api.ServiceAccountCreateServiceAccountCredsHandler = saApi.CreateServiceAccountCredsHandlerFunc(func(params saApi.CreateServiceAccountCredsParams, session *models.Principal) middleware.Responder {
    61  		creds, err := getCreateServiceAccountCredsResponse(session, params)
    62  		if err != nil {
    63  			return saApi.NewCreateServiceAccountDefault(err.Code).WithPayload(err.APIError)
    64  		}
    65  		return userApi.NewCreateServiceAccountCredentialsCreated().WithPayload(creds)
    66  	})
    67  	// List Service Accounts for User
    68  	api.ServiceAccountListUserServiceAccountsHandler = saApi.ListUserServiceAccountsHandlerFunc(func(params saApi.ListUserServiceAccountsParams, session *models.Principal) middleware.Responder {
    69  		ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
    70  		defer cancel()
    71  		serviceAccounts, err := getUserServiceAccountsResponse(ctx, session, "")
    72  		if err != nil {
    73  			return saApi.NewListUserServiceAccountsDefault(err.Code).WithPayload(err.APIError)
    74  		}
    75  		return saApi.NewListUserServiceAccountsOK().WithPayload(serviceAccounts)
    76  	})
    77  
    78  	// Delete a User's service account
    79  	api.ServiceAccountDeleteServiceAccountHandler = saApi.DeleteServiceAccountHandlerFunc(func(params saApi.DeleteServiceAccountParams, session *models.Principal) middleware.Responder {
    80  		if err := getDeleteServiceAccountResponse(session, params); err != nil {
    81  			return saApi.NewDeleteServiceAccountDefault(err.Code).WithPayload(err.APIError)
    82  		}
    83  		return saApi.NewDeleteServiceAccountNoContent()
    84  	})
    85  
    86  	// List Service Accounts for User
    87  	api.UserListAUserServiceAccountsHandler = userApi.ListAUserServiceAccountsHandlerFunc(func(params userApi.ListAUserServiceAccountsParams, session *models.Principal) middleware.Responder {
    88  		ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
    89  		defer cancel()
    90  		serviceAccounts, err := getUserServiceAccountsResponse(ctx, session, params.Name)
    91  		if err != nil {
    92  			return saApi.NewListUserServiceAccountsDefault(err.Code).WithPayload(err.APIError)
    93  		}
    94  		return saApi.NewListUserServiceAccountsOK().WithPayload(serviceAccounts)
    95  	})
    96  
    97  	api.ServiceAccountGetServiceAccountHandler = saApi.GetServiceAccountHandlerFunc(func(params saApi.GetServiceAccountParams, session *models.Principal) middleware.Responder {
    98  		serviceAccounts, err := getServiceAccountInfo(session, params)
    99  		if err != nil {
   100  			return saApi.NewGetServiceAccountDefault(err.Code).WithPayload(err.APIError)
   101  		}
   102  		return saApi.NewGetServiceAccountOK().WithPayload(serviceAccounts)
   103  	})
   104  
   105  	api.ServiceAccountUpdateServiceAccountHandler = saApi.UpdateServiceAccountHandlerFunc(func(params saApi.UpdateServiceAccountParams, session *models.Principal) middleware.Responder {
   106  		err := updateSetServiceAccountResponse(session, params)
   107  		if err != nil {
   108  			return saApi.NewUpdateServiceAccountDefault(err.Code).WithPayload(err.APIError)
   109  		}
   110  		return saApi.NewUpdateServiceAccountOK()
   111  	})
   112  
   113  	// Delete multiple service accounts
   114  	api.ServiceAccountDeleteMultipleServiceAccountsHandler = saApi.DeleteMultipleServiceAccountsHandlerFunc(func(params saApi.DeleteMultipleServiceAccountsParams, session *models.Principal) middleware.Responder {
   115  		if err := getDeleteMultipleServiceAccountsResponse(session, params); err != nil {
   116  			return saApi.NewDeleteMultipleServiceAccountsDefault(err.Code).WithPayload(err.APIError)
   117  		}
   118  		return saApi.NewDeleteMultipleServiceAccountsNoContent()
   119  	})
   120  }
   121  
   122  // createServiceAccount adds a service account to the userClient and assigns a policy to him if defined.
   123  func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy string, name string, description string, expiry *time.Time, comment string) (*models.ServiceAccountCreds, error) {
   124  	creds, err := userClient.addServiceAccount(ctx, policy, "", "", "", name, description, expiry, comment)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey, URL: getMinIOServer()}, nil
   129  }
   130  
   131  // createServiceAccount adds a service account with the given credentials to the
   132  // userClient and assigns a policy to him if defined.
   133  func createServiceAccountCreds(ctx context.Context, userClient MinioAdmin, policy string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (*models.ServiceAccountCreds, error) {
   134  	creds, err := userClient.addServiceAccount(ctx, policy, "", accessKey, secretKey, name, description, expiry, comment)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey, URL: getMinIOServer()}, nil
   139  }
   140  
   141  // getCreateServiceAccountResponse creates a service account with the defined policy for the user that
   142  // is requesting, it first gets the credentials of the user and creates a client which is going to
   143  // make the call to create the Service Account
   144  func getCreateServiceAccountResponse(session *models.Principal, params saApi.CreateServiceAccountParams) (*models.ServiceAccountCreds, *CodedAPIError) {
   145  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   146  	defer cancel()
   147  
   148  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   149  	if err != nil {
   150  		return nil, ErrorWithContext(ctx, err)
   151  	}
   152  	// create a MinIO user Admin Client interface implementation
   153  	// defining the client to be used
   154  	userAdminClient := AdminClient{Client: userAdmin}
   155  
   156  	var expiry *time.Time
   157  	if params.Body.Expiry != "" {
   158  		parsedExpiry, err := time.Parse(time.RFC3339, params.Body.Expiry)
   159  		if err != nil {
   160  			return nil, ErrorWithContext(ctx, err)
   161  		}
   162  		expiry = &parsedExpiry
   163  	}
   164  	saCreds, err := createServiceAccount(ctx, userAdminClient, params.Body.Policy, params.Body.Name, params.Body.Description, expiry, params.Body.Comment)
   165  	if err != nil {
   166  		return nil, ErrorWithContext(ctx, err)
   167  	}
   168  	return saCreds, nil
   169  }
   170  
   171  // createServiceAccount adds a service account to a given user and assigns a policy to him if defined.
   172  func createAUserServiceAccount(ctx context.Context, userClient MinioAdmin, policy string, user string, name string, description string, expiry *time.Time, comment string) (*models.ServiceAccountCreds, error) {
   173  	creds, err := userClient.addServiceAccount(ctx, policy, user, "", "", name, description, expiry, comment)
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey, URL: getMinIOServer()}, nil
   178  }
   179  
   180  func createAUserServiceAccountCreds(ctx context.Context, userClient MinioAdmin, policy string, user string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (*models.ServiceAccountCreds, error) {
   181  	creds, err := userClient.addServiceAccount(ctx, policy, user, accessKey, secretKey, name, description, expiry, comment)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  	return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey, URL: getMinIOServer()}, nil
   186  }
   187  
   188  // getCreateServiceAccountResponse creates a service account with the defined policy for the user that
   189  // is requesting it ,it first gets the credentials of the user and creates a client which is going to
   190  // make the call to create the Service Account
   191  func getCreateAUserServiceAccountResponse(session *models.Principal, params userApi.CreateAUserServiceAccountParams) (*models.ServiceAccountCreds, *CodedAPIError) {
   192  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   193  	defer cancel()
   194  
   195  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   196  	if err != nil {
   197  		return nil, ErrorWithContext(ctx, err)
   198  	}
   199  	// create a MinIO user Admin Client interface implementation
   200  	// defining the client to be used
   201  	userAdminClient := AdminClient{Client: userAdmin}
   202  	name, err := utils.DecodeBase64(params.Name)
   203  	if err != nil {
   204  		return nil, ErrorWithContext(ctx, err)
   205  	}
   206  
   207  	var expiry *time.Time
   208  	if params.Body.Expiry != "" {
   209  		parsedExpiry, err := time.Parse(time.RFC3339, params.Body.Expiry)
   210  		if err != nil {
   211  			return nil, ErrorWithContext(ctx, err)
   212  		}
   213  		expiry = &parsedExpiry
   214  	}
   215  	saCreds, err := createAUserServiceAccount(ctx, userAdminClient, params.Body.Policy, name, params.Body.Name, params.Body.Description, expiry, params.Body.Comment)
   216  	if err != nil {
   217  		return nil, ErrorWithContext(ctx, err)
   218  	}
   219  	return saCreds, nil
   220  }
   221  
   222  // getCreateServiceAccountCredsResponse creates a service account with the defined policy for the user that
   223  // is requesting it, and with the credentials provided
   224  func getCreateAUserServiceAccountCredsResponse(session *models.Principal, params userApi.CreateServiceAccountCredentialsParams) (*models.ServiceAccountCreds, *CodedAPIError) {
   225  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   226  	defer cancel()
   227  
   228  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   229  	if err != nil {
   230  		return nil, ErrorWithContext(ctx, err)
   231  	}
   232  	// create a MinIO user Admin Client interface implementation
   233  	// defining the client to be used
   234  	userAdminClient := AdminClient{Client: userAdmin}
   235  	serviceAccount := params.Body
   236  	user, err := utils.DecodeBase64(params.Name)
   237  	if err != nil {
   238  		return nil, ErrorWithContext(ctx, err)
   239  	}
   240  	if user == serviceAccount.AccessKey {
   241  		return nil, ErrorWithContext(ctx, errors.New("Access Key already in use"))
   242  	}
   243  	accounts, err := userAdminClient.listServiceAccounts(ctx, user)
   244  	if err != nil {
   245  		return nil, ErrorWithContext(ctx, err)
   246  	}
   247  	for i := 0; i < len(accounts.Accounts); i++ {
   248  		if accounts.Accounts[i].AccessKey == serviceAccount.AccessKey {
   249  			return nil, ErrorWithContext(ctx, errors.New("Access Key already in use"))
   250  		}
   251  	}
   252  
   253  	var expiry *time.Time
   254  	if serviceAccount.Expiry != "" {
   255  		parsedExpiry, err := time.Parse(time.RFC3339, serviceAccount.Expiry)
   256  		if err != nil {
   257  			return nil, ErrorWithContext(ctx, err)
   258  		}
   259  		expiry = &parsedExpiry
   260  	}
   261  	saCreds, err := createAUserServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, user, serviceAccount.AccessKey, serviceAccount.SecretKey, serviceAccount.Name, serviceAccount.Description, expiry, serviceAccount.Comment)
   262  	if err != nil {
   263  		return nil, ErrorWithContext(ctx, err)
   264  	}
   265  	return saCreds, nil
   266  }
   267  
   268  func getCreateServiceAccountCredsResponse(session *models.Principal, params saApi.CreateServiceAccountCredsParams) (*models.ServiceAccountCreds, *CodedAPIError) {
   269  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   270  	defer cancel()
   271  	serviceAccount := params.Body
   272  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   273  	if err != nil {
   274  		return nil, ErrorWithContext(ctx, err)
   275  	}
   276  	// create a MinIO user Admin Client interface implementation
   277  	// defining the client to be used
   278  	userAdminClient := AdminClient{Client: userAdmin}
   279  
   280  	if session.AccountAccessKey == serviceAccount.AccessKey {
   281  		return nil, ErrorWithContext(ctx, errors.New("Access Key already in use"))
   282  	}
   283  
   284  	accounts, err := userAdminClient.listServiceAccounts(ctx, "")
   285  	if err != nil {
   286  		return nil, ErrorWithContext(ctx, err)
   287  	}
   288  
   289  	for i := 0; i < len(accounts.Accounts); i++ {
   290  		if accounts.Accounts[i].AccessKey == serviceAccount.AccessKey {
   291  			return nil, ErrorWithContext(ctx, errors.New("Access Key already in use"))
   292  		}
   293  	}
   294  
   295  	var expiry *time.Time
   296  	if params.Body.Expiry != "" {
   297  		parsedExpiry, err := time.Parse(time.RFC3339, params.Body.Expiry)
   298  		if err != nil {
   299  			return nil, ErrorWithContext(ctx, err)
   300  		}
   301  		expiry = &parsedExpiry
   302  	}
   303  
   304  	saCreds, err := createServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, serviceAccount.AccessKey, serviceAccount.SecretKey, params.Body.Name, params.Body.Description, expiry, params.Body.Comment)
   305  	if err != nil {
   306  		return nil, ErrorWithContext(ctx, err)
   307  	}
   308  	return saCreds, nil
   309  }
   310  
   311  // getUserServiceAccount gets list of the user's service accounts
   312  func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin, user string) (models.ServiceAccounts, error) {
   313  	listServAccs, err := userClient.listServiceAccounts(ctx, user)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	saList := models.ServiceAccounts{}
   318  
   319  	for _, acc := range listServAccs.Accounts {
   320  		if acc.AccountStatus != "" {
   321  			// Newer releases of MinIO would support enhanced listServiceAccounts()
   322  			// we can avoid infoServiceAccount() at that point, this scales well
   323  			// for 100's of service accounts.
   324  			expiry := ""
   325  			if acc.Expiration != nil {
   326  				expiry = acc.Expiration.Format(time.RFC3339)
   327  			}
   328  
   329  			saList = append(saList, &models.ServiceAccountsItems0{
   330  				AccountStatus: acc.AccountStatus,
   331  				Description:   acc.Description,
   332  				Expiration:    expiry,
   333  				Name:          acc.Name,
   334  				AccessKey:     acc.AccessKey,
   335  			})
   336  			continue
   337  		}
   338  
   339  		aInfo, err := userClient.infoServiceAccount(ctx, acc.AccessKey)
   340  		if err != nil {
   341  			continue
   342  		}
   343  		expiry := ""
   344  		if aInfo.Expiration != nil {
   345  			expiry = aInfo.Expiration.Format(time.RFC3339)
   346  		}
   347  
   348  		saList = append(saList, &models.ServiceAccountsItems0{
   349  			AccountStatus: aInfo.AccountStatus,
   350  			Description:   aInfo.Description,
   351  			Expiration:    expiry,
   352  			Name:          aInfo.Name,
   353  			AccessKey:     acc.AccessKey,
   354  		})
   355  	}
   356  	return saList, nil
   357  }
   358  
   359  // getUserServiceAccountsResponse authenticates the user and calls
   360  // getUserServiceAccounts to list the user's service accounts
   361  func getUserServiceAccountsResponse(ctx context.Context, session *models.Principal, user string) (models.ServiceAccounts, *CodedAPIError) {
   362  	userAdmin, err := NewMinioAdminClient(ctx, session)
   363  	if err != nil {
   364  		return nil, ErrorWithContext(ctx, err)
   365  	}
   366  	// create a MinIO user Admin Client interface implementation
   367  	// defining the client to be used
   368  	userAdminClient := AdminClient{Client: userAdmin}
   369  	user, err = utils.DecodeBase64(user)
   370  	if err != nil {
   371  		return nil, ErrorWithContext(ctx, err)
   372  	}
   373  	serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient, user)
   374  	if err != nil {
   375  		return nil, ErrorWithContext(ctx, err)
   376  	}
   377  	return serviceAccounts, nil
   378  }
   379  
   380  // deleteServiceAccount calls delete service account api
   381  func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey string) error {
   382  	return userClient.deleteServiceAccount(ctx, accessKey)
   383  }
   384  
   385  // getDeleteServiceAccountResponse authenticates the user and calls deleteServiceAccount
   386  func getDeleteServiceAccountResponse(session *models.Principal, params saApi.DeleteServiceAccountParams) *CodedAPIError {
   387  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   388  	defer cancel()
   389  	accessKey, err := utils.DecodeBase64(params.AccessKey)
   390  	if err != nil {
   391  		return ErrorWithContext(ctx, err)
   392  	}
   393  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   394  	if err != nil {
   395  		return ErrorWithContext(ctx, err)
   396  	}
   397  	// create a MinIO user Admin Client interface implementation
   398  	// defining the client to be used
   399  	userAdminClient := AdminClient{Client: userAdmin}
   400  	if err := deleteServiceAccount(ctx, userAdminClient, accessKey); err != nil {
   401  		return ErrorWithContext(ctx, err)
   402  	}
   403  	return nil
   404  }
   405  
   406  // getServiceAccountDetails gets policy for a service account
   407  func getServiceAccountDetails(ctx context.Context, userClient MinioAdmin, accessKey string) (*models.ServiceAccount, error) {
   408  	saInfo, err := userClient.infoServiceAccount(ctx, accessKey)
   409  	if err != nil {
   410  		return nil, err
   411  	}
   412  
   413  	var policyJSON string
   414  	var policy iampolicy.Policy
   415  	json.Unmarshal([]byte(saInfo.Policy), &policy)
   416  	if policy.Statements == nil {
   417  		policyJSON = ""
   418  	} else {
   419  		policyJSON = saInfo.Policy
   420  	}
   421  
   422  	expiry := ""
   423  	if saInfo.Expiration != nil {
   424  		expiry = saInfo.Expiration.Format(time.RFC3339)
   425  	}
   426  
   427  	sa := models.ServiceAccount{
   428  		AccountStatus: saInfo.AccountStatus,
   429  		Description:   saInfo.Description,
   430  		Expiration:    expiry,
   431  		ImpliedPolicy: saInfo.ImpliedPolicy,
   432  		Name:          saInfo.Name,
   433  		ParentUser:    saInfo.ParentUser,
   434  		Policy:        policyJSON,
   435  	}
   436  	return &sa, nil
   437  }
   438  
   439  // getServiceAccountInfo authenticates the user and calls
   440  // getServiceAccountInfo to get the policy for a service account
   441  func getServiceAccountInfo(session *models.Principal, params saApi.GetServiceAccountParams) (*models.ServiceAccount, *CodedAPIError) {
   442  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   443  	defer cancel()
   444  	accessKey, err := utils.DecodeBase64(params.AccessKey)
   445  	if err != nil {
   446  		return nil, ErrorWithContext(ctx, err)
   447  	}
   448  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   449  	if err != nil {
   450  		return nil, ErrorWithContext(ctx, err)
   451  	}
   452  	// create a MinIO user Admin Client interface implementation
   453  	// defining the client to be used
   454  	userAdminClient := AdminClient{Client: userAdmin}
   455  
   456  	serviceAccount, err := getServiceAccountDetails(ctx, userAdminClient, accessKey)
   457  	if err != nil {
   458  		return nil, ErrorWithContext(ctx, err)
   459  	}
   460  
   461  	return serviceAccount, nil
   462  }
   463  
   464  // setServiceAccountPolicy sets policy for a service account
   465  func updateServiceAccountDetails(ctx context.Context, userClient MinioAdmin, accessKey string, policy string, expiry *time.Time, name string, description string, status string, secretKey string) error {
   466  	req := madmin.UpdateServiceAccountReq{
   467  		NewPolicy:      json.RawMessage(policy),
   468  		NewSecretKey:   secretKey,
   469  		NewStatus:      status,
   470  		NewName:        name,
   471  		NewDescription: description,
   472  		NewExpiration:  expiry,
   473  	}
   474  
   475  	err := userClient.updateServiceAccount(ctx, accessKey, req)
   476  	return err
   477  }
   478  
   479  // updateSetServiceAccountResponse authenticates the user and calls
   480  // getSetServiceAccountPolicy to set the policy for a service account
   481  func updateSetServiceAccountResponse(session *models.Principal, params saApi.UpdateServiceAccountParams) *CodedAPIError {
   482  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   483  	defer cancel()
   484  	accessKey, err := utils.DecodeBase64(params.AccessKey)
   485  	if err != nil {
   486  		return ErrorWithContext(ctx, err)
   487  	}
   488  	policy := *params.Body.Policy
   489  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   490  	if err != nil {
   491  		return ErrorWithContext(ctx, err)
   492  	}
   493  	// create a MinIO user Admin Client interface implementation
   494  	// defining the client to be used
   495  	userAdminClient := AdminClient{Client: userAdmin}
   496  
   497  	var expiry *time.Time
   498  	if params.Body.Expiry != "" {
   499  		parsedExpiry, err := time.Parse(time.RFC3339, params.Body.Expiry)
   500  		if err != nil {
   501  			return ErrorWithContext(ctx, err)
   502  		}
   503  		expiry = &parsedExpiry
   504  	}
   505  	err = updateServiceAccountDetails(ctx, userAdminClient, accessKey, policy, expiry, params.Body.Name, params.Body.Description, params.Body.Status, params.Body.SecretKey)
   506  	if err != nil {
   507  		return ErrorWithContext(ctx, err)
   508  	}
   509  	return nil
   510  }
   511  
   512  // getDeleteMultipleServiceAccountsResponse authenticates the user and calls deleteServiceAccount for each account listed in selectedSAs
   513  func getDeleteMultipleServiceAccountsResponse(session *models.Principal, params saApi.DeleteMultipleServiceAccountsParams) *CodedAPIError {
   514  	ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
   515  	defer cancel()
   516  	selectedSAs := params.SelectedSA
   517  	userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
   518  	if err != nil {
   519  		return ErrorWithContext(ctx, err)
   520  	}
   521  	// create a MinIO user Admin Client interface implementation
   522  	// defining the client to be used
   523  	userAdminClient := AdminClient{Client: userAdmin}
   524  	for _, sa := range selectedSAs {
   525  		if err := deleteServiceAccount(ctx, userAdminClient, sa); err != nil {
   526  			return ErrorWithContext(ctx, err)
   527  		}
   528  	}
   529  	return nil
   530  }