github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/sshclient/facade.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package sshclient implements the API endpoint required for Juju 5 // clients that wish to make SSH connections to Juju managed machines. 6 package sshclient 7 8 import ( 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/apiserver/common" 12 "github.com/juju/juju/apiserver/facade" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/network" 15 "github.com/juju/juju/permission" 16 ) 17 18 func init() { 19 common.RegisterStandardFacade("SSHClient", 1, newFacade) 20 } 21 22 // Facade implements the API required by the sshclient worker. 23 type Facade struct { 24 backend Backend 25 authorizer facade.Authorizer 26 } 27 28 // New returns a new API facade for the sshclient worker. 29 func New(backend Backend, _ facade.Resources, authorizer facade.Authorizer) (*Facade, error) { 30 if !authorizer.AuthClient() { 31 return nil, common.ErrPerm 32 } 33 return &Facade{backend: backend, authorizer: authorizer}, nil 34 } 35 36 func (facade *Facade) checkIsModelAdmin() error { 37 isModelAdmin, err := facade.authorizer.HasPermission(permission.AdminAccess, facade.backend.ModelTag()) 38 if err != nil { 39 return errors.Trace(err) 40 } 41 if !isModelAdmin { 42 return common.ErrPerm 43 } 44 return nil 45 } 46 47 // PublicAddress reports the preferred public network address for one 48 // or more entities. Machines and units are suppored. 49 func (facade *Facade) PublicAddress(args params.Entities) (params.SSHAddressResults, error) { 50 if err := facade.checkIsModelAdmin(); err != nil { 51 return params.SSHAddressResults{}, errors.Trace(err) 52 } 53 54 getter := func(m SSHMachine) (network.Address, error) { return m.PublicAddress() } 55 return facade.getAddresses(args, getter) 56 } 57 58 // PrivateAddress reports the preferred private network address for one or 59 // more entities. Machines and units are supported. 60 func (facade *Facade) PrivateAddress(args params.Entities) (params.SSHAddressResults, error) { 61 if err := facade.checkIsModelAdmin(); err != nil { 62 return params.SSHAddressResults{}, errors.Trace(err) 63 } 64 65 getter := func(m SSHMachine) (network.Address, error) { return m.PrivateAddress() } 66 return facade.getAddresses(args, getter) 67 } 68 69 func (facade *Facade) getAddresses(args params.Entities, getter func(SSHMachine) (network.Address, error)) ( 70 params.SSHAddressResults, error, 71 ) { 72 out := params.SSHAddressResults{ 73 Results: make([]params.SSHAddressResult, len(args.Entities)), 74 } 75 for i, entity := range args.Entities { 76 machine, err := facade.backend.GetMachineForEntity(entity.Tag) 77 if err != nil { 78 out.Results[i].Error = common.ServerError(err) 79 } else { 80 address, err := getter(machine) 81 if err != nil { 82 out.Results[i].Error = common.ServerError(err) 83 } else { 84 out.Results[i].Address = address.Value 85 } 86 } 87 } 88 return out, nil 89 } 90 91 // PublicKeys returns the public SSH hosts for one or more 92 // entities. Machines and units are supported. 93 func (facade *Facade) PublicKeys(args params.Entities) (params.SSHPublicKeysResults, error) { 94 if err := facade.checkIsModelAdmin(); err != nil { 95 return params.SSHPublicKeysResults{}, errors.Trace(err) 96 } 97 98 out := params.SSHPublicKeysResults{ 99 Results: make([]params.SSHPublicKeysResult, len(args.Entities)), 100 } 101 for i, entity := range args.Entities { 102 machine, err := facade.backend.GetMachineForEntity(entity.Tag) 103 if err != nil { 104 out.Results[i].Error = common.ServerError(err) 105 } else { 106 keys, err := facade.backend.GetSSHHostKeys(machine.MachineTag()) 107 if err != nil { 108 out.Results[i].Error = common.ServerError(err) 109 } else { 110 out.Results[i].PublicKeys = []string(keys) 111 } 112 } 113 } 114 return out, nil 115 } 116 117 // Proxy returns whether SSH connections should be proxied through the 118 // controller hosts for the model associated with the API connection. 119 func (facade *Facade) Proxy() (params.SSHProxyResult, error) { 120 if err := facade.checkIsModelAdmin(); err != nil { 121 return params.SSHProxyResult{}, errors.Trace(err) 122 } 123 config, err := facade.backend.ModelConfig() 124 if err != nil { 125 return params.SSHProxyResult{}, err 126 } 127 return params.SSHProxyResult{UseProxy: config.ProxySSH()}, nil 128 }