...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package downscope_test
16
17 import (
18 "context"
19 "fmt"
20 "io"
21 "os"
22 "testing"
23 "time"
24
25 "cloud.google.com/go/auth"
26 "cloud.google.com/go/auth/credentials"
27 "cloud.google.com/go/auth/credentials/downscope"
28 "cloud.google.com/go/auth/internal/credsfile"
29 "cloud.google.com/go/auth/internal/testutil"
30 "cloud.google.com/go/auth/internal/testutil/testgcs"
31 )
32
33 const (
34 rootTokenScope = "https://www.googleapis.com/auth/cloud-platform"
35 object1 = "cab-first-c45wknuy.txt"
36 object2 = "cab-second-c45wknuy.txt"
37 bucket = "dulcet-port-762"
38 )
39
40 func TestDownscopedToken(t *testing.T) {
41 testutil.IntegrationTestCheck(t)
42 creds, err := credentials.DetectDefault(&credentials.DetectOptions{
43 CredentialsFile: os.Getenv(credsfile.GoogleAppCredsEnvVar),
44 Scopes: []string{rootTokenScope},
45 })
46 if err != nil {
47 t.Fatalf("DefaultCredentials() = %v", err)
48 }
49
50 var downscopeTests = []struct {
51 name string
52 rule downscope.AccessBoundaryRule
53 objectName string
54 expectError bool
55 }{
56 {
57 name: "successfulDownscopedRead",
58 rule: downscope.AccessBoundaryRule{
59 AvailableResource: "//storage.googleapis.com/projects/_/buckets/" + bucket,
60 AvailablePermissions: []string{"inRole:roles/storage.objectViewer"},
61 Condition: &downscope.AvailabilityCondition{
62 Expression: "resource.name.startsWith('projects/_/buckets/" + bucket + "/objects/" + object1 + "')",
63 },
64 },
65 objectName: object1,
66 expectError: false,
67 },
68 {
69 name: "readWithoutPermission",
70 rule: downscope.AccessBoundaryRule{
71 AvailableResource: "//storage.googleapis.com/projects/_/buckets/" + bucket,
72 AvailablePermissions: []string{"inRole:roles/storage.objectViewer"},
73 Condition: &downscope.AvailabilityCondition{
74 Expression: "resource.name.startsWith('projects/_/buckets/" + bucket + "/objects/" + object1 + "')",
75 },
76 },
77 objectName: object2,
78 expectError: true,
79 },
80 }
81
82 for _, tt := range downscopeTests {
83 t.Run(tt.name, func(t *testing.T) {
84 err := testDownscopedToken(t, tt.rule, tt.objectName, creds)
85 if !tt.expectError && err != nil {
86 t.Errorf("test case %v should have succeeded, but instead returned %v", tt.name, err)
87 } else if tt.expectError && err == nil {
88 t.Errorf(" test case %v should have returned an error, but instead returned nil", tt.name)
89 }
90 })
91 }
92 }
93
94 func testDownscopedToken(t *testing.T, rule downscope.AccessBoundaryRule, objectName string, creds *auth.Credentials) error {
95 t.Helper()
96 ctx := context.Background()
97 creds, err := downscope.NewCredentials(&downscope.Options{Credentials: creds, Rules: []downscope.AccessBoundaryRule{rule}})
98 if err != nil {
99 return fmt.Errorf("downscope.NewCredentials() = %v", err)
100 }
101
102 ctx, cancel := context.WithTimeout(ctx, time.Second*30)
103 defer cancel()
104 client := testgcs.NewClient(creds)
105 resp, err := client.DownloadObject(ctx, bucket, objectName)
106 if err != nil {
107 return err
108 }
109 defer resp.Body.Close()
110 _, err = io.ReadAll(resp.Body)
111 if err != nil {
112 return err
113 }
114 return nil
115 }
116
View as plain text