// NewRefreshTokenSource returns a token source that obtains its initial token // based on the provided config and the refresh token. func NewRefreshTokenSource(config *oauth2.Config, refreshToken string) oauth2.TokenSource { var noInitialToken *oauth2.Token = nil return oauth2.ReuseTokenSource(noInitialToken, config.TokenSource( oauth2.NoContext, // TODO: maybe accept a context later. &oauth2.Token{RefreshToken: refreshToken}, )) }
func (c *googinitCmd) RunCommand(args []string) error { var ( err error clientId string clientSecret string oauthConfig *oauth2.Config ) if c.storageType != "drive" && c.storageType != "cloud" { return cmdmain.UsageError("Invalid storage type: must be drive for Google Drive or cloud for Google Cloud Storage.") } clientId, clientSecret = getClientInfo() switch c.storageType { case "drive": oauthConfig = &oauth2.Config{ Scopes: []string{drive.Scope}, Endpoint: google.Endpoint, ClientID: clientId, ClientSecret: clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } case "cloud": oauthConfig = &oauth2.Config{ Scopes: []string{googlestorage.Scope}, Endpoint: google.Endpoint, ClientID: clientId, ClientSecret: clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } } token, err := oauth2.ReuseTokenSource(nil, &oauthutil.TokenSource{ Config: oauthConfig, AuthCode: func() string { fmt.Fprintf(cmdmain.Stdout, "Get auth code from:\n\n") fmt.Fprintf(cmdmain.Stdout, "%v\n\n", oauthConfig.AuthCodeURL("", oauth2.AccessTypeOffline, oauth2.ApprovalForce)) return prompt("Enter auth code:") }, }).Token() if err != nil { return fmt.Errorf("could not acquire token: %v", err) } fmt.Fprintf(cmdmain.Stdout, "\nYour Google auth object:\n\n") enc := json.NewEncoder(cmdmain.Stdout) authObj := map[string]string{ "client_id": clientId, "client_secret": clientSecret, "refresh_token": token.RefreshToken, } enc.Encode(authObj) fmt.Fprint(cmdmain.Stdout, "\n") return nil }
func (c *gceCmd) RunCommand(args []string) error { if c.verbose { gce.Verbose = true } if c.project == "" { return cmdmain.UsageError("Missing --project flag.") } if (c.certFile == "") != (c.keyFile == "") { return cmdmain.UsageError("--cert and --key must both be given together.") } if c.certFile == "" && c.hostname == "" { return cmdmain.UsageError("Either --hostname, or --cert & --key must provided.") } config := gce.NewOAuthConfig(readFile(clientIdDat), readFile(clientSecretDat)) config.RedirectURL = "urn:ietf:wg:oauth:2.0:oob" instConf := &gce.InstanceConf{ Name: c.instName, Project: c.project, Machine: c.machine, Zone: c.zone, CertFile: c.certFile, KeyFile: c.keyFile, Hostname: c.hostname, } if c.sshPub != "" { instConf.SSHPub = strings.TrimSpace(readFile(c.sshPub)) } depl := &gce.Deployer{ Client: oauth2.NewClient(oauth2.NoContext, oauth2.ReuseTokenSource(nil, &oauthutil.TokenSource{ Config: config, CacheFile: c.project + "-token.json", AuthCode: func() string { fmt.Println("Get auth code from:") fmt.Printf("%v\n", config.AuthCodeURL("my-state", oauth2.AccessTypeOffline, oauth2.ApprovalForce)) fmt.Println("Enter auth code:") sc := bufio.NewScanner(os.Stdin) sc.Scan() return strings.TrimSpace(sc.Text()) }, })), Conf: instConf, } inst, err := depl.Create(context.TODO()) if err != nil { return err } log.Printf("Instance is up at %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP) return nil }
func TestStorage(t *testing.T) { if (*parentId == "" || *parentId == "root") && *configFile == "" { t.Skip("Skipping test, refusing to use goodle drive's root directory. (you need to specify --parentDir or --config).") } var refreshToken string if *configFile != "" { data, err := ioutil.ReadFile(*configFile) if err != nil { t.Fatalf("Error reading config file %v: %v", *configFile, err) } var conf Config if err := json.Unmarshal(data, &conf); err != nil { t.Fatalf("Error decoding config file %v: %v", *configFile, err) } *clientID = conf.Auth.ClientID *clientSecret = conf.Auth.ClientSecret refreshToken = conf.Auth.RefreshToken *parentId = conf.ParentDir } if *parentId == "" || *parentId == "root" { t.Fatal("ParentDir must be specified, and not \"root\"") } if *clientID == "" || *clientSecret == "" { t.Fatal("--client_id and --client_secret required. Obtain from https://console.developers.google.com/ > Project > APIs & Auth > Credentials. Should be a 'native' or 'Installed application'") } if *configFile == "" { config := &oauth2.Config{ Scopes: []string{Scope}, Endpoint: google.Endpoint, ClientID: *clientID, ClientSecret: *clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } token, err := oauth2.ReuseTokenSource(nil, &oauthutil.TokenSource{ Config: config, CacheFile: *tokenCache, AuthCode: func() string { if *authCode == "" { t.Skipf("Re-run using --auth_code= with the value obtained from %s", config.AuthCodeURL("", oauth2.AccessTypeOffline, oauth2.ApprovalForce)) return "" } return *authCode }, }).Token() if err != nil { t.Fatalf("could not acquire token: %v", err) } refreshToken = token.RefreshToken } storagetest.TestOpt(t, storagetest.Opts{ New: func(t *testing.T) (sto blobserver.Storage, cleanup func()) { sto, err := newFromConfig(nil, jsonconfig.Obj{ "parent_id": *parentId, "auth": map[string]interface{}{ "client_id": *clientID, "client_secret": *clientSecret, "refresh_token": refreshToken, }, }) if err != nil { t.Fatal(err) } if !testing.Short() { log.Printf("Warning: this test does many serial operations. Without the go test -short flag, this test will be very slow.") } clearDirectory := func() { log.Printf("WARNING: no cleanup in %v directory was done.", *parentId) } return sto, clearDirectory }, SkipEnum: true, }) }
// ComputeTokenSource returns a token source that fetches access tokens // from Google Compute Engine (GCE)'s metadata server. It's only valid to use // this token source if your program is running on a GCE instance. // If no account is specified, "default" is used. // Further information about retrieving access tokens from the GCE metadata // server can be found at https://cloud.google.com/compute/docs/authentication. func ComputeTokenSource(account string) oauth2.TokenSource { return oauth2.ReuseTokenSource(nil, computeSource{account: account}) }
func testStorage(t *testing.T, bucketDir string) { if *bucket == "" && *configFile == "" { t.Skip("Skipping test without --bucket or --config flag") } var refreshToken string if *configFile != "" { data, err := ioutil.ReadFile(*configFile) if err != nil { t.Fatalf("Error reading config file %v: %v", *configFile, err) } var conf Config if err := json.Unmarshal(data, &conf); err != nil { t.Fatalf("Error decoding config file %v: %v", *configFile, err) } *clientID = conf.Auth.ClientID *clientSecret = conf.Auth.ClientSecret refreshToken = conf.Auth.RefreshToken *bucket = conf.Bucket } if *bucket == "" { t.Fatal("bucket not provided in config file or as a flag.") } if *clientID == "" || *clientSecret == "" { t.Fatal("client ID and client secret required. Obtain from https://console.developers.google.com/ > Project > APIs & Auth > Credentials. Should be a 'native' or 'Installed application'") } if *configFile == "" { config := &oauth2.Config{ Scopes: []string{googlestorage.Scope}, Endpoint: google.Endpoint, ClientID: *clientID, ClientSecret: *clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } token, err := oauth2.ReuseTokenSource(nil, &oauthutil.TokenSource{ Config: config, CacheFile: *tokenCache, AuthCode: func() string { if *authCode == "" { t.Skipf("Re-run using --auth_code= with the value obtained from %s", config.AuthCodeURL("", oauth2.AccessTypeOffline, oauth2.ApprovalForce)) return "" } return *authCode }, }).Token() if err != nil { t.Fatalf("could not acquire token: %v", err) } refreshToken = token.RefreshToken } bucketWithDir := path.Join(*bucket, bucketDir) storagetest.TestOpt(t, storagetest.Opts{ New: func(t *testing.T) (sto blobserver.Storage, cleanup func()) { sto, err := newFromConfig(nil, jsonconfig.Obj{ "bucket": bucketWithDir, "auth": map[string]interface{}{ "client_id": *clientID, "client_secret": *clientSecret, "refresh_token": refreshToken, }, }) if err != nil { t.Fatal(err) } if !testing.Short() { log.Printf("Warning: this test does many serial operations. Without the go test -short flag, this test will be very slow.") } // Bail if bucket is not empty objs, err := sto.(*Storage).client.EnumerateObjects(*bucket, "", 1) if err != nil { t.Fatalf("Error checking if bucket is empty: %v", err) } if len(objs) != 0 { t.Fatalf("Refusing to run test: bucket %v is not empty", *bucket) } if bucketWithDir != *bucket { // Adding "a", and "c" objects in the bucket to make sure objects out of the // "directory" are not touched and have no influence. for _, key := range []string{"a", "c"} { err := sto.(*Storage).client.PutObject( &googlestorage.Object{Bucket: sto.(*Storage).bucket, Key: key}, strings.NewReader(key)) if err != nil { t.Fatalf("could not insert object %s in bucket %v: %v", key, sto.(*Storage).bucket, err) } } } clearBucket := func(beforeTests bool) func() { return func() { var all []blob.Ref blobserver.EnumerateAll(context.New(), sto, func(sb blob.SizedRef) error { t.Logf("Deleting: %v", sb.Ref) all = append(all, sb.Ref) return nil }) if err := sto.RemoveBlobs(all); err != nil { t.Fatalf("Error removing blobs during cleanup: %v", err) } if beforeTests { return } if bucketWithDir != *bucket { // checking that "a" and "c" at the root were left untouched. for _, key := range []string{"a", "c"} { if _, _, err := sto.(*Storage).client.GetObject(&googlestorage.Object{Bucket: sto.(*Storage).bucket, Key: key}); err != nil { t.Fatalf("could not find object %s after tests: %v", key, err) } if err := sto.(*Storage).client.DeleteObject(&googlestorage.Object{Bucket: sto.(*Storage).bucket, Key: key}); err != nil { t.Fatalf("could not remove object %s after tests: %v", key, err) } } } } } clearBucket(true)() return sto, clearBucket(false) }, }) }
// TokenSource returns a JWT TokenSource using the configuration // in c and the HTTP client from the provided context. func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource { return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c}) }