diff --git a/cmd/iam.go b/cmd/iam.go index 07debbe6c..52de3fe2d 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -1425,6 +1425,8 @@ func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args, parentUser string) bool { return false } policies = newMappedPolicy(sys.rolesMap[arn]).toSlice() + } else if parentUser == globalActiveCred.AccessKey { + policies = []string{"consoleAdmin"} } else { // Lookup the parent user's mapping if there's no role-ARN. mp, ok := sys.store.GetMappedPolicy(parentUser, false) diff --git a/cmd/sts-handlers_test.go b/cmd/sts-handlers_test.go index 47c3dfba5..c907ff7a0 100644 --- a/cmd/sts-handlers_test.go +++ b/cmd/sts-handlers_test.go @@ -31,11 +31,14 @@ import ( "github.com/minio/madmin-go" minio "github.com/minio/minio-go/v7" cr "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/minio/minio-go/v7/pkg/set" "golang.org/x/oauth2" ) func runAllIAMSTSTests(suite *TestSuiteIAM, c *check) { suite.SetUpSuite(c) + // The STS for root test needs to be the first one after setup. + suite.TestSTSForRoot(c) suite.TestSTS(c) suite.TearDownSuite(c) } @@ -154,6 +157,81 @@ func (s *TestSuiteIAM) TestSTS(c *check) { } } +// 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") + } +} + func (s *TestSuiteIAM) GetLDAPServer(c *check) string { return os.Getenv(EnvTestLDAPServer) }