Example #1
0
func MakeClient(token string) *github.Client {
	var client *http.Client
	var transport http.RoundTripper
	if *useMemoryCache {
		transport = httpcache.NewMemoryCacheTransport()
	} else {
		transport = http.DefaultTransport
	}
	if len(token) > 0 {
		rateLimitTransport := &RateLimitRoundTripper{
			delegate: transport,
			// Global limit is 5000 Q/Hour, try to only use 1800 to make room for other apps
			throttle: util.NewTokenBucketRateLimiter(0.5, 10),
		}
		ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
		client = &http.Client{
			Transport: &oauth2.Transport{
				Base:   rateLimitTransport,
				Source: oauth2.ReuseTokenSource(nil, ts),
			},
		}
	} else {
		rateLimitTransport := &RateLimitRoundTripper{
			delegate: transport,
			throttle: util.NewTokenBucketRateLimiter(0.01, 10),
		}
		client = &http.Client{
			Transport: rateLimitTransport,
		}
	}
	return github.NewClient(client)
}
Example #2
0
// New returns a new Amazon Cloud Drive "acd" Client. configFile must exist and must be a valid JSON decodable into Config.
func New(configFile string) (*Client, error) {
	config, err := loadConfig(configFile)
	if err != nil {
		return nil, err
	}

	ts, err := token.New(config.TokenFile)
	if err != nil {
		return nil, err
	}
	c := &Client{
		config:    config,
		cacheFile: config.CacheFile,
		httpClient: &http.Client{
			Timeout: config.Timeout,
			Transport: &oauth2.Transport{
				Source: oauth2.ReuseTokenSource(nil, ts),
			},
		},
	}
	if err := setEndpoints(c); err != nil {
		return nil, err
	}

	return c, nil
}
Example #3
0
// 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},
	))
}
Example #4
0
// TokenSource returns a TokenSource that returns t until t expires,
// automatically refreshing it as necessary using the provided context and the
// client ID and client secret.
//
// Most users will use Config.Client instead.
func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
	source := &tokenSource{
		ctx:  ctx,
		conf: c,
	}
	return oauth2.ReuseTokenSource(nil, source)
}
Example #5
0
// TokenSource returns a ReuseTokenSource.
func (c *Config) TokenSource(ctx context.Context, t *oauth2.Token) oauth2.TokenSource {
	tts := &TokenStorageSource{
		source: c.Config.TokenSource(ctx, t),
		config: c,
	}
	return oauth2.ReuseTokenSource(t, tts)
}
Example #6
0
// tokenSource returns a reusable oauth2.TokenSource.
// When expired, a new token will be obtained using cred.RefreshToken
// and stored in a persistent db.
// The returned TokenSource valid only within provided context c.
func (cred *oauth2Credentials) tokenSource(c context.Context) oauth2.TokenSource {
	t := &oauth2.Token{
		AccessToken: cred.AccessToken,
		Expiry:      cred.Expiry,
	}
	return oauth2.ReuseTokenSource(t, &tokenRefresher{c, cred})
}
Example #7
0
// PreExecute will initialize the Config. It MUST be run before the config
// may be used to get information from Github
func (config *Config) PreExecute() error {
	if len(config.Org) == 0 {
		glog.Fatalf("--organization is required.")
	}
	if len(config.Project) == 0 {
		glog.Fatalf("--project is required.")
	}

	token := config.Token
	if len(token) == 0 && len(config.TokenFile) != 0 {
		data, err := ioutil.ReadFile(config.TokenFile)
		if err != nil {
			glog.Fatalf("error reading token file: %v", err)
		}
		token = strings.TrimSpace(string(data))
	}

	// We need to get our Transport/RoundTripper in order based on arguments
	//    oauth2 Transport // if we have an auth token
	//    zeroCacheRoundTripper // if we are using the cache want faster timeouts
	//    webCacheRoundTripper // if we are using the cache
	//    callLimitRoundTripper ** always
	//    [http.DefaultTransport] ** always implicit

	var transport http.RoundTripper

	callLimitTransport := &callLimitRoundTripper{
		remaining: tokenLimit + 500, // put in 500 so we at least have a couple to check our real limits
		resetTime: time.Now().Add(1 * time.Minute),
	}
	config.apiLimit = callLimitTransport
	transport = callLimitTransport

	if config.useMemoryCache {
		t := httpcache.NewMemoryCacheTransport()
		t.Transport = transport

		zeroCacheTransport := &zeroCacheRoundTripper{
			delegate: t,
		}

		transport = zeroCacheTransport
	}

	if len(token) > 0 {
		ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
		transport = &oauth2.Transport{
			Base:   transport,
			Source: oauth2.ReuseTokenSource(nil, ts),
		}
	}

	client := &http.Client{
		Transport: transport,
	}
	config.client = github.NewClient(client)
	config.ResetAPICount()
	return nil
}
Example #8
0
func newAltTokenSource(tokenURL string) oauth2.TokenSource {
	client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))
	a := &altTokenSource{
		oauthClient: client,
		tokenURL:    tokenURL,
	}
	return oauth2.ReuseTokenSource(nil, a)
}
func newOauthClient(authTokenPath string) (*http.Client, error) {
	token, err := oauth2.ReuseTokenSource(nil, gobSource{path: authTokenPath, base: browserSource{}}).Token()
	if err != nil {
		log.Infof("problem exchanging code: %s", err)
		return nil, err
	}
	return oauth2Config.Client(context.Background(), token), nil
}
Example #10
0
// NewClientFrom returns an http client which will use the provided func
// as a source for oauth tokens. The underlying transport handles automatic
// retries and logging that is useful for integration tests and agents.
func NewClientFrom(src oauth2.TokenSource) *http.Client {
	// Wrapping in a ReuseTokenSource will cache the returned token so that src
	// is only called when a new token is needed.
	return newAuthenticatedClient(
		oauth2.ReuseTokenSource(nil, src),
		transport(),
	)
}
Example #11
0
// GetTokenSource builds a new oauth2.TokenSource that uses the ttnctl config to store the token
func GetTokenSource(ctx log.Interface) oauth2.TokenSource {
	if tokenSource != nil {
		return tokenSource
	}
	token := getStoredToken(ctx)
	source := oauth2.ReuseTokenSource(token, getAccountServerTokenSource(token))
	tokenSource = &ttnctlTokenSource{ctx, source}
	return tokenSource
}
Example #12
0
func newAltTokenSource(tokenURL string) oauth2.TokenSource {
	client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))
	a := &altTokenSource{
		oauthClient: client,
		tokenURL:    tokenURL,
		throttle:    util.NewTokenBucketRateLimiter(tokenURLQPS, tokenURLBurst),
	}
	return oauth2.ReuseTokenSource(nil, a)
}
Example #13
0
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{storage.ScopeReadWrite},
			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\nFor server-config.json, your 'googlecloudstorage' value (update with your bucket name and path):\n\n")
	fmt.Fprintf(cmdmain.Stdout, "%s:%s:%s:bucketName[/optional/dir]\n", clientId, clientSecret, token.RefreshToken)
	return nil
}
Example #14
0
// ForceRefreshToken forces a refresh of the access token
func ForceRefreshToken(ctx log.Interface) {
	tokenSource := GetTokenSource(ctx).(*ttnctlTokenSource)
	token, err := tokenSource.Token()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get access token")
	}
	token.Expiry = time.Now().Add(-1 * time.Second)
	tokenSource.source = oauth2.ReuseTokenSource(token, getAccountServerTokenSource(token))
	tokenSource.Token()
}
Example #15
0
func tokenSource() oauth2.TokenSource {
	var tokensource oauth2.TokenSource
	tokenSource, err := google.DefaultTokenSource(oauth2.NoContext)
	if err == nil {
		return tokenSource
	}
	oauthConfig := &oauth2.Config{
		// The client-id and secret should be for an "Installed Application" when using
		// the CLI. Later we'll use a web application with a callback.
		ClientID:     readFile(stagingPrefix() + "client-id.dat"),
		ClientSecret: readFile(stagingPrefix() + "client-secret.dat"),
		Endpoint:     google.Endpoint,
		Scopes: []string{
			compute.DevstorageFullControlScope,
			compute.ComputeScope,
			compute.CloudPlatformScope,
			"https://www.googleapis.com/auth/sqlservice",
			"https://www.googleapis.com/auth/sqlservice.admin",
		},
		RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
	}
	tokenFileName := stagingPrefix() + "token.dat"
	tokenFile := tokenCacheFile(tokenFileName)
	tokenSource = oauth2.ReuseTokenSource(nil, tokenFile)
	token, err := tokenSource.Token()
	if err != nil {
		log.Printf("Error getting token from %s: %v", tokenFileName, err)
		log.Printf("Get auth code from %v", oauthConfig.AuthCodeURL("my-state"))
		fmt.Print("\nEnter auth code: ")
		sc := bufio.NewScanner(os.Stdin)
		sc.Scan()
		authCode := strings.TrimSpace(sc.Text())
		token, err = oauthConfig.Exchange(oauth2.NoContext, authCode)
		if err != nil {
			log.Fatalf("Error exchanging auth code for a token: %v", err)
		}
		if err := tokenFile.WriteToken(token); err != nil {
			log.Fatalf("Error writing to %s: %v", tokenFileName, err)
		}
		tokenSource = oauth2.ReuseTokenSource(token, nil)
	}
	return tokensource
}
Example #16
0
// PreExecute will initialize the GithubConfig. It MUST be run before the config
// may be used to get information from Github
func (config *GithubConfig) PreExecute() error {
	if len(config.Org) == 0 {
		glog.Fatalf("--organization is required.")
	}
	if len(config.Project) == 0 {
		glog.Fatalf("--project is required.")
	}

	token := config.Token
	if len(token) == 0 && len(config.TokenFile) != 0 {
		data, err := ioutil.ReadFile(config.TokenFile)
		if err != nil {
			glog.Fatalf("error reading token file: %v", err)
		}
		token = string(data)
	}

	transport := http.DefaultTransport
	if config.useMemoryCache {
		transport = httpcache.NewMemoryCacheTransport()
	}

	// convert from queries per hour to queries per second
	config.RateLimit = config.RateLimit / 3600
	// ignore the configured rate limit if you don't have a token.
	// only get 60 requests per hour!
	if len(token) == 0 {
		glog.Warningf("Ignoring --rate-limit because no token data available")
		config.RateLimit = 0.01
		config.RateLimitBurst = 10
	}
	rateLimitTransport := &rateLimitRoundTripper{
		delegate: transport,
		throttle: util.NewTokenBucketRateLimiter(config.RateLimit, config.RateLimitBurst),
	}

	client := &http.Client{
		Transport: rateLimitTransport,
	}
	if len(token) > 0 {
		ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
		client = &http.Client{
			Transport: &oauth2.Transport{
				Base:   rateLimitTransport,
				Source: oauth2.ReuseTokenSource(nil, ts),
			},
		}
	}
	config.client = github.NewClient(client)
	config.analytics.lastAPIReset = time.Now()
	return nil
}
Example #17
0
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
}
Example #18
0
// sourceForToken returns a TokenSource based on the following rules:
//   - if token is not "" it is used as the bearer token for the source
//   - if the binary is running on GCE, tokens will be retrieved from the metadata server
//   - otherwise, a source is returned which returns an error each time it is used.
func sourceForToken(token string) oauth2.TokenSource {
	if token != "" {
		return oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
	}

	tok, err := gceToken()
	if err == nil {
		return oauth2.ReuseTokenSource(tok, tokenFunc(gceToken))
	}
	log.Printf("Can't find GCE metadata server: %v", err)
	return tokenFunc(func() (*oauth2.Token, error) {
		return nil, errors.New("must provide a token on command line or run on GCE")
	})
}
Example #19
0
func (config *GithubConfig) PreExecute() error {
	if len(config.Org) == 0 {
		glog.Fatalf("--organization is required.")
	}
	if len(config.Project) == 0 {
		glog.Fatalf("--project is required.")
	}

	token := config.Token
	if len(token) == 0 && len(config.TokenFile) != 0 {
		data, err := ioutil.ReadFile(config.TokenFile)
		if err != nil {
			glog.Fatalf("error reading token file: %v", err)
		}
		token = string(data)
	}

	var client *http.Client
	var transport http.RoundTripper
	if config.useMemoryCache {
		transport = httpcache.NewMemoryCacheTransport()
	} else {
		transport = http.DefaultTransport
	}
	if len(token) > 0 {
		rateLimitTransport := &RateLimitRoundTripper{
			delegate: transport,
			// Global limit is 5000 Q/Hour, try to only use 1800 to make room for other apps
			throttle: util.NewTokenBucketRateLimiter(0.5, 10),
		}
		ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
		client = &http.Client{
			Transport: &oauth2.Transport{
				Base:   rateLimitTransport,
				Source: oauth2.ReuseTokenSource(nil, ts),
			},
		}
	} else {
		rateLimitTransport := &RateLimitRoundTripper{
			delegate: transport,
			throttle: util.NewTokenBucketRateLimiter(0.01, 10),
		}
		client = &http.Client{
			Transport: rateLimitTransport,
		}
	}
	config.client = github.NewClient(client)
	return nil
}
Example #20
0
func RefreshFacebookTokens(c *gin.Context) {
	if auth.IsAuthenticated(c) {
		user := auth.GetUser(c)
		if user.LoginType == "facebook" {
			aecontext := appengine.NewContext(c.Request)
			conf := FBConfig()
			toksource := conf.TokenSource(aecontext, &user.Token)
			sourceToken := oauth2.ReuseTokenSource(&user.Token, toksource)
			client := oauth2.NewClient(aecontext, sourceToken)
			client.Get("...")
			t, _ := sourceToken.Token()
			user.Token = *t
			auth.UpdateUser(c, &user)
			log.Debugf(aecontext, fmt.Sprintf("refresh tokens %#v", t))
		}
	}
}
// SetFromGcloud retrieves and sets any missing config values from the gcloud
// configuration if possible possible
func (c *Config) SetFromGcloud() error {

	if c.Creds == "" {
		c.Creds = os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
		if c.Creds == "" {
			log.Printf("-creds flag unset, will use gcloud credential")
		}
	} else {
		os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", c.Creds)
	}

	if c.Project == "" {
		log.Printf("-project flag unset, will use gcloud active project")
	}

	if c.Creds != "" && c.Project != "" {
		return nil
	}

	gcloudCmd := "gcloud"
	if runtime.GOOS == "windows" {
		gcloudCmd = gcloudCmd + ".cmd"
	}

	gcloudCmdArgs := []string{"config", "config-helper",
		"--format=json(configuration.properties.core.project,credential)"}

	gcloudConfig, err := LoadGcloudConfig(gcloudCmd, gcloudCmdArgs)
	if err != nil {
		return err
	}

	if c.Project == "" && gcloudConfig.Configuration.Properties.Core.Project != "" {
		log.Printf("gcloud active project is \"%s\"",
			gcloudConfig.Configuration.Properties.Core.Project)
		c.Project = gcloudConfig.Configuration.Properties.Core.Project
	}

	if c.Creds == "" {
		c.TokenSource = oauth2.ReuseTokenSource(
			gcloudConfig.Credential.Token(),
			&GcloudCmdTokenSource{Command: gcloudCmd, Args: gcloudCmdArgs})
	}

	return nil
}
Example #22
0
// tokenSource creates a new oauth2.TokenSource backed by tokenRefresher,
// using previously stored user credentials if available.
func tokenSource(provider string) (oauth2.TokenSource, error) {
	conf := authConfig[provider]
	if conf == nil {
		return nil, fmt.Errorf("no auth config for %q", provider)
	}
	t, err := readToken(provider)
	if err != nil {
		t, err = authorize(conf)
	}
	if err != nil {
		return nil, fmt.Errorf("unable to obtain access token for %q", provider)
	}
	cache := &cachedTokenSource{
		src:      conf.TokenSource(context.Background(), t),
		provider: provider,
		config:   conf,
	}
	return oauth2.ReuseTokenSource(nil, cache), nil
}
Example #23
0
// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON
// key file to read the credentials that authorize and authenticate the
// requests, and returns a TokenSource that does not use any OAuth2 flow but
// instead creates a JWT and sends that as the access token.
// The audience is typically a URL that specifies the scope of the credentials.
func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
	cfg, err := JWTConfigFromJSON(jsonKey)
	if err != nil {
		return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
	}
	pk, err := internal.ParseKey(cfg.PrivateKey)
	if err != nil {
		return nil, fmt.Errorf("google: could not parse key: %v", err)
	}
	ts := &jwtAccessTokenSource{
		email:    cfg.Email,
		audience: audience,
		pk:       pk,
	}
	tok, err := ts.Token()
	if err != nil {
		return nil, err
	}
	return oauth2.ReuseTokenSource(tok, ts), nil
}
Example #24
0
func getEvents(count int64) []*calendar.Event {

	sourceToken := oauth2.ReuseTokenSource(nil, &fileTokenSource{})
	t, _ := sourceToken.Token()
	client := clientConfig.Client(oauth2.NoContext, t)

	svc, err := calendar.New(client)
	if err != nil {
		fmt.Println(err)
	}
	//c, err := svc.CalendarList.List().Do()
	startTime := time.Now().Format(time.RFC3339)
	c, err := svc.Events.List(*calendarId).SingleEvents(true).OrderBy("startTime").TimeMin(startTime).MaxResults(count).Do()
	//c, err := svc.Events.List(*calendarId).Do()
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return c.Items

}
Example #25
0
// GetClient returns the generated Client.
func GetClient(scopes ...string) *http.Client {
	b, err := ioutil.ReadFile("client_secret.json")
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v", err)
	}

	config, err := google.ConfigFromJSON(b, scopes...)
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}

	tok, err := tokenFromFile(tokenFile)
	if err != nil {
		tok = getTokenFromWeb(config)
		saveToken(tokenFile, tok)
	}
	ctx := context.Background()
	//Very hacky, but somehow works
	ts := oauth2.ReuseTokenSource(nil, config.TokenSource(ctx, tok))
	t, _ := ts.Token()
	return config.Client(ctx, t)
}
Example #26
0
// 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})
}
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 == "" {
		if !metadata.OnGCE() {
			if *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'")
			}
		} else {
			*clientID = "auto"
		}
	}
	if *configFile == "" {
		config := &oauth2.Config{
			Scopes:       []string{storage.ScopeReadWrite},
			Endpoint:     google.Endpoint,
			ClientID:     *clientID,
			ClientSecret: *clientSecret,
			RedirectURL:  oauthutil.TitleBarRedirectURL,
		}
		if !metadata.OnGCE() {
			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
			ctx := context.Background()
			stor := sto.(*Storage)
			objs, err := stor.client.Bucket(stor.bucket).List(ctx, nil)
			if err != nil {
				t.Fatalf("Error checking if bucket is empty: %v", err)
			}
			if len(objs.Results) != 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"} {
					w := stor.client.Bucket(stor.bucket).Object(key).NewWriter(ctx)
					if _, err := io.Copy(w, strings.NewReader(key)); err != nil {
						t.Fatalf("could not insert object %s in bucket %v: %v", key, sto.(*Storage).bucket, err)
					}
					if err := w.Close(); 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.TODO(), 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"} {
							rc, err := stor.client.Bucket(stor.bucket).Object(key).NewReader(ctx)
							if err != nil {
								t.Fatalf("could not find object %s after tests: %v", key, err)
							}
							if _, err := io.Copy(ioutil.Discard, rc); err != nil {
								t.Fatalf("could not find object %s after tests: %v", key, err)
							}
							if err := stor.client.Bucket(stor.bucket).Object(key).Delete(ctx); err != nil {
								t.Fatalf("could not remove object %s after tests: %v", key, err)
							}

						}
					}
				}
			}
			clearBucket(true)()
			return sto, clearBucket(false)
		},
	})
}
Example #28
0
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.")
	}

	// We embed the client ID and client secret, per
	// https://developers.google.com/identity/protocols/OAuth2InstalledApp
	// Notably: "The client ID and client secret obtained from the
	// Developers Console are embedded in the source code of your
	// application. In this context, the client secret is
	// obviously not treated as a secret."
	//
	// These were created at:
	// https://console.developers.google.com/apis/credentials?project=camlistore-website
	// (Notes for Brad and Mathieu)
	const (
		clientID     = "574004351801-9qqoggh6b5v3jqt722v43ikmgmtv60h3.apps.googleusercontent.com"
		clientSecret = "Gf1zwaOcbJnRTE5zD4feKaTI" // NOT a secret, despite name
	)
	config := gce.NewOAuthConfig(clientID, clientSecret)
	config.RedirectURL = "urn:ietf:wg:oauth:2.0:oob"

	hc := 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\n", config.AuthCodeURL("my-state", oauth2.AccessTypeOffline, oauth2.ApprovalForce))
			fmt.Print("Enter auth code: ")
			sc := bufio.NewScanner(os.Stdin)
			sc.Scan()
			return strings.TrimSpace(sc.Text())
		},
	}))

	zone := c.zone
	if gce.LooksLikeRegion(zone) {
		region := zone
		zones, err := gce.ZonesOfRegion(hc, c.project, region)
		if err != nil {
			return err
		}
		if len(zones) == 0 {
			return fmt.Errorf("no zones found in region %q; invalid region?", region)
		}
		zone = zones[rand.Intn(len(zones))]
	}

	instConf := &gce.InstanceConf{
		Name:     c.instName,
		Project:  c.project,
		Machine:  c.machine,
		Zone:     zone,
		CertFile: c.certFile,
		KeyFile:  c.keyFile,
		Hostname: c.hostname,
	}
	if c.sshPub != "" {
		instConf.SSHPub = strings.TrimSpace(readFile(c.sshPub))
	}

	log.Printf("Creating instance %s (in project %s) in zone %s ...", c.instName, c.project, zone)
	depl := &gce.Deployer{
		Client: hc,
		Conf:   instConf,
	}
	inst, err := depl.Create(context.Background())
	if err != nil {
		return err
	}

	log.Printf("Instance created; starting up at %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP)
	return nil
}
Example #29
0
// 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})
}
Example #30
0
func main() {
	flag.Parse()
	if *proj == "" {
		log.Fatalf("Missing --project flag")
	}
	prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
	machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach

	const tokenFileName = "token.dat"
	tokenFile := tokenCacheFile(tokenFileName)
	tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
	token, err := tokenSource.Token()
	if err != nil {
		if *writeObject != "" {
			log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
		}
		log.Printf("Error getting token from %s: %v", tokenFileName, err)
		log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
		fmt.Print("\nEnter auth code: ")
		sc := bufio.NewScanner(os.Stdin)
		sc.Scan()
		authCode := strings.TrimSpace(sc.Text())
		token, err = config.Exchange(oauth2.NoContext, authCode)
		if err != nil {
			log.Fatalf("Error exchanging auth code for a token: %v", err)
		}
		if err := tokenFile.WriteToken(token); err != nil {
			log.Fatalf("Error writing to %s: %v", tokenFileName, err)
		}
		tokenSource = oauth2.ReuseTokenSource(token, nil)
	}

	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)

	if *writeObject != "" {
		writeCloudStorageObject(oauthClient)
		return
	}

	computeService, _ := compute.New(oauthClient)

	natIP := *staticIP
	if natIP == "" {
		// Try to find it by name.
		aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
		if err != nil {
			log.Fatal(err)
		}
		// http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
	IPLoop:
		for _, asl := range aggAddrList.Items {
			for _, addr := range asl.Addresses {
				if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
					natIP = addr.Address
					break IPLoop
				}
			}
		}
	}

	cloudConfig := baseConfig
	if *sshPub != "" {
		key := strings.TrimSpace(readFile(*sshPub))
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", key)
	}
	if os.Getenv("USER") == "bradfitz" {
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= [email protected]")
	}
	const maxCloudConfig = 32 << 10 // per compute API docs
	if len(cloudConfig) > maxCloudConfig {
		log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
	}

	instance := &compute.Instance{
		Name:        *instName,
		Description: "Go Builder",
		MachineType: machType,
		Disks:       []*compute.AttachedDisk{instanceDisk(computeService)},
		Tags: &compute.Tags{
			Items: []string{"http-server", "https-server"},
		},
		Metadata: &compute.Metadata{
			Items: []*compute.MetadataItems{
				{
					Key:   "user-data",
					Value: cloudConfig,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			&compute.NetworkInterface{
				AccessConfigs: []*compute.AccessConfig{
					&compute.AccessConfig{
						Type:  "ONE_TO_ONE_NAT",
						Name:  "External NAT",
						NatIP: natIP,
					},
				},
				Network: prefix + "/global/networks/default",
			},
		},
		ServiceAccounts: []*compute.ServiceAccount{
			{
				Email: "default",
				Scopes: []string{
					compute.DevstorageFull_controlScope,
					compute.ComputeScope,
				},
			},
		},
	}

	log.Printf("Creating instance...")
	op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
	if err != nil {
		log.Fatalf("Failed to create instance: %v", err)
	}
	opName := op.Name
	log.Printf("Created. Waiting on operation %v", opName)
OpLoop:
	for {
		time.Sleep(2 * time.Second)
		op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
		if err != nil {
			log.Fatalf("Failed to get op %s: %v", opName, err)
		}
		switch op.Status {
		case "PENDING", "RUNNING":
			log.Printf("Waiting on operation %v", opName)
			continue
		case "DONE":
			if op.Error != nil {
				for _, operr := range op.Error.Errors {
					log.Printf("Error: %+v", operr)
				}
				log.Fatalf("Failed to start.")
			}
			log.Printf("Success. %+v", op)
			break OpLoop
		default:
			log.Fatalf("Unknown status %q: %+v", op.Status, op)
		}
	}

	inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
	if err != nil {
		log.Fatalf("Error getting instance after creation: %v", err)
	}
	ij, _ := json.MarshalIndent(inst, "", "    ")
	log.Printf("Instance: %s", ij)
}