...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package idtoken
16
17 import (
18 "context"
19 "fmt"
20 "net/url"
21 "time"
22
23 "cloud.google.com/go/auth"
24 "cloud.google.com/go/auth/internal"
25 "cloud.google.com/go/compute/metadata"
26 )
27
28 const identitySuffix = "instance/service-accounts/default/identity"
29
30
31
32
33 func computeCredentials(opts *Options) (*auth.Credentials, error) {
34 if opts.CustomClaims != nil {
35 return nil, fmt.Errorf("idtoken: Options.CustomClaims can't be used with the metadata service, please provide a service account if you would like to use this feature")
36 }
37 tp := computeIDTokenProvider{
38 audience: opts.Audience,
39 format: opts.ComputeTokenFormat,
40 client: *metadata.NewClient(opts.client()),
41 }
42 return auth.NewCredentials(&auth.CredentialsOptions{
43 TokenProvider: auth.NewCachedTokenProvider(tp, &auth.CachedTokenProviderOptions{
44 ExpireEarly: 5 * time.Minute,
45 }),
46 ProjectIDProvider: auth.CredentialsPropertyFunc(func(context.Context) (string, error) {
47 return metadata.ProjectID()
48 }),
49 UniverseDomainProvider: &internal.ComputeUniverseDomainProvider{},
50 }), nil
51 }
52
53 type computeIDTokenProvider struct {
54 audience string
55 format ComputeTokenFormat
56 client metadata.Client
57 }
58
59 func (c computeIDTokenProvider) Token(ctx context.Context) (*auth.Token, error) {
60 v := url.Values{}
61 v.Set("audience", c.audience)
62 if c.format != ComputeTokenFormatStandard {
63 v.Set("format", "full")
64 }
65 if c.format == ComputeTokenFormatFullWithLicense {
66 v.Set("licenses", "TRUE")
67 }
68 urlSuffix := identitySuffix + "?" + v.Encode()
69 res, err := c.client.Get(urlSuffix)
70 if err != nil {
71 return nil, err
72 }
73 if res == "" {
74 return nil, fmt.Errorf("idtoken: invalid empty response from metadata service")
75 }
76 return &auth.Token{
77 Value: res,
78 Type: internal.TokenTypeBearer,
79
80
81 Expiry: time.Now().Add(1 * time.Hour),
82 }, nil
83 }
84
View as plain text