github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/user_test.go (about) 1 // Copyright 2013, 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 "regexp" 9 "time" 10 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/permission" 18 "github.com/juju/juju/state" 19 "github.com/juju/juju/testing" 20 "github.com/juju/juju/testing/factory" 21 ) 22 23 type UserSuite struct { 24 ConnSuite 25 } 26 27 var _ = gc.Suite(&UserSuite{}) 28 29 func (s *UserSuite) TestAddInvalidNames(c *gc.C) { 30 for _, name := range []string{ 31 "", 32 "a", 33 "b^b", 34 "a.", 35 "a-", 36 "user@local", 37 "@ubuntuone", 38 } { 39 c.Logf("check invalid name %q", name) 40 user, err := s.State.AddUser(name, "ignored", "ignored", "ignored") 41 c.Check(err, gc.ErrorMatches, `invalid user name "`+regexp.QuoteMeta(name)+`"`) 42 c.Check(user, gc.IsNil) 43 } 44 } 45 46 func (s *UserSuite) TestAddUser(c *gc.C) { 47 name := "f00-Bar.ram77" 48 displayName := "Display" 49 password := "password" 50 creator := "admin" 51 52 now := testing.NonZeroTime().Round(time.Second).UTC() 53 54 user, err := s.State.AddUser(name, displayName, password, creator) 55 c.Assert(err, jc.ErrorIsNil) 56 c.Assert(user, gc.NotNil) 57 c.Assert(user.Name(), gc.Equals, name) 58 c.Assert(user.DisplayName(), gc.Equals, displayName) 59 c.Assert(user.PasswordValid(password), jc.IsTrue) 60 c.Assert(user.CreatedBy(), gc.Equals, creator) 61 c.Assert(user.DateCreated().After(now) || 62 user.DateCreated().Equal(now), jc.IsTrue) 63 lastLogin, err := user.LastLogin() 64 c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError) 65 c.Assert(lastLogin, gc.DeepEquals, time.Time{}) 66 67 user, err = s.State.User(user.UserTag()) 68 c.Assert(err, jc.ErrorIsNil) 69 c.Assert(user, gc.NotNil) 70 c.Assert(user.Name(), gc.Equals, name) 71 c.Assert(user.DisplayName(), gc.Equals, displayName) 72 c.Assert(user.PasswordValid(password), jc.IsTrue) 73 c.Assert(user.CreatedBy(), gc.Equals, creator) 74 c.Assert(user.DateCreated().After(now) || 75 user.DateCreated().Equal(now), jc.IsTrue) 76 lastLogin, err = user.LastLogin() 77 c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError) 78 c.Assert(lastLogin, gc.DeepEquals, time.Time{}) 79 } 80 81 func (s *UserSuite) TestCheckUserExists(c *gc.C) { 82 user := s.Factory.MakeUser(c, nil) 83 exists, err := state.CheckUserExists(s.State, user.Name()) 84 c.Assert(err, jc.ErrorIsNil) 85 c.Assert(exists, jc.IsTrue) 86 exists, err = state.CheckUserExists(s.State, "notAUser") 87 c.Assert(err, jc.ErrorIsNil) 88 c.Assert(exists, jc.IsFalse) 89 } 90 91 func (s *UserSuite) TestString(c *gc.C) { 92 user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foo"}) 93 c.Assert(user.String(), gc.Equals, "foo@local") 94 } 95 96 func (s *UserSuite) TestUpdateLastLogin(c *gc.C) { 97 now := testing.NonZeroTime().Round(time.Second).UTC() 98 user := s.Factory.MakeUser(c, nil) 99 err := user.UpdateLastLogin() 100 c.Assert(err, jc.ErrorIsNil) 101 lastLogin, err := user.LastLogin() 102 c.Assert(err, jc.ErrorIsNil) 103 c.Assert(lastLogin.After(now) || 104 lastLogin.Equal(now), jc.IsTrue) 105 } 106 107 func (s *UserSuite) TestSetPassword(c *gc.C) { 108 user := s.Factory.MakeUser(c, nil) 109 testSetPassword(c, func() (state.Authenticator, error) { 110 return s.State.User(user.UserTag()) 111 }) 112 } 113 114 func (s *UserSuite) TestAddUserSetsSalt(c *gc.C) { 115 user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"}) 116 salt, hash := state.GetUserPasswordSaltAndHash(user) 117 c.Assert(hash, gc.Not(gc.Equals), "") 118 c.Assert(salt, gc.Not(gc.Equals), "") 119 c.Assert(utils.UserPasswordHash("a-password", salt), gc.Equals, hash) 120 c.Assert(user.PasswordValid("a-password"), jc.IsTrue) 121 } 122 123 func (s *UserSuite) TestSetPasswordChangesSalt(c *gc.C) { 124 user := s.Factory.MakeUser(c, nil) 125 origSalt, origHash := state.GetUserPasswordSaltAndHash(user) 126 c.Assert(origSalt, gc.Not(gc.Equals), "") 127 user.SetPassword("a-password") 128 newSalt, newHash := state.GetUserPasswordSaltAndHash(user) 129 c.Assert(newSalt, gc.Not(gc.Equals), "") 130 c.Assert(newSalt, gc.Not(gc.Equals), origSalt) 131 c.Assert(newHash, gc.Not(gc.Equals), origHash) 132 c.Assert(user.PasswordValid("a-password"), jc.IsTrue) 133 } 134 135 func (s *UserSuite) TestRemoveUserNonExistent(c *gc.C) { 136 err := s.State.RemoveUser(names.NewUserTag("harvey")) 137 c.Assert(errors.IsNotFound(err), jc.IsTrue) 138 } 139 140 func isDeletedUserError(err error) bool { 141 _, ok := errors.Cause(err).(state.DeletedUserError) 142 return ok 143 } 144 145 func (s *UserSuite) TestAllUsersSkipsDeletedUsers(c *gc.C) { 146 user := s.Factory.MakeUser(c, &factory.UserParams{Name: "one"}) 147 _ = s.Factory.MakeUser(c, &factory.UserParams{Name: "two"}) 148 _ = s.Factory.MakeUser(c, &factory.UserParams{Name: "three"}) 149 150 all, err := s.State.AllUsers(true) 151 c.Check(err, jc.ErrorIsNil) 152 c.Check(len(all), jc.DeepEquals, 4) 153 154 var got []string 155 for _, u := range all { 156 got = append(got, u.Name()) 157 } 158 c.Check(got, jc.SameContents, []string{"test-admin", "one", "two", "three"}) 159 160 s.State.RemoveUser(user.UserTag()) 161 162 all, err = s.State.AllUsers(true) 163 got = nil 164 for _, u := range all { 165 got = append(got, u.Name()) 166 } 167 c.Check(err, jc.ErrorIsNil) 168 c.Check(len(all), jc.DeepEquals, 3) 169 c.Check(got, jc.SameContents, []string{"test-admin", "two", "three"}) 170 171 } 172 173 func (s *UserSuite) TestRemoveUser(c *gc.C) { 174 user := s.Factory.MakeUser(c, &factory.UserParams{Password: "so sekrit"}) 175 176 // Assert user exists and can authenticate. 177 c.Assert(user.PasswordValid("so sekrit"), jc.IsTrue) 178 179 // Look for the user. 180 u, err := s.State.User(user.UserTag()) 181 c.Check(err, jc.ErrorIsNil) 182 c.Assert(u, jc.DeepEquals, user) 183 184 // Remove the user. 185 err = s.State.RemoveUser(user.UserTag()) 186 c.Check(err, jc.ErrorIsNil) 187 188 // Check that we cannot update last login. 189 err = u.UpdateLastLogin() 190 c.Check(err, gc.NotNil) 191 c.Check(isDeletedUserError(err), jc.IsTrue) 192 c.Assert(err.Error(), jc.DeepEquals, 193 fmt.Sprintf("cannot update last login: user %q deleted", user.Name())) 194 195 // Check that we cannot set a password. 196 err = u.SetPassword("should fail too") 197 c.Check(err, gc.NotNil) 198 c.Check(isDeletedUserError(err), jc.IsTrue) 199 c.Assert(err.Error(), jc.DeepEquals, 200 fmt.Sprintf("cannot set password: user %q deleted", user.Name())) 201 202 // Check that we cannot set the password hash. 203 err = u.SetPasswordHash("also", "fail") 204 c.Check(err, gc.NotNil) 205 c.Check(isDeletedUserError(err), jc.IsTrue) 206 c.Assert(err.Error(), jc.DeepEquals, 207 fmt.Sprintf("cannot set password hash: user %q deleted", user.Name())) 208 209 // Check that we cannot validate a password. 210 c.Assert(u.PasswordValid("should fail"), jc.IsFalse) 211 212 // Check that we cannot enable the user. 213 err = u.Enable() 214 c.Check(err, gc.NotNil) 215 c.Check(isDeletedUserError(err), jc.IsTrue) 216 c.Assert(err.Error(), jc.DeepEquals, 217 fmt.Sprintf("cannot enable: user %q deleted", user.Name())) 218 219 // Check that we cannot disable the user. 220 err = u.Disable() 221 c.Check(err, gc.NotNil) 222 c.Check(isDeletedUserError(err), jc.IsTrue) 223 c.Assert(err.Error(), jc.DeepEquals, 224 fmt.Sprintf("cannot disable: user %q deleted", user.Name())) 225 226 // Check again to verify the user cannot be retrieved. 227 u, err = s.State.User(user.UserTag()) 228 c.Check(err, jc.Satisfies, errors.IsUserNotFound) 229 } 230 231 func (s *UserSuite) TestRemoveUserRemovesUserAccess(c *gc.C) { 232 user := s.Factory.MakeUser(c, &factory.UserParams{Password: "so sekrit"}) 233 234 // Assert user exists and can authenticate. 235 c.Assert(user.PasswordValid("so sekrit"), jc.IsTrue) 236 237 s.State.SetUserAccess(user.UserTag(), s.State.ModelTag(), permission.AdminAccess) 238 s.State.SetUserAccess(user.UserTag(), s.State.ControllerTag(), permission.SuperuserAccess) 239 240 uam, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag()) 241 c.Assert(err, jc.ErrorIsNil) 242 c.Assert(uam.Access, gc.Equals, permission.AdminAccess) 243 244 uac, err := s.State.UserAccess(user.UserTag(), s.State.ControllerTag()) 245 c.Assert(err, jc.ErrorIsNil) 246 c.Assert(uac.Access, gc.Equals, permission.SuperuserAccess) 247 248 // Look for the user. 249 u, err := s.State.User(user.UserTag()) 250 c.Check(err, jc.ErrorIsNil) 251 c.Assert(u, jc.DeepEquals, user) 252 253 // Remove the user. 254 err = s.State.RemoveUser(user.UserTag()) 255 c.Check(err, jc.ErrorIsNil) 256 257 uam, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag()) 258 c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name())) 259 260 uac, err = s.State.UserAccess(user.UserTag(), s.State.ControllerTag()) 261 c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name())) 262 } 263 264 func (s *UserSuite) TestDisable(c *gc.C) { 265 user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"}) 266 c.Assert(user.IsDisabled(), jc.IsFalse) 267 c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin", user.Name()}) 268 269 err := user.Disable() 270 c.Assert(err, jc.ErrorIsNil) 271 c.Assert(user.IsDisabled(), jc.IsTrue) 272 c.Assert(user.PasswordValid("a-password"), jc.IsFalse) 273 c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin"}) 274 275 err = user.Enable() 276 c.Assert(err, jc.ErrorIsNil) 277 c.Assert(user.IsDisabled(), jc.IsFalse) 278 c.Assert(user.PasswordValid("a-password"), jc.IsTrue) 279 c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin", user.Name()}) 280 } 281 282 func (s *UserSuite) activeUsers(c *gc.C) []string { 283 users, err := s.State.AllUsers(false) 284 c.Assert(err, jc.ErrorIsNil) 285 names := make([]string, len(users)) 286 for i, u := range users { 287 names[i] = u.Name() 288 } 289 return names 290 } 291 292 func (s *UserSuite) TestSetPasswordHash(c *gc.C) { 293 user := s.Factory.MakeUser(c, nil) 294 295 salt, err := utils.RandomSalt() 296 c.Assert(err, jc.ErrorIsNil) 297 err = user.SetPasswordHash(utils.UserPasswordHash("foo", salt), salt) 298 c.Assert(err, jc.ErrorIsNil) 299 300 c.Assert(user.PasswordValid("foo"), jc.IsTrue) 301 c.Assert(user.PasswordValid("bar"), jc.IsFalse) 302 303 // User passwords should *not* use the fast PasswordHash function 304 hash := utils.AgentPasswordHash("foo-12345678901234567890") 305 c.Assert(err, jc.ErrorIsNil) 306 err = user.SetPasswordHash(hash, "") 307 c.Assert(err, jc.ErrorIsNil) 308 309 c.Assert(user.PasswordValid("foo-12345678901234567890"), jc.IsFalse) 310 } 311 312 func (s *UserSuite) TestSetPasswordHashWithSalt(c *gc.C) { 313 user := s.Factory.MakeUser(c, nil) 314 315 err := user.SetPasswordHash(utils.UserPasswordHash("foo", "salted"), "salted") 316 c.Assert(err, jc.ErrorIsNil) 317 318 c.Assert(user.PasswordValid("foo"), jc.IsTrue) 319 salt, _ := state.GetUserPasswordSaltAndHash(user) 320 c.Assert(salt, gc.Equals, "salted") 321 } 322 323 func (s *UserSuite) TestCantDisableAdmin(c *gc.C) { 324 user, err := s.State.User(s.Owner) 325 c.Assert(err, jc.ErrorIsNil) 326 err = user.Disable() 327 c.Assert(err, gc.ErrorMatches, "cannot disable controller model owner") 328 } 329 330 func (s *UserSuite) TestCaseSensitiveUsersErrors(c *gc.C) { 331 s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"}) 332 333 _, err := s.State.AddUser( 334 "boB", "ignored", "ignored", "ignored") 335 c.Assert(errors.IsAlreadyExists(err), jc.IsTrue) 336 c.Assert(err, gc.ErrorMatches, "user already exists") 337 } 338 339 func (s *UserSuite) TestCaseInsensitiveLookup(c *gc.C) { 340 expectedUser := s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"}) 341 342 assertCaseInsensitiveLookup := func(name string) { 343 userTag := names.NewUserTag(name) 344 obtainedUser, err := s.State.User(userTag) 345 c.Assert(err, jc.ErrorIsNil) 346 c.Assert(obtainedUser, gc.DeepEquals, expectedUser) 347 } 348 349 assertCaseInsensitiveLookup("bob") 350 assertCaseInsensitiveLookup("bOb") 351 assertCaseInsensitiveLookup("boB") 352 assertCaseInsensitiveLookup("BOB") 353 } 354 355 func (s *UserSuite) TestAllUsers(c *gc.C) { 356 // Create in non-alphabetical order. 357 s.Factory.MakeUser(c, &factory.UserParams{Name: "conrad"}) 358 s.Factory.MakeUser(c, &factory.UserParams{Name: "adam"}) 359 s.Factory.MakeUser(c, &factory.UserParams{Name: "debbie", Disabled: true}) 360 s.Factory.MakeUser(c, &factory.UserParams{Name: "barbara"}) 361 s.Factory.MakeUser(c, &factory.UserParams{Name: "fred", Disabled: true}) 362 s.Factory.MakeUser(c, &factory.UserParams{Name: "erica"}) 363 // There is the existing controller owner called "test-admin" 364 365 includeDeactivated := false 366 users, err := s.State.AllUsers(includeDeactivated) 367 c.Assert(err, jc.ErrorIsNil) 368 c.Assert(users, gc.HasLen, 5) 369 c.Check(users[0].Name(), gc.Equals, "adam") 370 c.Check(users[1].Name(), gc.Equals, "barbara") 371 c.Check(users[2].Name(), gc.Equals, "conrad") 372 c.Check(users[3].Name(), gc.Equals, "erica") 373 c.Check(users[4].Name(), gc.Equals, "test-admin") 374 375 includeDeactivated = true 376 users, err = s.State.AllUsers(includeDeactivated) 377 c.Assert(err, jc.ErrorIsNil) 378 c.Assert(users, gc.HasLen, 7) 379 c.Check(users[0].Name(), gc.Equals, "adam") 380 c.Check(users[1].Name(), gc.Equals, "barbara") 381 c.Check(users[2].Name(), gc.Equals, "conrad") 382 c.Check(users[3].Name(), gc.Equals, "debbie") 383 c.Check(users[4].Name(), gc.Equals, "erica") 384 c.Check(users[5].Name(), gc.Equals, "fred") 385 c.Check(users[6].Name(), gc.Equals, "test-admin") 386 } 387 388 func (s *UserSuite) TestAddUserNoSecretKey(c *gc.C) { 389 u, err := s.State.AddUser("bob", "display", "pass", "admin") 390 c.Assert(err, jc.ErrorIsNil) 391 c.Assert(u.SecretKey(), gc.IsNil) 392 } 393 394 func (s *UserSuite) TestAddUserSecretKey(c *gc.C) { 395 u, err := s.State.AddUserWithSecretKey("bob", "display", "admin") 396 c.Assert(err, jc.ErrorIsNil) 397 c.Assert(u.SecretKey(), gc.HasLen, 32) 398 c.Assert(u.PasswordValid(""), jc.IsFalse) 399 } 400 401 func (s *UserSuite) TestSetPasswordClearsSecretKey(c *gc.C) { 402 u, err := s.State.AddUserWithSecretKey("bob", "display", "admin") 403 c.Assert(err, jc.ErrorIsNil) 404 c.Assert(u.SecretKey(), gc.HasLen, 32) 405 err = u.SetPassword("anything") 406 c.Assert(err, jc.ErrorIsNil) 407 c.Assert(u.SecretKey(), gc.IsNil) 408 err = u.Refresh() 409 c.Assert(err, jc.ErrorIsNil) 410 c.Assert(u.SecretKey(), gc.IsNil) 411 }