Ejemplo n.º 1
0
func authFromScratch(credsResult *CredentialsResult, serviceType string, urlType gophercloud.Availability, logger *logrus.Logger) (*gophercloud.ServiceClient, error) {
	logger.Info("Not using cache; Authenticating from scratch.\n")

	ao := credsResult.AuthOpts
	region := credsResult.Region

	pc, err := rackspace.AuthenticatedClient(*ao)
	if err != nil {
		switch err.(type) {
		case *tokens2.ErrNoPassword:
			return nil, errors.New("Please supply an API key.")
		}
		return nil, err
	}
	pc.HTTPClient = newHTTPClient()
	var sc *gophercloud.ServiceClient
	switch serviceType {
	case "compute":
		sc, err = rackspace.NewComputeV2(pc, gophercloud.EndpointOpts{
			Region:       region,
			Availability: urlType,
		})
		break
	case "object-store":
		sc, err = rackspace.NewObjectStorageV1(pc, gophercloud.EndpointOpts{
			Region:       region,
			Availability: urlType,
		})
		break
	case "blockstorage":
		sc, err = rackspace.NewBlockStorageV1(pc, gophercloud.EndpointOpts{
			Region:       region,
			Availability: urlType,
		})
		break
	case "network":
		sc, err = rackspace.NewNetworkV2(pc, gophercloud.EndpointOpts{
			Region:       region,
			Availability: urlType,
		})
		break
	}
	if err != nil {
		return nil, err
	}
	if sc == nil {
		return nil, fmt.Errorf("Unable to create service client: Unknown service type: %s\n", serviceType)
	}
	if sc.Endpoint == "/" {
		return nil, fmt.Errorf(strings.Join([]string{"You wanted to use service net for the %s request",
			"but the %s service doesn't have an internal URL.\n"}, " "), serviceType, serviceType)
	}
	logger.Debugf("Created %s service client: %+v", serviceType, sc)
	sc.UserAgent.Prepend(util.UserAgent)
	return sc, nil
}
Ejemplo n.º 2
0
func authFromScratch(credsResult *CredentialsResult, serviceType string, logger *logrus.Logger) (*gophercloud.ServiceClient, error) {
	logger.Info("Not using cache; Authenticating from scratch.\n")

	ao := credsResult.AuthOpts
	region := credsResult.Region

	pc, err := rackspace.AuthenticatedClient(*ao)
	if err != nil {
		return nil, err
	}
	pc.HTTPClient = newHTTPClient()
	var sc *gophercloud.ServiceClient
	switch serviceType {
	case "compute":
		sc, err = rackspace.NewComputeV2(pc, gophercloud.EndpointOpts{
			Region: region,
		})
		break
	case "object-store":
		sc, err = rackspace.NewObjectStorageV1(pc, gophercloud.EndpointOpts{
			Region: region,
		})
		break
	case "blockstorage":
		sc, err = rackspace.NewBlockStorageV1(pc, gophercloud.EndpointOpts{
			Region: region,
		})
		break
	case "network":
		sc, err = rackspace.NewNetworkV2(pc, gophercloud.EndpointOpts{
			Region: region,
		})
		break
	}
	if err != nil {
		return nil, err
	}
	if sc == nil {
		return nil, fmt.Errorf("Unable to create service client: Unknown service type: %s\n", serviceType)
	}
	sc.UserAgent.Prepend(util.UserAgent)
	return sc, nil
}
Ejemplo n.º 3
0
// NewClient creates and returns a Rackspace client for the given service.
func NewClient(c *cli.Context, serviceType string, logger *logrus.Logger, noCache bool) (*gophercloud.ServiceClient, error) {
	// get the user's authentication credentials
	credsResult, err := Credentials(c, logger)
	if err != nil {
		return nil, err
	}

	if noCache {
		return authFromScratch(credsResult, serviceType, logger)
	}

	ao := credsResult.AuthOpts
	region := credsResult.Region

	// form the cache key
	cacheKey := CacheKey(*ao, region, serviceType)
	// initialize cache
	cache := &Cache{}
	logger.Infof("Looking in the cache for cache key: %s\n", cacheKey)
	// get the value from the cache
	creds, err := cache.Value(cacheKey)
	// if there was an error accessing the cache or there was nothing in the cache,
	// authenticate from scratch
	if err == nil && creds != nil {
		// we successfully retrieved a value from the cache
		logger.Infof("Using token from cache: %s\n", creds.TokenID)
		pc, err := rackspace.NewClient(ao.IdentityEndpoint)
		if err == nil {
			pc.TokenID = creds.TokenID
			pc.ReauthFunc = reauthFunc(pc, *ao)
			pc.UserAgent.Prepend(util.UserAgent)
			pc.HTTPClient = newHTTPClient()
			return &gophercloud.ServiceClient{
				ProviderClient: pc,
				Endpoint:       creds.ServiceEndpoint,
			}, nil
		}
	} else {
		return authFromScratch(credsResult, serviceType, logger)
	}

	return nil, nil
}
Ejemplo n.º 4
0
// Credentials determines the appropriate authentication method for the user.
// It returns a gophercloud.AuthOptions object and a region.
//
// It will use command-line authentication parameters if available, then it will
// look for any unset parameters in the config file, and then finally in
// environment variables.
func Credentials(c *cli.Context, logger *logrus.Logger) (*CredentialsResult, error) {
	ao := &gophercloud.AuthOptions{
		AllowReauth: true,
	}

	have := make(map[string]commandoptions.Cred)

	// let's looks for a region and identity endpoint
	want := map[string]string{
		"auth-url": "",
		"region":   "",
	}

	err := findAuthOpts(c, have, want)
	if err != nil {
		return nil, err
	}

	// if the user didn't provide an auth URL, default to the Rackspace US endpoint
	if _, ok := have["auth-url"]; !ok || have["auth-url"].Value == "" {
		have["auth-url"] = commandoptions.Cred{Value: rackspace.RackspaceUSIdentity, From: "default value"}
		delete(want, "auth-url")
	}
	ao.IdentityEndpoint = have["auth-url"].Value

	// upper-case the region
	region := strings.ToUpper(have["region"].Value)
	delete(want, "region")

	// now we check for token authentication (only allowed via the command-line)
	want["auth-tenant-id"] = ""
	want["auth-token"] = ""
	commandoptions.CLIopts(c, have, want)

	// if a tenant ID was provided on the command-line, we don't bother checking for a
	// username or api key
	if have["auth-tenant-id"].Value != "" || have["auth-token"].Value != "" {
		if tenantID, ok := have["auth-tenant-id"]; ok {
			ao.TenantID = tenantID.Value
			ao.TokenID = have["auth-token"].Value
			delete(want, "auth-token")
		} else {
			return nil, Err(have, want, tenantIDAuthErrSlice)
		}
	} else {
		// otherwise, let's look for a username and API key
		want = map[string]string{
			"username": "",
			"api-key":  "",
		}
		err = findAuthOpts(c, have, want)
		if err != nil {
			return nil, err
		}
		if have["username"].Value != "" || have["api-key"].Value != "" {
			if username, ok := have["username"]; ok {
				ao.Username = username.Value
				ao.APIKey = have["api-key"].Value
				delete(want, "api-key")
			} else {
				return nil, Err(have, want, usernameAuthErrSlice)
			}
		} else {
			return nil, Err(have, want, usernameAuthErrSlice)
		}
	}

	if logger != nil {
		haveString := ""
		for k, v := range have {
			haveString += fmt.Sprintf("%s: %s (from %s)\n", k, v.Value, v.From)
		}
		logger.Infof("Authentication Credentials:\n%s\n", haveString)
	}

	credsResult := &CredentialsResult{
		AuthOpts: ao,
		Region:   region,
		Have:     have,
		Want:     want,
	}

	return credsResult, nil
}
Ejemplo n.º 5
0
// Credentials determines the appropriate authentication method for the user.
// It returns a gophercloud.AuthOptions object and a region.
//
// It will use command-line authentication parameters if available, then it will
// look for any unset parameters in the config file, and then finally in
// environment variables.
func Credentials(c *cli.Context, logger *logrus.Logger) (*gophercloud.AuthOptions, string, error) {
	have := make(map[string]authCred)
	need := map[string]string{
		"username": "",
		"apikey":   "",
		"authurl":  "",
		"region":   "",
	}

	// use command-line options if available
	cliopts(c, have, need)
	// are there any unset auth variables?
	if len(need) != 0 {
		// if so, look in config file
		err := configfile(c, have, need)
		if err != nil {
			return nil, "", err
		}
		// still unset auth variables?
		if len(need) != 0 {
			// if so, look in environment variables
			envvars(have, need)
		}
	}

	// if the user didn't provide an auth URL, default to the Rackspace US endpoint
	if _, ok := have["authurl"]; !ok || have["authurl"].value == "" {
		have["authurl"] = authCred{value: rackspace.RackspaceUSIdentity, from: "default value"}
		delete(need, "authurl")
	}

	haveString := ""
	for k, v := range have {
		haveString += fmt.Sprintf("%s: %s (from %s)\n", k, v.value, v.from)
	}

	if len(need) > 0 {
		needString := ""
		for k := range need {
			needString += fmt.Sprintf("%s\n", k)
		}

		authErrSlice := []string{"There are some required Rackspace Cloud credentials that we couldn't find.",
			"Here's what we have:",
			fmt.Sprintf("%s", haveString),
			"and here's what we we're missing:",
			fmt.Sprintf("%s", needString),
			"",
			"You can set any of these credentials in the following ways:",
			"- Run `rack configure` to interactively create a configuration file,",
			"- Specify it in the command as a flag (--username, --apikey, --region), or",
			"- Export it as an environment variable (RS_USERNAME, RS_API_KEY, RS_REGION_NAME).",
			"",
		}

		return nil, "", fmt.Errorf(strings.Join(authErrSlice, "\n"))
	}

	if logger != nil {
		logger.Infof("Authentication Credentials:\n%s\n", haveString)
	}

	ao := &gophercloud.AuthOptions{
		Username:         have["username"].value,
		APIKey:           have["apikey"].value,
		IdentityEndpoint: have["authurl"].value,
	}

	// upper-case the region
	region := strings.ToUpper(have["region"].value)
	// allow Gophercloud to re-authenticate
	ao.AllowReauth = true

	return ao, region, nil
}