diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service.go b/internal/servers/controller/handlers/authmethods/authmethod_service.go index 1e95a9912..a5c693f70 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service.go @@ -13,6 +13,7 @@ import ( pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/authmethods" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/types/scope" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/wrapperspb" @@ -90,7 +91,7 @@ func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethod if err := validateCreateRequest(req); err != nil { return nil, err } - u, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem()) + u, err := s.createInRepo(ctx, req.GetItem().GetScopeId(), req.GetItem()) if err != nil { return nil, err } @@ -292,6 +293,10 @@ func validateGetRequest(req *pbs.GetAuthMethodRequest) error { func validateCreateRequest(req *pbs.CreateAuthMethodRequest) error { return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { badFields := map[string]string{} + if !handlers.ValidId(scope.Org.Prefix(), req.GetItem().GetScopeId()) && + scope.Global.String() != req.GetItem().GetScopeId() { + badFields["scope_id"] = "This field is missing or improperly formatted." + } switch auth.SubtypeFromType(req.GetItem().GetType()) { case auth.PasswordSubtype: pwAttrs := &pb.PasswordAuthMethodAttributes{} diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go index 8a92405f1..494f82eb0 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go @@ -339,6 +339,34 @@ func TestCreate(t *testing.T) { }, errCode: codes.OK, }, + { + name: "Create a global AuthMethod", + req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ + ScopeId: scope.Global.String(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Type: "password", + }}, + res: &pbs.CreateAuthMethodResponse{ + Uri: fmt.Sprintf("auth-methods/%s_", password.AuthMethodPrefix), + Item: &pb.AuthMethod{ + Id: defaultAm.GetPublicId(), + ScopeId: scope.Global.String(), + CreatedTime: defaultAm.GetCreateTime().GetTimestamp(), + UpdatedTime: defaultAm.GetUpdateTime().GetTimestamp(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Scope: &scopepb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Version: 1, + Type: "password", + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ + "min_password_length": structpb.NewNumberValue(8), + "min_login_name_length": structpb.NewNumberValue(3), + }}, + }, + }, + errCode: codes.OK, + }, { name: "Can't specify Id", req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ @@ -411,7 +439,7 @@ func TestCreate(t *testing.T) { s, err := authmethods.NewService(repoFn) require.NoError(err, "Error when getting new auth_method service.") - got, gErr := s.CreateAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), tc.req) + got, gErr := s.CreateAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(tc.req.GetItem().GetScopeId())), tc.req) assert.Equal(tc.errCode, status.Code(gErr), "CreateAuthMethod(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) if tc.res == nil { require.Nil(got) @@ -456,6 +484,7 @@ func TestUpdate(t *testing.T) { freshAuthMethod := func() (*pb.AuthMethod, func()) { am, err := tested.CreateAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ + ScopeId: o.GetPublicId(), Name: wrapperspb.String("default"), Description: wrapperspb.String("default"), Type: "password", diff --git a/internal/servers/controller/handlers/groups/group_service.go b/internal/servers/controller/handlers/groups/group_service.go index 3db65ae1c..43f4f47f4 100644 --- a/internal/servers/controller/handlers/groups/group_service.go +++ b/internal/servers/controller/handlers/groups/group_service.go @@ -378,8 +378,10 @@ func validateGetRequest(req *pbs.GetGroupRequest) error { func validateCreateRequest(req *pbs.CreateGroupRequest) error { return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { badFields := map[string]string{} - if !handlers.ValidId(scope.Org.Prefix(), req.GetItem().GetScopeId()) && !handlers.ValidId(scope.Project.Prefix(), req.GetItem().GetScopeId()) { - badFields["scope_id"] = "Incorrectly formatted identifier." + if !handlers.ValidId(scope.Org.Prefix(), req.GetItem().GetScopeId()) && + !handlers.ValidId(scope.Project.Prefix(), req.GetItem().GetScopeId()) && + scope.Global.String() != req.GetItem().GetScopeId() { + badFields["scope_id"] = "This field is missing or improperly formatted." } return badFields }) diff --git a/internal/servers/controller/handlers/groups/group_service_test.go b/internal/servers/controller/handlers/groups/group_service_test.go index cf40a6217..2c9cdd5cc 100644 --- a/internal/servers/controller/handlers/groups/group_service_test.go +++ b/internal/servers/controller/handlers/groups/group_service_test.go @@ -441,6 +441,25 @@ func TestCreate(t *testing.T) { }, errCode: codes.OK, }, + { + name: "Create a global Group", + req: &pbs.CreateGroupRequest{Item: &pb.Group{ + ScopeId: scope.Global.String(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + }}, + res: &pbs.CreateGroupResponse{ + Uri: fmt.Sprintf("groups/%s_", iam.GroupPrefix), + Item: &pb.Group{ + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + }, + }, + errCode: codes.OK, + }, { name: "Create a valid Project Scoped Group", req: &pbs.CreateGroupRequest{ diff --git a/internal/servers/controller/handlers/roles/role_service.go b/internal/servers/controller/handlers/roles/role_service.go index e880d00cc..b1f858076 100644 --- a/internal/servers/controller/handlers/roles/role_service.go +++ b/internal/servers/controller/handlers/roles/role_service.go @@ -537,7 +537,7 @@ func validateCreateRequest(req *pbs.CreateRoleRequest, s *scopes.ScopeInfo) erro if !handlers.ValidId(scope.Org.Prefix(), item.GetScopeId()) && !handlers.ValidId(scope.Project.Prefix(), item.GetScopeId()) && scope.Global.String() != item.GetScopeId() { - badFields["scope_id"] = "Improperly formatted field." + badFields["scope_id"] = "This field is missing or improperly formatted." } if item.GetGrantScopeId() != nil && s.GetType() == scope.Project.String() { if item.GetGrantScopeId().Value != s.GetId() { diff --git a/internal/servers/controller/handlers/roles/role_service_test.go b/internal/servers/controller/handlers/roles/role_service_test.go index c2b4dea86..c6632e9ef 100644 --- a/internal/servers/controller/handlers/roles/role_service_test.go +++ b/internal/servers/controller/handlers/roles/role_service_test.go @@ -396,6 +396,27 @@ func TestCreate(t *testing.T) { }, errCode: codes.OK, }, + { + name: "Create a valid Global Role", + req: &pbs.CreateRoleRequest{Item: &pb.Role{ + ScopeId: scope.Global.String(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, + }}, + res: &pbs.CreateRoleResponse{ + Uri: fmt.Sprintf("roles/%s_", iam.RolePrefix), + Item: &pb.Role{ + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, + Version: 1, + }, + }, + errCode: codes.OK, + }, { name: "Create a valid Project Scoped Role", req: &pbs.CreateRoleRequest{ diff --git a/internal/servers/controller/handlers/scopes/scope_service.go b/internal/servers/controller/handlers/scopes/scope_service.go index c626f909d..ada9dac1e 100644 --- a/internal/servers/controller/handlers/scopes/scope_service.go +++ b/internal/servers/controller/handlers/scopes/scope_service.go @@ -92,21 +92,13 @@ func (s Service) GetScope(ctx context.Context, req *pbs.GetScopeRequest) (*pbs.G // CreateScope implements the interface pbs.ScopeServiceServer. func (s Service) CreateScope(ctx context.Context, req *pbs.CreateScopeRequest) (*pbs.CreateScopeResponse, error) { - if req.GetItem().GetScopeId() == "" { - return nil, handlers.InvalidArgumentErrorf( - "Argument errors found in the request.", - map[string]string{"scope_id": "Missing value for scope_id"}, - ) + if err := validateCreateRequest(req); err != nil { + return nil, err } authResults := auth.Verify(ctx, auth.WithScopeId(req.GetItem().GetScopeId())) if authResults.Error != nil { return nil, authResults.Error } - - if err := validateCreateRequest(req); err != nil { - return nil, err - } - p, err := s.createInRepo(ctx, authResults, req) if err != nil { return nil, err @@ -334,6 +326,9 @@ func validateGetRequest(req *pbs.GetScopeRequest) error { func validateCreateRequest(req *pbs.CreateScopeRequest) error { badFields := map[string]string{} item := req.GetItem() + if req.GetItem().GetScopeId() == "" { + badFields["scope_id"] = "This is a required field." + } if item.GetId() != "" { badFields["id"] = "This is a read only field." } diff --git a/internal/servers/controller/handlers/users/user_service.go b/internal/servers/controller/handlers/users/user_service.go index 405bcbfbb..be0b9dd41 100644 --- a/internal/servers/controller/handlers/users/user_service.go +++ b/internal/servers/controller/handlers/users/user_service.go @@ -266,8 +266,9 @@ func validateGetRequest(req *pbs.GetUserRequest) error { func validateCreateRequest(req *pbs.CreateUserRequest) error { return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { badFields := map[string]string{} - if !handlers.ValidId(scope.Org.Prefix(), req.GetItem().GetScopeId()) { - badFields["scope_id"] = "Invalidly formatted required identifer." + if !handlers.ValidId(scope.Org.Prefix(), req.GetItem().GetScopeId()) && + scope.Global.String() != req.GetItem().GetScopeId() { + badFields["scope_id"] = "This field is missing or improperly formatted." } return badFields }) diff --git a/internal/servers/controller/handlers/users/user_service_test.go b/internal/servers/controller/handlers/users/user_service_test.go index ff8e9e1e7..6d08c656c 100644 --- a/internal/servers/controller/handlers/users/user_service_test.go +++ b/internal/servers/controller/handlers/users/user_service_test.go @@ -268,6 +268,25 @@ func TestCreate(t *testing.T) { }, errCode: codes.OK, }, + { + name: "Create a valid Global User", + req: &pbs.CreateUserRequest{Item: &pb.User{ + ScopeId: scope.Global.String(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + }}, + res: &pbs.CreateUserResponse{ + Uri: fmt.Sprintf("users/%s_", iam.UserPrefix), + Item: &pb.User{ + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + }, + }, + errCode: codes.OK, + }, { name: "Can't specify Id", req: &pbs.CreateUserRequest{Item: &pb.User{ @@ -302,7 +321,7 @@ func TestCreate(t *testing.T) { s, err := users.NewService(repo) require.NoError(err, "Error when getting new user service.") - got, gErr := s.CreateUser(auth.DisabledAuthTestContext(auth.WithScopeId(defaultUser.GetScopeId())), tc.req) + got, gErr := s.CreateUser(auth.DisabledAuthTestContext(auth.WithScopeId(tc.req.GetItem().GetScopeId())), tc.req) assert.Equal(tc.errCode, status.Code(gErr), "CreateUser(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) if got != nil { assert.Contains(got.GetUri(), tc.res.Uri)