github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/usermanager/usermanager_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package usermanager_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/macaroon.v1" 14 15 "github.com/juju/juju/apiserver/common" 16 commontesting "github.com/juju/juju/apiserver/common/testing" 17 "github.com/juju/juju/apiserver/params" 18 apiservertesting "github.com/juju/juju/apiserver/testing" 19 "github.com/juju/juju/apiserver/usermanager" 20 jujutesting "github.com/juju/juju/juju/testing" 21 "github.com/juju/juju/state" 22 "github.com/juju/juju/testing/factory" 23 ) 24 25 type userManagerSuite struct { 26 jujutesting.JujuConnSuite 27 28 usermanager *usermanager.UserManagerAPI 29 authorizer apiservertesting.FakeAuthorizer 30 adminName string 31 resources *common.Resources 32 createLocalLoginMacaroon func(names.UserTag) (*macaroon.Macaroon, error) 33 34 commontesting.BlockHelper 35 } 36 37 var _ = gc.Suite(&userManagerSuite{}) 38 39 func (s *userManagerSuite) SetUpTest(c *gc.C) { 40 s.JujuConnSuite.SetUpTest(c) 41 42 s.createLocalLoginMacaroon = func(tag names.UserTag) (*macaroon.Macaroon, error) { 43 return nil, errors.NotSupportedf("CreateLocalLoginMacaroon") 44 } 45 s.resources = common.NewResources() 46 s.resources.RegisterNamed("createLocalLoginMacaroon", common.ValueResource{ 47 func(tag names.UserTag) (*macaroon.Macaroon, error) { 48 return s.createLocalLoginMacaroon(tag) 49 }, 50 }) 51 52 adminTag := s.AdminUserTag(c) 53 s.adminName = adminTag.Name() 54 s.authorizer = apiservertesting.FakeAuthorizer{ 55 Tag: adminTag, 56 } 57 var err error 58 s.usermanager, err = usermanager.NewUserManagerAPI(s.State, s.resources, s.authorizer) 59 c.Assert(err, jc.ErrorIsNil) 60 61 s.BlockHelper = commontesting.NewBlockHelper(s.APIState) 62 s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() }) 63 } 64 65 func (s *userManagerSuite) TestNewUserManagerAPIRefusesNonClient(c *gc.C) { 66 anAuthoriser := s.authorizer 67 anAuthoriser.Tag = names.NewMachineTag("1") 68 endPoint, err := usermanager.NewUserManagerAPI(s.State, s.resources, anAuthoriser) 69 c.Assert(endPoint, gc.IsNil) 70 c.Assert(err, gc.ErrorMatches, "permission denied") 71 } 72 73 func (s *userManagerSuite) assertAddUser(c *gc.C, access params.ModelAccessPermission, sharedModelTags []string) { 74 sharedModelState := s.Factory.MakeModel(c, nil) 75 defer sharedModelState.Close() 76 77 args := params.AddUsers{ 78 Users: []params.AddUser{{ 79 Username: "foobar", 80 DisplayName: "Foo Bar", 81 Password: "password", 82 SharedModelTags: sharedModelTags, 83 ModelAccess: access, 84 }}} 85 86 result, err := s.usermanager.AddUser(args) 87 // Check that the call is successful 88 c.Assert(err, jc.ErrorIsNil) 89 c.Assert(result.Results, gc.HasLen, 1) 90 foobarTag := names.NewLocalUserTag("foobar") 91 c.Assert(result.Results[0], gc.DeepEquals, params.AddUserResult{ 92 Tag: foobarTag.String()}) 93 // Check that the call results in a new user being created 94 user, err := s.State.User(foobarTag) 95 c.Assert(err, jc.ErrorIsNil) 96 c.Assert(user, gc.NotNil) 97 c.Assert(user.Name(), gc.Equals, "foobar") 98 c.Assert(user.DisplayName(), gc.Equals, "Foo Bar") 99 } 100 101 func (s *userManagerSuite) TestAddUser(c *gc.C) { 102 s.assertAddUser(c, params.ModelAccessPermission(""), nil) 103 } 104 105 func (s *userManagerSuite) TestAddUserWithSecretKey(c *gc.C) { 106 args := params.AddUsers{ 107 Users: []params.AddUser{{ 108 Username: "foobar", 109 DisplayName: "Foo Bar", 110 Password: "", // assign secret key 111 }}} 112 113 result, err := s.usermanager.AddUser(args) 114 // Check that the call is succesful 115 c.Assert(err, jc.ErrorIsNil) 116 c.Assert(result.Results, gc.HasLen, 1) 117 foobarTag := names.NewLocalUserTag("foobar") 118 119 // Check that the call results in a new user being created 120 user, err := s.State.User(foobarTag) 121 c.Assert(err, jc.ErrorIsNil) 122 c.Assert(user, gc.NotNil) 123 c.Assert(user.Name(), gc.Equals, "foobar") 124 c.Assert(user.DisplayName(), gc.Equals, "Foo Bar") 125 c.Assert(user.SecretKey(), gc.NotNil) 126 c.Assert(user.PasswordValid(""), jc.IsFalse) 127 128 // Check that the secret key returned by the API matches what 129 // is in state. 130 c.Assert(result.Results[0], gc.DeepEquals, params.AddUserResult{ 131 Tag: foobarTag.String(), 132 SecretKey: user.SecretKey(), 133 }) 134 } 135 136 func (s *userManagerSuite) TestAddReadAccessUser(c *gc.C) { 137 s.addUserWithSharedModel(c, params.ModelReadAccess) 138 } 139 140 func (s *userManagerSuite) TestAddWriteAccessUser(c *gc.C) { 141 s.addUserWithSharedModel(c, params.ModelWriteAccess) 142 } 143 144 func (s *userManagerSuite) addUserWithSharedModel(c *gc.C, access params.ModelAccessPermission) { 145 sharedModelState := s.Factory.MakeModel(c, nil) 146 defer sharedModelState.Close() 147 148 s.assertAddUser(c, access, []string{sharedModelState.ModelTag().String()}) 149 150 // Check that the model has been shared. 151 sharedModel, err := sharedModelState.Model() 152 c.Assert(err, jc.ErrorIsNil) 153 users, err := sharedModel.Users() 154 c.Assert(err, jc.ErrorIsNil) 155 var modelUserTags = make([]names.UserTag, len(users)) 156 for i, u := range users { 157 modelUserTags[i] = u.UserTag() 158 if u.UserName() == "foobar" { 159 c.Assert(u.ReadOnly(), gc.Equals, access == params.ModelReadAccess) 160 } else if u.UserName() == "admin" { 161 c.Assert(u.ReadOnly(), gc.Equals, false) 162 } 163 } 164 c.Assert(modelUserTags, jc.SameContents, []names.UserTag{ 165 names.NewLocalUserTag("foobar"), 166 names.NewLocalUserTag("admin"), 167 }) 168 } 169 170 func (s *userManagerSuite) TestBlockAddUser(c *gc.C) { 171 args := params.AddUsers{ 172 Users: []params.AddUser{{ 173 Username: "foobar", 174 DisplayName: "Foo Bar", 175 Password: "password", 176 }}} 177 178 s.BlockAllChanges(c, "TestBlockAddUser") 179 result, err := s.usermanager.AddUser(args) 180 // Check that the call is blocked 181 s.AssertBlocked(c, err, "TestBlockAddUser") 182 c.Assert(result.Results, gc.HasLen, 1) 183 //check that user is not created 184 foobarTag := names.NewLocalUserTag("foobar") 185 c.Assert(result.Results[0], gc.DeepEquals, params.AddUserResult{}) 186 // Check that the call results in a new user being created 187 _, err = s.State.User(foobarTag) 188 c.Assert(err, gc.ErrorMatches, `user "foobar" not found`) 189 } 190 191 func (s *userManagerSuite) TestAddUserAsNormalUser(c *gc.C) { 192 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 193 usermanager, err := usermanager.NewUserManagerAPI( 194 s.State, s.resources, apiservertesting.FakeAuthorizer{Tag: alex.Tag()}) 195 c.Assert(err, jc.ErrorIsNil) 196 197 args := params.AddUsers{ 198 Users: []params.AddUser{{ 199 Username: "foobar", 200 DisplayName: "Foo Bar", 201 Password: "password", 202 }}} 203 204 _, err = usermanager.AddUser(args) 205 c.Assert(err, gc.ErrorMatches, "permission denied") 206 207 _, err = s.State.User(names.NewLocalUserTag("foobar")) 208 c.Assert(err, jc.Satisfies, errors.IsNotFound) 209 } 210 211 func (s *userManagerSuite) TestDisableUser(c *gc.C) { 212 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex"}) 213 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", Disabled: true}) 214 215 args := params.Entities{ 216 Entities: []params.Entity{ 217 {alex.Tag().String()}, 218 {barb.Tag().String()}, 219 {names.NewLocalUserTag("ellie").String()}, 220 {names.NewUserTag("fred@remote").String()}, 221 {"not-a-tag"}, 222 }} 223 result, err := s.usermanager.DisableUser(args) 224 c.Assert(err, jc.ErrorIsNil) 225 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 226 Results: []params.ErrorResult{ 227 {Error: nil}, 228 {Error: nil}, 229 {Error: ¶ms.Error{ 230 Message: "permission denied", 231 Code: params.CodeUnauthorized, 232 }}, 233 {Error: ¶ms.Error{ 234 Message: "permission denied", 235 Code: params.CodeUnauthorized, 236 }}, 237 {Error: ¶ms.Error{ 238 Message: `"not-a-tag" is not a valid tag`, 239 }}, 240 }}) 241 err = alex.Refresh() 242 c.Assert(err, jc.ErrorIsNil) 243 c.Assert(alex.IsDisabled(), jc.IsTrue) 244 245 err = barb.Refresh() 246 c.Assert(err, jc.ErrorIsNil) 247 c.Assert(barb.IsDisabled(), jc.IsTrue) 248 } 249 250 func (s *userManagerSuite) TestBlockDisableUser(c *gc.C) { 251 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex"}) 252 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", Disabled: true}) 253 254 args := params.Entities{ 255 Entities: []params.Entity{ 256 {alex.Tag().String()}, 257 {barb.Tag().String()}, 258 {names.NewLocalUserTag("ellie").String()}, 259 {names.NewUserTag("fred@remote").String()}, 260 {"not-a-tag"}, 261 }} 262 263 s.BlockAllChanges(c, "TestBlockDisableUser") 264 _, err := s.usermanager.DisableUser(args) 265 // Check that the call is blocked 266 s.AssertBlocked(c, err, "TestBlockDisableUser") 267 268 err = alex.Refresh() 269 c.Assert(err, jc.ErrorIsNil) 270 c.Assert(alex.IsDisabled(), jc.IsFalse) 271 272 err = barb.Refresh() 273 c.Assert(err, jc.ErrorIsNil) 274 c.Assert(barb.IsDisabled(), jc.IsTrue) 275 } 276 277 func (s *userManagerSuite) TestEnableUser(c *gc.C) { 278 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex"}) 279 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", Disabled: true}) 280 281 args := params.Entities{ 282 Entities: []params.Entity{ 283 {alex.Tag().String()}, 284 {barb.Tag().String()}, 285 {names.NewLocalUserTag("ellie").String()}, 286 {names.NewUserTag("fred@remote").String()}, 287 {"not-a-tag"}, 288 }} 289 result, err := s.usermanager.EnableUser(args) 290 c.Assert(err, jc.ErrorIsNil) 291 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 292 Results: []params.ErrorResult{ 293 {Error: nil}, 294 {Error: nil}, 295 {Error: ¶ms.Error{ 296 Message: "permission denied", 297 Code: params.CodeUnauthorized, 298 }}, 299 {Error: ¶ms.Error{ 300 Message: "permission denied", 301 Code: params.CodeUnauthorized, 302 }}, 303 {Error: ¶ms.Error{ 304 Message: `"not-a-tag" is not a valid tag`, 305 }}, 306 }}) 307 err = alex.Refresh() 308 c.Assert(err, jc.ErrorIsNil) 309 c.Assert(alex.IsDisabled(), jc.IsFalse) 310 311 err = barb.Refresh() 312 c.Assert(err, jc.ErrorIsNil) 313 c.Assert(barb.IsDisabled(), jc.IsFalse) 314 } 315 316 func (s *userManagerSuite) TestBlockEnableUser(c *gc.C) { 317 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex"}) 318 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", Disabled: true}) 319 320 args := params.Entities{ 321 Entities: []params.Entity{ 322 {alex.Tag().String()}, 323 {barb.Tag().String()}, 324 {names.NewLocalUserTag("ellie").String()}, 325 {names.NewUserTag("fred@remote").String()}, 326 {"not-a-tag"}, 327 }} 328 329 s.BlockAllChanges(c, "TestBlockEnableUser") 330 _, err := s.usermanager.EnableUser(args) 331 // Check that the call is blocked 332 s.AssertBlocked(c, err, "TestBlockEnableUser") 333 334 err = alex.Refresh() 335 c.Assert(err, jc.ErrorIsNil) 336 c.Assert(alex.IsDisabled(), jc.IsFalse) 337 338 err = barb.Refresh() 339 c.Assert(err, jc.ErrorIsNil) 340 c.Assert(barb.IsDisabled(), jc.IsTrue) 341 } 342 343 func (s *userManagerSuite) TestDisableUserAsNormalUser(c *gc.C) { 344 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 345 usermanager, err := usermanager.NewUserManagerAPI( 346 s.State, s.resources, apiservertesting.FakeAuthorizer{Tag: alex.Tag()}) 347 c.Assert(err, jc.ErrorIsNil) 348 349 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb"}) 350 351 args := params.Entities{ 352 []params.Entity{{barb.Tag().String()}}, 353 } 354 _, err = usermanager.DisableUser(args) 355 c.Assert(err, gc.ErrorMatches, "permission denied") 356 357 err = barb.Refresh() 358 c.Assert(err, jc.ErrorIsNil) 359 c.Assert(barb.IsDisabled(), jc.IsFalse) 360 } 361 362 func (s *userManagerSuite) TestEnableUserAsNormalUser(c *gc.C) { 363 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 364 usermanager, err := usermanager.NewUserManagerAPI( 365 s.State, s.resources, apiservertesting.FakeAuthorizer{Tag: alex.Tag()}) 366 c.Assert(err, jc.ErrorIsNil) 367 368 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", Disabled: true}) 369 370 args := params.Entities{ 371 []params.Entity{{barb.Tag().String()}}, 372 } 373 _, err = usermanager.EnableUser(args) 374 c.Assert(err, gc.ErrorMatches, "permission denied") 375 376 err = barb.Refresh() 377 c.Assert(err, jc.ErrorIsNil) 378 c.Assert(barb.IsDisabled(), jc.IsTrue) 379 } 380 381 func (s *userManagerSuite) TestUserInfo(c *gc.C) { 382 userFoo := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar", DisplayName: "Foo Bar"}) 383 userBar := s.Factory.MakeUser(c, &factory.UserParams{Name: "barfoo", DisplayName: "Bar Foo", Disabled: true}) 384 385 args := params.UserInfoRequest{ 386 Entities: []params.Entity{ 387 { 388 Tag: userFoo.Tag().String(), 389 }, { 390 Tag: userBar.Tag().String(), 391 }, { 392 Tag: names.NewLocalUserTag("ellie").String(), 393 }, { 394 Tag: names.NewUserTag("not@remote").String(), 395 }, { 396 Tag: "not-a-tag", 397 }, 398 }} 399 400 results, err := s.usermanager.UserInfo(args) 401 c.Assert(err, jc.ErrorIsNil) 402 var expected params.UserInfoResults 403 for _, r := range []struct { 404 user *state.User 405 info *params.UserInfo 406 err *params.Error 407 }{ 408 { 409 user: userFoo, 410 info: ¶ms.UserInfo{ 411 Username: "foobar", 412 DisplayName: "Foo Bar", 413 }, 414 }, { 415 user: userBar, 416 info: ¶ms.UserInfo{ 417 Username: "barfoo", 418 DisplayName: "Bar Foo", 419 Disabled: true, 420 }, 421 }, { 422 err: ¶ms.Error{ 423 Message: "permission denied", 424 Code: params.CodeUnauthorized, 425 }, 426 }, { 427 err: ¶ms.Error{ 428 Message: "permission denied", 429 Code: params.CodeUnauthorized, 430 }, 431 }, { 432 err: ¶ms.Error{ 433 Message: `"not-a-tag" is not a valid tag`, 434 }, 435 }, 436 } { 437 if r.info != nil { 438 r.info.DateCreated = r.user.DateCreated() 439 r.info.LastConnection = lastLoginPointer(c, r.user) 440 r.info.CreatedBy = s.adminName 441 } 442 expected.Results = append(expected.Results, params.UserInfoResult{Result: r.info, Error: r.err}) 443 } 444 445 c.Assert(results, jc.DeepEquals, expected) 446 } 447 448 func (s *userManagerSuite) TestUserInfoAll(c *gc.C) { 449 admin, err := s.State.User(s.AdminUserTag(c)) 450 c.Assert(err, jc.ErrorIsNil) 451 userFoo := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar", DisplayName: "Foo Bar"}) 452 userAardvark := s.Factory.MakeUser(c, &factory.UserParams{Name: "aardvark", DisplayName: "Aard Vark", Disabled: true}) 453 454 args := params.UserInfoRequest{IncludeDisabled: true} 455 results, err := s.usermanager.UserInfo(args) 456 c.Assert(err, jc.ErrorIsNil) 457 var expected params.UserInfoResults 458 for _, r := range []struct { 459 user *state.User 460 info *params.UserInfo 461 }{{ 462 user: userAardvark, 463 info: ¶ms.UserInfo{ 464 Username: "aardvark", 465 DisplayName: "Aard Vark", 466 Disabled: true, 467 }, 468 }, { 469 user: admin, 470 info: ¶ms.UserInfo{ 471 Username: s.adminName, 472 DisplayName: admin.DisplayName(), 473 }, 474 }, { 475 user: userFoo, 476 info: ¶ms.UserInfo{ 477 Username: "foobar", 478 DisplayName: "Foo Bar", 479 }, 480 }} { 481 r.info.CreatedBy = s.adminName 482 r.info.DateCreated = r.user.DateCreated() 483 r.info.LastConnection = lastLoginPointer(c, r.user) 484 expected.Results = append(expected.Results, params.UserInfoResult{Result: r.info}) 485 } 486 c.Assert(results, jc.DeepEquals, expected) 487 488 results, err = s.usermanager.UserInfo(params.UserInfoRequest{}) 489 c.Assert(err, jc.ErrorIsNil) 490 // Same results as before, but without the deactivated user 491 expected.Results = expected.Results[1:] 492 c.Assert(results, jc.DeepEquals, expected) 493 } 494 495 func lastLoginPointer(c *gc.C, user *state.User) *time.Time { 496 lastLogin, err := user.LastLogin() 497 if err != nil { 498 if state.IsNeverLoggedInError(err) { 499 return nil 500 } 501 c.Fatal(err) 502 } 503 return &lastLogin 504 } 505 506 func (s *userManagerSuite) TestSetPassword(c *gc.C) { 507 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 508 509 args := params.EntityPasswords{ 510 Changes: []params.EntityPassword{{ 511 Tag: alex.Tag().String(), 512 Password: "new-password", 513 }}} 514 results, err := s.usermanager.SetPassword(args) 515 c.Assert(err, jc.ErrorIsNil) 516 c.Assert(results.Results, gc.HasLen, 1) 517 c.Assert(results.Results[0], gc.DeepEquals, params.ErrorResult{Error: nil}) 518 519 err = alex.Refresh() 520 c.Assert(err, jc.ErrorIsNil) 521 522 c.Assert(alex.PasswordValid("new-password"), jc.IsTrue) 523 } 524 525 func (s *userManagerSuite) TestBlockSetPassword(c *gc.C) { 526 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 527 528 args := params.EntityPasswords{ 529 Changes: []params.EntityPassword{{ 530 Tag: alex.Tag().String(), 531 Password: "new-password", 532 }}} 533 534 s.BlockAllChanges(c, "TestBlockSetPassword") 535 _, err := s.usermanager.SetPassword(args) 536 // Check that the call is blocked 537 s.AssertBlocked(c, err, "TestBlockSetPassword") 538 539 err = alex.Refresh() 540 c.Assert(err, jc.ErrorIsNil) 541 542 c.Assert(alex.PasswordValid("new-password"), jc.IsFalse) 543 } 544 545 func (s *userManagerSuite) TestSetPasswordForSelf(c *gc.C) { 546 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 547 usermanager, err := usermanager.NewUserManagerAPI( 548 s.State, s.resources, apiservertesting.FakeAuthorizer{Tag: alex.Tag()}) 549 c.Assert(err, jc.ErrorIsNil) 550 551 args := params.EntityPasswords{ 552 Changes: []params.EntityPassword{{ 553 Tag: alex.Tag().String(), 554 Password: "new-password", 555 }}} 556 results, err := usermanager.SetPassword(args) 557 c.Assert(err, jc.ErrorIsNil) 558 c.Assert(results.Results, gc.HasLen, 1) 559 c.Assert(results.Results[0], gc.DeepEquals, params.ErrorResult{Error: nil}) 560 561 err = alex.Refresh() 562 c.Assert(err, jc.ErrorIsNil) 563 564 c.Assert(alex.PasswordValid("new-password"), jc.IsTrue) 565 } 566 567 func (s *userManagerSuite) TestSetPasswordForOther(c *gc.C) { 568 alex := s.Factory.MakeUser(c, &factory.UserParams{Name: "alex", NoModelUser: true}) 569 barb := s.Factory.MakeUser(c, &factory.UserParams{Name: "barb", NoModelUser: true}) 570 usermanager, err := usermanager.NewUserManagerAPI( 571 s.State, s.resources, apiservertesting.FakeAuthorizer{Tag: alex.Tag()}) 572 c.Assert(err, jc.ErrorIsNil) 573 574 args := params.EntityPasswords{ 575 Changes: []params.EntityPassword{{ 576 Tag: barb.Tag().String(), 577 Password: "new-password", 578 }}} 579 results, err := usermanager.SetPassword(args) 580 c.Assert(err, jc.ErrorIsNil) 581 c.Assert(results.Results, gc.HasLen, 1) 582 c.Assert(results.Results[0], gc.DeepEquals, params.ErrorResult{ 583 Error: ¶ms.Error{ 584 Message: "permission denied", 585 Code: params.CodeUnauthorized, 586 }}) 587 588 err = barb.Refresh() 589 c.Assert(err, jc.ErrorIsNil) 590 591 c.Assert(barb.PasswordValid("new-password"), jc.IsFalse) 592 }