github.com/minio/console@v1.3.0/integration/service_account_test.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  package integration
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/base64"
    22  	"encoding/json"
    23  	"fmt"
    24  	"log"
    25  	"net/http"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/go-openapi/swag"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  func TestAddServiceAccount(t *testing.T) {
    35  	/*
    36  		This is an atomic API Test to add a user service account, the intention
    37  		is simple, add a user and make sure the response is 201 meaning that the
    38  		user got added successfully.
    39  		After test completion, it is expected that user is removed, so other
    40  		tests like users.ts can run over clean data and we don't collide against
    41  		it.
    42  	*/
    43  
    44  	assert := assert.New(t)
    45  
    46  	client := &http.Client{
    47  		Timeout: 3 * time.Second,
    48  	}
    49  
    50  	// Add service account
    51  	requestDataAddServiceAccount := map[string]interface{}{
    52  		"accessKey": "testuser1",
    53  		"secretKey": "password",
    54  		"policy": `{
    55    "Version": "2012-10-17",
    56    "Statement": [
    57      {
    58        "Effect": "Allow",
    59        "Action": [
    60          "s3:GetBucketLocation",
    61          "s3:GetObject"
    62        ],
    63        "Resource": [
    64          "arn:aws:s3:::*"
    65        ]
    66      }
    67    ]
    68  }`,
    69  	}
    70  
    71  	requestDataJSON, _ := json.Marshal(requestDataAddServiceAccount)
    72  	requestDataBody := bytes.NewReader(requestDataJSON)
    73  	request, err := http.NewRequest(
    74  		"POST", "http://localhost:9090/api/v1/service-account-credentials", requestDataBody)
    75  	if err != nil {
    76  		log.Println(err)
    77  		return
    78  	}
    79  	request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
    80  	request.Header.Add("Content-Type", "application/json")
    81  
    82  	response, err := client.Do(request)
    83  	if err != nil {
    84  		log.Println(err)
    85  		return
    86  	}
    87  	if response != nil {
    88  		fmt.Println("POST StatusCode:", response.StatusCode)
    89  		assert.Equal(201, response.StatusCode, "Status Code is incorrect")
    90  	}
    91  
    92  	// {{baseUrl}}/user?name=proident velit
    93  	// Investiga como se borra en el browser.
    94  	request, err = http.NewRequest(
    95  		"DELETE", "http://localhost:9090/api/v1/service-accounts/"+base64.StdEncoding.EncodeToString([]byte("testuser1")), nil)
    96  	if err != nil {
    97  		log.Println(err)
    98  		return
    99  	}
   100  	request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
   101  	request.Header.Add("Content-Type", "application/json")
   102  	response, err = client.Do(request)
   103  	if err != nil {
   104  		log.Println(err)
   105  		return
   106  	}
   107  	if response != nil {
   108  		fmt.Println("DELETE StatusCode:", response.StatusCode)
   109  		assert.Equal(204, response.StatusCode, "has to be 204 when delete user")
   110  	}
   111  }
   112  
   113  func Test_ServiceAccountsAPI(t *testing.T) {
   114  	assert := assert.New(t)
   115  
   116  	type args struct {
   117  		api    string
   118  		policy *string
   119  	}
   120  	tests := []struct {
   121  		name           string
   122  		args           args
   123  		expectedStatus int
   124  		expectedError  error
   125  	}{
   126  		{
   127  			name: "Create Service Account - Default",
   128  			args: args{
   129  				api:    "/service-accounts",
   130  				policy: nil,
   131  			},
   132  			expectedStatus: 201,
   133  			expectedError:  nil,
   134  		},
   135  		{
   136  			name: "Create Service Account - Valid Policy",
   137  			args: args{
   138  				api: "/service-accounts",
   139  				policy: swag.String(`
   140    {
   141    "Version": "2012-10-17",
   142    "Statement": [
   143      {
   144        "Effect": "Allow",
   145        "Action": [
   146          "s3:GetBucketLocation",
   147          "s3:GetObject"
   148        ],
   149        "Resource": [
   150          "arn:aws:s3:::*"
   151        ]
   152      }
   153    ]
   154  }`),
   155  			},
   156  			expectedStatus: 201,
   157  			expectedError:  nil,
   158  		},
   159  		{
   160  			name: "Create Service Account - Invalid Policy",
   161  			args: args{
   162  				api: "/service-accounts",
   163  				policy: swag.String(`
   164    {
   165    "Version": "2012-10-17",
   166    "Statement": [
   167      {
   168        "Effect": "Allow",
   169        "Action": [
   170          "s3:GetBucketLocation"
   171          "s3:GetObject"
   172        ],
   173        "Resource": [
   174          "arn:aws:s3:::*"
   175        ]
   176      }
   177    ]
   178  }`),
   179  			},
   180  			expectedStatus: 500,
   181  			expectedError:  nil,
   182  		},
   183  	}
   184  
   185  	for _, tt := range tests {
   186  		t.Run(tt.name, func(_ *testing.T) {
   187  			client := &http.Client{
   188  				Timeout: 3 * time.Second,
   189  			}
   190  
   191  			// Add service account
   192  
   193  			requestDataPolicy := map[string]interface{}{}
   194  			if tt.args.policy != nil {
   195  				requestDataPolicy["policy"] = *tt.args.policy
   196  			}
   197  
   198  			requestDataJSON, _ := json.Marshal(requestDataPolicy)
   199  			requestDataBody := bytes.NewReader(requestDataJSON)
   200  			request, err := http.NewRequest(
   201  				"POST", fmt.Sprintf("http://localhost:9090/api/v1%s", tt.args.api), requestDataBody)
   202  			if err != nil {
   203  				log.Println(err)
   204  				return
   205  			}
   206  			request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
   207  			request.Header.Add("Content-Type", "application/json")
   208  			response, err := client.Do(request)
   209  			if err != nil {
   210  				log.Println(err)
   211  				return
   212  			}
   213  			if response != nil {
   214  				assert.Equal(tt.expectedStatus, response.StatusCode, "Status Code is incorrect")
   215  			}
   216  		})
   217  	}
   218  }
   219  
   220  func DeleteMultipleServiceAccounts(serviceAccounts []string) (*http.Response, error) {
   221  	/*
   222  		Helper function to delete multiple service accounts
   223  		URL: http://localhost:9001/api/v1/service-accounts/delete-multi
   224  		HTTP Verb: DELETE
   225  		Data: ["U3RADB7J2ZZHELR0WSBB","ZE8H1HYOA6AVGKFCV6YU"]
   226  		Response: Status Code: 204 No Content
   227  	*/
   228  	client := &http.Client{
   229  		Timeout: 3 * time.Second,
   230  	}
   231  	requestDataJSON, _ := json.Marshal(serviceAccounts)
   232  	requestDataBody := bytes.NewReader(requestDataJSON)
   233  	request, err := http.NewRequest(
   234  		"DELETE", "http://localhost:9090/api/v1/service-accounts/delete-multi", requestDataBody)
   235  	if err != nil {
   236  		log.Println(err)
   237  	}
   238  	request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
   239  	request.Header.Add("Content-Type", "application/json")
   240  	response, err := client.Do(request)
   241  	return response, err
   242  }
   243  
   244  func TestCreateServiceAccountForUserWithCredentials(t *testing.T) {
   245  	/*
   246  		To test creation of service account for a user.
   247  	*/
   248  
   249  	// Test's variables
   250  	userName := "testcreateserviceaccountforuserwithcredentials1"
   251  	assert := assert.New(t)
   252  	policy := ""
   253  
   254  	// 1. Create the user
   255  	groups := []string{}
   256  	policies := []string{}
   257  	secretKey := "testcreateserviceaccountforuserwithcrede"
   258  	response, err := AddUser(userName, "secretKey", groups, policies)
   259  	if err != nil {
   260  		log.Println(err)
   261  		return
   262  	}
   263  	if response != nil {
   264  		fmt.Println("StatusCode:", response.StatusCode)
   265  		assert.Equal(201, response.StatusCode, "Status Code is incorrect")
   266  	}
   267  
   268  	// Table driven testing part
   269  	type args struct {
   270  		accessKey string
   271  	}
   272  	tests := []struct {
   273  		name           string
   274  		args           args
   275  		expectedStatus int
   276  	}{
   277  		{
   278  			name:           "Service Account With Valid Credentials",
   279  			expectedStatus: 201,
   280  			args: args{
   281  				accessKey: "testcreateserviceacc",
   282  			},
   283  		},
   284  		{
   285  			name:           "Service Account With Invalid Credentials",
   286  			expectedStatus: 500,
   287  			args: args{
   288  				accessKey: "tooooooooooooooooooooolongggggggggggggggggg",
   289  			},
   290  		},
   291  	}
   292  	for _, tt := range tests {
   293  		t.Run(tt.name, func(_ *testing.T) {
   294  			// 2. Create the service account for the user
   295  			createServiceAccountWithCredentialsResponse,
   296  				createServiceAccountWithCredentialsError := CreateServiceAccountForUserWithCredentials(
   297  				userName,
   298  				policy,
   299  				tt.args.accessKey,
   300  				secretKey,
   301  			)
   302  			if createServiceAccountWithCredentialsError != nil {
   303  				log.Println(createServiceAccountWithCredentialsError)
   304  				assert.Fail("Error in createServiceAccountWithCredentialsError")
   305  			}
   306  			if createServiceAccountWithCredentialsResponse != nil {
   307  				fmt.Println("StatusCode:", createServiceAccountWithCredentialsResponse.StatusCode)
   308  				assert.Equal(
   309  					tt.expectedStatus, // different status expected per table's row
   310  					createServiceAccountWithCredentialsResponse.StatusCode,
   311  					inspectHTTPResponse(createServiceAccountWithCredentialsResponse),
   312  				)
   313  			}
   314  
   315  			// 3. Verify the service account for the user
   316  			listOfAccountsResponse,
   317  				listOfAccountsError := ReturnsAListOfServiceAccountsForAUser(userName)
   318  			if listOfAccountsError != nil {
   319  				log.Println(listOfAccountsError)
   320  				assert.Fail("Error in listOfAccountsError")
   321  			}
   322  			finalResponse := inspectHTTPResponse(listOfAccountsResponse)
   323  			if listOfAccountsResponse != nil {
   324  				fmt.Println("StatusCode:", listOfAccountsResponse.StatusCode)
   325  				assert.Equal(
   326  					200, listOfAccountsResponse.StatusCode,
   327  					finalResponse,
   328  				)
   329  			}
   330  		})
   331  	}
   332  
   333  	// Delete Multiple Service Accounts
   334  	serviceAccount := make([]string, 1)
   335  	serviceAccount[0] = "testcreateserviceacc"
   336  	response, err = DeleteMultipleServiceAccounts(serviceAccount)
   337  	if err != nil {
   338  		log.Println(err)
   339  		return
   340  	}
   341  	if response != nil {
   342  		fmt.Println("StatusCode:", response.StatusCode)
   343  		assert.Equal(
   344  			204,
   345  			response.StatusCode,
   346  			inspectHTTPResponse(response),
   347  		)
   348  	}
   349  }