...

Source file src/cloud.google.com/go/auth/credentials/idtoken/compute.go

Documentation: cloud.google.com/go/auth/credentials/idtoken

     1  // Copyright 2023 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 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  // computeCredentials checks if this code is being run on GCE. If it is, it
    31  // will use the metadata service to build a Credentials that fetches ID
    32  // tokens.
    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  		// Compute tokens are valid for one hour:
    80  		// https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#create-id
    81  		Expiry: time.Now().Add(1 * time.Hour),
    82  	}, nil
    83  }
    84  

View as plain text