github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/jujud/util/password/password_windows_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Copyright 2015 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  // +build windows
     6  
     7  package password
     8  
     9  import (
    10  	"fmt"
    11  	"regexp"
    12  
    13  	// https://bugs.launchpad.net/juju-core/+bug/1470820
    14  	"github.com/gabriel-samfira/sys/windows/registry"
    15  	"github.com/juju/errors"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/utils"
    18  	gc "gopkg.in/check.v1"
    19  
    20  	"github.com/juju/juju/service/windows"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  var (
    25  	_ = gc.Suite(&ServicePasswordChangerSuite{})
    26  	_ = gc.Suite(&EnsurePasswordSuite{})
    27  )
    28  
    29  type myAmazingServiceManager struct {
    30  	windows.SvcManager
    31  	svcNames []string
    32  	pwd      string
    33  }
    34  
    35  func (mgr *myAmazingServiceManager) ChangeServicePassword(name, newPassword string) error {
    36  	mgr.svcNames = append(mgr.svcNames, name)
    37  	mgr.pwd = newPassword
    38  	if name == "failme" {
    39  		return errors.New("wubwub")
    40  	}
    41  	return nil
    42  }
    43  
    44  type ServicePasswordChangerSuite struct {
    45  	coretesting.BaseSuite
    46  	c   *passwordChanger
    47  	mgr *myAmazingServiceManager
    48  }
    49  
    50  func (s *ServicePasswordChangerSuite) SetUpTest(c *gc.C) {
    51  	s.BaseSuite.SetUpTest(c)
    52  	s.c = &passwordChanger{}
    53  	s.mgr = &myAmazingServiceManager{}
    54  }
    55  
    56  func listServices() ([]string, error) {
    57  	return []string{"boom", "pow"}, nil
    58  }
    59  
    60  func listServicesFailingService() ([]string, error) {
    61  	return []string{"boom", "failme", "pow"}, nil
    62  }
    63  
    64  func brokenListServices() ([]string, error) {
    65  	return nil, errors.New("ludicrous")
    66  }
    67  
    68  func (s *ServicePasswordChangerSuite) TestChangeServicePasswordListSucceeds(c *gc.C) {
    69  	err := s.c.changeJujudServicesPassword("newPass", s.mgr, listServices)
    70  	c.Assert(err, jc.ErrorIsNil)
    71  	c.Assert(s.mgr.svcNames, gc.DeepEquals, []string{"boom", "pow"})
    72  	c.Assert(s.mgr.pwd, gc.Equals, "newPass")
    73  }
    74  
    75  func (s *ServicePasswordChangerSuite) TestChangeServicePasswordListFails(c *gc.C) {
    76  	err := s.c.changeJujudServicesPassword("newPass", s.mgr, brokenListServices)
    77  	c.Assert(err, gc.ErrorMatches, "ludicrous")
    78  }
    79  
    80  func (s *ServicePasswordChangerSuite) TestChangePasswordFails(c *gc.C) {
    81  	err := s.c.changeJujudServicesPassword("newPass", s.mgr, listServicesFailingService)
    82  	c.Assert(err, gc.ErrorMatches, "wubwub")
    83  	c.Assert(s.mgr.svcNames, gc.DeepEquals, []string{"boom", "failme"})
    84  	c.Assert(s.mgr.pwd, gc.Equals, "newPass")
    85  }
    86  
    87  type helpersStub struct {
    88  	k               registry.Key
    89  	deleteRegEntry  bool
    90  	regEntry        string
    91  	failLocalhost   bool
    92  	failServices    bool
    93  	localhostCalled bool
    94  	serviceCalled   bool
    95  }
    96  
    97  func (s *helpersStub) reset() {
    98  	s.localhostCalled = false
    99  	s.serviceCalled = false
   100  }
   101  
   102  func (s *helpersStub) changeUserPasswordLocalhost(newPassword string) error {
   103  	s.localhostCalled = true
   104  	if s.deleteRegEntry {
   105  		s.k.DeleteValue(s.regEntry)
   106  	}
   107  	if s.failLocalhost {
   108  		return errors.New("zzz")
   109  	}
   110  	return nil
   111  }
   112  
   113  func (s *helpersStub) changeJujudServicesPassword(newPassword string, mgr windows.ServiceManager, listServices func() ([]string, error)) error {
   114  	s.serviceCalled = true
   115  	if s.deleteRegEntry {
   116  		s.k.DeleteValue(s.regEntry)
   117  	}
   118  	if s.failServices {
   119  		return errors.New("splat")
   120  	}
   121  	return nil
   122  }
   123  
   124  type EnsurePasswordSuite struct {
   125  	coretesting.BaseSuite
   126  	tempRegKey   string
   127  	username     string
   128  	newPassword  string
   129  	tempRegEntry string
   130  	k            registry.Key
   131  }
   132  
   133  func (s *EnsurePasswordSuite) SetUpSuite(c *gc.C) {
   134  	s.username = "jujud"
   135  	s.newPassword = "pass"
   136  	s.tempRegKey = `HKLM:\SOFTWARE\juju-1348930201394`
   137  	s.tempRegEntry = `password`
   138  }
   139  
   140  func (s *EnsurePasswordSuite) TestKeyNonexistent(c *gc.C) {
   141  	stub := helpersStub{}
   142  	err := ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   143  	c.Assert(err, gc.ErrorMatches, "failed to open juju registry key: .*")
   144  	c.Assert(errors.Cause(err), gc.ErrorMatches, utils.NoSuchFileErrRegexp)
   145  }
   146  
   147  func (s *EnsurePasswordSuite) setUpKey(c *gc.C) {
   148  	k, exist, err := registry.CreateKey(registry.LOCAL_MACHINE, s.tempRegKey[6:], registry.ALL_ACCESS)
   149  	// If we get in here it means cleanup failed at some point earlier
   150  	if exist {
   151  		err = registry.DeleteKey(registry.LOCAL_MACHINE, s.tempRegKey[6:])
   152  		k, exist, err = registry.CreateKey(registry.LOCAL_MACHINE, s.tempRegKey[6:], registry.ALL_ACCESS)
   153  	}
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	c.Assert(exist, jc.IsFalse)
   156  	s.k = k
   157  }
   158  
   159  func (s *EnsurePasswordSuite) tearDownKey(c *gc.C, shouldBeDeleted bool) {
   160  	err := s.k.DeleteValue(s.tempRegEntry)
   161  	if shouldBeDeleted {
   162  		c.Assert(err, gc.ErrorMatches, utils.NoSuchFileErrRegexp)
   163  	} else {
   164  		c.Assert(err, jc.ErrorIsNil)
   165  	}
   166  	s.k.Close()
   167  	err = registry.DeleteKey(registry.LOCAL_MACHINE, s.tempRegKey[6:])
   168  	c.Assert(err, jc.ErrorIsNil)
   169  }
   170  
   171  func (s *EnsurePasswordSuite) TestKeyExists(c *gc.C) {
   172  	s.setUpKey(c)
   173  	defer s.tearDownKey(c, false)
   174  	stub := helpersStub{}
   175  	err := ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   176  	c.Assert(err, jc.ErrorIsNil)
   177  }
   178  
   179  func (s *EnsurePasswordSuite) TestKeyExistsValueWritten(c *gc.C) {
   180  	s.setUpKey(c)
   181  	defer s.tearDownKey(c, false)
   182  	stub := helpersStub{}
   183  	err := ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(stub.localhostCalled, jc.IsTrue)
   186  	c.Assert(stub.serviceCalled, jc.IsTrue)
   187  
   188  	stub.reset()
   189  
   190  	err = ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   191  	c.Assert(err, gc.Equals, ERR_REGKEY_EXIST)
   192  	c.Assert(stub.localhostCalled, jc.IsFalse)
   193  	c.Assert(stub.serviceCalled, jc.IsFalse)
   194  }
   195  
   196  func (s *EnsurePasswordSuite) TestChangeServicesFails(c *gc.C) {
   197  	s.setUpKey(c)
   198  	defer s.tearDownKey(c, true)
   199  	stub := helpersStub{failServices: true}
   200  	err := ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   201  	c.Assert(err, gc.ErrorMatches, "could not change password for all jujud services: splat")
   202  	c.Assert(errors.Cause(err), gc.ErrorMatches, "splat")
   203  	c.Assert(stub.localhostCalled, jc.IsTrue)
   204  	c.Assert(stub.serviceCalled, jc.IsTrue)
   205  }
   206  
   207  func (s *EnsurePasswordSuite) TestChangeServicesFailsDeleteFails(c *gc.C) {
   208  	s.setUpKey(c)
   209  	defer s.tearDownKey(c, true)
   210  	stub := helpersStub{failServices: true, deleteRegEntry: true, regEntry: s.tempRegEntry, k: s.k}
   211  	err := ensureJujudPasswordHelper(s.username, s.newPassword, s.tempRegKey, s.tempRegEntry, nil, &stub)
   212  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("could not change password for all jujud services; could not erase entry %s at %s: splat", regexp.QuoteMeta(s.tempRegEntry), regexp.QuoteMeta(s.tempRegKey)))
   213  	c.Assert(errors.Cause(err), gc.ErrorMatches, "splat")
   214  	c.Assert(stub.localhostCalled, jc.IsTrue)
   215  	c.Assert(stub.serviceCalled, jc.IsTrue)
   216  }