You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

116 lines
3.5 KiB

  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package google
  5. import (
  6. "encoding/json"
  7. "fmt"
  8. "io/ioutil"
  9. "net/http"
  10. "os"
  11. "path/filepath"
  12. "runtime"
  13. "cloud.google.com/go/compute/metadata"
  14. "golang.org/x/net/context"
  15. "golang.org/x/oauth2"
  16. )
  17. // DefaultClient returns an HTTP Client that uses the
  18. // DefaultTokenSource to obtain authentication credentials.
  19. func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
  20. ts, err := DefaultTokenSource(ctx, scope...)
  21. if err != nil {
  22. return nil, err
  23. }
  24. return oauth2.NewClient(ctx, ts), nil
  25. }
  26. // DefaultTokenSource returns the token source for
  27. // "Application Default Credentials".
  28. // It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource.
  29. func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) {
  30. creds, err := FindDefaultCredentials(ctx, scope...)
  31. if err != nil {
  32. return nil, err
  33. }
  34. return creds.TokenSource, nil
  35. }
  36. // Common implementation for FindDefaultCredentials.
  37. func findDefaultCredentials(ctx context.Context, scopes []string) (*DefaultCredentials, error) {
  38. // First, try the environment variable.
  39. const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
  40. if filename := os.Getenv(envVar); filename != "" {
  41. creds, err := readCredentialsFile(ctx, filename, scopes)
  42. if err != nil {
  43. return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
  44. }
  45. return creds, nil
  46. }
  47. // Second, try a well-known file.
  48. filename := wellKnownFile()
  49. if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil {
  50. return creds, nil
  51. } else if !os.IsNotExist(err) {
  52. return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
  53. }
  54. // Third, if we're on Google App Engine use those credentials.
  55. if appengineTokenFunc != nil && !appengineFlex {
  56. return &DefaultCredentials{
  57. ProjectID: appengineAppIDFunc(ctx),
  58. TokenSource: AppEngineTokenSource(ctx, scopes...),
  59. }, nil
  60. }
  61. // Fourth, if we're on Google Compute Engine use the metadata server.
  62. if metadata.OnGCE() {
  63. id, _ := metadata.ProjectID()
  64. return &DefaultCredentials{
  65. ProjectID: id,
  66. TokenSource: ComputeTokenSource(""),
  67. }, nil
  68. }
  69. // None are found; return helpful error.
  70. const url = "https://developers.google.com/accounts/docs/application-default-credentials"
  71. return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
  72. }
  73. // Common implementation for CredentialsFromJSON.
  74. func credentialsFromJSON(ctx context.Context, jsonData []byte, scopes []string) (*DefaultCredentials, error) {
  75. var f credentialsFile
  76. if err := json.Unmarshal(jsonData, &f); err != nil {
  77. return nil, err
  78. }
  79. ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
  80. if err != nil {
  81. return nil, err
  82. }
  83. return &DefaultCredentials{
  84. ProjectID: f.ProjectID,
  85. TokenSource: ts,
  86. JSON: jsonData,
  87. }, nil
  88. }
  89. func wellKnownFile() string {
  90. const f = "application_default_credentials.json"
  91. if runtime.GOOS == "windows" {
  92. return filepath.Join(os.Getenv("APPDATA"), "gcloud", f)
  93. }
  94. return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
  95. }
  96. func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
  97. b, err := ioutil.ReadFile(filename)
  98. if err != nil {
  99. return nil, err
  100. }
  101. return CredentialsFromJSON(ctx, b, scopes...)
  102. }