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  }