github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/openstack/credentials.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package openstack 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 "regexp" 11 12 "github.com/juju/errors" 13 "github.com/juju/utils" 14 "gopkg.in/goose.v1/identity" 15 "gopkg.in/ini.v1" 16 17 "github.com/juju/juju/cloud" 18 ) 19 20 type OpenstackCredentials struct{} 21 22 // CredentialSchemas is part of the environs.ProviderCredentials interface. 23 func (OpenstackCredentials) CredentialSchemas() map[cloud.AuthType]cloud.CredentialSchema { 24 return map[cloud.AuthType]cloud.CredentialSchema{ 25 cloud.UserPassAuthType: { 26 { 27 "username", cloud.CredentialAttr{Description: "The username to authenticate with."}, 28 }, { 29 "password", cloud.CredentialAttr{ 30 Description: "The password for the specified username.", 31 Hidden: true, 32 }, 33 }, { 34 "tenant-name", cloud.CredentialAttr{Description: "The OpenStack tenant name."}, 35 }, { 36 "domain-name", cloud.CredentialAttr{ 37 Description: "The OpenStack domain name.", 38 Optional: true, 39 }, 40 }, 41 }, 42 cloud.AccessKeyAuthType: { 43 { 44 "access-key", cloud.CredentialAttr{Description: "The access key to authenticate with."}, 45 }, { 46 "secret-key", cloud.CredentialAttr{ 47 Description: "The secret key to authenticate with.", 48 Hidden: true, 49 }, 50 }, { 51 "tenant-name", cloud.CredentialAttr{Description: "The OpenStack tenant name."}, 52 }, 53 }, 54 } 55 } 56 57 // DetectCredentials is part of the environs.ProviderCredentials interface. 58 func (c OpenstackCredentials) DetectCredentials() (*cloud.CloudCredential, error) { 59 result := cloud.CloudCredential{ 60 AuthCredentials: make(map[string]cloud.Credential), 61 } 62 63 // Try just using environment variables 64 creds, user, region, err := c.detectCredential() 65 if err == nil { 66 result.DefaultRegion = region 67 result.AuthCredentials[user] = *creds 68 } 69 70 // Now look for .novarc file in home dir. 71 novarc := filepath.Join(utils.Home(), ".novarc") 72 novaInfo, err := ini.LooseLoad(novarc) 73 if err != nil { 74 return nil, errors.Annotate(err, "loading novarc file") 75 } 76 stripExport := regexp.MustCompile(`(?i)^\s*export\s*`) 77 keyValues := novaInfo.Section(ini.DEFAULT_SECTION).KeysHash() 78 if len(keyValues) > 0 { 79 for k, v := range keyValues { 80 k = stripExport.ReplaceAllString(k, "") 81 os.Setenv(k, v) 82 } 83 creds, user, region, err := c.detectCredential() 84 if err == nil { 85 result.DefaultRegion = region 86 result.AuthCredentials[user] = *creds 87 } 88 } 89 if len(result.AuthCredentials) == 0 { 90 return nil, errors.NotFoundf("openstack credentials") 91 } 92 return &result, nil 93 } 94 95 func (c OpenstackCredentials) detectCredential() (*cloud.Credential, string, string, error) { 96 creds := identity.CredentialsFromEnv() 97 if creds.TenantName == "" { 98 return nil, "", "", errors.NewNotFound(nil, "OS_TENANT_NAME environment variable not set") 99 } 100 if creds.User == "" { 101 return nil, "", "", errors.NewNotFound(nil, "neither OS_USERNAME nor OS_ACCESS_KEY environment variable not set") 102 } 103 if creds.Secrets == "" { 104 return nil, "", "", errors.NewNotFound(nil, "neither OS_PASSWORD nor OS_SECRET_KEY environment variable not set") 105 } 106 107 user, err := utils.LocalUsername() 108 if err != nil { 109 return nil, "", "", errors.Trace(err) 110 } 111 112 // If OS_USERNAME or NOVA_USERNAME is set, assume userpass. 113 var credential cloud.Credential 114 if os.Getenv("OS_USERNAME") != "" || os.Getenv("NOVA_USERNAME") != "" { 115 user = creds.User 116 credential = cloud.NewCredential( 117 cloud.UserPassAuthType, 118 map[string]string{ 119 "username": creds.User, 120 "password": creds.Secrets, 121 "tenant-name": creds.TenantName, 122 "domain-name": creds.DomainName, 123 }, 124 ) 125 } else { 126 credential = cloud.NewCredential( 127 cloud.AccessKeyAuthType, 128 map[string]string{ 129 "access-key": creds.User, 130 "secret-key": creds.Secrets, 131 "tenant-name": creds.TenantName, 132 }, 133 ) 134 } 135 region := creds.Region 136 if region == "" { 137 region = "<unspecified>" 138 } 139 credential.Label = fmt.Sprintf("openstack region %q project %q user %q", region, creds.TenantName, user) 140 return &credential, user, creds.Region, nil 141 }