mirror of
https://github.com/minio/minio.git
synced 2024-12-25 22:55:54 -05:00
gcs: Check if the given project id argument exists (#4583)
Using GCS resource manager API, check if the provided project id is already created and associated to the current user account.
This commit is contained in:
parent
6b70f429ed
commit
eaa41e4086
@ -22,6 +22,9 @@ var (
|
|||||||
// Project ID format is not valid.
|
// Project ID format is not valid.
|
||||||
errGCSInvalidProjectID = errors.New("GCS project id is either empty or invalid")
|
errGCSInvalidProjectID = errors.New("GCS project id is either empty or invalid")
|
||||||
|
|
||||||
|
// Project ID not found
|
||||||
|
errGCSProjectIDNotFound = errors.New("unknown project id")
|
||||||
|
|
||||||
// Multipart identifier is not in the correct form.
|
// Multipart identifier is not in the correct form.
|
||||||
errGCSNotValidMultipartIdentifier = errors.New("Not a valid multipart identifier")
|
errGCSNotValidMultipartIdentifier = errors.New("Not a valid multipart identifier")
|
||||||
)
|
)
|
||||||
|
@ -29,7 +29,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2/google"
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
|
cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
|
|
||||||
@ -176,14 +179,56 @@ func gcsToObjectError(err error, params ...string) error {
|
|||||||
// gcsProjectIDRegex defines a valid gcs project id format
|
// gcsProjectIDRegex defines a valid gcs project id format
|
||||||
var gcsProjectIDRegex = regexp.MustCompile("^[a-z][a-z0-9-]{5,29}$")
|
var gcsProjectIDRegex = regexp.MustCompile("^[a-z][a-z0-9-]{5,29}$")
|
||||||
|
|
||||||
// isValidGCSProjectId - checks if a given project id is valid or not.
|
// isValidGCSProjectIDFormat - checks if a given project id format is valid or not.
|
||||||
// Project IDs must start with a lowercase letter and can have lowercase
|
// Project IDs must start with a lowercase letter and can have lowercase ASCII letters,
|
||||||
// ASCII letters, digits or hyphens. Project IDs must be between 6 and 30 characters.
|
// digits or hyphens. Project IDs must be between 6 and 30 characters.
|
||||||
// Ref: https://cloud.google.com/resource-manager/reference/rest/v1/projects#Project (projectId section)
|
// Ref: https://cloud.google.com/resource-manager/reference/rest/v1/projects#Project (projectId section)
|
||||||
func isValidGCSProjectID(projectID string) bool {
|
func isValidGCSProjectIDFormat(projectID string) bool {
|
||||||
|
// Checking projectID format
|
||||||
return gcsProjectIDRegex.MatchString(projectID)
|
return gcsProjectIDRegex.MatchString(projectID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkGCSProjectID - checks if the project ID does really exist using resource manager API.
|
||||||
|
func checkGCSProjectID(ctx context.Context, projectID string) error {
|
||||||
|
// Check if a project id associated to the current account does really exist
|
||||||
|
resourceManagerClient, err := google.DefaultClient(ctx, cloudresourcemanager.CloudPlatformReadOnlyScope)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
baseSvc, err := cloudresourcemanager.New(resourceManagerClient)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
projectSvc := cloudresourcemanager.NewProjectsService(baseSvc)
|
||||||
|
|
||||||
|
curPageToken := ""
|
||||||
|
|
||||||
|
// Iterate over projects list result pages and immediately return nil when
|
||||||
|
// the project ID is found.
|
||||||
|
for {
|
||||||
|
resp, err := projectSvc.List().PageToken(curPageToken).Context(ctx).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error getting projects list: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range resp.Projects {
|
||||||
|
if p.ProjectId == projectID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.NextPageToken != "" {
|
||||||
|
curPageToken = resp.NextPageToken
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errGCSProjectIDNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// gcsGateway - Implements gateway for Minio and GCS compatible object storage servers.
|
// gcsGateway - Implements gateway for Minio and GCS compatible object storage servers.
|
||||||
type gcsGateway struct {
|
type gcsGateway struct {
|
||||||
client *storage.Client
|
client *storage.Client
|
||||||
@ -198,6 +243,11 @@ const googleStorageEndpoint = "storage.googleapis.com"
|
|||||||
func newGCSGateway(projectID string) (GatewayLayer, error) {
|
func newGCSGateway(projectID string) (GatewayLayer, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
err := checkGCSProjectID(ctx, projectID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize a GCS client.
|
// Initialize a GCS client.
|
||||||
client, err := storage.NewClient(ctx)
|
client, err := storage.NewClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,8 +66,8 @@ func TestToGCSPageToken(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestValidGCSProjectID tests the behavior of isValidGCSProjectID
|
// TestIsValidGCSProjectIDFormat tests isValidGCSProjectIDFormat
|
||||||
func TestValidGCSProjectID(t *testing.T) {
|
func TestValidGCSProjectIDFormat(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
ProjectID string
|
ProjectID string
|
||||||
Valid bool
|
Valid bool
|
||||||
@ -93,8 +93,9 @@ func TestValidGCSProjectID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
if isValidGCSProjectID(testCase.ProjectID) != testCase.Valid {
|
valid := isValidGCSProjectIDFormat(testCase.ProjectID)
|
||||||
t.Errorf("Test %d: Expected %v, got %v", i+1, isValidGCSProjectID(testCase.ProjectID), testCase.Valid)
|
if valid != testCase.Valid {
|
||||||
|
t.Errorf("Test %d: Expected %v, got %v", i+1, valid, testCase.Valid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ func gcsGatewayMain(ctx *cli.Context) {
|
|||||||
cli.ShowCommandHelpAndExit(ctx, "gcs", 1)
|
cli.ShowCommandHelpAndExit(ctx, "gcs", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isValidGCSProjectID(ctx.Args().First()) {
|
if !isValidGCSProjectIDFormat(ctx.Args().First()) {
|
||||||
errorIf(errGCSInvalidProjectID, "Unable to start GCS gateway with %s", ctx.Args().First())
|
errorIf(errGCSInvalidProjectID, "Unable to start GCS gateway with %s", ctx.Args().First())
|
||||||
cli.ShowCommandHelpAndExit(ctx, "gcs", 1)
|
cli.ShowCommandHelpAndExit(ctx, "gcs", 1)
|
||||||
}
|
}
|
||||||
|
7794
vendor/google.golang.org/api/cloudresourcemanager/v1/cloudresourcemanager-gen.go
generated
vendored
Normal file
7794
vendor/google.golang.org/api/cloudresourcemanager/v1/cloudresourcemanager-gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -599,6 +599,12 @@
|
|||||||
"revision": "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4",
|
"revision": "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4",
|
||||||
"revisionTime": "2017-04-25T18:31:26Z"
|
"revisionTime": "2017-04-25T18:31:26Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "M1wpFKbvAwtmAafEAYAvJ5mUlf0=",
|
||||||
|
"path": "google.golang.org/api/cloudresourcemanager/v1",
|
||||||
|
"revision": "4a52eba41712e0b12c17258ac017e177abeaf535",
|
||||||
|
"revisionTime": "2017-06-21T19:15:06Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "C7k1pbU/WU4CBoBwA4EBUnV/iek=",
|
"checksumSHA1": "C7k1pbU/WU4CBoBwA4EBUnV/iek=",
|
||||||
"path": "google.golang.org/api/gensupport",
|
"path": "google.golang.org/api/gensupport",
|
||||||
|
Loading…
Reference in New Issue
Block a user