| 
									
										
										
										
											2021-10-29 00:05:51 +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/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 05:46:50 +08:00
										 |  |  | 	"github.com/minio/madmin-go/v2" | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	minio "github.com/minio/minio-go/v7" | 
					
						
							|  |  |  | 	cr "github.com/minio/minio-go/v7/pkg/credentials" | 
					
						
							| 
									
										
										
										
											2021-12-20 15:05:20 +08:00
										 |  |  | 	"github.com/minio/minio-go/v7/pkg/set" | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func runAllIAMSTSTests(suite *TestSuiteIAM, c *check) { | 
					
						
							|  |  |  | 	suite.SetUpSuite(c) | 
					
						
							| 
									
										
										
										
											2021-12-20 15:05:20 +08:00
										 |  |  | 	// The STS for root test needs to be the first one after setup.
 | 
					
						
							|  |  |  | 	suite.TestSTSForRoot(c) | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	suite.TestSTS(c) | 
					
						
							| 
									
										
										
										
											2023-02-08 10:31:00 +08:00
										 |  |  | 	suite.TestSTSWithDenyDeleteVersion(c) | 
					
						
							| 
									
										
										
										
											2022-10-03 03:29:29 +08:00
										 |  |  | 	suite.TestSTSWithTags(c) | 
					
						
							| 
									
										
										
										
											2023-02-10 22:52:31 +08:00
										 |  |  | 	suite.TestSTSServiceAccountsWithUsername(c) | 
					
						
							| 
									
										
										
										
											2021-12-21 06:07:16 +08:00
										 |  |  | 	suite.TestSTSWithGroupPolicy(c) | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	suite.TearDownSuite(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIAMInternalIDPSTSServerSuite(t *testing.T) { | 
					
						
							| 
									
										
										
										
											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-10-29 00:05:51 +08:00
										 |  |  | 		// Init and run test on Erasure backend.
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 		{serverType: "Erasure", signer: signerV4}, | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +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-10-29 00:05:51 +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) { | 
					
						
							|  |  |  | 				runAllIAMSTSTests(testCase, &check{t, testCase.serverType}) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 22:52:31 +08:00
										 |  |  | func (s *TestSuiteIAM) TestSTSServiceAccountsWithUsername(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := "dillon-bucket" | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy
 | 
					
						
							|  |  |  | 	policy := "mypolicy-username" | 
					
						
							|  |  |  | 	policyBytes := []byte(`{ | 
					
						
							|  |  |  |  "Version": "2012-10-17", | 
					
						
							|  |  |  |  "Statement": [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |    "Effect": "Allow", | 
					
						
							|  |  |  |    "Action": [ | 
					
						
							|  |  |  |     "s3:*" | 
					
						
							|  |  |  |    ], | 
					
						
							|  |  |  |    "Resource": [ | 
					
						
							|  |  |  |     "arn:aws:s3:::${aws:username}-*" | 
					
						
							|  |  |  |    ] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ] | 
					
						
							|  |  |  | }`) | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err = s.adm.AddUser(ctx, "dillon", "dillon-123"); err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, "dillon", false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: "dillon", | 
					
						
							|  |  |  | 			SecretKey: "dillon-123", | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that the LDAP sts cred is actually working.
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	svcClient := s.getUserClient(c, cr.AccessKey, cr.SecretKey, "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check S3 access for service account ListObjects()
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, svcClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check S3 access for upload
 | 
					
						
							|  |  |  | 	c.mustUpload(ctx, svcClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access for download
 | 
					
						
							|  |  |  | 	c.mustDownload(ctx, svcClient, bucket) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 10:31:00 +08:00
										 |  |  | func (s *TestSuiteIAM) TestSTSWithDenyDeleteVersion(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{ObjectLocking: true}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy, user and associate policy
 | 
					
						
							|  |  |  | 	policy := "mypolicy" | 
					
						
							|  |  |  | 	policyBytes := []byte(fmt.Sprintf(`{ | 
					
						
							|  |  |  |   "Version": "2012-10-17", | 
					
						
							|  |  |  |   "Statement": [ | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |     "Sid": "ObjectActionsRW", | 
					
						
							|  |  |  |     "Effect": "Allow", | 
					
						
							|  |  |  |     "Action": [ | 
					
						
							|  |  |  |      "s3:PutObject", | 
					
						
							|  |  |  |      "s3:PutObjectTagging", | 
					
						
							|  |  |  |      "s3:AbortMultipartUpload", | 
					
						
							|  |  |  |      "s3:DeleteObject", | 
					
						
							|  |  |  |      "s3:GetObject", | 
					
						
							|  |  |  |      "s3:GetObjectTagging", | 
					
						
							|  |  |  |      "s3:GetObjectVersion", | 
					
						
							|  |  |  |      "s3:ListMultipartUploadParts" | 
					
						
							|  |  |  |     ], | 
					
						
							|  |  |  |     "Resource": [ | 
					
						
							|  |  |  |      "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |    }, | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |     "Sid": "DenyDeleteVersionAction", | 
					
						
							|  |  |  |     "Effect": "Deny", | 
					
						
							|  |  |  |     "Action": [ | 
					
						
							|  |  |  |      "s3:DeleteObjectVersion" | 
					
						
							|  |  |  |     ], | 
					
						
							|  |  |  |     "Resource": [ | 
					
						
							|  |  |  |      "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  |  } | 
					
						
							|  |  |  | `, bucket, bucket)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// confirm that the user is able to access the bucket
 | 
					
						
							|  |  |  | 	uClient := s.getUserClient(c, accessKey, secretKey, "") | 
					
						
							|  |  |  | 	versions := c.mustUploadReturnVersions(ctx, uClient, bucket) | 
					
						
							|  |  |  | 	c.mustNotDelete(ctx, uClient, bucket, versions[0]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: accessKey, | 
					
						
							|  |  |  | 			SecretKey: secretKey, | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("err calling assumeRole: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	versions = c.mustUploadReturnVersions(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 	c.mustNotDelete(ctx, minioClient, bucket, versions[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 03:29:29 +08:00
										 |  |  | func (s *TestSuiteIAM) TestSTSWithTags(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	object := getRandomObjectName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy, user and associate policy
 | 
					
						
							|  |  |  | 	policy := "mypolicy" | 
					
						
							|  |  |  | 	policyBytes := []byte(fmt.Sprintf(`{ | 
					
						
							|  |  |  |   "Version": "2012-10-17", | 
					
						
							|  |  |  |   "Statement": [ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       "Effect":     "Allow", | 
					
						
							|  |  |  |       "Action":     "s3:GetObject", | 
					
						
							|  |  |  |       "Resource":    "arn:aws:s3:::%s/*", | 
					
						
							|  |  |  |       "Condition": {  "StringEquals": {"s3:ExistingObjectTag/security": "public" } } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       "Effect":     "Allow", | 
					
						
							|  |  |  |       "Action":     "s3:DeleteObjectTagging", | 
					
						
							|  |  |  |       "Resource":    "arn:aws:s3:::%s/*", | 
					
						
							|  |  |  |       "Condition": {  "StringEquals": {"s3:ExistingObjectTag/security": "public" } } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       "Effect":     "Allow", | 
					
						
							|  |  |  |       "Action":     "s3:DeleteObject", | 
					
						
							|  |  |  |       "Resource":    "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       "Effect": "Allow", | 
					
						
							|  |  |  |       "Action": [ | 
					
						
							|  |  |  |         "s3:PutObject" | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       "Resource": [ | 
					
						
							|  |  |  |         "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       "Condition": { | 
					
						
							|  |  |  |         "ForAllValues:StringLike": { | 
					
						
							|  |  |  |           "s3:RequestObjectTagKeys": [ | 
					
						
							|  |  |  |             "security", | 
					
						
							|  |  |  |             "virus" | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | }`, bucket, bucket, bucket, bucket)) | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// confirm that the user is able to access the bucket
 | 
					
						
							|  |  |  | 	uClient := s.getUserClient(c, accessKey, secretKey, "") | 
					
						
							|  |  |  | 	c.mustPutObjectWithTags(ctx, uClient, bucket, object) | 
					
						
							|  |  |  | 	c.mustGetObject(ctx, uClient, bucket, object) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: accessKey, | 
					
						
							|  |  |  | 			SecretKey: secretKey, | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("err calling assumeRole: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate sts creds can access the object
 | 
					
						
							| 
									
										
										
										
											2023-02-08 10:31:00 +08:00
										 |  |  | 	c.mustPutObjectWithTags(ctx, minioClient, bucket, object) | 
					
						
							|  |  |  | 	c.mustGetObject(ctx, minioClient, bucket, object) | 
					
						
							|  |  |  | 	c.mustHeadObject(ctx, minioClient, bucket, object, 2) | 
					
						
							| 
									
										
										
										
											2022-10-03 03:29:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client can remove objects
 | 
					
						
							|  |  |  | 	if err = minioClient.RemoveObjectTagging(ctx, bucket, object, minio.RemoveObjectTaggingOptions{}); err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("user is unable to delete the object tags: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err = minioClient.RemoveObject(ctx, bucket, object, minio.RemoveObjectOptions{}); err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("user is unable to delete the object: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | func (s *TestSuiteIAM) TestSTS(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy, user and associate 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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 10:47:49 +08:00
										 |  |  | 	// confirm that the user is able to access the bucket
 | 
					
						
							|  |  |  | 	uClient := s.getUserClient(c, accessKey, secretKey, "") | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, uClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 00:05:51 +08:00
										 |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: accessKey, | 
					
						
							|  |  |  | 			SecretKey: secretKey, | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("err calling assumeRole: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client cannot remove any objects
 | 
					
						
							|  |  |  | 	err = minioClient.RemoveObject(ctx, bucket, "someobject", minio.RemoveObjectOptions{}) | 
					
						
							|  |  |  | 	if err.Error() != "Access Denied." { | 
					
						
							|  |  |  | 		c.Fatalf("unexpected non-access-denied err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-21 06:07:16 +08:00
										 |  |  | func (s *TestSuiteIAM) TestSTSWithGroupPolicy(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy, user and associate 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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accessKey, secretKey := mustGenerateCredentials(c) | 
					
						
							|  |  |  | 	err = s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set user: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// confirm that the user is unable to access the bucket - we have not
 | 
					
						
							|  |  |  | 	// yet set any policy
 | 
					
						
							|  |  |  | 	uClient := s.getUserClient(c, accessKey, secretKey, "") | 
					
						
							|  |  |  | 	c.mustNotListObjects(ctx, uClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = s.adm.UpdateGroupMembers(ctx, madmin.GroupAddRemove{ | 
					
						
							|  |  |  | 		Group:   "test-group", | 
					
						
							|  |  |  | 		Members: []string{accessKey}, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("unable to add user to group: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, "test-group", true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// confirm that the user is able to access the bucket - permission comes
 | 
					
						
							|  |  |  | 	// from group.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, uClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create STS user.
 | 
					
						
							|  |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: accessKey, | 
					
						
							|  |  |  | 			SecretKey: secretKey, | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("err calling assumeRole: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that STS user client has access coming from parent user's
 | 
					
						
							|  |  |  | 	// group.
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client cannot remove any objects
 | 
					
						
							|  |  |  | 	err = minioClient.RemoveObject(ctx, bucket, "someobject", minio.RemoveObjectOptions{}) | 
					
						
							|  |  |  | 	if err.Error() != "Access Denied." { | 
					
						
							|  |  |  | 		c.Fatalf("unexpected non-access-denied err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-20 15:05:20 +08:00
										 |  |  | // TestSTSForRoot - needs to be the first test after server setup due to the
 | 
					
						
							|  |  |  | // buckets list check.
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestSTSForRoot(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assumeRole := cr.STSAssumeRole{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		Options: cr.STSAssumeRoleOptions{ | 
					
						
							|  |  |  | 			AccessKey: globalActiveCred.AccessKey, | 
					
						
							|  |  |  | 			SecretKey: globalActiveCred.SecretKey, | 
					
						
							|  |  |  | 			Location:  "", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := assumeRole.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("err calling assumeRole: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that a bucket can be created
 | 
					
						
							|  |  |  | 	bucket2 := getRandomBucketName() | 
					
						
							|  |  |  | 	err = minioClient.MakeBucket(ctx, bucket2, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket creat error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that admin APIs can be called - create an madmin client with
 | 
					
						
							|  |  |  | 	// user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accInfo, err := userAdmClient.AccountInfo(ctx, madmin.AccountOpts{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("root user STS should be able to get account info: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gotBuckets := set.NewStringSet() | 
					
						
							|  |  |  | 	for _, b := range accInfo.Buckets { | 
					
						
							|  |  |  | 		gotBuckets.Add(b.Name) | 
					
						
							|  |  |  | 		if !(b.Access.Read && b.Access.Write) { | 
					
						
							|  |  |  | 			c.Fatalf("root user should have read and write access to bucket: %v", b.Name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	shouldHaveBuckets := set.CreateStringSet(bucket2, bucket) | 
					
						
							|  |  |  | 	if !gotBuckets.Equals(shouldHaveBuckets) { | 
					
						
							|  |  |  | 		c.Fatalf("root user should have access to all buckets") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-03-14 03:46:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// This must fail.
 | 
					
						
							|  |  |  | 	if err := userAdmClient.AddUser(ctx, globalActiveCred.AccessKey, globalActiveCred.SecretKey); err == nil { | 
					
						
							|  |  |  | 		c.Fatal("AddUser() for root credential must fail via root STS creds") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-12-20 15:05:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | // SetUpLDAP - expects to setup an LDAP test server using the test LDAP
 | 
					
						
							|  |  |  | // container and canned data from https://github.com/minio/minio-ldap-testing
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | func (s *TestSuiteIAM) SetUpLDAP(c *check, serverAddr string) { | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configCmds := []string{ | 
					
						
							|  |  |  | 		"identity_ldap", | 
					
						
							|  |  |  | 		fmt.Sprintf("server_addr=%s", serverAddr), | 
					
						
							|  |  |  | 		"server_insecure=on", | 
					
						
							|  |  |  | 		"lookup_bind_dn=cn=admin,dc=min,dc=io", | 
					
						
							|  |  |  | 		"lookup_bind_password=admin", | 
					
						
							|  |  |  | 		"user_dn_search_base_dn=dc=min,dc=io", | 
					
						
							|  |  |  | 		"user_dn_search_filter=(uid=%s)", | 
					
						
							|  |  |  | 		"group_search_base_dn=ou=swengg,dc=min,dc=io", | 
					
						
							|  |  |  | 		"group_search_filter=(&(objectclass=groupofnames)(member=%d))", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_, err := s.adm.SetConfigKV(ctx, strings.Join(configCmds, " ")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("unable to setup LDAP for tests: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s.RestartIAMSuite(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	EnvTestLDAPServer = "LDAP_TEST_SERVER" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | func TestIAMWithLDAPServerSuite(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 		t.Run( | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ldapServer := os.Getenv(EnvTestLDAPServer) | 
					
						
							|  |  |  | 				if ldapServer == "" { | 
					
						
							|  |  |  | 					c.Skip("Skipping LDAP test as no LDAP server is provided.") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				suite.SetUpLDAP(c, ldapServer) | 
					
						
							|  |  |  | 				suite.TestLDAPSTS(c) | 
					
						
							| 
									
										
										
										
											2021-11-25 07:19:33 +08:00
										 |  |  | 				suite.TestLDAPSTSServiceAccounts(c) | 
					
						
							| 
									
										
										
										
											2023-02-07 19:43:08 +08:00
										 |  |  | 				suite.TestLDAPSTSServiceAccountsWithUsername(c) | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | 				suite.TestLDAPSTSServiceAccountsWithGroups(c) | 
					
						
							| 
									
										
										
										
											2021-11-10 01:25:13 +08:00
										 |  |  | 				suite.TearDownSuite(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestLDAPSTS(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 	// Create policy
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldapID := cr.LDAPIdentity{ | 
					
						
							|  |  |  | 		Client:       s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint:  s.endPoint, | 
					
						
							|  |  |  | 		LDAPUsername: "dillon", | 
					
						
							|  |  |  | 		LDAPPassword: "dillon", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 		c.Fatalf("Expected to fail to create STS cred with no associated policy!") | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-14 07:55:52 +08:00
										 |  |  | 	// Attempting to set a non-existent policy should fail.
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	userDN := "uid=dillon,ou=people,ou=swengg,dc=min,dc=io" | 
					
						
							| 
									
										
										
										
											2021-12-14 07:55:52 +08:00
										 |  |  | 	err = s.adm.SetPolicy(ctx, policy+"x", userDN, false) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		c.Fatalf("should not be able to set non-existent policy") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	err = s.adm.SetPolicy(ctx, policy, userDN, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-10 07:55:28 +08:00
										 |  |  | 	// Validate that user listing does not return any entries
 | 
					
						
							|  |  |  | 	usersList, err := s.adm.ListUsers(ctx) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("list users should not fail: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-16 12:26:02 +08:00
										 |  |  | 	if len(usersList) != 1 { | 
					
						
							|  |  |  | 		c.Fatalf("expected user listing output: %v", usersList) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	uinfo := usersList[userDN] | 
					
						
							|  |  |  | 	if uinfo.PolicyName != policy || uinfo.Status != madmin.AccountEnabled { | 
					
						
							|  |  |  | 		c.Fatalf("expected user listing content: %v", uinfo) | 
					
						
							| 
									
										
										
										
											2021-12-10 07:55:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 23:16:30 +08:00
										 |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client cannot remove any objects
 | 
					
						
							|  |  |  | 	err = minioClient.RemoveObject(ctx, bucket, "someobject", minio.RemoveObjectOptions{}) | 
					
						
							|  |  |  | 	if err.Error() != "Access Denied." { | 
					
						
							|  |  |  | 		c.Fatalf("unexpected non-access-denied err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Remove the policy assignment on the user DN:
 | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, "", userDN, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to remove policy setting: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to fail to create a user with no associated policy!") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set policy via group and validate policy assignment.
 | 
					
						
							|  |  |  | 	groupDN := "cn=projectb,ou=groups,ou=swengg,dc=min,dc=io" | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, groupDN, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set group policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err = ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err = minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client cannot remove any objects
 | 
					
						
							|  |  |  | 	err = minioClient.RemoveObject(ctx, bucket, "someobject", minio.RemoveObjectOptions{}) | 
					
						
							|  |  |  | 	c.Assert(err.Error(), "Access Denied.") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-25 07:19:33 +08:00
										 |  |  | func (s *TestSuiteIAM) TestLDAPSTSServiceAccounts(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create 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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userDN := "uid=dillon,ou=people,ou=swengg,dc=min,dc=io" | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, userDN, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldapID := cr.LDAPIdentity{ | 
					
						
							|  |  |  | 		Client:       s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint:  s.endPoint, | 
					
						
							|  |  |  | 		LDAPUsername: "dillon", | 
					
						
							|  |  |  | 		LDAPPassword: "dillon", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that the LDAP sts cred is actually working.
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check that svc account appears in listing
 | 
					
						
							|  |  |  | 	c.assertSvcAccAppearsInListing(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check that svc account info can be queried
 | 
					
						
							|  |  |  | 	c.assertSvcAccInfoQueryable(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey, true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access
 | 
					
						
							|  |  |  | 	c.assertSvcAccS3Access(ctx, s, cr, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that svc account can restrict the policy, and that the
 | 
					
						
							|  |  |  | 	// session policy can be updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSessionPolicyUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that service account's secret key and account status can be
 | 
					
						
							|  |  |  | 	// updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSecretKeyAndStatusUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 5. Check that service account can be deleted.
 | 
					
						
							|  |  |  | 	c.assertSvcAccDeletion(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							| 
									
										
										
										
											2022-04-12 06:30:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 6. Check that service account cannot be created for some other user.
 | 
					
						
							|  |  |  | 	c.mustNotCreateSvcAccount(ctx, globalActiveCred.AccessKey, userAdmClient) | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 19:43:08 +08:00
										 |  |  | func (s *TestSuiteIAM) TestLDAPSTSServiceAccountsWithUsername(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := "dillon" | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy
 | 
					
						
							|  |  |  | 	policy := "mypolicy-username" | 
					
						
							|  |  |  | 	policyBytes := []byte(`{ | 
					
						
							|  |  |  |  "Version": "2012-10-17", | 
					
						
							|  |  |  |  "Statement": [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |    "Effect": "Allow", | 
					
						
							|  |  |  |    "Action": [ | 
					
						
							|  |  |  |     "s3:PutObject", | 
					
						
							|  |  |  |     "s3:GetObject", | 
					
						
							|  |  |  |     "s3:ListBucket" | 
					
						
							|  |  |  |    ], | 
					
						
							|  |  |  |    "Resource": [ | 
					
						
							|  |  |  |     "arn:aws:s3:::${ldap:username}/*" | 
					
						
							|  |  |  |    ] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ] | 
					
						
							|  |  |  | }`) | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userDN := "uid=dillon,ou=people,ou=swengg,dc=min,dc=io" | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, userDN, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldapID := cr.LDAPIdentity{ | 
					
						
							|  |  |  | 		Client:       s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint:  s.endPoint, | 
					
						
							|  |  |  | 		LDAPUsername: "dillon", | 
					
						
							|  |  |  | 		LDAPPassword: "dillon", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that the LDAP sts cred is actually working.
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	svcClient := s.getUserClient(c, cr.AccessKey, cr.SecretKey, "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check S3 access for service account ListObjects()
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, svcClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check S3 access for upload
 | 
					
						
							|  |  |  | 	c.mustUpload(ctx, svcClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access for download
 | 
					
						
							|  |  |  | 	c.mustDownload(ctx, svcClient, bucket) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | // In this test, the parent users gets their permissions from a group, rather
 | 
					
						
							|  |  |  | // than having a policy set directly on them.
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestLDAPSTSServiceAccountsWithGroups(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create 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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	groupDN := "cn=projecta,ou=groups,ou=swengg,dc=min,dc=io" | 
					
						
							|  |  |  | 	err = s.adm.SetPolicy(ctx, policy, groupDN, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Unable to set policy: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldapID := cr.LDAPIdentity{ | 
					
						
							|  |  |  | 		Client:       s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint:  s.endPoint, | 
					
						
							|  |  |  | 		LDAPUsername: "dillon", | 
					
						
							|  |  |  | 		LDAPPassword: "dillon", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := ldapID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that the LDAP sts cred is actually working.
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							| 
									
										
										
										
											2021-11-25 07:19:33 +08:00
										 |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check that svc account appears in listing
 | 
					
						
							|  |  |  | 	c.assertSvcAccAppearsInListing(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check that svc account info can be queried
 | 
					
						
							|  |  |  | 	c.assertSvcAccInfoQueryable(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey, true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access
 | 
					
						
							|  |  |  | 	c.assertSvcAccS3Access(ctx, s, cr, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that svc account can restrict the policy, and that the
 | 
					
						
							|  |  |  | 	// session policy can be updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSessionPolicyUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that service account's secret key and account status can be
 | 
					
						
							|  |  |  | 	// updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSecretKeyAndStatusUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 5. Check that service account can be deleted.
 | 
					
						
							|  |  |  | 	c.assertSvcAccDeletion(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							| 
									
										
										
										
											2022-04-12 06:30:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 6. Check that service account cannot be created for some other user.
 | 
					
						
							|  |  |  | 	c.mustNotCreateSvcAccount(ctx, globalActiveCred.AccessKey, userAdmClient) | 
					
						
							| 
									
										
										
										
											2021-11-25 07:19:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | func (s *TestSuiteIAM) TestOpenIDSTS(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity STS token by interacting with OpenID IDP.
 | 
					
						
							| 
									
										
										
										
											2022-01-08 09:41:43 +08:00
										 |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, testAppParams, "dillon@example.io", "dillon") | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// fmt.Printf("TOKEN: %s\n", token)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy - with name as one of the groups in OpenID the user is
 | 
					
						
							|  |  |  | 	// a member of.
 | 
					
						
							|  |  |  | 	policy := "projecta" | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client cannot remove any objects
 | 
					
						
							|  |  |  | 	err = minioClient.RemoveObject(ctx, bucket, "someobject", minio.RemoveObjectOptions{}) | 
					
						
							|  |  |  | 	if err.Error() != "Access Denied." { | 
					
						
							|  |  |  | 		c.Fatalf("unexpected non-access-denied err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-11 05:04:21 +08:00
										 |  |  | func (s *TestSuiteIAM) TestOpenIDSTSAddUser(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity STS token by interacting with OpenID IDP.
 | 
					
						
							| 
									
										
										
										
											2022-01-08 09:41:43 +08:00
										 |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, testAppParams, "dillon@example.io", "dillon") | 
					
						
							| 
									
										
										
										
											2021-12-11 05:04:21 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy - with name as one of the groups in OpenID the user is
 | 
					
						
							|  |  |  | 	// a member of.
 | 
					
						
							|  |  |  | 	policy := "projecta" | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.mustNotCreateIAMUser(ctx, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create admin user policy.
 | 
					
						
							|  |  |  | 	policyBytes = []byte(`{ | 
					
						
							|  |  |  |  "Version": "2012-10-17", | 
					
						
							|  |  |  |  "Statement": [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |    "Effect": "Allow", | 
					
						
							|  |  |  |    "Action": [ | 
					
						
							|  |  |  |     "admin:*" | 
					
						
							|  |  |  |    ] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ] | 
					
						
							|  |  |  | }`) | 
					
						
							|  |  |  | 	err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-11 07:03:39 +08:00
										 |  |  | 	cr := c.mustCreateIAMUser(ctx, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userInfo := c.mustGetIAMUserInfo(ctx, userAdmClient, cr.AccessKey) | 
					
						
							|  |  |  | 	c.Assert(userInfo.Status, madmin.AccountEnabled) | 
					
						
							| 
									
										
										
										
											2021-12-11 05:04:21 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 18:07:16 +08:00
										 |  |  | func (s *TestSuiteIAM) TestOpenIDServiceAcc(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity STS token by interacting with OpenID IDP.
 | 
					
						
							| 
									
										
										
										
											2022-01-08 09:41:43 +08:00
										 |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, testAppParams, "dillon@example.io", "dillon") | 
					
						
							| 
									
										
										
										
											2021-11-20 18:07:16 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policy - with name as one of the groups in OpenID the user is
 | 
					
						
							|  |  |  | 	// a member of.
 | 
					
						
							|  |  |  | 	policy := "projecta" | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check that svc account appears in listing
 | 
					
						
							|  |  |  | 	c.assertSvcAccAppearsInListing(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check that svc account info can be queried
 | 
					
						
							|  |  |  | 	c.assertSvcAccInfoQueryable(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey, true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access
 | 
					
						
							|  |  |  | 	c.assertSvcAccS3Access(ctx, s, cr, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that svc account can restrict the policy, and that the
 | 
					
						
							|  |  |  | 	// session policy can be updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSessionPolicyUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that service account's secret key and account status can be
 | 
					
						
							|  |  |  | 	// updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSecretKeyAndStatusUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 5. Check that service account can be deleted.
 | 
					
						
							|  |  |  | 	c.assertSvcAccDeletion(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							| 
									
										
										
										
											2022-04-12 06:30:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 6. Check that service account cannot be created for some other user.
 | 
					
						
							|  |  |  | 	c.mustNotCreateSvcAccount(ctx, globalActiveCred.AccessKey, userAdmClient) | 
					
						
							| 
									
										
										
										
											2021-11-20 18:07:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-08 09:41:43 +08:00
										 |  |  | var testAppParams = OpenIDClientAppParams{ | 
					
						
							|  |  |  | 	ClientID:     "minio-client-app", | 
					
						
							|  |  |  | 	ClientSecret: "minio-client-app-secret", | 
					
						
							|  |  |  | 	ProviderURL:  "http://127.0.0.1:5556/dex", | 
					
						
							|  |  |  | 	RedirectURL:  "http://127.0.0.1:10000/oauth_callback", | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	EnvTestOpenIDServer  = "OPENID_TEST_SERVER" | 
					
						
							|  |  |  | 	EnvTestOpenIDServer2 = "OPENID_TEST_SERVER_2" | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | // SetUpOpenIDs - sets up one or more OpenID test servers using the test OpenID
 | 
					
						
							|  |  |  | // container and canned data from https://github.com/minio/minio-ldap-testing
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Each set of client app params corresponds to a separate openid server, and
 | 
					
						
							|  |  |  | // the i-th server in this will be applied the i-th policy in `rolePolicies`. If
 | 
					
						
							|  |  |  | // a rolePolicies entry is an empty string, that server will be configured as
 | 
					
						
							|  |  |  | // policy-claim based openid server. NOTE that a valid configuration can have a
 | 
					
						
							|  |  |  | // policy claim based provider only if it is the only OpenID provider.
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) SetUpOpenIDs(c *check, testApps []OpenIDClientAppParams, rolePolicies []string) error { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, testApp := range testApps { | 
					
						
							|  |  |  | 		configCmds := []string{ | 
					
						
							|  |  |  | 			fmt.Sprintf("identity_openid:%d", i), | 
					
						
							|  |  |  | 			fmt.Sprintf("config_url=%s/.well-known/openid-configuration", testApp.ProviderURL), | 
					
						
							|  |  |  | 			fmt.Sprintf("client_id=%s", testApp.ClientID), | 
					
						
							|  |  |  | 			fmt.Sprintf("client_secret=%s", testApp.ClientSecret), | 
					
						
							|  |  |  | 			"scopes=openid,groups", | 
					
						
							|  |  |  | 			fmt.Sprintf("redirect_uri=%s", testApp.RedirectURL), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if rolePolicies[i] != "" { | 
					
						
							|  |  |  | 			configCmds = append(configCmds, fmt.Sprintf("role_policy=%s", rolePolicies[i])) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			configCmds = append(configCmds, "claim_name=groups") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		_, err := s.adm.SetConfigKV(ctx, strings.Join(configCmds, " ")) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return fmt.Errorf("unable to setup OpenID for tests: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s.RestartIAMSuite(c) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | // SetUpOpenID - expects to setup an OpenID test server using the test OpenID
 | 
					
						
							|  |  |  | // container and canned data from https://github.com/minio/minio-ldap-testing
 | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | func (s *TestSuiteIAM) SetUpOpenID(c *check, serverAddr string, rolePolicy string) { | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configCmds := []string{ | 
					
						
							|  |  |  | 		"identity_openid", | 
					
						
							|  |  |  | 		fmt.Sprintf("config_url=%s/.well-known/openid-configuration", serverAddr), | 
					
						
							|  |  |  | 		"client_id=minio-client-app", | 
					
						
							|  |  |  | 		"client_secret=minio-client-app-secret", | 
					
						
							|  |  |  | 		"scopes=openid,groups", | 
					
						
							|  |  |  | 		"redirect_uri=http://127.0.0.1:10000/oauth_callback", | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	if rolePolicy != "" { | 
					
						
							|  |  |  | 		configCmds = append(configCmds, fmt.Sprintf("role_policy=%s", rolePolicy)) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		configCmds = append(configCmds, "claim_name=groups") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 	_, err := s.adm.SetConfigKV(ctx, strings.Join(configCmds, " ")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("unable to setup OpenID for tests: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s.RestartIAMSuite(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIAMWithOpenIDServerSuite(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 		t.Run( | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 				if openIDServer == "" { | 
					
						
							|  |  |  | 					c.Skip("Skipping OpenID test as no OpenID server is provided.") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 				suite.SetUpOpenID(c, openIDServer, "") | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 				suite.TestOpenIDSTS(c) | 
					
						
							| 
									
										
										
										
											2021-11-20 18:07:16 +08:00
										 |  |  | 				suite.TestOpenIDServiceAcc(c) | 
					
						
							| 
									
										
										
										
											2021-12-11 05:04:21 +08:00
										 |  |  | 				suite.TestOpenIDSTSAddUser(c) | 
					
						
							| 
									
										
										
										
											2021-11-12 03:23:30 +08:00
										 |  |  | 				suite.TearDownSuite(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestIAMWithOpenIDWithRolePolicyServerSuite(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 		t.Run( | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 				if openIDServer == "" { | 
					
						
							|  |  |  | 					c.Skip("Skipping OpenID test as no OpenID server is provided.") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				suite.SetUpOpenID(c, openIDServer, "readwrite") | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 				suite.TestOpenIDSTSWithRolePolicy(c, testRoleARNs[0], testRoleMap[testRoleARNs[0]]) | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 				suite.TestOpenIDServiceAccWithRolePolicy(c) | 
					
						
							|  |  |  | 				suite.TearDownSuite(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 00:45:36 +08:00
										 |  |  | func TestIAMWithOpenIDWithRolePolicyWithPolicyVariablesServerSuite(t *testing.T) { | 
					
						
							|  |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 				if openIDServer == "" { | 
					
						
							|  |  |  | 					c.Skip("Skipping OpenID test as no OpenID server is provided.") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				suite.SetUpOpenID(c, openIDServer, "projecta,projectb,projectaorb") | 
					
						
							|  |  |  | 				suite.TestOpenIDSTSWithRolePolicyWithPolVar(c, testRoleARNs[0], testRoleMap[testRoleARNs[0]]) | 
					
						
							|  |  |  | 				suite.TearDownSuite(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	testRoleARN  = "arn:minio:iam:::role/nOybJqMNzNmroqEKq5D0EUsRZw0" | 
					
						
							|  |  |  | 	testRoleARN2 = "arn:minio:iam:::role/domXb70kze7Ugc1SaxaeFchhLP4" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	testRoleARNs = []string{testRoleARN, testRoleARN2} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Load test client app and test role mapping depending on test
 | 
					
						
							|  |  |  | 	// environment.
 | 
					
						
							|  |  |  | 	testClientApps, testRoleMap = func() ([]OpenIDClientAppParams, map[string]OpenIDClientAppParams) { | 
					
						
							|  |  |  | 		var apps []OpenIDClientAppParams | 
					
						
							|  |  |  | 		m := map[string]OpenIDClientAppParams{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 		if openIDServer != "" { | 
					
						
							|  |  |  | 			apps = append(apps, OpenIDClientAppParams{ | 
					
						
							|  |  |  | 				ClientID:     "minio-client-app", | 
					
						
							|  |  |  | 				ClientSecret: "minio-client-app-secret", | 
					
						
							|  |  |  | 				ProviderURL:  openIDServer, | 
					
						
							|  |  |  | 				RedirectURL:  "http://127.0.0.1:10000/oauth_callback", | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			m[testRoleARNs[len(apps)-1]] = apps[len(apps)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		openIDServer2 := os.Getenv(EnvTestOpenIDServer2) | 
					
						
							|  |  |  | 		if openIDServer2 != "" { | 
					
						
							|  |  |  | 			apps = append(apps, OpenIDClientAppParams{ | 
					
						
							|  |  |  | 				ClientID:     "minio-client-app-2", | 
					
						
							|  |  |  | 				ClientSecret: "minio-client-app-secret-2", | 
					
						
							|  |  |  | 				ProviderURL:  openIDServer2, | 
					
						
							|  |  |  | 				RedirectURL:  "http://127.0.0.1:10000/oauth_callback", | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			m[testRoleARNs[len(apps)-1]] = apps[len(apps)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return apps, m | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | func (s *TestSuiteIAM) TestOpenIDSTSWithRolePolicy(c *check, roleARN string, clientApp OpenIDClientAppParams) { | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	// Generate web identity JWT by interacting with OpenID IDP.
 | 
					
						
							|  |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, clientApp, "dillon@example.io", "dillon") | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	// Generate STS credential.
 | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 		RoleARN: roleARN, | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// fmt.Printf("value: %#v\n", value)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestOpenIDServiceAccWithRolePolicy(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity STS token by interacting with OpenID IDP.
 | 
					
						
							| 
									
										
										
										
											2022-01-08 09:41:43 +08:00
										 |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, testAppParams, "dillon@example.io", "dillon") | 
					
						
							| 
									
										
										
										
											2021-11-27 11:22:40 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		RoleARN: testRoleARN, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check that svc account appears in listing
 | 
					
						
							|  |  |  | 	c.assertSvcAccAppearsInListing(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check that svc account info can be queried
 | 
					
						
							|  |  |  | 	c.assertSvcAccInfoQueryable(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey, true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access
 | 
					
						
							|  |  |  | 	c.assertSvcAccS3Access(ctx, s, cr, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that svc account can restrict the policy, and that the
 | 
					
						
							|  |  |  | 	// session policy can be updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSessionPolicyUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that service account's secret key and account status can be
 | 
					
						
							|  |  |  | 	// updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSecretKeyAndStatusUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 5. Check that service account can be deleted.
 | 
					
						
							|  |  |  | 	c.assertSvcAccDeletion(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 00:45:36 +08:00
										 |  |  | // Constants for Policy Variables test.
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	policyProjectA = `{ | 
					
						
							|  |  |  |     "Version": "2012-10-17", | 
					
						
							|  |  |  |     "Statement": [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": [ | 
					
						
							|  |  |  |                         "s3:GetBucketLocation", | 
					
						
							|  |  |  |                         "s3:ListAllMyBuckets" | 
					
						
							|  |  |  |                       ], | 
					
						
							|  |  |  |             "Resource": "arn:aws:s3:::*" | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": "s3:*", | 
					
						
							|  |  |  |             "Resource": [ | 
					
						
							|  |  |  |                 "arn:aws:s3:::projecta", | 
					
						
							|  |  |  |                 "arn:aws:s3:::projecta/*" | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             "Condition": { | 
					
						
							|  |  |  |                 "ForAnyValue:StringEquals": { | 
					
						
							|  |  |  |                     "jwt:groups": [ | 
					
						
							|  |  |  |                         "projecta" | 
					
						
							|  |  |  |                     ] | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	policyProjectB = `{ | 
					
						
							|  |  |  |     "Version": "2012-10-17", | 
					
						
							|  |  |  |     "Statement": [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": [ | 
					
						
							|  |  |  |                         "s3:GetBucketLocation", | 
					
						
							|  |  |  |                         "s3:ListAllMyBuckets" | 
					
						
							|  |  |  |                       ], | 
					
						
							|  |  |  |             "Resource": "arn:aws:s3:::*" | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": "s3:*", | 
					
						
							|  |  |  |             "Resource": [ | 
					
						
							|  |  |  |                 "arn:aws:s3:::projectb", | 
					
						
							|  |  |  |                 "arn:aws:s3:::projectb/*" | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             "Condition": { | 
					
						
							|  |  |  |                 "ForAnyValue:StringEquals": { | 
					
						
							|  |  |  |                     "jwt:groups": [ | 
					
						
							|  |  |  |                         "projectb" | 
					
						
							|  |  |  |                     ] | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	policyProjectAorB = `{ | 
					
						
							|  |  |  |     "Version": "2012-10-17", | 
					
						
							|  |  |  |     "Statement": [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": [ | 
					
						
							|  |  |  |                         "s3:GetBucketLocation", | 
					
						
							|  |  |  |                         "s3:ListAllMyBuckets" | 
					
						
							|  |  |  |                       ], | 
					
						
							|  |  |  |             "Resource": "arn:aws:s3:::*" | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Effect": "Allow", | 
					
						
							|  |  |  |             "Action": "s3:*", | 
					
						
							|  |  |  |             "Resource": [ | 
					
						
							|  |  |  |                 "arn:aws:s3:::projectaorb", | 
					
						
							|  |  |  |                 "arn:aws:s3:::projectaorb/*" | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             "Condition": { | 
					
						
							|  |  |  |                 "ForAnyValue:StringEquals": { | 
					
						
							|  |  |  |                     "jwt:groups": [ | 
					
						
							|  |  |  |                         "projecta", | 
					
						
							|  |  |  |                         "projectb" | 
					
						
							|  |  |  |                     ] | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | }` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policyProjectsMap = map[string]string{ | 
					
						
							|  |  |  | 		// grants access to bucket `projecta` if user is in group `projecta`
 | 
					
						
							|  |  |  | 		"projecta": policyProjectA, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// grants access to bucket `projectb` if user is in group `projectb`
 | 
					
						
							|  |  |  | 		"projectb": policyProjectB, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// grants access to bucket `projectaorb` if user is in either group
 | 
					
						
							|  |  |  | 		// `projecta` or `projectb`
 | 
					
						
							|  |  |  | 		"projectaorb": policyProjectAorB, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestOpenIDSTSWithRolePolicyWithPolVar(c *check, roleARN string, clientApp OpenIDClientAppParams) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create project buckets
 | 
					
						
							|  |  |  | 	buckets := []string{"projecta", "projectb", "projectaorb", "other"} | 
					
						
							|  |  |  | 	for _, bucket := range buckets { | 
					
						
							|  |  |  | 		err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create policies
 | 
					
						
							|  |  |  | 	for polName, polContent := range policyProjectsMap { | 
					
						
							|  |  |  | 		err := s.adm.AddCannedPolicy(ctx, polName, []byte(polContent)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("policy add error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	makeSTSClient := func(user, password string) *minio.Client { | 
					
						
							|  |  |  | 		// Generate web identity JWT by interacting with OpenID IDP.
 | 
					
						
							|  |  |  | 		token, err := MockOpenIDTestUserInteraction(ctx, clientApp, user, password) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Generate STS credential.
 | 
					
						
							|  |  |  | 		webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 			Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 			STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 			GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 				return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 					Token: token, | 
					
						
							|  |  |  | 				}, nil | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			RoleARN: roleARN, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		value, err := webID.Retrieve() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// fmt.Printf("value: %#v\n", value)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 			Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 			Secure:    s.secure, | 
					
						
							|  |  |  | 			Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return minioClient | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// user dillon's groups attribute is ["projecta", "projectb"]
 | 
					
						
							|  |  |  | 	dillonClient := makeSTSClient("dillon@example.io", "dillon") | 
					
						
							|  |  |  | 	// Validate client's permissions
 | 
					
						
							|  |  |  | 	c.mustListBuckets(ctx, dillonClient) | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, dillonClient, "projecta") | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, dillonClient, "projectb") | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, dillonClient, "projectaorb") | 
					
						
							|  |  |  | 	c.mustNotListObjects(ctx, dillonClient, "other") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// this user's groups attribute is ["projectb"]
 | 
					
						
							|  |  |  | 	lisaClient := makeSTSClient("ejones@example.io", "liza") | 
					
						
							|  |  |  | 	// Validate client's permissions
 | 
					
						
							|  |  |  | 	c.mustListBuckets(ctx, lisaClient) | 
					
						
							|  |  |  | 	c.mustNotListObjects(ctx, lisaClient, "projecta") | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, lisaClient, "projectb") | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, lisaClient, "projectaorb") | 
					
						
							|  |  |  | 	c.mustNotListObjects(ctx, lisaClient, "other") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-30 07:40:49 +08:00
										 |  |  | func TestIAMWithOpenIDMultipleConfigsValidation1(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 	openIDServer2 := os.Getenv(EnvTestOpenIDServer2) | 
					
						
							|  |  |  | 	if openIDServer == "" || openIDServer2 == "" { | 
					
						
							|  |  |  | 		t.Skip("Skipping OpenID test as enough OpenID servers are not provided.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testApps := testClientApps | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rolePolicies := []string{ | 
					
						
							|  |  |  | 		"", // Treated as claim-based provider as no role policy is given.
 | 
					
						
							|  |  |  | 		"readwrite", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-30 07:40:49 +08:00
										 |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				defer suite.TearDownSuite(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				err := suite.SetUpOpenIDs(c, testApps, rolePolicies) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					c.Fatalf("config with 1 claim based and 1 role based provider should pass but got: %v", err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIAMWithOpenIDMultipleConfigsValidation2(t *testing.T) { | 
					
						
							|  |  |  | 	openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 	openIDServer2 := os.Getenv(EnvTestOpenIDServer2) | 
					
						
							|  |  |  | 	if openIDServer == "" || openIDServer2 == "" { | 
					
						
							|  |  |  | 		t.Skip("Skipping OpenID test as enough OpenID servers are not provided.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testApps := testClientApps | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rolePolicies := []string{ | 
					
						
							|  |  |  | 		"", // Treated as claim-based provider as no role policy is given.
 | 
					
						
							|  |  |  | 		"", // Treated as claim-based provider as no role policy is given.
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				defer suite.TearDownSuite(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				err := suite.SetUpOpenIDs(c, testApps, rolePolicies) | 
					
						
							|  |  |  | 				if err == nil { | 
					
						
							| 
									
										
										
										
											2022-11-30 07:40:49 +08:00
										 |  |  | 					c.Fatalf("config with 2 claim based provider should fail") | 
					
						
							| 
									
										
										
										
											2022-04-29 09:27:09 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIAMWithOpenIDWithMultipleRolesServerSuite(t *testing.T) { | 
					
						
							|  |  |  | 	openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 	openIDServer2 := os.Getenv(EnvTestOpenIDServer2) | 
					
						
							|  |  |  | 	if openIDServer == "" || openIDServer2 == "" { | 
					
						
							|  |  |  | 		t.Skip("Skipping OpenID test as enough OpenID servers are not provided.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testApps := testClientApps | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rolePolicies := []string{ | 
					
						
							|  |  |  | 		"consoleAdmin", | 
					
						
							|  |  |  | 		"readwrite", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				err := suite.SetUpOpenIDs(c, testApps, rolePolicies) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					c.Fatalf("Error setting up openid providers for tests: %v", err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				suite.TestOpenIDSTSWithRolePolicy(c, testRoleARNs[0], testRoleMap[testRoleARNs[0]]) | 
					
						
							|  |  |  | 				suite.TestOpenIDSTSWithRolePolicy(c, testRoleARNs[1], testRoleMap[testRoleARNs[1]]) | 
					
						
							|  |  |  | 				suite.TestOpenIDServiceAccWithRolePolicy(c) | 
					
						
							|  |  |  | 				suite.TearDownSuite(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-05-14 03:48:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Access Management Plugin tests
 | 
					
						
							|  |  |  | func TestIAM_AMPWithOpenIDWithMultipleRolesServerSuite(t *testing.T) { | 
					
						
							|  |  |  | 	openIDServer := os.Getenv(EnvTestOpenIDServer) | 
					
						
							|  |  |  | 	openIDServer2 := os.Getenv(EnvTestOpenIDServer2) | 
					
						
							|  |  |  | 	if openIDServer == "" || openIDServer2 == "" { | 
					
						
							|  |  |  | 		t.Skip("Skipping OpenID test as enough OpenID servers are not provided.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testApps := testClientApps | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rolePolicies := []string{ | 
					
						
							|  |  |  | 		"consoleAdmin", | 
					
						
							|  |  |  | 		"readwrite", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, testCase := range iamTestSuites { | 
					
						
							|  |  |  | 		t.Run( | 
					
						
							|  |  |  | 			fmt.Sprintf("Test: %d, ServerType: %s", i+1, testCase.ServerTypeDescription), | 
					
						
							|  |  |  | 			func(t *testing.T) { | 
					
						
							|  |  |  | 				c := &check{t, testCase.serverType} | 
					
						
							|  |  |  | 				suite := testCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpSuite(c) | 
					
						
							|  |  |  | 				defer suite.TearDownSuite(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				err := suite.SetUpOpenIDs(c, testApps, rolePolicies) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					c.Fatalf("Error setting up openid providers for tests: %v", err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.SetUpAccMgmtPlugin(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				suite.TestOpenIDSTSWithRolePolicyUnderAMP(c, testRoleARNs[0], testRoleMap[testRoleARNs[0]]) | 
					
						
							|  |  |  | 				suite.TestOpenIDSTSWithRolePolicyUnderAMP(c, testRoleARNs[1], testRoleMap[testRoleARNs[1]]) | 
					
						
							|  |  |  | 				suite.TestOpenIDServiceAccWithRolePolicyUnderAMP(c) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestOpenIDSTSWithRolePolicyUnderAMP(c *check, roleARN string, clientApp OpenIDClientAppParams) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity JWT by interacting with OpenID IDP.
 | 
					
						
							|  |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, clientApp, "dillon@example.io", "dillon") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate STS credential.
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		RoleARN: roleARN, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// fmt.Printf("value: %#v\n", value)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	minioClient, err := minio.New(s.endpoint, &minio.Options{ | 
					
						
							|  |  |  | 		Creds:     cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure:    s.secure, | 
					
						
							|  |  |  | 		Transport: s.TestSuiteCommon.client.Transport, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Error initializing client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from sts creds can access the bucket.
 | 
					
						
							|  |  |  | 	c.mustListObjects(ctx, minioClient, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate that the client from STS creds cannot upload any object as
 | 
					
						
							|  |  |  | 	// it is denied by the plugin.
 | 
					
						
							|  |  |  | 	c.mustNotUpload(ctx, minioClient, bucket) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *TestSuiteIAM) TestOpenIDServiceAccWithRolePolicyUnderAMP(c *check) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := getRandomBucketName() | 
					
						
							|  |  |  | 	err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("bucket create error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate web identity STS token by interacting with OpenID IDP.
 | 
					
						
							|  |  |  | 	token, err := MockOpenIDTestUserInteraction(ctx, testAppParams, "dillon@example.io", "dillon") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("mock user err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webID := cr.STSWebIdentity{ | 
					
						
							|  |  |  | 		Client:      s.TestSuiteCommon.client, | 
					
						
							|  |  |  | 		STSEndpoint: s.endPoint, | 
					
						
							|  |  |  | 		GetWebIDTokenExpiry: func() (*cr.WebIdentityToken, error) { | 
					
						
							|  |  |  | 			return &cr.WebIdentityToken{ | 
					
						
							|  |  |  | 				Token: token, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		RoleARN: testRoleARN, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err := webID.Retrieve() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Expected to generate STS creds, got err: %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create an madmin client with user creds
 | 
					
						
							|  |  |  | 	userAdmClient, err := madmin.NewWithOptions(s.endpoint, &madmin.Options{ | 
					
						
							|  |  |  | 		Creds:  cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), | 
					
						
							|  |  |  | 		Secure: s.secure, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Fatalf("Err creating user admin client: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	userAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create svc acc
 | 
					
						
							|  |  |  | 	cr := c.mustCreateSvcAccount(ctx, value.AccessKeyID, userAdmClient) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. Check that svc account appears in listing
 | 
					
						
							|  |  |  | 	c.assertSvcAccAppearsInListing(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 2. Check that svc account info can be queried
 | 
					
						
							|  |  |  | 	c.assertSvcAccInfoQueryable(ctx, userAdmClient, value.AccessKeyID, cr.AccessKey, true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3. Check S3 access
 | 
					
						
							|  |  |  | 	c.assertSvcAccS3Access(ctx, s, cr, bucket) | 
					
						
							|  |  |  | 	// 3.1 Validate that the client from STS creds cannot upload any object as
 | 
					
						
							|  |  |  | 	// it is denied by the plugin.
 | 
					
						
							|  |  |  | 	c.mustNotUpload(ctx, s.getUserClient(c, cr.AccessKey, cr.SecretKey, ""), bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that session policies do not apply - as policy enforcement is
 | 
					
						
							|  |  |  | 	// delegated to plugin.
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		svcAK, svcSK := mustGenerateCredentials(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// This policy does not allow listing objects.
 | 
					
						
							|  |  |  | 		policyBytes := []byte(fmt.Sprintf(`{ | 
					
						
							|  |  |  |  "Version": "2012-10-17", | 
					
						
							|  |  |  |  "Statement": [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |    "Effect": "Allow", | 
					
						
							|  |  |  |    "Action": [ | 
					
						
							|  |  |  |     "s3:PutObject", | 
					
						
							|  |  |  |     "s3:GetObject" | 
					
						
							|  |  |  |    ], | 
					
						
							|  |  |  |    "Resource": [ | 
					
						
							|  |  |  |     "arn:aws:s3:::%s/*" | 
					
						
							|  |  |  |    ] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ] | 
					
						
							|  |  |  | }`, bucket)) | 
					
						
							|  |  |  | 		cr, err := userAdmClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{ | 
					
						
							|  |  |  | 			Policy:     policyBytes, | 
					
						
							|  |  |  | 			TargetUser: value.AccessKeyID, | 
					
						
							|  |  |  | 			AccessKey:  svcAK, | 
					
						
							|  |  |  | 			SecretKey:  svcSK, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.Fatalf("Unable to create svc acc: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		svcClient := s.getUserClient(c, cr.AccessKey, cr.SecretKey, "") | 
					
						
							|  |  |  | 		// Though the attached policy does not allow listing, it will be
 | 
					
						
							|  |  |  | 		// ignored because the plugin allows it.
 | 
					
						
							|  |  |  | 		c.mustListObjects(ctx, svcClient, bucket) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4. Check that service account's secret key and account status can be
 | 
					
						
							|  |  |  | 	// updated.
 | 
					
						
							|  |  |  | 	c.assertSvcAccSecretKeyAndStatusUpdate(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 5. Check that service account can be deleted.
 | 
					
						
							|  |  |  | 	c.assertSvcAccDeletion(ctx, s, userAdmClient, value.AccessKeyID, bucket) | 
					
						
							|  |  |  | } |