...

Source file src/google.golang.org/api/impersonate/integration_test.go

Documentation: google.golang.org/api/impersonate

     1  // Copyright 2021 Google LLC.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package impersonate_test
     6  
     7  import (
     8  	"context"
     9  	"flag"
    10  	"fmt"
    11  	"math/rand"
    12  	"os"
    13  	"testing"
    14  	"time"
    15  
    16  	admin "google.golang.org/api/admin/directory/v1"
    17  	"google.golang.org/api/idtoken"
    18  	"google.golang.org/api/impersonate"
    19  	"google.golang.org/api/option"
    20  
    21  	"google.golang.org/api/storage/v1"
    22  )
    23  
    24  var (
    25  	baseKeyFile   string
    26  	readerKeyFile string
    27  	readerEmail   string
    28  	writerEmail   string
    29  	projectID     string
    30  	domain        string
    31  	domainAdmin   string
    32  )
    33  
    34  func TestMain(m *testing.M) {
    35  	flag.Parse()
    36  	rand.Seed(time.Now().UnixNano())
    37  	baseKeyFile = os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
    38  	projectID = os.Getenv("GOOGLE_CLOUD_PROJECT")
    39  	readerKeyFile = os.Getenv("GCLOUD_TESTS_IMPERSONATE_READER_KEY")
    40  	readerEmail = os.Getenv("GCLOUD_TESTS_IMPERSONATE_READER_EMAIL")
    41  	writerEmail = os.Getenv("GCLOUD_TESTS_IMPERSONATE_WRITER_EMAIL")
    42  	domain = os.Getenv("GCLOUD_TESTS_IMPERSONATE_DOMAIN")
    43  	domainAdmin = os.Getenv("GCLOUD_TESTS_IMPERSONATE_DOMAIN_ADMIN")
    44  
    45  	os.Exit(m.Run())
    46  }
    47  
    48  func validateEnvVars(t *testing.T) {
    49  	t.Helper()
    50  	if baseKeyFile == "" ||
    51  		readerKeyFile == "" ||
    52  		readerEmail == "" ||
    53  		writerEmail == "" ||
    54  		projectID == "" {
    55  		t.Skip("required environment variable not set, skipping")
    56  	}
    57  }
    58  
    59  func TestCredentialsTokenSourceIntegration(t *testing.T) {
    60  	if testing.Short() {
    61  		t.Skip("skipping integration test")
    62  	}
    63  	validateEnvVars(t)
    64  
    65  	ctx := context.Background()
    66  	tests := []struct {
    67  		name        string
    68  		baseKeyFile string
    69  		delegates   []string
    70  	}{
    71  		{
    72  			name:        "SA -> SA",
    73  			baseKeyFile: readerKeyFile,
    74  		},
    75  		{
    76  			name:        "SA -> Delegate -> SA",
    77  			baseKeyFile: baseKeyFile,
    78  			delegates:   []string{readerEmail},
    79  		},
    80  	}
    81  
    82  	for _, tt := range tests {
    83  		t.Run(tt.name, func(t *testing.T) {
    84  			ts, err := impersonate.CredentialsTokenSource(ctx,
    85  				impersonate.CredentialsConfig{
    86  					TargetPrincipal: writerEmail,
    87  					Scopes:          []string{"https://www.googleapis.com/auth/devstorage.full_control"},
    88  					Delegates:       tt.delegates,
    89  				},
    90  				option.WithCredentialsFile(tt.baseKeyFile),
    91  			)
    92  			if err != nil {
    93  				t.Fatalf("failed to create ts: %v", err)
    94  			}
    95  			svc, err := storage.NewService(ctx, option.WithTokenSource(ts))
    96  			if err != nil {
    97  				t.Fatalf("failed to create client: %v", err)
    98  			}
    99  			bucketName := fmt.Sprintf("%s-%d", projectID, rand.Int63())
   100  			if _, err := svc.Buckets.Insert(projectID, &storage.Bucket{
   101  				Name: bucketName,
   102  			}).Do(); err != nil {
   103  				t.Fatalf("error creating bucket: %v", err)
   104  			}
   105  			if err := svc.Buckets.Delete(bucketName).Do(); err != nil {
   106  				t.Fatalf("unable to cleanup bucket %q: %v", bucketName, err)
   107  			}
   108  		})
   109  	}
   110  }
   111  
   112  func TestIDTokenSourceIntegration(t *testing.T) {
   113  	if testing.Short() {
   114  		t.Skip("skipping integration test")
   115  	}
   116  	validateEnvVars(t)
   117  
   118  	ctx := context.Background()
   119  	tests := []struct {
   120  		name        string
   121  		baseKeyFile string
   122  		delegates   []string
   123  	}{
   124  		{
   125  			name:        "SA -> SA",
   126  			baseKeyFile: readerKeyFile,
   127  		},
   128  		{
   129  			name:        "SA -> Delegate -> SA",
   130  			baseKeyFile: baseKeyFile,
   131  			delegates:   []string{readerEmail},
   132  		},
   133  	}
   134  
   135  	for _, tt := range tests {
   136  		name := tt.name
   137  		t.Run(name, func(t *testing.T) {
   138  			aud := "http://example.com/"
   139  			ts, err := impersonate.IDTokenSource(ctx,
   140  				impersonate.IDTokenConfig{
   141  					TargetPrincipal: writerEmail,
   142  					Audience:        aud,
   143  					Delegates:       tt.delegates,
   144  					IncludeEmail:    true,
   145  				},
   146  				option.WithCredentialsFile(tt.baseKeyFile),
   147  			)
   148  			if err != nil {
   149  				t.Fatalf("failed to create ts: %v", err)
   150  			}
   151  			tok, err := ts.Token()
   152  			if err != nil {
   153  				t.Fatalf("unable to retrieve Token: %v", err)
   154  			}
   155  			validTok, err := idtoken.Validate(context.Background(), tok.AccessToken, aud)
   156  			if err != nil {
   157  				t.Fatalf("token validation failed: %v", err)
   158  			}
   159  			if validTok.Audience != aud {
   160  				t.Fatalf("got %q, want %q", validTok.Audience, aud)
   161  			}
   162  			if validTok.Claims["email"] != writerEmail {
   163  				t.Fatalf("got %q, want %q", validTok.Claims["email"], writerEmail)
   164  			}
   165  		})
   166  	}
   167  }
   168  
   169  func TestTokenSourceIntegration_user(t *testing.T) {
   170  	t.Skip("https://github.com/googleapis/google-api-go-client/issues/948")
   171  	if testing.Short() {
   172  		t.Skip("skipping integration test")
   173  	}
   174  	validateEnvVars(t)
   175  	ctx := context.Background()
   176  	tests := []struct {
   177  		name        string
   178  		baseKeyFile string
   179  		delegates   []string
   180  	}{
   181  		{
   182  			name:        "SA -> SA",
   183  			baseKeyFile: readerKeyFile,
   184  		},
   185  		{
   186  			name:        "SA -> Delegate -> SA",
   187  			baseKeyFile: baseKeyFile,
   188  			delegates:   []string{readerEmail},
   189  		},
   190  	}
   191  
   192  	for _, tt := range tests {
   193  		t.Run(tt.name, func(t *testing.T) {
   194  			ts, err := impersonate.CredentialsTokenSource(ctx,
   195  				impersonate.CredentialsConfig{
   196  					TargetPrincipal: writerEmail,
   197  					Delegates:       tt.delegates,
   198  					Scopes:          []string{"https://www.googleapis.com/auth/admin.directory.user", "https://www.googleapis.com/auth/admin.directory.group"},
   199  					Subject:         domainAdmin,
   200  				},
   201  				option.WithCredentialsFile(baseKeyFile),
   202  			)
   203  			if err != nil {
   204  				t.Fatalf("failed to create ts: %v", err)
   205  			}
   206  			svc, err := admin.NewService(ctx, option.WithTokenSource(ts))
   207  			if err != nil {
   208  				t.Fatalf("failed to create client: %v", err)
   209  			}
   210  			if _, err := svc.Users.List().Domain(domain).Do(); err != nil {
   211  				t.Fatalf("failed to list users: %v", err)
   212  			}
   213  		})
   214  	}
   215  }
   216  

View as plain text