github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go (about) 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 5 package google 6 7 import ( 8 "encoding/json" 9 "errors" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "os" 14 "path/filepath" 15 "runtime" 16 17 "golang.org/x/net/context" 18 "golang.org/x/oauth2" 19 "golang.org/x/oauth2/jwt" 20 "google.golang.org/cloud/compute/metadata" 21 ) 22 23 // DefaultClient returns an HTTP Client that uses the 24 // DefaultTokenSource to obtain authentication credentials. 25 // 26 // This client should be used when developing services 27 // that run on Google App Engine or Google Compute Engine 28 // and use "Application Default Credentials." 29 // 30 // For more details, see: 31 // https://developers.google.com/accounts/docs/application-default-credentials 32 // 33 func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) { 34 ts, err := DefaultTokenSource(ctx, scope...) 35 if err != nil { 36 return nil, err 37 } 38 return oauth2.NewClient(ctx, ts), nil 39 } 40 41 // DefaultTokenSource is a token source that uses 42 // "Application Default Credentials". 43 // 44 // It looks for credentials in the following places, 45 // preferring the first location found: 46 // 47 // 1. A JSON file whose path is specified by the 48 // GOOGLE_APPLICATION_CREDENTIALS environment variable. 49 // 2. A JSON file in a location known to the gcloud command-line tool. 50 // On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. 51 // On other systems, $HOME/.config/gcloud/application_default_credentials.json. 52 // 3. On Google App Engine it uses the appengine.AccessToken function. 53 // 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches 54 // credentials from the metadata server. 55 // (In this final case any provided scopes are ignored.) 56 // 57 // For more details, see: 58 // https://developers.google.com/accounts/docs/application-default-credentials 59 // 60 func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) { 61 // First, try the environment variable. 62 const envVar = "GOOGLE_APPLICATION_CREDENTIALS" 63 if filename := os.Getenv(envVar); filename != "" { 64 ts, err := tokenSourceFromFile(ctx, filename, scope) 65 if err != nil { 66 return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) 67 } 68 return ts, nil 69 } 70 71 // Second, try a well-known file. 72 filename := wellKnownFile() 73 _, err := os.Stat(filename) 74 if err == nil { 75 ts, err2 := tokenSourceFromFile(ctx, filename, scope) 76 if err2 == nil { 77 return ts, nil 78 } 79 err = err2 80 } else if os.IsNotExist(err) { 81 err = nil // ignore this error 82 } 83 if err != nil { 84 return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) 85 } 86 87 // Third, if we're on Google App Engine use those credentials. 88 if appengineTokenFunc != nil && !appengineVM { 89 return AppEngineTokenSource(ctx, scope...), nil 90 } 91 92 // Fourth, if we're on Google Compute Engine use the metadata server. 93 if metadata.OnGCE() { 94 return ComputeTokenSource(""), nil 95 } 96 97 // None are found; return helpful error. 98 const url = "https://developers.google.com/accounts/docs/application-default-credentials" 99 return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) 100 } 101 102 func wellKnownFile() string { 103 const f = "application_default_credentials.json" 104 if runtime.GOOS == "windows" { 105 return filepath.Join(os.Getenv("APPDATA"), "gcloud", f) 106 } 107 return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f) 108 } 109 110 func tokenSourceFromFile(ctx context.Context, filename string, scopes []string) (oauth2.TokenSource, error) { 111 b, err := ioutil.ReadFile(filename) 112 if err != nil { 113 return nil, err 114 } 115 var d struct { 116 // Common fields 117 Type string 118 ClientID string `json:"client_id"` 119 120 // User Credential fields 121 ClientSecret string `json:"client_secret"` 122 RefreshToken string `json:"refresh_token"` 123 124 // Service Account fields 125 ClientEmail string `json:"client_email"` 126 PrivateKeyID string `json:"private_key_id"` 127 PrivateKey string `json:"private_key"` 128 } 129 if err := json.Unmarshal(b, &d); err != nil { 130 return nil, err 131 } 132 switch d.Type { 133 case "authorized_user": 134 cfg := &oauth2.Config{ 135 ClientID: d.ClientID, 136 ClientSecret: d.ClientSecret, 137 Scopes: append([]string{}, scopes...), // copy 138 Endpoint: Endpoint, 139 } 140 tok := &oauth2.Token{RefreshToken: d.RefreshToken} 141 return cfg.TokenSource(ctx, tok), nil 142 case "service_account": 143 cfg := &jwt.Config{ 144 Email: d.ClientEmail, 145 PrivateKey: []byte(d.PrivateKey), 146 Scopes: append([]string{}, scopes...), // copy 147 TokenURL: JWTTokenURL, 148 } 149 return cfg.TokenSource(ctx), nil 150 case "": 151 return nil, errors.New("missing 'type' field in credentials") 152 default: 153 return nil, fmt.Errorf("unknown credential type: %q", d.Type) 154 } 155 }