assume.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package tokens
  15. import (
  16. "context"
  17. "yunion.io/x/pkg/errors"
  18. "yunion.io/x/pkg/util/rbacscope"
  19. api "yunion.io/x/onecloud/pkg/apis/identity"
  20. "yunion.io/x/onecloud/pkg/cloudcommon/policy"
  21. "yunion.io/x/onecloud/pkg/httperrors"
  22. "yunion.io/x/onecloud/pkg/keystone/models"
  23. "yunion.io/x/onecloud/pkg/mcclient"
  24. )
  25. // authUserByAssume allows an admin token to login as any user without password
  26. func authUserByAssume(ctx context.Context, input mcclient.SAuthenticationInputV3) (*api.SUserExtended, error) {
  27. // Validate admin token
  28. if len(input.Auth.Identity.Token.Id) == 0 {
  29. return nil, httperrors.NewInputParameterError("admin token is required for assume authentication")
  30. }
  31. // Decode and validate the admin token
  32. adminToken, err := TokenStrDecode(ctx, input.Auth.Identity.Token.Id)
  33. if err != nil {
  34. return nil, errors.Wrap(err, "decode admin token")
  35. }
  36. // Check if admin token is expired
  37. if adminToken.IsExpired() {
  38. return nil, ErrExpiredToken
  39. }
  40. scopedProject, err := models.ProjectManager.FetchProject(
  41. input.Auth.Scope.Project.Id,
  42. input.Auth.Scope.Project.Name,
  43. input.Auth.Scope.Project.Domain.Id,
  44. input.Auth.Scope.Project.Domain.Name,
  45. )
  46. if err != nil {
  47. return nil, errors.Wrap(err, "fetch scoped project")
  48. }
  49. var requireScope rbacscope.TRbacScope
  50. if adminToken.ProjectId == scopedProject.Id {
  51. requireScope = rbacscope.ScopeProject
  52. } else if adminToken.DomainId == scopedProject.DomainId {
  53. requireScope = rbacscope.ScopeDomain
  54. } else {
  55. requireScope = rbacscope.ScopeSystem
  56. }
  57. adminToken.ProjectId = scopedProject.Id
  58. adminToken.DomainId = scopedProject.DomainId
  59. adminTokenCred, err := adminToken.GetSimpleUserCred(input.Auth.Identity.Token.Id)
  60. if err != nil {
  61. return nil, errors.Wrap(err, "get admin token credential")
  62. }
  63. // Validate target user information
  64. assumeUser := input.Auth.Identity.Assume.User
  65. if len(assumeUser.Id) == 0 && len(assumeUser.Name) == 0 {
  66. return nil, httperrors.NewInputParameterError("target user id or name is required")
  67. }
  68. // Fetch target user
  69. targetUser, err := models.UserManager.FetchUserExtended(
  70. assumeUser.Id,
  71. assumeUser.Name,
  72. assumeUser.Domain.Id,
  73. assumeUser.Domain.Name,
  74. )
  75. if err != nil {
  76. return nil, errors.Wrap(err, "fetch target user")
  77. }
  78. if adminTokenCred.GetUserId() != targetUser.Id {
  79. if policy.PolicyManager.Allow(requireScope, adminTokenCred, api.SERVICE_TYPE, "tokens", "perform", "assume").Result.IsDeny() {
  80. return nil, httperrors.NewForbiddenError("%s not allow to assume user in project %s", adminTokenCred.GetUserName(), scopedProject.Name)
  81. }
  82. }
  83. // Set audit IDs to include both admin token and assume operation
  84. targetUser.AuditIds = []string{adminTokenCred.GetUserId()}
  85. return targetUser, nil
  86. }