| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | //go:build !race
 | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | // +build !race
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests in this file are not run under the `-race` flag as they are too slow
 | 
					
						
							|  |  |  | // and cause context deadline errors.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2022-05-18 10:58:47 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 05:46:50 +08:00
										 |  |  | 	"github.com/minio/madmin-go/v2" | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	minio "github.com/minio/minio-go/v7" | 
					
						
							| 
									
										
										
										
											2023-04-26 13:57:40 +08:00
										 |  |  | 	"github.com/minio/pkg/sync/errgroup" | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func runAllIAMConcurrencyTests(suite *TestSuiteIAM, c *check) { | 
					
						
							|  |  |  | 	suite.SetUpSuite(c) | 
					
						
							|  |  |  | 	suite.TestDeleteUserRace(c) | 
					
						
							|  |  |  | 	suite.TearDownSuite(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIAMInternalIDPConcurrencyServerSuite(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-05-18 10:58:47 +08:00
										 |  |  | 	if runtime.GOOS == globalWindowsOSName { | 
					
						
							|  |  |  | 		t.Skip("windows is clunky") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 	baseTestCases := []TestSuiteCommon{ | 
					
						
							| 
									
										
										
										
											2022-05-31 01:58:37 +08:00
										 |  |  | 		// Init and run test on ErasureSD backend with signature v4.
 | 
					
						
							|  |  |  | 		{serverType: "ErasureSD", signer: signerV4}, | 
					
						
							|  |  |  | 		// Init and run test on ErasureSD backend, with tls enabled.
 | 
					
						
							|  |  |  | 		{serverType: "ErasureSD", signer: signerV4, secure: true}, | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 		// Init and run test on Erasure backend.
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 		{serverType: "Erasure", signer: signerV4}, | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 		// Init and run test on ErasureSet backend.
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 		{serverType: "ErasureSet", signer: signerV4}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testCases := []*TestSuiteIAM{} | 
					
						
							|  |  |  | 	for _, bt := range baseTestCases { | 
					
						
							|  |  |  | 		testCases = append(testCases, | 
					
						
							|  |  |  | 			newTestSuiteIAM(bt, false), | 
					
						
							|  |  |  | 			newTestSuiteIAM(bt, true), | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 		etcdStr := "" | 
					
						
							|  |  |  | 		if testCase.withEtcdBackend { | 
					
						
							|  |  |  | 			etcdStr = " (with etcd backend)" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s%s", i+1, testCase.serverType, etcdStr), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				runAllIAMConcurrencyTests(testCase, &check{t, testCase.serverType}) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestDeleteUserRace(c *check) { | 
					
						
							| 
									
										
										
										
											2022-04-26 11:14:20 +08:00
										 |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a policy policy
 | 
					
						
							|  |  |  | 	policy := "mypolicy" | 
					
						
							|  |  |  | 	policyBytes := []byte(fmt.Sprintf(`{ | 
					
						
							|  |  |  |  "Version": "2012-10-17", | 
					
						
							|  |  |  |  "Statement": [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |    "Effect": "Allow", | 
					
						
							|  |  |  |    "Action": [ | 
					
						
							|  |  |  |     "s3:PutObject", | 
					
						
							|  |  |  |     "s3:GetObject", | 
					
						
							|  |  |  |     "s3:ListBucket" | 
					
						
							|  |  |  |    ], | 
					
						
							|  |  |  |    "Resource": [ | 
					
						
							|  |  |  |     "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |    ] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ] | 
					
						
							|  |  |  | }`, bucket)) | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userCount := 50 | 
					
						
							|  |  |  | 	accessKeys := make([]string, userCount) | 
					
						
							|  |  |  | 	secretKeys := make([]string, userCount) | 
					
						
							|  |  |  | 	for i := 0; i < userCount; i++ { | 
					
						
							|  |  |  | 		accessKey, secretKey := mustGenerateCredentials(c) | 
					
						
							|  |  |  | 		err = s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("Unable to set user: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = s.adm.SetPolicy(ctx, policy, accessKey, false) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		accessKeys[i] = accessKey | 
					
						
							|  |  |  | 		secretKeys[i] = secretKey | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-05 12:57:35 +08:00
										 |  |  | 	g := errgroup.Group{} | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	for i := 0; i < userCount; i++ { | 
					
						
							| 
									
										
										
										
											2023-03-05 12:57:35 +08:00
										 |  |  | 		g.Go(func(i int) func() error { | 
					
						
							|  |  |  | 			return func() error { | 
					
						
							|  |  |  | 				uClient := s.getUserClient(c, accessKeys[i], secretKeys[i], "") | 
					
						
							|  |  |  | 				err := s.adm.RemoveUser(ctx, accessKeys[i]) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				c.mustNotListObjects(ctx, uClient, bucket) | 
					
						
							|  |  |  | 				return nil | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-03-05 12:57:35 +08:00
										 |  |  | 		}(i), i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if errs := g.Wait(); len(errs) > 0 { | 
					
						
							|  |  |  | 		c.Fatalf("unable to remove users: %v", errs) | 
					
						
							| 
									
										
										
										
											2021-11-02 06:03:07 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |