github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/maas/credentials.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package maas 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "strings" 13 14 "github.com/juju/errors" 15 "github.com/juju/utils" 16 17 "github.com/juju/juju/cloud" 18 "github.com/juju/juju/environs" 19 ) 20 21 const ( 22 credAttrMAASOAuth = "maas-oauth" 23 ) 24 25 type environProviderCredentials struct{} 26 27 // CredentialSchemas is part of the environs.ProviderCredentials interface. 28 func (environProviderCredentials) CredentialSchemas() map[cloud.AuthType]cloud.CredentialSchema { 29 return map[cloud.AuthType]cloud.CredentialSchema{ 30 cloud.OAuth1AuthType: {{ 31 credAttrMAASOAuth, cloud.CredentialAttr{ 32 Description: "OAuth/API-key credentials for MAAS", 33 Hidden: true, 34 }, 35 }}, 36 } 37 } 38 39 // DetectCredentials is part of the environs.ProviderCredentials interface. 40 func (environProviderCredentials) DetectCredentials() (*cloud.CloudCredential, error) { 41 // MAAS stores credentials in a json file: ~/.maasrc 42 // {"Server": "http://<ip>/MAAS", "OAuth": "<key>"} 43 maasrc := filepath.Join(utils.Home(), ".maasrc") 44 fileBytes, err := ioutil.ReadFile(maasrc) 45 if os.IsNotExist(err) { 46 return nil, errors.NotFoundf("maas credentials") 47 } 48 if err != nil { 49 return nil, errors.Trace(err) 50 } 51 52 details := make(map[string]interface{}) 53 err = json.Unmarshal(fileBytes, &details) 54 if err != nil { 55 return nil, errors.Trace(err) 56 } 57 oauthKey := details["OAuth"] 58 if oauthKey == "" { 59 return nil, errors.New("MAAS credentials require a value for OAuth token") 60 } 61 cred := cloud.NewCredential(cloud.OAuth1AuthType, map[string]string{ 62 credAttrMAASOAuth: fmt.Sprintf("%v", oauthKey), 63 }) 64 server, ok := details["Server"] 65 if server == "" || !ok { 66 server = "unspecified server" 67 } 68 cred.Label = fmt.Sprintf("MAAS credential for %s", server) 69 70 return &cloud.CloudCredential{ 71 AuthCredentials: map[string]cloud.Credential{ 72 "default": cred, 73 }, 74 }, nil 75 } 76 77 func parseOAuthToken(cred cloud.Credential) (string, error) { 78 oauth := cred.Attributes()[credAttrMAASOAuth] 79 if strings.Count(oauth, ":") != 2 { 80 return "", errMalformedMaasOAuth 81 } 82 return oauth, nil 83 } 84 85 var errMalformedMaasOAuth = errors.New("malformed maas-oauth (3 items separated by colons)") 86 87 // FinalizeCredential is part of the environs.ProviderCredentials interface. 88 func (environProviderCredentials) FinalizeCredential(_ environs.FinalizeCredentialContext, args environs.FinalizeCredentialParams) (*cloud.Credential, error) { 89 return &args.Credential, nil 90 }