github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/controller/authentication/authentication.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package authentication
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/utils"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/api"
    14  	apiprovisioner "github.com/juju/juju/api/provisioner"
    15  	"github.com/juju/juju/mongo"
    16  )
    17  
    18  // TaggedPasswordChanger defines an interface for a entity with a
    19  // Tag() and SetPassword() methods.
    20  type TaggedPasswordChanger interface {
    21  	SetPassword(string) error
    22  	Tag() names.Tag
    23  }
    24  
    25  // AuthenticationProvider defines the single method that the provisioner
    26  // task needs to set up authentication for a machine.
    27  type AuthenticationProvider interface {
    28  	SetupAuthentication(machine TaggedPasswordChanger) (*mongo.MongoInfo, *api.Info, error)
    29  }
    30  
    31  // NewAPIAuthenticator gets the state and api info once from the
    32  // provisioner API.
    33  func NewAPIAuthenticator(st *apiprovisioner.State) (AuthenticationProvider, error) {
    34  	stateAddresses, err := st.StateAddresses()
    35  	if err != nil {
    36  		return nil, errors.Trace(err)
    37  	}
    38  	apiAddresses, err := st.APIAddresses()
    39  	if err != nil {
    40  		return nil, errors.Trace(err)
    41  	}
    42  	caCert, err := st.CACert()
    43  	if err != nil {
    44  		return nil, errors.Trace(err)
    45  	}
    46  	modelUUID, err := st.ModelUUID()
    47  	if err != nil {
    48  		return nil, errors.Trace(err)
    49  	}
    50  	stateInfo := &mongo.MongoInfo{
    51  		Info: mongo.Info{
    52  			Addrs:  stateAddresses,
    53  			CACert: caCert,
    54  		},
    55  	}
    56  	apiInfo := &api.Info{
    57  		Addrs:    apiAddresses,
    58  		CACert:   caCert,
    59  		ModelTag: names.NewModelTag(modelUUID),
    60  	}
    61  	return &simpleAuth{stateInfo, apiInfo}, nil
    62  }
    63  
    64  // SetupAuthentication generates a random password for the given machine,
    65  // recording it via the machine's SetPassword method, and updates the
    66  // info arguments with the tag and password.
    67  func SetupAuthentication(
    68  	machine TaggedPasswordChanger,
    69  	stateInfo *mongo.MongoInfo,
    70  	apiInfo *api.Info,
    71  ) (*mongo.MongoInfo, *api.Info, error) {
    72  	auth := simpleAuth{stateInfo, apiInfo}
    73  	return auth.SetupAuthentication(machine)
    74  }
    75  
    76  type simpleAuth struct {
    77  	stateInfo *mongo.MongoInfo
    78  	apiInfo   *api.Info
    79  }
    80  
    81  func (auth *simpleAuth) SetupAuthentication(machine TaggedPasswordChanger) (*mongo.MongoInfo, *api.Info, error) {
    82  	password, err := utils.RandomPassword()
    83  	if err != nil {
    84  		return nil, nil, fmt.Errorf("cannot make password for machine %v: %v", machine, err)
    85  	}
    86  	if err := machine.SetPassword(password); err != nil {
    87  		return nil, nil, fmt.Errorf("cannot set API password for machine %v: %v", machine, err)
    88  	}
    89  	var stateInfo *mongo.MongoInfo
    90  	if auth.stateInfo != nil {
    91  		stateInfoCopy := *auth.stateInfo
    92  		stateInfo = &stateInfoCopy
    93  		stateInfo.Tag = machine.Tag()
    94  		stateInfo.Password = password
    95  	}
    96  	var apiInfo *api.Info
    97  	if auth.apiInfo != nil {
    98  		apiInfoCopy := *auth.apiInfo
    99  		apiInfo = &apiInfoCopy
   100  		apiInfo.Tag = machine.Tag()
   101  		apiInfo.Password = password
   102  	}
   103  	return stateInfo, apiInfo, nil
   104  }