github.com/minio/console@v1.4.1/api/service_accounts_handlers_test.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  	"errors"
    22  	"fmt"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/minio/madmin-go/v3"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  func TestAddServiceAccount(t *testing.T) {
    31  	assert := assert.New(t)
    32  	// mock minIO client
    33  	client := AdminClientMock{}
    34  	function := "createServiceAccount()"
    35  	// Test-1: createServiceAccount create a service account by assigning it a policy
    36  	ctx, cancel := context.WithCancel(context.Background())
    37  	defer cancel()
    38  	policyDefinition := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::bucket1/*\"]}]}"
    39  	mockResponse := madmin.Credentials{
    40  		AccessKey: "minio",
    41  		SecretKey: "minio123",
    42  	}
    43  	minioAddServiceAccountMock = func(_ context.Context, _ string, _ string, _ string, _ string, _ string, _ string, _ *time.Time, _ string) (madmin.Credentials, error) {
    44  		return mockResponse, nil
    45  	}
    46  	saCreds, err := createServiceAccount(ctx, client, policyDefinition, "", "", nil, "")
    47  	if err != nil {
    48  		t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
    49  	}
    50  	assert.Equal(mockResponse.AccessKey, saCreds.AccessKey, fmt.Sprintf("Failed on %s:, error occurred: AccessKey differ", function))
    51  	assert.Equal(mockResponse.SecretKey, saCreds.SecretKey, fmt.Sprintf("Failed on %s:, error occurred: SecretKey differ", function))
    52  
    53  	// Test-2: if an error occurs on server while creating service account (valid policy), handle it
    54  	policyDefinition = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::bucket1/*\"]}]}"
    55  	mockResponse = madmin.Credentials{
    56  		AccessKey: "minio",
    57  		SecretKey: "minio123",
    58  	}
    59  	minioAddServiceAccountMock = func(_ context.Context, _ string, _ string, _ string, _ string, _ string, _ string, _ *time.Time, _ string) (madmin.Credentials, error) {
    60  		return madmin.Credentials{}, errors.New("error")
    61  	}
    62  	_, err = createServiceAccount(ctx, client, policyDefinition, "", "", nil, "")
    63  	if assert.Error(err) {
    64  		assert.Equal("error", err.Error())
    65  	}
    66  }
    67  
    68  func TestListServiceAccounts(t *testing.T) {
    69  	assert := assert.New(t)
    70  	// mock minIO client
    71  	client := AdminClientMock{}
    72  	function := "getUserServiceAccounts()"
    73  
    74  	// Test-1: getUserServiceAccounts list serviceaccounts for a user
    75  	ctx, cancel := context.WithCancel(context.Background())
    76  	defer cancel()
    77  	mockResponse := madmin.ListServiceAccountsResp{
    78  		Accounts: []madmin.ServiceAccountInfo{
    79  			{
    80  				AccessKey: "accesskey1",
    81  			}, {
    82  				AccessKey: "accesskey2",
    83  			},
    84  		},
    85  	}
    86  	minioListServiceAccountsMock = func(_ context.Context, _ string) (madmin.ListServiceAccountsResp, error) {
    87  		return mockResponse, nil
    88  	}
    89  
    90  	mockInfoResp := madmin.InfoServiceAccountResp{
    91  		ParentUser:    "",
    92  		AccountStatus: "",
    93  		ImpliedPolicy: false,
    94  		Policy:        "",
    95  		Name:          "",
    96  		Description:   "",
    97  		Expiration:    nil,
    98  	}
    99  	minioInfoServiceAccountMock = func(_ context.Context, _ string) (madmin.InfoServiceAccountResp, error) {
   100  		return mockInfoResp, nil
   101  	}
   102  	_, err := getUserServiceAccounts(ctx, client, "")
   103  	if err != nil {
   104  		t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
   105  	}
   106  
   107  	// Test-2: getUserServiceAccounts returns an error, handle it properly
   108  	minioListServiceAccountsMock = func(_ context.Context, _ string) (madmin.ListServiceAccountsResp, error) {
   109  		return madmin.ListServiceAccountsResp{}, errors.New("error")
   110  	}
   111  	_, err = getUserServiceAccounts(ctx, client, "")
   112  	if assert.Error(err) {
   113  		assert.Equal("error", err.Error())
   114  	}
   115  }
   116  
   117  func TestDeleteServiceAccount(t *testing.T) {
   118  	assert := assert.New(t)
   119  	// mock minIO client
   120  	client := AdminClientMock{}
   121  	function := "deleteServiceAccount()"
   122  	ctx, cancel := context.WithCancel(context.Background())
   123  	defer cancel()
   124  
   125  	// Test-1: deleteServiceAccount receive a service account to delete
   126  	testServiceAccount := "accesskeytest"
   127  	minioDeleteServiceAccountMock = func(_ context.Context, _ string) error {
   128  		return nil
   129  	}
   130  	if err := deleteServiceAccount(ctx, client, testServiceAccount); err != nil {
   131  		t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
   132  	}
   133  
   134  	// Test-2: if an invalid policy is assigned to the service account, this will raise an error
   135  	minioDeleteServiceAccountMock = func(_ context.Context, _ string) error {
   136  		return errors.New("error")
   137  	}
   138  
   139  	if err := deleteServiceAccount(ctx, client, testServiceAccount); assert.Error(err) {
   140  		assert.Equal("error", err.Error())
   141  	}
   142  }
   143  
   144  func TestGetServiceAccountDetails(t *testing.T) {
   145  	assert := assert.New(t)
   146  	// mock minIO client
   147  	client := AdminClientMock{}
   148  	function := "getServiceAccountDetails()"
   149  
   150  	// Test-1: getServiceAccountPolicy list serviceaccounts for a user
   151  	ctx, cancel := context.WithCancel(context.Background())
   152  	defer cancel()
   153  	mockResponse := madmin.InfoServiceAccountResp{
   154  		Policy: `
   155  {
   156    "Version": "2012-10-17",
   157    "Statement": [
   158      {
   159        "Effect": "Allow",
   160        "Action": [
   161          "s3:PutObject"
   162        ],
   163        "Resource": [
   164          "arn:aws:s3:::*"
   165        ]
   166      }
   167    ]
   168  }`,
   169  	}
   170  
   171  	minioInfoServiceAccountMock = func(_ context.Context, _ string) (madmin.InfoServiceAccountResp, error) {
   172  		return mockResponse, nil
   173  	}
   174  	serviceAccount, err := getServiceAccountDetails(ctx, client, "")
   175  	if err != nil {
   176  		t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
   177  	}
   178  	assert.Equal(mockResponse.Policy, serviceAccount.Policy)
   179  
   180  	// Test-2: getServiceAccountPolicy returns an error, handle it properly
   181  	minioInfoServiceAccountMock = func(_ context.Context, _ string) (madmin.InfoServiceAccountResp, error) {
   182  		return madmin.InfoServiceAccountResp{}, errors.New("error")
   183  	}
   184  	_, err = getServiceAccountDetails(ctx, client, "")
   185  	if assert.Error(err) {
   186  		assert.Equal("error", err.Error())
   187  	}
   188  }