...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/gcp/gcp.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/gcp

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package testgcp
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"fmt"
    21  	"net/http"
    22  	"os"
    23  	"os/user"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/gcp"
    28  
    29  	"golang.org/x/oauth2/google"
    30  	"google.golang.org/api/cloudresourcemanager/v1"
    31  	"google.golang.org/api/compute/v1"
    32  	"google.golang.org/api/iam/v1"
    33  	"google.golang.org/api/storage/v1"
    34  )
    35  
    36  const (
    37  	TestFolderId                            = "TEST_FOLDER_ID"
    38  	TestFolder2Id                           = "TEST_FOLDER_2_ID"
    39  	TestOrgId                               = "TEST_ORG_ID"
    40  	TestDependentOrgProjectId               = "TEST_DEPENDENT_ORG_PROJECT_ID"
    41  	TestDependentFolderProjectId            = "TEST_DEPENDENT_FOLDER_PROJECT_ID"
    42  	TestDependentNoNetworkProjectId         = "TEST_DEPENDENT_NO_NETWORK_PROJECT_ID" // A dependent project with default network disabled
    43  	IAMIntegrationTestsOrganizationId       = "IAM_INTEGRATION_TESTS_ORGANIZATION_ID"
    44  	IsolatedTestOrgName                     = "ISOLATED_TEST_ORG_NAME"
    45  	TestBillingAccountId                    = "TEST_BILLING_ACCOUNT_ID"
    46  	TestBillingAccountIDForBillingResources = "BILLING_ACCOUNT_ID_FOR_BILLING_RESOURCES"
    47  	IAMIntegrationTestsBillingAccountId     = "IAM_INTEGRATION_TESTS_BILLING_ACCOUNT_ID"
    48  	FirestoreTestProject                    = "FIRESTORE_TEST_PROJECT"
    49  	CloudFunctionsTestProject               = "CLOUD_FUNCTIONS_TEST_PROJECT"
    50  	IdentityPlatformTestProject             = "IDENTITY_PLATFORM_TEST_PROJECT"
    51  	InterconnectTestProject                 = "INTERCONNECT_TEST_PROJECT"
    52  	HighCPUQuotaTestProject                 = "HIGH_CPU_QUOTA_TEST_PROJECT"
    53  	RecaptchaEnterpriseTestProject          = "RECAPTCHA_ENTERPRISE_TEST_PROJECT"
    54  	DLPTestBucket                           = "DLP_TEST_BUCKET"
    55  )
    56  
    57  var (
    58  	testFolderID                            = os.Getenv(TestFolderId)
    59  	testFolder2Id                           = os.Getenv(TestFolder2Id)
    60  	testOrgID                               = os.Getenv(TestOrgId)
    61  	testDependentOrgProjectId               = os.Getenv(TestDependentOrgProjectId)
    62  	testDependentFolderProjectId            = os.Getenv(TestDependentFolderProjectId)
    63  	testDependentNoNetworkProjectId         = os.Getenv(TestDependentNoNetworkProjectId)
    64  	isolatedTestOrgName                     = os.Getenv(IsolatedTestOrgName)
    65  	iamIntegrationTestsOrganizationId       = os.Getenv(IAMIntegrationTestsOrganizationId)
    66  	testBillingAccountID                    = os.Getenv(TestBillingAccountId)
    67  	testBillingAccountIDForBillingResources = os.Getenv(TestBillingAccountIDForBillingResources)
    68  	iamIntegrationTestsBillingAccountId     = os.Getenv(IAMIntegrationTestsBillingAccountId)
    69  	firestoreTestProject                    = os.Getenv(FirestoreTestProject)
    70  	cloudFunctionsTestProject               = os.Getenv(CloudFunctionsTestProject)
    71  	identityPlatformTestProject             = os.Getenv(IdentityPlatformTestProject)
    72  	interconnectTestProject                 = os.Getenv(InterconnectTestProject)
    73  	highCpuQuotaTestProject                 = os.Getenv(HighCPUQuotaTestProject)
    74  	recaptchaEnterpriseTestProject          = os.Getenv(RecaptchaEnterpriseTestProject)
    75  	dlpTestBucket                           = os.Getenv(DLPTestBucket)
    76  )
    77  
    78  // GetDefaultProjectID returns the ID of user's configured default GCP project.
    79  func GetDefaultProjectID(t *testing.T) string {
    80  	t.Helper()
    81  	projectID, err := gcp.GetDefaultProjectID()
    82  	if err != nil {
    83  		t.Fatalf("error retrieving gcloud sdk credentials: %v", err)
    84  	}
    85  	return projectID
    86  }
    87  
    88  type GCPProject struct {
    89  	ProjectID     string
    90  	ProjectNumber int64
    91  }
    92  
    93  // GetDefaultProject returns the ID of user's configured default GCP project.
    94  func GetDefaultProject(t *testing.T) GCPProject {
    95  	t.Helper()
    96  	ctx := context.TODO()
    97  
    98  	projectID, err := gcp.GetDefaultProjectID()
    99  	if err != nil {
   100  		t.Fatalf("error getting default project: %v", err)
   101  	}
   102  	projectNumber, err := GetProjectNumber(ctx, projectID)
   103  	if err != nil {
   104  		t.Fatalf("error getting project number for %q: %v", projectID, err)
   105  	}
   106  	return GCPProject{ProjectID: projectID, ProjectNumber: projectNumber}
   107  }
   108  
   109  func GetProjectNumber(ctx context.Context, projectID string) (int64, error) {
   110  	client, err := gcp.NewCloudResourceManagerClient(ctx)
   111  	if err != nil {
   112  		return 0, fmt.Errorf("error creating resource manager client: %w", err)
   113  	}
   114  	project, err := client.Projects.Get(projectID).Do()
   115  	if err != nil {
   116  		return 0, fmt.Errorf("error getting project with id %q: %w", projectID, err)
   117  	}
   118  
   119  	return project.ProjectNumber, nil
   120  }
   121  
   122  // FindDefaultServiceAccount returns the service account used to access the user's configured default GCP project.
   123  // If the credentials cannot be found, returns ("", nil)
   124  func FindDefaultServiceAccount() (string, error) {
   125  	creds, err := google.FindDefaultCredentials(context.TODO(), cloudresourcemanager.CloudPlatformScope)
   126  	if err != nil {
   127  		msg := err.Error()
   128  		if strings.Contains(msg, "could not find default credentials") {
   129  			return "", nil
   130  		}
   131  		return "", fmt.Errorf("error getting credentials: %w", err)
   132  	}
   133  	if creds == nil {
   134  		return "", nil
   135  	}
   136  
   137  	var rawCreds map[string]string
   138  	if err := json.Unmarshal(creds.JSON, &rawCreds); err != nil {
   139  		return "", fmt.Errorf("creds file malformed: %w", err)
   140  	}
   141  
   142  	return rawCreds["client_email"], nil
   143  }
   144  
   145  func GetFolderID(t *testing.T) string {
   146  	return testFolderID
   147  }
   148  
   149  func GetFolder2ID(t *testing.T) string {
   150  	return testFolder2Id
   151  }
   152  
   153  func GetBillingAccountID(t *testing.T) string {
   154  	return testBillingAccountID
   155  }
   156  
   157  func GetTestBillingAccountIDForBillingResources(t *testing.T) string {
   158  	return testBillingAccountIDForBillingResources
   159  }
   160  
   161  func GetOrgID(t *testing.T) string {
   162  	return testOrgID
   163  }
   164  
   165  func GetDependentOrgProjectID(t *testing.T) string {
   166  	return testDependentOrgProjectId
   167  }
   168  
   169  func GetDependentFolderProjectID(t *testing.T) string {
   170  	return testDependentFolderProjectId
   171  }
   172  
   173  func GetDependentNoNetworkProjectID(t *testing.T) string {
   174  	return testDependentNoNetworkProjectId
   175  }
   176  
   177  func GetIsolatedTestOrgName(t *testing.T) string {
   178  	return isolatedTestOrgName
   179  }
   180  
   181  func GetIAMIntegrationTestsBillingAccountId(t *testing.T) string {
   182  	return iamIntegrationTestsBillingAccountId
   183  }
   184  
   185  func GetIAMIntegrationTestsOrganizationId(t *testing.T) string {
   186  	return iamIntegrationTestsOrganizationId
   187  }
   188  
   189  func GetFirestoreTestProject(t *testing.T) string {
   190  	return firestoreTestProject
   191  }
   192  
   193  func GetCloudFunctionsTestProject(t *testing.T) string {
   194  	return cloudFunctionsTestProject
   195  }
   196  
   197  func GetIdentityPlatformTestProject(t *testing.T) string {
   198  	return identityPlatformTestProject
   199  }
   200  
   201  func GetInterconnectTestProject(t *testing.T) string {
   202  	return interconnectTestProject
   203  }
   204  
   205  func GetHighCpuQuotaTestProject(t *testing.T) string {
   206  	return highCpuQuotaTestProject
   207  }
   208  
   209  func GetRecaptchaEnterpriseTestProject(t *testing.T) string {
   210  	return recaptchaEnterpriseTestProject
   211  }
   212  
   213  func GetDLPTestBucket(t *testing.T) string {
   214  	return dlpTestBucket
   215  }
   216  
   217  // attempts to return a valid IAM policy binding for the current credential by searching for an email in the cloud credentials file and defaulting to the
   218  // current user if on a corp machine.
   219  func GetIAMPolicyBindingMember(t *testing.T) string {
   220  	currentUser, err := user.Current()
   221  	if err != nil {
   222  		t.Fatalf("unable to find current user: %v", err)
   223  	}
   224  	hostname, err := os.Hostname()
   225  	if err != nil {
   226  		t.Fatalf("unable to get hostname: %v", err)
   227  	}
   228  	if serviceAccountEmail, err := FindDefaultServiceAccount(); err != nil {
   229  		t.Fatalf("error from FindDefaultServiceAccount: %v", err)
   230  	} else if serviceAccountEmail != "" {
   231  		return fmt.Sprintf("serviceAccount:%v", serviceAccountEmail)
   232  	}
   233  	if strings.HasSuffix(hostname, ".corp.google.com") {
   234  		return fmt.Sprintf("user:%s@google.com", currentUser.Username)
   235  	}
   236  	if strings.HasSuffix(hostname, ".c.googlers.com") {
   237  		return fmt.Sprintf("user:%s@google.com", currentUser.Username)
   238  	}
   239  	t.Fatalf("Unable to get safety binding member")
   240  	return ""
   241  }
   242  
   243  func NewDefaultHTTPClient(t *testing.T) *http.Client {
   244  	t.Helper()
   245  	client, err := google.DefaultClient(context.TODO(), compute.CloudPlatformScope)
   246  	if err != nil {
   247  		t.Fatalf("error creating default google client: %v", err)
   248  	}
   249  	return client
   250  }
   251  
   252  func NewStorageClient(t *testing.T) *storage.Service {
   253  	t.Helper()
   254  	client, err := gcp.NewStorageClient(context.TODO())
   255  	if err != nil {
   256  		t.Fatalf("error creating storage client: %v", err)
   257  	}
   258  	return client
   259  }
   260  
   261  func NewResourceManagerClient(t *testing.T) *cloudresourcemanager.Service {
   262  	t.Helper()
   263  	client, err := gcp.NewCloudResourceManagerClient(context.TODO())
   264  	if err != nil {
   265  		t.Fatalf("error creating cloud resource manager client: %v", err)
   266  	}
   267  	return client
   268  }
   269  
   270  func NewIAMClient(t *testing.T) *iam.Service {
   271  	t.Helper()
   272  	client, err := gcp.NewIAMClient(context.TODO())
   273  	if err != nil {
   274  		t.Fatalf("error creating IAM client: %v", err)
   275  	}
   276  	return client
   277  }
   278  
   279  func ResourceSupportsDeletion(resourceKind string) bool {
   280  	switch resourceKind {
   281  	case "BigQueryJob",
   282  		"BinaryAuthorizationPolicy",
   283  		"ComputeProjectMetadata",
   284  		"DataflowFlexTemplateJob",
   285  		"DataflowJob",
   286  		"IAMCustomRole",
   287  		"IAMWorkforcePool",
   288  		"IAMWorkforcePoolProvider",
   289  		"IAMWorkloadIdentityPool",
   290  		"IAMWorkloadIdentityPoolProvider",
   291  		"KMSCryptoKey",
   292  		"KMSKeyRing",
   293  		"LoggingLogBucket",
   294  		"PrivateCACertificate",
   295  		"PrivateCACertificateAuthority",
   296  		"ResourceManagerPolicy",
   297  		"SecretManagerSecretVersion":
   298  		return false
   299  	default:
   300  		return true
   301  	}
   302  }
   303  

View as plain text