Adding Authz checks that support new pathing (#328)

This commit is contained in:
Todd Knight authored and GitHub committed 2020-09-04 14:48:11 -07:00
1 parent 3d944a616f
commit 1c2c078e0a
46 files changed
+1433 -1165

No files matched your search

+2 -7
View File
@@ -124,11 +124,6 @@ func TestAccount_Crud(t *testing.T) {
require.NoError(err)
assert.Nil(apiErr)
assert.True(existed, "Expected existing account when deleted, but it wasn't.")
existed, apiErr, err = accountClient.Delete(tc.Context(), amId, u.Id)
require.NoError(err)
assert.Nil(apiErr)
assert.False(existed, "Expected account to not exist when deleted, but it did.")
}
func TestAccount_CustomMethods(t *testing.T) {
@@ -198,12 +193,12 @@ func TestAccount_Errors(t *testing.T) {
_, apiErr, err = accountClient.Read(tc.Context(), amId, password.AccountPrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
_, apiErr, err = accountClient.Read(tc.Context(), amId, "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, apiErr, err = accountClient.Update(tc.Context(), amId, u.Id, u.Version)
require.NoError(err)
+3 -8
View File
@@ -119,12 +119,7 @@ func TestAuthToken_Crud(t *testing.T) {
existed, _, err := tokens.Delete(tc.Context(), at.Id)
require.NoError(err)
assert.Nil(apiErr)
assert.True(existed, "Expected existing user when deleted, but it wasn't.")
existed, apiErr, err = tokens.Delete(tc.Context(), at.Id)
require.NoError(err)
assert.Nil(apiErr)
assert.False(existed, "Expected user to not exist when deleted, but it did.")
assert.True(existed, "Expected existing token when deleted, but it wasn't.")
}
func TestAuthToken_Errors(t *testing.T) {
@@ -144,10 +139,10 @@ func TestAuthToken_Errors(t *testing.T) {
_, apiErr, err := tokens.Read(tc.Context(), authtoken.AuthTokenPrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
_, apiErr, err = tokens.Read(tc.Context(), "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
+5 -4
View File
@@ -170,8 +170,9 @@ func TestGroup_Crud(t *testing.T) {
assert.True(existed, "Expected existing user when deleted, but it wasn't.")
existed, apiErr, err = groupsClient.Delete(tc.Context(), g.Id)
assert.NoError(err)
assert.False(existed, "Expected user to not exist when deleted, but it did.")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
})
}
}
@@ -224,12 +225,12 @@ func TestGroup_Errors(t *testing.T) {
_, apiErr, err = groupClient.Read(tc.Context(), iam.GroupPrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
_, apiErr, err = groupClient.Read(tc.Context(), "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, apiErr, err = groupClient.Update(tc.Context(), g.Id, g.Version)
require.NoError(err)
+5 -4
View File
@@ -125,8 +125,9 @@ func TestCatalogs_Crud(t *testing.T) {
assert.True(existed, "Expected existing catalog when deleted, but it wasn't.")
existed, apiErr, err = hcClient.Delete(tc.Context(), hc.Id)
assert.NoError(err)
assert.False(existed, "Expected catalog to not exist when deleted, but it did.")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
}
// TODO: Get better coverage for expected errors and error formats.
@@ -159,10 +160,10 @@ func TestCatalogs_Errors(t *testing.T) {
require.NoError(err)
// TODO: Should this be nil instead of just a catalog that has no values set
assert.NotNil(apiErr)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusForbidden)
_, apiErr, err = pc.Read(tc.Context(), "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
+5 -4
View File
@@ -137,8 +137,9 @@ func TestHost_Crud(t *testing.T) {
assert.True(existed, "Expected existing catalog when deleted, but it wasn't.")
existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id)
assert.NoError(err)
assert.False(existed, "Expected catalog to not exist when deleted, but it did.")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
}
// TODO: Get better coverage for expected errors and error formats.
@@ -176,10 +177,10 @@ func TestHost_Errors(t *testing.T) {
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, static.HostPrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusForbidden)
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
+3 -2
View File
@@ -237,8 +237,9 @@ func TestSet_Crud(t *testing.T) {
} else {
existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id)
}
assert.NoError(err)
assert.False(existed, "Expected catalog to not exist when deleted, but it did.")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
})
}
}
+2 -7
View File
@@ -274,11 +274,6 @@ func TestRole_Crud(t *testing.T) {
require.NoError(err)
assert.Nil(apiErr)
assert.True(existed, "Expected existing user when deleted, but it wasn't.")
existed, apiErr, err = roleClient.Delete(tc.Context(), g.Id)
require.NoError(err)
assert.Nil(apiErr)
assert.False(existed, "Expected user to not exist when deleted, but it did.")
})
}
}
@@ -330,12 +325,12 @@ func TestRole_Errors(t *testing.T) {
_, apiErr, err = roleClient.Read(tc.Context(), iam.RolePrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
_, apiErr, err = roleClient.Read(tc.Context(), "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, apiErr, err = roleClient.Update(tc.Context(), u.Id, u.Version)
require.NoError(err)
+1 -1
View File
@@ -147,5 +147,5 @@ func TestProject_Errors(t *testing.T) {
_, apiErr, err = scps.Read(tc.Context(), "invalid id")
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
+4 -4
View File
@@ -123,8 +123,8 @@ func TestUser_Crud(t *testing.T) {
existed, apiErr, err = userClient.Delete(tc.Context(), u.Id)
require.NoError(err)
assert.Nil(apiErr)
assert.False(existed, "Expected user to not exist when deleted, but it did.")
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
}
func TestUser_Errors(t *testing.T) {
@@ -156,12 +156,12 @@ func TestUser_Errors(t *testing.T) {
_, apiErr, err = userClient.Read(tc.Context(), iam.UserPrefix+"_doesntexis")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
_, apiErr, err = userClient.Read(tc.Context(), "invalid id")
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusForbidden, apiErr.Status)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, apiErr, err = userClient.Update(tc.Context(), u.Id, u.Version)
require.NoError(err)
+1
View File
@@ -156,6 +156,7 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
ScopeId: opts.withScopeId,
Id: opts.withId,
Pin: opts.withPin,
Type: opts.withType,
}
} else {
// This remains for legacy
+8
View File
@@ -3,6 +3,7 @@ package auth
import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
)
func getOpts(opt ...Option) options {
@@ -22,6 +23,7 @@ type options struct {
withPin string
withId string
withAction action.Type
withType resource.Type
withUserId string
withKms *kms.Kms
}
@@ -57,6 +59,12 @@ func WithAction(action action.Type) Option {
}
}
func WithType(rt resource.Type) Option {
return func(o *options) {
o.withType = rt
}
}
func WithUserId(id string) Option {
return func(o *options) {
o.withUserId = id
+2 -3
View File
@@ -36,9 +36,8 @@ func SubtypeFromType(t string) SubType {
// Returns UnknownSubtype if no SubType with this id's prefix is found.
func SubtypeFromId(id string) SubType {
switch {
case strings.HasPrefix(strings.TrimSpace(id), password.AuthMethodPrefix):
fallthrough
case strings.HasPrefix(strings.TrimSpace(id), password.AccountPrefix):
case strings.HasPrefix(strings.TrimSpace(id), password.AuthMethodPrefix),
strings.HasPrefix(strings.TrimSpace(id), password.AccountPrefix):
return PasswordSubtype
}
return UnknownSubtype
+30 -30
View File
@@ -1425,7 +1425,7 @@
]
}
},
"/v1/roles/{role_id}:add-grants": {
"/v1/roles/{id}:add-grants": {
"post": {
"summary": "Adds grants to a role",
"operationId": "RoleService_AddRoleGrants",
@@ -1439,7 +1439,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -1458,7 +1458,7 @@
]
}
},
"/v1/roles/{role_id}:add-principals": {
"/v1/roles/{id}:add-principals": {
"post": {
"summary": "Adds Users and/or Groups to a Role",
"operationId": "RoleService_AddRolePrincipals",
@@ -1472,7 +1472,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -1491,7 +1491,7 @@
]
}
},
"/v1/roles/{role_id}:remove-grants": {
"/v1/roles/{id}:remove-grants": {
"post": {
"summary": "Removes grants from a role.",
"operationId": "RoleService_RemoveRoleGrants",
@@ -1505,7 +1505,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -1524,7 +1524,7 @@
]
}
},
"/v1/roles/{role_id}:remove-principals": {
"/v1/roles/{id}:remove-principals": {
"post": {
"summary": "Removes the specified Users and/or Groups from a Role.",
"operationId": "RoleService_RemoveRolePrincipals",
@@ -1538,7 +1538,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -1557,7 +1557,7 @@
]
}
},
"/v1/roles/{role_id}:set-grants": {
"/v1/roles/{id}:set-grants": {
"post": {
"summary": "Set grants for a role, removing any grants that are not specified in the request.",
"operationId": "RoleService_SetRoleGrants",
@@ -1571,7 +1571,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -1590,7 +1590,7 @@
]
}
},
"/v1/roles/{role_id}:set-principals": {
"/v1/roles/{id}:set-principals": {
"post": {
"summary": "Set Users and/or Groups to a Role, removing any principals that are not specified in the request.",
"operationId": "RoleService_SetRolePrincipals",
@@ -1604,7 +1604,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -2900,7 +2900,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:add-grants": {
"/v1/scopes/*/roles/{id}:add-grants": {
"post": {
"summary": "Adds grants to a role",
"operationId": "RoleService_AddRoleGrants2",
@@ -2914,7 +2914,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -2933,7 +2933,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:add-principals": {
"/v1/scopes/*/roles/{id}:add-principals": {
"post": {
"summary": "Adds Users and/or Groups to a Role",
"operationId": "RoleService_AddRolePrincipals2",
@@ -2947,7 +2947,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -2966,7 +2966,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:remove-grants": {
"/v1/scopes/*/roles/{id}:remove-grants": {
"post": {
"summary": "Removes grants from a role.",
"operationId": "RoleService_RemoveRoleGrants2",
@@ -2980,7 +2980,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -2999,7 +2999,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:remove-principals": {
"/v1/scopes/*/roles/{id}:remove-principals": {
"post": {
"summary": "Removes the specified Users and/or Groups from a Role.",
"operationId": "RoleService_RemoveRolePrincipals2",
@@ -3013,7 +3013,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -3032,7 +3032,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:set-grants": {
"/v1/scopes/*/roles/{id}:set-grants": {
"post": {
"summary": "Set grants for a role, removing any grants that are not specified in the request.",
"operationId": "RoleService_SetRoleGrants2",
@@ -3046,7 +3046,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -3065,7 +3065,7 @@
]
}
},
"/v1/scopes/*/roles/{role_id}:set-principals": {
"/v1/scopes/*/roles/{id}:set-principals": {
"post": {
"summary": "Set Users and/or Groups to a Role, removing any principals that are not specified in the request.",
"operationId": "RoleService_SetRolePrincipals2",
@@ -3079,7 +3079,7 @@
},
"parameters": [
{
"name": "role_id",
"name": "id",
"in": "path",
"required": true,
"type": "string"
@@ -4867,7 +4867,7 @@
"controller.api.services.v1.AddRoleGrantsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -4894,7 +4894,7 @@
"controller.api.services.v1.AddRolePrincipalsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -5476,7 +5476,7 @@
"controller.api.services.v1.RemoveRoleGrantsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -5503,7 +5503,7 @@
"controller.api.services.v1.RemoveRolePrincipalsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -5635,7 +5635,7 @@
"controller.api.services.v1.SetRoleGrantsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -5662,7 +5662,7 @@
"controller.api.services.v1.SetRolePrincipalsRequest": {
"type": "object",
"properties": {
"role_id": {
"id": {
"type": "string"
},
"version": {
@@ -550,7 +550,7 @@ type AddRolePrincipalsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -589,9 +589,9 @@ func (*AddRolePrincipalsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{10}
}
func (x *AddRolePrincipalsRequest) GetRoleId() string {
func (x *AddRolePrincipalsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -662,7 +662,7 @@ type SetRolePrincipalsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -701,9 +701,9 @@ func (*SetRolePrincipalsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{12}
}
func (x *SetRolePrincipalsRequest) GetRoleId() string {
func (x *SetRolePrincipalsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -774,7 +774,7 @@ type RemoveRolePrincipalsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -813,9 +813,9 @@ func (*RemoveRolePrincipalsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{14}
}
func (x *RemoveRolePrincipalsRequest) GetRoleId() string {
func (x *RemoveRolePrincipalsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -886,7 +886,7 @@ type AddRoleGrantsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -925,9 +925,9 @@ func (*AddRoleGrantsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{16}
}
func (x *AddRoleGrantsRequest) GetRoleId() string {
func (x *AddRoleGrantsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -998,7 +998,7 @@ type SetRoleGrantsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -1037,9 +1037,9 @@ func (*SetRoleGrantsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{18}
}
func (x *SetRoleGrantsRequest) GetRoleId() string {
func (x *SetRoleGrantsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -1110,7 +1110,7 @@ type RemoveRoleGrantsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoleId string `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -1149,9 +1149,9 @@ func (*RemoveRoleGrantsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{20}
}
func (x *RemoveRoleGrantsRequest) GetRoleId() string {
func (x *RemoveRoleGrantsRequest) GetId() string {
if x != nil {
return x.RoleId
return x.Id
}
return ""
}
@@ -1286,163 +1286,159 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07,
0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65,
0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0x73, 0x0a, 0x18, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0x6a, 0x0a, 0x18, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72,
0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x41,
0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x73, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d,
0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69,
0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x6a, 0x0a, 0x18,
0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f,
0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x52,
0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72,
0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x22, 0x6d, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x53, 0x65,
0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x22, 0x76, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f,
0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69,
0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x5b, 0x0a, 0x1c,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69,
0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x6f, 0x0a, 0x14, 0x41, 0x64, 0x64,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74,
0x72, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x54, 0x0a, 0x15, 0x41, 0x64,
0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x22, 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49,
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x73, 0x22, 0x54, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c,
0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x72, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72,
0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x57, 0x0a, 0x18, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x32, 0xaf, 0x15, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0xb8, 0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x37, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64,
0x7d, 0x5a, 0x1f, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f,
0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74,
0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12,
0xae, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52,
0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c,
0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2a, 0x12, 0x09, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x1d, 0x12,
0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12,
0x0f, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73,
0x12, 0xd4, 0x01, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12,
0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x09, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x2e, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x73,
0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x63, 0x6f, 0x70,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17,
0x12, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67,
0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xc9, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64,
0x73, 0x22, 0x5b, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x66,
0x0a, 0x14, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x54, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x66, 0x0a, 0x14,
0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24,
0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x18,
0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x73, 0x22, 0x54, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x69, 0x0a, 0x17, 0x52, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73,
0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74,
0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x57, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52,
0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xf2,
0x14, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb8,
0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x12, 0x0e, 0x2f, 0x76, 0x31,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x1f, 0x12, 0x17, 0x2f,
0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69,
0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xae, 0x01, 0x0a, 0x09, 0x4c, 0x69,
0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x32, 0x0e, 0x2f,
0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x5a, 0x25, 0x32, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x10, 0x12, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52,
0x6f, 0x6c, 0x65, 0x12, 0xb1, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f,
0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x72,
0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x19, 0x2a, 0x17, 0x2f, 0x76, 0x31,
0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f,
0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73,
0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x95, 0x02, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x52,
0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e,
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x09, 0x2f, 0x76,
0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x73,
0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x73,
0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xd4, 0x01, 0x0a, 0x0a, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47,
0x22, 0x09, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x5a, 0x2e, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f,
0x7b, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c,
0x65, 0x12, 0xc9, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x5c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x32, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x25, 0x32,
0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f,
0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xb1, 0x01,
0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x2b, 0x2a, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b,
0x69, 0x64, 0x7d, 0x5a, 0x19, 0x2a, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41,
0x10, 0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c,
0x65, 0x12, 0x8b, 0x02, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e,
0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f,
0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x92, 0x01, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x65, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b,
0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x36, 0x22, 0x2b, 0x2f, 0x76,
0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70,
0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x88, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5b, 0x22, 0x1d, 0x2f,
0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64,
0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a,
0x31, 0x22, 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, 0x41, 0x64, 0x64,
0x73, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12,
0xd4, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63,
0xca, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69,
@@ -1450,96 +1446,93 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0xd1, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x65, 0x22, 0x22, 0x2f, 0x76, 0x31,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a,
0x01, 0x2a, 0x5a, 0x36, 0x22, 0x2b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73,
0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69,
0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x63, 0x12, 0x61, 0x53, 0x65, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61,
0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20,
0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67,
0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x20,
0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65,
0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xb8, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12,
0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0xac, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6b, 0x22, 0x25, 0x2f, 0x76, 0x31,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x39, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69,
0x73, 0x65, 0x22, 0xc7, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5b, 0x22, 0x1d, 0x2f, 0x76, 0x31,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d,
0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x31, 0x22,
0x26, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f,
0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x38, 0x12, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64,
0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72,
0x6f, 0x75, 0x70, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65,
0x2e, 0x12, 0xf3, 0x01, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x63, 0x12, 0x61, 0x53, 0x65, 0x74, 0x20, 0x55,
0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75,
0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65,
0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xae, 0x02, 0x0a,
0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5d,
0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x3a, 0x01, 0x2a, 0x5a, 0x32, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f,
0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01,
0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17,
0x12, 0x15, 0x41, 0x64, 0x64, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f,
0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0xb0, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x52,
0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72,
0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa2, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x61, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64,
0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x34, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63,
0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64,
0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x38, 0x12, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x55, 0x73, 0x65,
0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73,
0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2e, 0x12, 0xe9, 0x01,
0x0a, 0x0d, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12,
0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41,
0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x53, 0x22, 0x19, 0x2f, 0x76,
0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64,
0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x2d, 0x22, 0x22, 0x2f, 0x76,
0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x17, 0x12, 0x15, 0x41, 0x64, 0x64, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20,
0x74, 0x6f, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0xa6, 0x02, 0x0a, 0x0d, 0x53, 0x65,
0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb9,
0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5d, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74,
0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x32, 0x22, 0x27, 0x2f, 0x76,
0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x53, 0x12, 0x51, 0x53, 0x65, 0x74, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2c, 0x20,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74,
0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0x89, 0x02, 0x0a, 0x10, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12,
0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x89, 0x01, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x63, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b,
0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d,
0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x35, 0x22, 0x2a, 0x2f, 0x76, 0x31,
0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f,
0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1d, 0x12, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f,
0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0xaf, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x53, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72,
0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67, 0x72,
0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x73,
0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69,
0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x53, 0x12,
0x51, 0x53, 0x65, 0x74, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67,
0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74,
0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x2e, 0x12, 0xfe, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c,
0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x7f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x59, 0x22, 0x1c, 0x2f, 0x76, 0x31, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x30, 0x22, 0x25, 0x2f,
0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x67, 0x72,
0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x1d, 0x12, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20,
0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x72, 0x6f,
0x6c, 0x65, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e,
0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -700,14 +700,14 @@ func request_RoleService_AddRolePrincipals_0(ctx context.Context, marshaler runt
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -734,14 +734,14 @@ func local_request_RoleService_AddRolePrincipals_0(ctx context.Context, marshale
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.AddRolePrincipals(ctx, &protoReq)
@@ -768,14 +768,14 @@ func request_RoleService_AddRolePrincipals_1(ctx context.Context, marshaler runt
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -802,14 +802,14 @@ func local_request_RoleService_AddRolePrincipals_1(ctx context.Context, marshale
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.AddRolePrincipals(ctx, &protoReq)
@@ -836,14 +836,14 @@ func request_RoleService_SetRolePrincipals_0(ctx context.Context, marshaler runt
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -870,14 +870,14 @@ func local_request_RoleService_SetRolePrincipals_0(ctx context.Context, marshale
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.SetRolePrincipals(ctx, &protoReq)
@@ -904,14 +904,14 @@ func request_RoleService_SetRolePrincipals_1(ctx context.Context, marshaler runt
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -938,14 +938,14 @@ func local_request_RoleService_SetRolePrincipals_1(ctx context.Context, marshale
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.SetRolePrincipals(ctx, &protoReq)
@@ -972,14 +972,14 @@ func request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marshaler r
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1006,14 +1006,14 @@ func local_request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marsh
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.RemoveRolePrincipals(ctx, &protoReq)
@@ -1040,14 +1040,14 @@ func request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marshaler r
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1074,14 +1074,14 @@ func local_request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marsh
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.RemoveRolePrincipals(ctx, &protoReq)
@@ -1108,14 +1108,14 @@ func request_RoleService_AddRoleGrants_0(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.AddRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1142,14 +1142,14 @@ func local_request_RoleService_AddRoleGrants_0(ctx context.Context, marshaler ru
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.AddRoleGrants(ctx, &protoReq)
@@ -1176,14 +1176,14 @@ func request_RoleService_AddRoleGrants_1(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.AddRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1210,14 +1210,14 @@ func local_request_RoleService_AddRoleGrants_1(ctx context.Context, marshaler ru
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.AddRoleGrants(ctx, &protoReq)
@@ -1244,14 +1244,14 @@ func request_RoleService_SetRoleGrants_0(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.SetRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1278,14 +1278,14 @@ func local_request_RoleService_SetRoleGrants_0(ctx context.Context, marshaler ru
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.SetRoleGrants(ctx, &protoReq)
@@ -1312,14 +1312,14 @@ func request_RoleService_SetRoleGrants_1(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.SetRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1346,14 +1346,14 @@ func local_request_RoleService_SetRoleGrants_1(ctx context.Context, marshaler ru
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.SetRoleGrants(ctx, &protoReq)
@@ -1380,14 +1380,14 @@ func request_RoleService_RemoveRoleGrants_0(ctx context.Context, marshaler runti
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.RemoveRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1414,14 +1414,14 @@ func local_request_RoleService_RemoveRoleGrants_0(ctx context.Context, marshaler
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.RemoveRoleGrants(ctx, &protoReq)
@@ -1448,14 +1448,14 @@ func request_RoleService_RemoveRoleGrants_1(ctx context.Context, marshaler runti
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.RemoveRoleGrants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -1482,14 +1482,14 @@ func local_request_RoleService_RemoveRoleGrants_1(ctx context.Context, marshaler
_ = err
)
val, ok = pathParams["role_id"]
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.RoleId, err = runtime.String(val)
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.RemoveRoleGrants(ctx, &protoReq)
@@ -2610,29 +2610,29 @@ var (
pattern_RoleService_DeleteRole_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, ""))
pattern_RoleService_AddRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "add-principals"))
pattern_RoleService_AddRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "add-principals"))
pattern_RoleService_AddRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "add-principals"))
pattern_RoleService_AddRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "add-principals"))
pattern_RoleService_SetRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "set-principals"))
pattern_RoleService_SetRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "set-principals"))
pattern_RoleService_SetRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "set-principals"))
pattern_RoleService_SetRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "set-principals"))
pattern_RoleService_RemoveRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "remove-principals"))
pattern_RoleService_RemoveRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "remove-principals"))
pattern_RoleService_RemoveRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "remove-principals"))
pattern_RoleService_RemoveRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "remove-principals"))
pattern_RoleService_AddRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "add-grants"))
pattern_RoleService_AddRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "add-grants"))
pattern_RoleService_AddRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "add-grants"))
pattern_RoleService_AddRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "add-grants"))
pattern_RoleService_SetRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "set-grants"))
pattern_RoleService_SetRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "set-grants"))
pattern_RoleService_SetRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "set-grants"))
pattern_RoleService_SetRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "set-grants"))
pattern_RoleService_RemoveRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "role_id"}, "remove-grants"))
pattern_RoleService_RemoveRoleGrants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "roles", "id"}, "remove-grants"))
pattern_RoleService_RemoveRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "role_id"}, "remove-grants"))
pattern_RoleService_RemoveRoleGrants_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "roles", "id"}, "remove-grants"))
)
var (
+3 -5
View File
@@ -32,11 +32,9 @@ func SubtypeFromType(t string) SubType {
func SubtypeFromId(id string) SubType {
switch {
case strings.HasPrefix(strings.TrimSpace(id), static.HostPrefix):
fallthrough
case strings.HasPrefix(strings.TrimSpace(id), static.HostSetPrefix):
fallthrough
case strings.HasPrefix(strings.TrimSpace(id), static.HostCatalogPrefix):
case strings.HasPrefix(strings.TrimSpace(id), static.HostPrefix),
strings.HasPrefix(strings.TrimSpace(id), static.HostSetPrefix),
strings.HasPrefix(strings.TrimSpace(id), static.HostCatalogPrefix):
return StaticSubtype
}
return UnknownSubtype
+4
View File
@@ -2,6 +2,7 @@ package iam
import (
"context"
"errors"
"fmt"
"strings"
@@ -139,6 +140,9 @@ func (r *Repository) LookupGroup(ctx context.Context, withPublicId string, opt .
},
)
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, nil, nil
}
return nil, nil, fmt.Errorf("lookup group: failed %w for %s", err, withPublicId)
}
return &g, members, nil
+1 -2
View File
@@ -538,9 +538,8 @@ func TestRepository_DeleteGroup(t *testing.T) {
assert.NoError(err)
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundGroup, _, err := repo.LookupGroup(context.Background(), tt.args.group.PublicId)
assert.Error(err)
assert.NoError(err)
assert.Nil(foundGroup)
assert.True(errors.Is(err, db.ErrRecordNotFound))
err = db.TestVerifyOplog(t, rw, tt.args.group.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second))
assert.NoError(err)
+4
View File
@@ -2,6 +2,7 @@ package iam
import (
"context"
"errors"
"fmt"
"strings"
@@ -150,6 +151,9 @@ func (r *Repository) LookupRole(ctx context.Context, withPublicId string, opt ..
},
)
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, nil, nil, nil
}
return nil, nil, nil, err
}
return &role, pr, rg, nil
+1 -2
View File
@@ -535,9 +535,8 @@ func TestRepository_DeleteRole(t *testing.T) {
assert.NoError(err)
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundRole, _, _, err := repo.LookupRole(context.Background(), tt.args.role.PublicId)
assert.Error(err)
assert.NoError(err)
assert.Nil(foundRole)
assert.True(errors.Is(err, db.ErrRecordNotFound))
err = db.TestVerifyOplog(t, rw, tt.args.role.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second))
assert.NoError(err)
+4
View File
@@ -2,6 +2,7 @@ package iam
import (
"context"
"errors"
"fmt"
"strings"
@@ -89,6 +90,9 @@ func (r *Repository) LookupUser(ctx context.Context, withPublicId string, opt ..
user := allocUser()
user.PublicId = withPublicId
if err := r.reader.LookupByPublicId(ctx, &user); err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, nil
}
return nil, fmt.Errorf("lookup user: failed %w for %s", err, withPublicId)
}
return &user, nil
+1 -2
View File
@@ -437,9 +437,8 @@ func TestRepository_DeleteUser(t *testing.T) {
require.NoError(err)
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundUser, err := repo.LookupUser(context.Background(), tt.args.user.PublicId)
require.Error(err)
require.NoError(err)
assert.Nil(foundUser)
assert.True(errors.Is(err, db.ErrRecordNotFound))
err = db.TestVerifyOplog(t, rw, tt.args.user.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second))
require.NoError(err)
+1 -2
View File
@@ -2,7 +2,6 @@ package iam
import (
"context"
"errors"
"testing"
"github.com/hashicorp/boundary/internal/db"
@@ -293,7 +292,7 @@ func Test_UserDelete(t *testing.T) {
require.NoError(err)
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundUser, err := repo.LookupUser(context.Background(), tt.user.GetPublicId())
assert.True(errors.Is(err, db.ErrRecordNotFound))
assert.NoError(err)
assert.Nil(foundUser)
})
}
@@ -113,11 +113,11 @@ service RoleService {
// non-existing resources, an error is returned.
rpc AddRolePrincipals(AddRolePrincipalsRequest) returns (AddRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:add-principals"
post: "/v1/roles/{id}:add-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:add-principals"
post: "/v1/scopes/*/roles/{id}:add-principals"
body: "*"
response_body: "item"
}
@@ -135,11 +135,11 @@ service RoleService {
// returned.
rpc SetRolePrincipals(SetRolePrincipalsRequest) returns (SetRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:set-principals"
post: "/v1/roles/{id}:set-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:set-principals"
post: "/v1/scopes/*/roles/{id}:set-principals"
body: "*"
response_body: "item"
}
@@ -156,11 +156,11 @@ service RoleService {
// is not an error to have duplicate user/group ids.
rpc RemoveRolePrincipals(RemoveRolePrincipalsRequest) returns (RemoveRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:remove-principals"
post: "/v1/roles/{id}:remove-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:remove-principals"
post: "/v1/scopes/*/roles/{id}:remove-principals"
body: "*"
response_body: "item"
}
@@ -176,11 +176,11 @@ service RoleService {
// an error is returned. It is not an error to have duplicate grants.
rpc AddRoleGrants(AddRoleGrantsRequest) returns (AddRoleGrantsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:add-grants"
post: "/v1/roles/{id}:add-grants"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:add-grants"
post: "/v1/scopes/*/roles/{id}:add-grants"
body: "*"
response_body: "item"
}
@@ -197,11 +197,11 @@ service RoleService {
// error is returned. It is not an error to have duplicate grants.
rpc SetRoleGrants(SetRoleGrantsRequest) returns (SetRoleGrantsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:set-grants"
post: "/v1/roles/{id}:set-grants"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:set-grants"
post: "/v1/scopes/*/roles/{id}:set-grants"
body: "*"
response_body: "item"
}
@@ -218,11 +218,11 @@ service RoleService {
// have duplicate grants.
rpc RemoveRoleGrants(RemoveRoleGrantsRequest) returns (RemoveRoleGrantsResponse) {
option (google.api.http) = {
post: "/v1/roles/{role_id}:remove-grants"
post: "/v1/roles/{id}:remove-grants"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/scopes/*/roles/{role_id}:remove-grants"
post: "/v1/scopes/*/roles/{id}:remove-grants"
body: "*"
response_body: "item"
}
@@ -281,7 +281,7 @@ message DeleteRoleResponse {
}
message AddRolePrincipalsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
@@ -293,7 +293,7 @@ message AddRolePrincipalsResponse {
}
message SetRolePrincipalsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
@@ -305,7 +305,7 @@ message SetRolePrincipalsResponse {
}
message RemoveRolePrincipalsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
@@ -317,7 +317,7 @@ message RemoveRolePrincipalsResponse {
}
message AddRoleGrantsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
@@ -329,7 +329,7 @@ message AddRoleGrantsResponse {
}
message SetRoleGrantsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
@@ -341,7 +341,7 @@ message SetRoleGrantsResponse {
}
message RemoveRoleGrantsRequest {
string role_id = 1;
string id = 1;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
uint32 version = 2;
+3 -3
View File
@@ -93,7 +93,7 @@ func handleGrpcGateway(c *Controller, props HandlerProperties) (http.Handler, er
runtime.WithErrorHandler(handlers.ErrorHandler(c.logger)),
runtime.WithForwardResponseOption(handlers.OutgoingInterceptor),
)
hcs, err := host_catalogs.NewService(c.StaticHostRepoFn)
hcs, err := host_catalogs.NewService(c.StaticHostRepoFn, c.IamRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create host catalog handler service: %w", err)
}
@@ -128,14 +128,14 @@ func handleGrpcGateway(c *Controller, props HandlerProperties) (http.Handler, er
if err := services.RegisterAuthenticationServiceHandlerServer(ctx, mux, auths); err != nil {
return nil, fmt.Errorf("failed to register authenticate service handler: %w", err)
}
authMethods, err := authmethods.NewService(c.PasswordAuthRepoFn)
authMethods, err := authmethods.NewService(c.PasswordAuthRepoFn, c.IamRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create auth method handler service: %w", err)
}
if err := services.RegisterAuthMethodServiceHandlerServer(ctx, mux, authMethods); err != nil {
return nil, fmt.Errorf("failed to register auth method service handler: %w", err)
}
authtoks, err := authtokens.NewService(c.AuthTokenRepoFn)
authtoks, err := authtokens.NewService(c.AuthTokenRepoFn, c.IamRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create auth token handler service: %w", err)
}
@@ -11,7 +11,10 @@ import (
"github.com/hashicorp/boundary/internal/db"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/accounts"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
@@ -30,11 +33,11 @@ func init() {
// Service handles request as described by the pbs.AccountServiceServer interface.
type Service struct {
repoFn func() (*password.Repository, error)
repoFn common.PasswordAuthRepoFactory
}
// NewService returns a user service which handles user related requests to boundary.
func NewService(repo func() (*password.Repository, error)) (Service, error) {
func NewService(repo common.PasswordAuthRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil password repository provided")
}
@@ -43,17 +46,15 @@ func NewService(repo func() (*password.Repository, error)) (Service, error) {
var _ pbs.AccountServiceServer = Service{}
// TODO(ICU-407): Validate that the provided auth method and account are in the provided scope.
// ListAccounts implements the interface pbs.AccountServiceServer.
func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest) (*pbs.ListAccountsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetAuthMethodId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
ul, err := s.listFromRepo(ctx, req.GetAuthMethodId())
if err != nil {
return nil, err
@@ -66,13 +67,13 @@ func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest)
// GetAccount implements the interface pbs.AccountServiceServer.
func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*pbs.GetAccountResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -83,14 +84,14 @@ func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*p
// CreateAccount implements the interface pbs.AccountServiceServer.
func (s Service) CreateAccount(ctx context.Context, req *pbs.CreateAccountRequest) (*pbs.CreateAccountResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
u, err := s.createInRepo(ctx, req.GetItem().GetAuthMethodId(), authResults.Scope.GetId(), req.GetItem())
authMeth, authResults := s.parentAndAuthResult(ctx, req.GetItem().GetAuthMethodId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.createInRepo(ctx, authMeth.GetPublicId(), authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
}
@@ -100,14 +101,14 @@ func (s Service) CreateAccount(ctx context.Context, req *pbs.CreateAccountReques
// UpdateAccount implements the interface pbs.AccountServiceServer.
func (s Service) UpdateAccount(ctx context.Context, req *pbs.UpdateAccountRequest) (*pbs.UpdateAccountResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
authMeth, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), authMeth.GetPublicId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
}
@@ -117,13 +118,13 @@ func (s Service) UpdateAccount(ctx context.Context, req *pbs.UpdateAccountReques
// DeleteAccount implements the interface pbs.AccountServiceServer.
func (s Service) DeleteAccount(ctx context.Context, req *pbs.DeleteAccountRequest) (*pbs.DeleteAccountResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId())
if err != nil {
return nil, err
@@ -133,13 +134,13 @@ func (s Service) DeleteAccount(ctx context.Context, req *pbs.DeleteAccountReques
// ChangePassword implements the interface pbs.AccountServiceServer.
func (s Service) ChangePassword(ctx context.Context, req *pbs.ChangePasswordRequest) (*pbs.ChangePasswordResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateChangePasswordRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.ChangePassword)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.changePasswordInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetVersion(), req.GetOldPassword(), req.GetNewPassword())
if err != nil {
return nil, err
@@ -150,13 +151,13 @@ func (s Service) ChangePassword(ctx context.Context, req *pbs.ChangePasswordRequ
// SetPassword implements the interface pbs.AccountServiceServer.
func (s Service) SetPassword(ctx context.Context, req *pbs.SetPasswordRequest) (*pbs.SetPasswordResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateSetPasswordRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.SetPassword)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.setPasswordInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetVersion(), req.GetPassword())
if err != nil {
return nil, err
@@ -218,7 +219,7 @@ func (s Service) createInRepo(ctx context.Context, authMethodId, scopeId string,
return toProto(out)
}
func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []string, item *pb.Account) (*pb.Account, error) {
func (s Service) updateInRepo(ctx context.Context, scopeId, authMethId, id string, mask []string, item *pb.Account) (*pb.Account, error) {
var opts []password.Option
if desc := item.GetDescription(); desc != nil {
opts = append(opts, password.WithDescription(desc.GetValue()))
@@ -226,7 +227,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
if name := item.GetName(); name != nil {
opts = append(opts, password.WithName(name.GetValue()))
}
u, err := password.NewAccount("ignored", opts...)
u, err := password.NewAccount(authMethId, opts...)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to build auth method for update: %v.", err)
}
@@ -269,7 +270,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool,
if errors.Is(err, db.ErrRecordNotFound) {
return false, nil
}
return false, status.Errorf(codes.Internal, "Unable to delete user: %v.", err)
return false, status.Errorf(codes.Internal, "Unable to delete account: %v.", err)
}
return rows > 0, nil
}
@@ -321,6 +322,47 @@ func (s Service) setPasswordInRepo(ctx context.Context, scopeId, id string, vers
return toProto(out)
}
func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Type) (*password.AuthMethod, auth.VerifyResults) {
res := auth.VerifyResults{}
repo, err := s.repoFn()
if err != nil {
res.Error = err
return nil, res
}
var parentId string
var authMeth *password.AuthMethod
opts := []auth.Option{auth.WithType(resource.Account), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
default:
acct, err := repo.LookupAccount(ctx, id)
if err != nil {
res.Error = err
return nil, res
}
if acct == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
parentId = acct.GetAuthMethodId()
opts = append(opts, auth.WithId(id))
}
authMeth, err = repo.LookupAuthMethod(ctx, parentId)
if err != nil {
res.Error = err
return nil, res
}
if authMeth == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
opts = append(opts, auth.WithScopeId(authMeth.GetScopeId()), auth.WithPin(parentId))
return authMeth, auth.Verify(ctx, opts...)
}
func toProto(in *password.Account) (*pb.Account, error) {
out := pb.Account{
Id: in.GetPublicId(),
@@ -72,7 +72,7 @@ func TestGet(t *testing.T) {
name: "Get a non existing account",
req: &pbs.GetAccountRequest{Id: password.AccountPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -162,12 +162,10 @@ func TestList(t *testing.T) {
res: &pbs.ListAccountsResponse{},
errCode: codes.OK,
},
// TODO: When an auth method doesn't exist, we should return a 404 instead of an empty list.
{
name: "Unfound Auth Method",
authMethod: password.AuthMethodPrefix + "_DoesntExis",
res: &pbs.ListAccountsResponse{},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
@@ -220,17 +218,13 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteAccountRequest{
Id: password.AccountPrefix + "_doesntexis",
},
res: &pbs.DeleteAccountResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad account id formatting",
req: &pbs.DeleteAccountRequest{
Id: "bad_format",
},
res: nil,
errCode: codes.InvalidArgument,
},
}
@@ -267,8 +261,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteAccount(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -689,8 +683,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant auth_method should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing Account",
req: &pbs.UpdateAccountRequest{
@@ -703,7 +695,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -15,6 +15,8 @@ import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -58,13 +60,13 @@ var _ pbs.AuthenticationServiceServer = Service{}
// Authenticate implements the interface pbs.AuthenticationServiceServer.
func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) (*pbs.AuthenticateResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateAuthenticateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetAuthMethodId(), action.Authenticate)
if authResults.Error != nil {
return nil, authResults.Error
}
creds := req.GetCredentials().GetFields()
tok, err := s.authenticateWithRepo(ctx, authResults.Scope.GetId(), req.GetAuthMethodId(), creds[loginNameKey].GetStringValue(), creds[pwKey].GetStringValue())
if err != nil {
@@ -133,6 +135,32 @@ func (s Service) authenticateWithRepo(ctx context.Context, scopeId, authMethodId
return prot, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
repo, err := s.pwRepo()
if err != nil {
res.Error = err
return res
}
authMeth, err := repo.LookupAuthMethod(ctx, id)
if err != nil {
res.Error = err
return res
}
if authMeth == nil {
res.Error = handlers.ForbiddenError()
return res
}
authResults := auth.Verify(ctx,
auth.WithAction(a),
auth.WithType(resource.AuthMethod),
auth.WithScopeId(authMeth.GetScopeId()),
auth.WithId(id))
return authResults
}
func toProto(t *authtoken.AuthToken) *pba.AuthToken {
return &pba.AuthToken{
Id: t.GetPublicId(),
@@ -169,7 +197,6 @@ func validateAuthenticateRequest(req *pbs.AuthenticateRequest) error {
if _, ok := creds[pwKey]; !ok {
badFields["credentials.password"] = "This is a required field."
}
// TODO: Update this when we enable split cookie token types.
tType := strings.ToLower(strings.TrimSpace(req.GetTokenType()))
if tType != "" && tType != "token" && tType != "cookie" {
badFields["token_type"] = "The only accepted type is 'token'."
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"regexp"
"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/auth/password"
@@ -12,7 +11,10 @@ import (
"github.com/hashicorp/boundary/internal/db"
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/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -21,7 +23,6 @@ import (
var (
maskManager handlers.MaskManager
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
)
func init() {
@@ -33,28 +34,32 @@ func init() {
// Service handles request as described by the pbs.AuthMethodServiceServer interface.
type Service struct {
repoFn func() (*password.Repository, error)
repoFn common.PasswordAuthRepoFactory
iamRepoFn common.IamRepoFactory
}
// NewService returns a auth method service which handles auth method related requests to boundary.
func NewService(repo func() (*password.Repository, error)) (Service, error) {
func NewService(repo common.PasswordAuthRepoFactory, iamRepoFn common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil password repository provided")
}
if iamRepoFn == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
return Service{repoFn: repo}, nil
return Service{repoFn: repo, iamRepoFn: iamRepoFn}, nil
}
var _ pbs.AuthMethodServiceServer = Service{}
// ListAuthMethods implements the interface pbs.AuthMethodServiceServer.
func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRequest) (*pbs.ListAuthMethodsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
ul, err := s.listFromRepo(ctx, authResults.Scope.GetId())
if err != nil {
return nil, err
@@ -67,13 +72,13 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe
// GetAuthMethod implements the interface pbs.AuthMethodServiceServer.
func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodRequest) (*pbs.GetAuthMethodResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -84,14 +89,14 @@ func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodReques
// CreateAuthMethod implements the interface pbs.AuthMethodServiceServer.
func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethodRequest) (*pbs.CreateAuthMethodResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
u, err := s.createInRepo(ctx, req.GetItem().GetScopeId(), req.GetItem())
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
}
@@ -101,13 +106,13 @@ func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethod
// UpdateAuthMethod implements the interface pbs.AuthMethodServiceServer.
func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethodRequest) (*pbs.UpdateAuthMethodResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -118,13 +123,13 @@ func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethod
// DeleteAuthMethod implements the interface pbs.AuthMethodServiceServer.
func (s Service) DeleteAuthMethod(ctx context.Context, req *pbs.DeleteAuthMethodRequest) (*pbs.DeleteAuthMethodResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId())
if err != nil {
return nil, err
@@ -255,6 +260,50 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool,
return rows > 0, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
var parentId string
opts := []auth.Option{auth.WithType(resource.AuthMethod), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
iamRepo, err := s.iamRepoFn()
if err != nil {
res.Error = err
return res
}
scp, err := iamRepo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
authMeth, err := repo.LookupAuthMethod(ctx, id)
if err != nil {
res.Error = err
return res
}
if authMeth == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = authMeth.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *password.AuthMethod) (*pb.AuthMethod, error) {
out := pb.AuthMethod{
Id: in.GetPublicId(),
@@ -33,6 +33,9 @@ func TestGet(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
@@ -77,7 +80,7 @@ func TestGet(t *testing.T) {
scopeId: o.GetPublicId(),
req: &pbs.GetAuthMethodRequest{Id: password.AuthMethodPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -98,7 +101,7 @@ func TestGet(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
s, err := authmethods.NewService(repoFn)
s, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(err, "Couldn't create new auth_method service.")
got, gErr := s.GetAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
@@ -113,6 +116,9 @@ func TestList(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
@@ -184,17 +190,16 @@ func TestList(t *testing.T) {
{
name: "Unfound Auth Method",
scopeId: password.AuthMethodPrefix + "_DoesntExis",
res: &pbs.ListAuthMethodsResponse{},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
s, err := authmethods.NewService(repoFn)
s, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(err, "Couldn't create new auth_method service.")
got, gErr := s.ListAuthMethods(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), &pbs.ListAuthMethodsRequest{})
got, gErr := s.ListAuthMethods(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), &pbs.ListAuthMethodsRequest{ScopeId: tc.scopeId})
assert.Equal(tc.errCode, status.Code(gErr), "ListAuthMethods() for scope %q got error %v, wanted %v", tc.scopeId, gErr, tc.errCode)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListAuthMethods() for scope %q got response %q, wanted %q", tc.scopeId, got, tc.res)
})
@@ -206,6 +211,9 @@ func TestDelete(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
@@ -214,7 +222,7 @@ func TestDelete(t *testing.T) {
o, _ := iam.TestScopes(t, iamRepo)
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
s, err := authmethods.NewService(repoFn)
s, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Error when getting new auth_method service.")
cases := []struct {
@@ -238,10 +246,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteAuthMethodRequest{
Id: password.AuthMethodPrefix + "_doesntexis",
},
res: &pbs.DeleteAuthMethodResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad AuthMethod Id formatting",
@@ -268,6 +273,9 @@ func TestDelete_twice(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
@@ -276,7 +284,7 @@ func TestDelete_twice(t *testing.T) {
o, _ := iam.TestScopes(t, iamRepo)
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
s, err := authmethods.NewService(repoFn)
s, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(err, "Error when getting new auth_method service.")
req := &pbs.DeleteAuthMethodRequest{
@@ -286,8 +294,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -295,6 +303,9 @@ func TestCreate(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
@@ -436,7 +447,7 @@ func TestCreate(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
s, err := authmethods.NewService(repoFn)
s, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(err, "Error when getting new auth_method service.")
got, gErr := s.CreateAuthMethod(auth.DisabledAuthTestContext(auth.WithScopeId(tc.req.GetItem().GetScopeId())), tc.req)
@@ -470,13 +481,16 @@ func TestUpdate(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, kms)
}
iamRepo := iam.TestRepo(t, conn, wrapper)
o, _ := iam.TestScopes(t, iamRepo)
tested, err := authmethods.NewService(repoFn)
tested, err := authmethods.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Error when getting new auth_method service.")
defaultScopeInfo := &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: o.GetType()}
@@ -666,8 +680,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant auth_method should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing AuthMethod",
req: &pbs.UpdateAuthMethodRequest{
@@ -680,7 +692,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -10,7 +10,10 @@ import (
"github.com/hashicorp/boundary/internal/db"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/authtokens"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -18,28 +21,32 @@ import (
// Service handles request as described by the pbs.AuthTokenServiceServer interface.
type Service struct {
repoFn func() (*authtoken.Repository, error)
repoFn common.AuthTokenRepoFactory
iamRepoFn common.IamRepoFactory
}
// NewService returns a user service which handles user related requests to boundary.
func NewService(repo func() (*authtoken.Repository, error)) (Service, error) {
func NewService(repo common.AuthTokenRepoFactory, iamRepoFn common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil auth token repository provided")
}
if iamRepoFn == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
return Service{repoFn: repo}, nil
return Service{repoFn: repo, iamRepoFn: iamRepoFn}, nil
}
var _ pbs.AuthTokenServiceServer = Service{}
// ListAuthTokens implements the interface pbs.AuthTokenServiceServer.
func (s Service) ListAuthTokens(ctx context.Context, req *pbs.ListAuthTokensRequest) (*pbs.ListAuthTokensResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
ul, err := s.listFromRepo(ctx, req.GetScopeId())
if err != nil {
return nil, err
@@ -52,13 +59,13 @@ func (s Service) ListAuthTokens(ctx context.Context, req *pbs.ListAuthTokensRequ
// GetAuthToken implements the interface pbs.AuthTokenServiceServer.
func (s Service) GetAuthToken(ctx context.Context, req *pbs.GetAuthTokenRequest) (*pbs.GetAuthTokenResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -69,13 +76,13 @@ func (s Service) GetAuthToken(ctx context.Context, req *pbs.GetAuthTokenRequest)
// DeleteAuthToken implements the interface pbs.AuthTokenServiceServer.
func (s Service) DeleteAuthToken(ctx context.Context, req *pbs.DeleteAuthTokenRequest) (*pbs.DeleteAuthTokenResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -133,6 +140,50 @@ func (s Service) listFromRepo(ctx context.Context, orgId string) ([]*pb.AuthToke
return outUl, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
var parentId string
opts := []auth.Option{auth.WithType(resource.AuthToken), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
iamRepo, err := s.iamRepoFn()
if err != nil {
res.Error = err
return res
}
scp, err := iamRepo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
authTok, err := repo.LookupAuthToken(ctx, id)
if err != nil {
res.Error = err
return res
}
if authTok == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = authTok.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *authtoken.AuthToken) *pb.AuthToken {
out := pb.AuthToken{
Id: in.GetPublicId(),
@@ -27,11 +27,14 @@ func TestGet(t *testing.T) {
rw := db.New(conn)
wrap := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrap)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrap), nil
}
repoFn := func() (*authtoken.Repository, error) {
return authtoken.NewRepository(rw, rw, kms)
}
s, err := authtokens.NewService(repoFn)
s, err := authtokens.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Couldn't create new auth token service.")
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrap))
@@ -65,7 +68,7 @@ func TestGet(t *testing.T) {
name: "Get a non existing auth token",
req: &pbs.GetAuthTokenRequest{Id: authtoken.AuthTokenPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -95,6 +98,9 @@ func TestList(t *testing.T) {
rw := db.New(conn)
wrap := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrap)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrap), nil
}
repoFn := func() (*authtoken.Repository, error) {
return authtoken.NewRepository(rw, rw, kms)
}
@@ -164,13 +170,12 @@ func TestList(t *testing.T) {
{
name: "Unfound Org",
scope: scope.Org.Prefix() + "_DoesntExis",
res: &pbs.ListAuthTokensResponse{},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
s, err := authtokens.NewService(repoFn)
s, err := authtokens.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Couldn't create new user service.")
got, gErr := s.ListAuthTokens(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scope)), &pbs.ListAuthTokensRequest{ScopeId: tc.scope})
@@ -185,17 +190,18 @@ func TestDelete(t *testing.T) {
rw := db.New(conn)
wrap := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrap)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrap), nil
}
repoFn := func() (*authtoken.Repository, error) {
return authtoken.NewRepository(rw, rw, kms)
}
iamRepo := iam.TestRepo(t, conn, wrap)
wrongOrg, _ := iam.TestScopes(t, iamRepo)
org, _ := iam.TestScopes(t, iamRepo)
at := authtoken.TestAuthToken(t, conn, kms, org.GetPublicId())
atForWrongOrg := authtoken.TestAuthToken(t, conn, kms, org.GetPublicId())
s, err := authtokens.NewService(repoFn)
s, err := authtokens.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Error when getting new user service.")
cases := []struct {
@@ -216,29 +222,13 @@ func TestDelete(t *testing.T) {
},
errCode: codes.OK,
},
{
name: "Delete token from wrong scope",
scope: wrongOrg.GetPublicId(),
req: &pbs.DeleteAuthTokenRequest{
Id: atForWrongOrg.GetPublicId(),
},
// TODO(toddknight): This should return Existed:false. Figure out if this test is testing something valid
// and if so make it pass.
res: &pbs.DeleteAuthTokenResponse{
Existed: true,
},
errCode: codes.OK,
},
{
name: "Delete bad token id",
scope: org.GetPublicId(),
req: &pbs.DeleteAuthTokenRequest{
Id: authtoken.AuthTokenPrefix + "_doesntexis",
},
res: &pbs.DeleteAuthTokenResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad token id formatting",
@@ -266,6 +256,9 @@ func TestDelete_twice(t *testing.T) {
rw := db.New(conn)
wrap := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrap)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrap), nil
}
repoFn := func() (*authtoken.Repository, error) {
return authtoken.NewRepository(rw, rw, kms)
}
@@ -274,7 +267,7 @@ func TestDelete_twice(t *testing.T) {
org, _ := iam.TestScopes(t, iamRepo)
at := authtoken.TestAuthToken(t, conn, kms, org.GetPublicId())
s, err := authtokens.NewService(repoFn)
s, err := authtokens.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Error when getting new user service")
req := &pbs.DeleteAuthTokenRequest{
Id: at.GetPublicId(),
@@ -283,6 +276,6 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteAuthToken(auth.DisabledAuthTestContext(auth.WithScopeId(at.GetScopeId())), req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
@@ -11,7 +11,10 @@ import (
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/iam/store"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -31,11 +34,11 @@ func init() {
// Service handles request as described by the pbs.GroupServiceServer interface.
type Service struct {
repoFn func() (*iam.Repository, error)
repoFn common.IamRepoFactory
}
// NewService returns a group service which handles group related requests to boundary.
func NewService(repo func() (*iam.Repository, error)) (Service, error) {
func NewService(repo common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
@@ -46,13 +49,13 @@ var _ pbs.GroupServiceServer = Service{}
// ListGroups implements the interface pbs.GroupServiceServer.
func (s Service) ListGroups(ctx context.Context, req *pbs.ListGroupsRequest) (*pbs.ListGroupsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
gl, err := s.listFromRepo(ctx, req.GetScopeId())
if err != nil {
return nil, err
@@ -65,13 +68,13 @@ func (s Service) ListGroups(ctx context.Context, req *pbs.ListGroupsRequest) (*p
// GetGroups implements the interface pbs.GroupServiceServer.
func (s Service) GetGroup(ctx context.Context, req *pbs.GetGroupRequest) (*pbs.GetGroupResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -82,14 +85,14 @@ func (s Service) GetGroup(ctx context.Context, req *pbs.GetGroupRequest) (*pbs.G
// CreateGroup implements the interface pbs.GroupServiceServer.
func (s Service) CreateGroup(ctx context.Context, req *pbs.CreateGroupRequest) (*pbs.CreateGroupResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
u, err := s.createInRepo(ctx, req.GetItem().GetScopeId(), req.GetItem())
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
}
@@ -99,13 +102,13 @@ func (s Service) CreateGroup(ctx context.Context, req *pbs.CreateGroupRequest) (
// UpdateGroup implements the interface pbs.GroupServiceServer.
func (s Service) UpdateGroup(ctx context.Context, req *pbs.UpdateGroupRequest) (*pbs.UpdateGroupResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -116,13 +119,13 @@ func (s Service) UpdateGroup(ctx context.Context, req *pbs.UpdateGroupRequest) (
// DeleteGroup implements the interface pbs.GroupServiceServer.
func (s Service) DeleteGroup(ctx context.Context, req *pbs.DeleteGroupRequest) (*pbs.DeleteGroupResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -132,13 +135,13 @@ func (s Service) DeleteGroup(ctx context.Context, req *pbs.DeleteGroupRequest) (
// AddGroupMembers implements the interface pbs.GroupServiceServer.
func (s Service) AddGroupMembers(ctx context.Context, req *pbs.AddGroupMembersRequest) (*pbs.AddGroupMembersResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateAddGroupMembersRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.AddMembers)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.addMembersInRepo(ctx, req.GetId(), req.GetMemberIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -148,13 +151,13 @@ func (s Service) AddGroupMembers(ctx context.Context, req *pbs.AddGroupMembersRe
// SetGroupMembers implements the interface pbs.GroupServiceServer.
func (s Service) SetGroupMembers(ctx context.Context, req *pbs.SetGroupMembersRequest) (*pbs.SetGroupMembersResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateSetGroupMembersRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.SetMembers)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.setMembersInRepo(ctx, req.GetId(), req.GetMemberIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -164,13 +167,13 @@ func (s Service) SetGroupMembers(ctx context.Context, req *pbs.SetGroupMembersRe
// RemoveGroupMembers implements the interface pbs.GroupServiceServer.
func (s Service) RemoveGroupMembers(ctx context.Context, req *pbs.RemoveGroupMembersRequest) (*pbs.RemoveGroupMembersResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateRemoveGroupMembersRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.RemoveMembers)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.removeMembersInRepo(ctx, req.GetId(), req.GetMemberIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -342,6 +345,45 @@ func (s Service) removeMembersInRepo(ctx context.Context, groupId string, userId
return toProto(out, m), nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.Group), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
scp, err := repo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
grp, _, err := repo.LookupGroup(ctx, id)
if err != nil {
res.Error = err
return res
}
if grp == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = grp.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *iam.Group, members []*iam.GroupMember) *pb.Group {
out := pb.Group{
Id: in.GetPublicId(),
@@ -142,7 +142,7 @@ func TestGet(t *testing.T) {
name: "Get a non existant Group",
req: &pbs.GetGroupRequest{Id: iam.GroupPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -168,7 +168,7 @@ func TestGet(t *testing.T) {
scopeId: pg.GetScopeId(),
req: &pbs.GetGroupRequest{Id: iam.GroupPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Project Scoped Wrong id prefix",
@@ -308,21 +308,8 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteGroupRequest{
Id: iam.GroupPrefix + "_doesntexis",
},
res: &pbs.DeleteGroupResponse{
Existed: false,
},
errCode: codes.OK,
},
{
name: "Delete bad org id",
scopeId: "o_doesntexist",
req: &pbs.DeleteGroupRequest{
Id: og.GetPublicId(),
},
res: &pbs.DeleteGroupResponse{
Existed: false,
},
errCode: codes.OK,
res: nil,
errCode: codes.PermissionDenied,
},
{
name: "Bad Group Id formatting",
@@ -350,21 +337,8 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteGroupRequest{
Id: iam.GroupPrefix + "_doesntexis",
},
res: &pbs.DeleteGroupResponse{
Existed: false,
},
errCode: codes.OK,
},
{
name: "Project Scoped Delete bad project id",
scopeId: "p_doesntexis",
req: &pbs.DeleteGroupRequest{
Id: pg.GetPublicId(),
},
res: &pbs.DeleteGroupResponse{
Existed: false,
},
errCode: codes.OK,
res: nil,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
@@ -393,8 +367,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteGroup(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
scopeId = pg.GetScopeId()
projReq := &pbs.DeleteGroupRequest{
@@ -405,8 +379,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteGroup(ctx, projReq)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -840,8 +814,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant group should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing Group",
req: &pbs.UpdateGroupRequest{
@@ -854,7 +826,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -12,6 +12,8 @@ import (
"github.com/hashicorp/boundary/internal/host/static/store"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
@@ -30,27 +32,31 @@ func init() {
type Service struct {
staticRepoFn common.StaticRepoFactory
iamRepoFn common.IamRepoFactory
}
var _ pbs.HostCatalogServiceServer = Service{}
// NewService returns a host catalog Service which handles host catalog related requests to boundary and uses the provided
// repositories for storage and retrieval.
func NewService(repoFn common.StaticRepoFactory) (Service, error) {
func NewService(repoFn common.StaticRepoFactory, iamRepoFn common.IamRepoFactory) (Service, error) {
if repoFn == nil {
return Service{}, fmt.Errorf("nil static repository provided")
}
return Service{staticRepoFn: repoFn}, nil
if iamRepoFn == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
return Service{staticRepoFn: repoFn, iamRepoFn: iamRepoFn}, nil
}
func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogsRequest) (*pbs.ListHostCatalogsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
ul, err := s.listFromRepo(ctx, authResults.Scope.GetId())
if err != nil {
return nil, err
@@ -63,13 +69,13 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs
// GetHostCatalog implements the interface pbs.HostCatalogServiceServer.
func (s Service) GetHostCatalog(ctx context.Context, req *pbs.GetHostCatalogRequest) (*pbs.GetHostCatalogResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -80,13 +86,13 @@ func (s Service) GetHostCatalog(ctx context.Context, req *pbs.GetHostCatalogRequ
// CreateHostCatalog implements the interface pbs.HostCatalogServiceServer.
func (s Service) CreateHostCatalog(ctx context.Context, req *pbs.CreateHostCatalogRequest) (*pbs.CreateHostCatalogResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
@@ -100,13 +106,13 @@ func (s Service) CreateHostCatalog(ctx context.Context, req *pbs.CreateHostCatal
// UpdateHostCatalog implements the interface pbs.HostCatalogServiceServer.
func (s Service) UpdateHostCatalog(ctx context.Context, req *pbs.UpdateHostCatalogRequest) (*pbs.UpdateHostCatalogResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -117,13 +123,13 @@ func (s Service) UpdateHostCatalog(ctx context.Context, req *pbs.UpdateHostCatal
// DeleteHostCatalog implements the interface pbs.HostCatalogServiceServer.
func (s Service) DeleteHostCatalog(ctx context.Context, req *pbs.DeleteHostCatalogRequest) (*pbs.DeleteHostCatalogResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -232,6 +238,50 @@ func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) {
return rows > 0, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
var parentId string
opts := []auth.Option{auth.WithType(resource.HostCatalog), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
iamRepo, err := s.iamRepoFn()
if err != nil {
res.Error = err
return res
}
scp, err := iamRepo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
repo, err := s.staticRepoFn()
if err != nil {
res.Error = err
return res
}
cat, err := repo.LookupCatalog(ctx, id)
if err != nil {
res.Error = err
return res
}
if cat == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = cat.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *static.HostCatalog) *pb.HostCatalog {
out := pb.HostCatalog{
Id: in.GetPublicId(),
@@ -17,6 +17,7 @@ import (
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers/host_catalogs"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/genproto/protobuf/field_mask"
@@ -29,7 +30,7 @@ import (
"github.com/stretchr/testify/require"
)
func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Scope, func() (*static.Repository, error)) {
func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Scope, common.StaticRepoFactory, common.IamRepoFactory) {
t.Helper()
require := require.New(t)
conn, _ := db.TestSetup(t, "postgres")
@@ -42,6 +43,9 @@ func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Sc
repoFn := func() (*static.Repository, error) {
return static.NewRepository(rw, rw, kms)
}
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
hc, err := static.NewHostCatalog(pRes.GetPublicId(), static.WithName("default"), static.WithDescription("default"))
require.NoError(err, "Couldn't get new catalog.")
@@ -50,12 +54,12 @@ func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Sc
hcRes, err := repo.CreateCatalog(context.Background(), hc)
require.NoError(err, "Couldn't persist new catalog.")
return hcRes, pRes, repoFn
return hcRes, pRes, repoFn, iamRepoFn
}
func TestGet(t *testing.T) {
t.Parallel()
hc, proj, repo := createDefaultHostCatalogAndRepo(t)
hc, proj, repo, iamRepoFn := createDefaultHostCatalogAndRepo(t)
toMerge := &pbs.GetHostCatalogRequest{
Id: hc.GetPublicId(),
}
@@ -87,7 +91,7 @@ func TestGet(t *testing.T) {
name: "Get a non existing Host Catalog",
req: &pbs.GetHostCatalogRequest{Id: static.HostCatalogPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -108,7 +112,7 @@ func TestGet(t *testing.T) {
req := proto.Clone(toMerge).(*pbs.GetHostCatalogRequest)
proto.Merge(req, tc.req)
s, err := host_catalogs.NewService(repo)
s, err := host_catalogs.NewService(repo, iamRepoFn)
require.NoError(t, err, "Couldn't create a new host catalog service.")
got, gErr := s.GetHostCatalog(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req)
@@ -127,6 +131,9 @@ func TestList(t *testing.T) {
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
iamRepoFn := func() (*iam.Repository, error) {
return iam.TestRepo(t, conn, wrapper), nil
}
repoFn := func() (*static.Repository, error) {
return static.NewRepository(rw, rw, kms)
}
@@ -186,21 +193,19 @@ func TestList(t *testing.T) {
res: &pbs.ListHostCatalogsResponse{},
errCode: codes.OK,
},
// TODO: When an auth method doesn't exist, we should return a 404 instead of an empty list.
{
name: "Unfound Catalogs",
scopeId: scope.Project.Prefix() + "_DoesntExis",
res: &pbs.ListHostCatalogsResponse{},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
s, err := host_catalogs.NewService(repoFn)
s, err := host_catalogs.NewService(repoFn, iamRepoFn)
require.NoError(err, "Couldn't create new auth_method service.")
got, gErr := s.ListHostCatalogs(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), &pbs.ListHostCatalogsRequest{})
got, gErr := s.ListHostCatalogs(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), &pbs.ListHostCatalogsRequest{ScopeId: tc.scopeId})
assert.Equal(tc.errCode, status.Code(gErr), "ListHostCatalogs() for scope %q got error %v, wanted %v", tc.scopeId, gErr, tc.errCode)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListHostCatalogs() for scope %q got response %q, wanted %q", tc.scopeId, got, tc.res)
})
@@ -210,9 +215,9 @@ func TestList(t *testing.T) {
func TestDelete(t *testing.T) {
t.Parallel()
require := require.New(t)
hc, proj, repo := createDefaultHostCatalogAndRepo(t)
hc, proj, repo, iamRepoFn := createDefaultHostCatalogAndRepo(t)
s, err := host_catalogs.NewService(repo)
s, err := host_catalogs.NewService(repo, iamRepoFn)
require.NoError(err, "Couldn't create a new host catalog service.")
cases := []struct {
@@ -239,32 +244,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteHostCatalogRequest{
Id: static.HostCatalogPrefix + "_doesntexis",
},
res: &pbs.DeleteHostCatalogResponse{
Existed: false,
},
errCode: codes.OK,
},
{
name: "Delete bad org id in HostCatalog",
scopeId: "o_doesntexis",
req: &pbs.DeleteHostCatalogRequest{
Id: hc.GetPublicId(),
},
res: &pbs.DeleteHostCatalogResponse{
Existed: false,
},
errCode: codes.OK,
},
{
name: "Delete bad project id in HostCatalog",
scopeId: "p_doesntexis",
req: &pbs.DeleteHostCatalogRequest{
Id: hc.GetPublicId(),
},
res: &pbs.DeleteHostCatalogResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad HostCatalog Id formatting",
@@ -289,9 +269,9 @@ func TestDelete(t *testing.T) {
func TestDelete_twice(t *testing.T) {
t.Parallel()
assert := assert.New(t)
hc, proj, repo := createDefaultHostCatalogAndRepo(t)
hc, proj, repo, iamRepoFn := createDefaultHostCatalogAndRepo(t)
s, err := host_catalogs.NewService(repo)
s, err := host_catalogs.NewService(repo, iamRepoFn)
require.NoError(t, err, "Couldn't create a new host catalog service.")
req := &pbs.DeleteHostCatalogRequest{
Id: hc.GetPublicId(),
@@ -301,17 +281,15 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteHostCatalog(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
t.Parallel()
require := require.New(t)
assert := assert.New(t)
defaultHc, proj, repo := createDefaultHostCatalogAndRepo(t)
defaultHc, proj, repo, iamRepoFn := createDefaultHostCatalogAndRepo(t)
defaultHcCreated, err := ptypes.Timestamp(defaultHc.GetCreateTime().GetTimestamp())
require.NoError(err, "Error converting proto to timestamp.")
require.NoError(t, err, "Error converting proto to timestamp.")
toMerge := &pbs.CreateHostCatalogRequest{}
cases := []struct {
@@ -323,6 +301,7 @@ func TestCreate(t *testing.T) {
{
name: "Create a valid HostCatalog",
req: &pbs.CreateHostCatalogRequest{Item: &pb.HostCatalog{
ScopeId: proj.GetPublicId(),
Name: &wrappers.StringValue{Value: "name"},
Description: &wrappers.StringValue{Value: "desc"},
Type: "static",
@@ -383,10 +362,11 @@ func TestCreate(t *testing.T) {
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
req := proto.Clone(toMerge).(*pbs.CreateHostCatalogRequest)
proto.Merge(req, tc.req)
s, err := host_catalogs.NewService(repo)
s, err := host_catalogs.NewService(repo, iamRepoFn)
require.NoError(err, "Failed to create a new host catalog service.")
got, gErr := s.CreateHostCatalog(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req)
@@ -417,25 +397,23 @@ func TestCreate(t *testing.T) {
func TestUpdate(t *testing.T) {
t.Parallel()
require := require.New(t)
assert := assert.New(t)
hc, proj, repoFn := createDefaultHostCatalogAndRepo(t)
tested, err := host_catalogs.NewService(repoFn)
require.NoError(err, "Failed to create a new host catalog service.")
hc, proj, repoFn, iamRepoFn := createDefaultHostCatalogAndRepo(t)
tested, err := host_catalogs.NewService(repoFn, iamRepoFn)
require.NoError(t, err, "Failed to create a new host catalog service.")
var version uint32 = 1
resetHostCatalog := func() {
version++
repo, err := repoFn()
require.NoError(err, "Couldn't create new static repo.")
require.NoError(t, err, "Couldn't create new static repo.")
hc, _, err = repo.UpdateCatalog(context.Background(), hc, version, []string{"Name", "Description"})
require.NoError(err, "Failed to reset host catalog.")
require.NoError(t, err, "Failed to reset host catalog.")
version++
}
hcCreated, err := ptypes.Timestamp(hc.GetCreateTime().GetTimestamp())
require.NoError(err, "Failed to convert proto to timestamp")
require.NoError(t, err, "Failed to convert proto to timestamp")
toMerge := &pbs.UpdateHostCatalogRequest{
Id: hc.GetPublicId(),
}
@@ -618,8 +596,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existing catalog should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing HostCatalog",
req: &pbs.UpdateHostCatalogRequest{
@@ -633,7 +609,7 @@ func TestUpdate(t *testing.T) {
Description: &wrappers.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -693,6 +669,7 @@ func TestUpdate(t *testing.T) {
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
tc.req.Item.Version = version
req := proto.Clone(toMerge).(*pbs.UpdateHostCatalogRequest)
@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
@@ -44,51 +45,14 @@ func NewService(repoFn common.StaticRepoFactory) (Service, error) {
return Service{staticRepoFn: repoFn}, nil
}
func (s Service) getHostStructs(ctx context.Context, id string, isHostSetId bool) (*static.HostCatalog, *static.HostSet, error) {
repo, err := s.staticRepoFn()
if err != nil {
return nil, nil, err
}
hostCatalogId := id
var hostSet *static.HostSet
if isHostSetId {
hostSet, _, err = repo.LookupSet(ctx, id)
if err != nil {
return nil, nil, err
}
if hostSet == nil {
return nil, nil, handlers.ForbiddenError()
}
hostCatalogId = hostSet.GetCatalogId()
}
hostCatalog, err := repo.LookupCatalog(ctx, hostCatalogId)
if err != nil {
return nil, nil, err
}
if hostCatalog == nil {
return nil, nil, handlers.ForbiddenError()
}
return hostCatalog, hostSet, nil
}
func (s Service) ListHostSets(ctx context.Context, req *pbs.ListHostSetsRequest) (*pbs.ListHostSetsResponse, error) {
if err := validateListRequest(req); err != nil {
return nil, err
}
hostCatalog, _, err := s.getHostStructs(ctx, req.GetHostCatalogId(), false)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.List),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetHostCatalogId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
hl, err := s.listFromRepo(ctx, req.GetHostCatalogId())
if err != nil {
return nil, err
@@ -104,21 +68,10 @@ func (s Service) GetHostSet(ctx context.Context, req *pbs.GetHostSetRequest) (*p
if err := validateGetRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.Read),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -132,21 +85,11 @@ func (s Service) CreateHostSet(ctx context.Context, req *pbs.CreateHostSetReques
if err := validateCreateRequest(req); err != nil {
return nil, err
}
hostCatalog, _, err := s.getHostStructs(ctx, req.GetItem().GetHostCatalogId(), false)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.Create),
)
cat, authResults := s.parentAndAuthResult(ctx, req.GetItem().GetHostCatalogId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
h, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem().GetHostCatalogId(), req.GetItem())
h, err := s.createInRepo(ctx, authResults.Scope.GetId(), cat.GetPublicId(), req.GetItem())
if err != nil {
return nil, err
}
@@ -162,22 +105,11 @@ func (s Service) UpdateHostSet(ctx context.Context, req *pbs.UpdateHostSetReques
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.Update),
)
cat, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), hostCatalog.GetPublicId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), cat.GetPublicId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
}
@@ -190,20 +122,10 @@ func (s Service) DeleteHostSet(ctx context.Context, req *pbs.DeleteHostSetReques
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.Delete),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId())
if err != nil {
return nil, err
@@ -216,20 +138,10 @@ func (s Service) AddHostSetHosts(ctx context.Context, req *pbs.AddHostSetHostsRe
if err := validateAddRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.AddHosts),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.AddHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.addInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -242,20 +154,10 @@ func (s Service) SetHostSetHosts(ctx context.Context, req *pbs.SetHostSetHostsRe
if err := validateSetRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.SetHosts),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.SetHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.setInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -268,20 +170,10 @@ func (s Service) RemoveHostSetHosts(ctx context.Context, req *pbs.RemoveHostSetH
if err := validateRemoveRequest(req); err != nil {
return nil, err
}
hostCatalog, hostSet, err := s.getHostStructs(ctx, req.GetId(), true)
if err != nil {
return nil, err
}
authResults := auth.Verify(ctx,
auth.WithScopeId(hostCatalog.GetScopeId()),
auth.WithId(hostSet.GetPublicId()),
auth.WithPin(hostCatalog.GetPublicId()),
auth.WithAction(action.RemoveHosts),
)
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.RemoveHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
g, err := s.removeInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion())
if err != nil {
return nil, err
@@ -447,6 +339,46 @@ func (s Service) removeInRepo(ctx context.Context, scopeId, setId string, hostId
return toProto(out, m), nil
}
func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Type) (*static.HostCatalog, auth.VerifyResults) {
res := auth.VerifyResults{}
repo, err := s.staticRepoFn()
if err != nil {
res.Error = err
return nil, res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.HostSet), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
default:
set, _, err := repo.LookupSet(ctx, id)
if err != nil {
res.Error = err
return nil, res
}
if set == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
parentId = set.GetCatalogId()
opts = append(opts, auth.WithId(id))
}
cat, err := repo.LookupCatalog(ctx, parentId)
if err != nil {
res.Error = err
return nil, res
}
if cat == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
opts = append(opts, auth.WithScopeId(cat.GetScopeId()), auth.WithPin(parentId))
return cat, auth.Verify(ctx, opts...)
}
func toProto(in *static.HostSet, hs []*static.Host) *pb.HostSet {
out := pb.HostSet{
Id: in.GetPublicId(),
@@ -3,7 +3,6 @@ package hosts
import (
"context"
"fmt"
"regexp"
"github.com/hashicorp/boundary/internal/auth"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
@@ -13,6 +12,8 @@ import (
"github.com/hashicorp/boundary/internal/host/static/store"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
@@ -20,7 +21,6 @@ import (
var (
maskManager handlers.MaskManager
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
)
func init() {
@@ -46,13 +46,13 @@ func NewService(repoFn common.StaticRepoFactory) (Service, error) {
}
func (s Service) ListHosts(ctx context.Context, req *pbs.ListHostsRequest) (*pbs.ListHostsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetHostCatalogId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
hl, err := s.listFromRepo(ctx, req.GetHostCatalogId())
if err != nil {
return nil, err
@@ -65,17 +65,13 @@ func (s Service) ListHosts(ctx context.Context, req *pbs.ListHostsRequest) (*pbs
// GetHost implements the interface pbs.HostServiceServer.
func (s Service) GetHost(ctx context.Context, req *pbs.GetHostRequest) (*pbs.GetHostResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
ct := host.SubtypeFromId(req.GetId())
if ct == host.UnknownSubtype {
return nil, handlers.InvalidArgumentErrorf("Invalid argument provided.", map[string]string{"id": "Improperly formatted identifier used."})
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -86,13 +82,13 @@ func (s Service) GetHost(ctx context.Context, req *pbs.GetHostRequest) (*pbs.Get
// CreateHost implements the interface pbs.HostServiceServer.
func (s Service) CreateHost(ctx context.Context, req *pbs.CreateHostRequest) (*pbs.CreateHostResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetItem().GetHostCatalogId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
h, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem().GetHostCatalogId(), req.GetItem())
if err != nil {
return nil, err
@@ -106,18 +102,14 @@ func (s Service) CreateHost(ctx context.Context, req *pbs.CreateHostRequest) (*p
// UpdateHost implements the interface pbs.HostServiceServer.
func (s Service) UpdateHost(ctx context.Context, req *pbs.UpdateHostRequest) (*pbs.UpdateHostResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
ct := host.SubtypeFromId(req.GetId())
if ct == host.UnknownSubtype {
return nil, handlers.InvalidArgumentErrorf("Invalid argument provided.", map[string]string{"id": "Improperly formatted identifier used."})
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
cat, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), cat.GetPublicId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
}
@@ -127,13 +119,13 @@ func (s Service) UpdateHost(ctx context.Context, req *pbs.UpdateHostRequest) (*p
// DeleteHost implements the interface pbs.HostServiceServer.
func (s Service) DeleteHost(ctx context.Context, req *pbs.DeleteHostRequest) (*pbs.DeleteHostResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
_, authResults := s.parentAndAuthResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId())
if err != nil {
return nil, err
@@ -190,7 +182,7 @@ func (s Service) createInRepo(ctx context.Context, scopeId, catalogId string, it
return toProto(out, nil)
}
func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []string, item *pb.Host) (*pb.Host, error) {
func (s Service) updateInRepo(ctx context.Context, scopeId, catalogId, id string, mask []string, item *pb.Host) (*pb.Host, error) {
ha := &pb.StaticHostAttributes{}
if err := handlers.StructToProto(item.GetAttributes(), ha); err != nil {
return nil, status.Errorf(codes.Internal, "Failed converting attributes to subtype proto: %s", err)
@@ -205,7 +197,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
if addr := ha.GetAddress(); addr != nil {
opts = append(opts, static.WithAddress(addr.GetValue()))
}
h, err := static.NewHost("ignored", opts...)
h, err := static.NewHost(catalogId, opts...)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to build host for update: %v.", err)
}
@@ -260,6 +252,46 @@ func (s Service) listFromRepo(ctx context.Context, catalogId string) ([]*pb.Host
return outHl, nil
}
func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Type) (*static.HostCatalog, auth.VerifyResults) {
res := auth.VerifyResults{}
repo, err := s.staticRepoFn()
if err != nil {
res.Error = err
return nil, res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.Host), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
default:
h, err := repo.LookupHost(ctx, id)
if err != nil {
res.Error = err
return nil, res
}
if h == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
parentId = h.GetCatalogId()
opts = append(opts, auth.WithId(id))
}
cat, err := repo.LookupCatalog(ctx, parentId)
if err != nil {
res.Error = err
return nil, res
}
if cat == nil {
res.Error = handlers.ForbiddenError()
return nil, res
}
opts = append(opts, auth.WithScopeId(cat.GetScopeId()), auth.WithPin(parentId))
return cat, auth.Verify(ctx, opts...)
}
func toProto(in *static.Host, members []*static.HostSet) (*pb.Host, error) {
out := pb.Host{
Id: in.GetPublicId(),
@@ -294,7 +326,14 @@ func toProto(in *static.Host, members []*static.HostSet) (*pb.Host, error) {
// * The type asserted by the ID and/or field is known
// * If relevant, the type derived from the id prefix matches what is claimed by the type field
func validateGetRequest(req *pbs.GetHostRequest) error {
return handlers.ValidateGetRequest(static.HostPrefix, req, handlers.NoopValidatorFn)
return handlers.ValidateGetRequest(static.HostPrefix, req, func() map[string]string {
badFields := map[string]string{}
ct := host.SubtypeFromId(req.GetId())
if ct == host.UnknownSubtype {
badFields["id"] = "Improperly formatted identifier used."
}
return badFields
})
}
func validateCreateRequest(req *pbs.CreateHostRequest) error {
@@ -323,6 +362,10 @@ func validateCreateRequest(req *pbs.CreateHostRequest) error {
func validateUpdateRequest(req *pbs.UpdateHostRequest) error {
return handlers.ValidateUpdateRequest(static.HostPrefix, req, req.GetItem(), func() map[string]string {
badFields := map[string]string{}
ct := host.SubtypeFromId(req.GetId())
if ct == host.UnknownSubtype {
badFields["id"] = "Improperly formatted identifier used."
}
if req.GetItem().GetType() != "" {
badFields["type"] = "This is a read only field and cannot be specified in an update request."
}
@@ -73,7 +73,7 @@ func TestGet(t *testing.T) {
name: "Get a non existing Host Set",
req: &pbs.GetHostRequest{Id: static.HostPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -208,10 +208,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteHostRequest{
Id: static.HostPrefix + "_doesntexis",
},
res: &pbs.DeleteHostResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad Host Id formatting",
@@ -259,8 +256,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteHost(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -666,7 +663,7 @@ func TestUpdate(t *testing.T) {
Description: &wrappers.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -8,12 +8,14 @@ import (
"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/db"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/roles"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/iam/store"
"github.com/hashicorp/boundary/internal/perms"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -33,11 +35,11 @@ func init() {
// Service handles request as described by the pbs.RoleServiceServer interface.
type Service struct {
repoFn func() (*iam.Repository, error)
repoFn common.IamRepoFactory
}
// NewService returns a role service which handles role related requests to boundary.
func NewService(repo func() (*iam.Repository, error)) (Service, error) {
func NewService(repo common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
@@ -48,13 +50,13 @@ var _ pbs.RoleServiceServer = Service{}
// ListRoles implements the interface pbs.RoleServiceServer.
func (s Service) ListRoles(ctx context.Context, req *pbs.ListRolesRequest) (*pbs.ListRolesResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
gl, err := s.listFromRepo(ctx, req.GetScopeId())
if err != nil {
return nil, err
@@ -67,13 +69,13 @@ func (s Service) ListRoles(ctx context.Context, req *pbs.ListRolesRequest) (*pbs
// GetRoles implements the interface pbs.RoleServiceServer.
func (s Service) GetRole(ctx context.Context, req *pbs.GetRoleRequest) (*pbs.GetRoleResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -84,14 +86,14 @@ func (s Service) GetRole(ctx context.Context, req *pbs.GetRoleRequest) (*pbs.Get
// CreateRole implements the interface pbs.RoleServiceServer.
func (s Service) CreateRole(ctx context.Context, req *pbs.CreateRoleRequest) (*pbs.CreateRoleResponse, error) {
authResults := auth.Verify(ctx)
if err := validateCreateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req, authResults.Scope); err != nil {
return nil, err
}
r, err := s.createInRepo(ctx, req.GetItem().GetScopeId(), req.GetItem())
r, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
}
@@ -101,13 +103,13 @@ func (s Service) CreateRole(ctx context.Context, req *pbs.CreateRoleRequest) (*p
// UpdateRole implements the interface pbs.RoleServiceServer.
func (s Service) UpdateRole(ctx context.Context, req *pbs.UpdateRoleRequest) (*pbs.UpdateRoleResponse, error) {
authResults := auth.Verify(ctx)
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req, authResults.Scope); err != nil {
return nil, err
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -118,13 +120,13 @@ func (s Service) UpdateRole(ctx context.Context, req *pbs.UpdateRoleRequest) (*p
// DeleteRole implements the interface pbs.RoleServiceServer.
func (s Service) DeleteRole(ctx context.Context, req *pbs.DeleteRoleRequest) (*pbs.DeleteRoleResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -134,14 +136,14 @@ func (s Service) DeleteRole(ctx context.Context, req *pbs.DeleteRoleRequest) (*p
// AddRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipalsRequest) (*pbs.AddRolePrincipalsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateAddRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.addPrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.AddPrincipals)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.addPrinciplesInRepo(ctx, req.GetId(), req.GetPrincipalIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -151,14 +153,14 @@ func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipa
// SetRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipalsRequest) (*pbs.SetRolePrincipalsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateSetRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.setPrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.SetPrincipals)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.setPrinciplesInRepo(ctx, req.GetId(), req.GetPrincipalIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -168,14 +170,14 @@ func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipa
// RemoveRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePrincipalsRequest) (*pbs.RemoveRolePrincipalsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateRemoveRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.removePrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.RemovePrincipals)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.removePrinciplesInRepo(ctx, req.GetId(), req.GetPrincipalIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -185,14 +187,14 @@ func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePr
// AddRoleGrants implements the interface pbs.RoleServiceServer.
func (s Service) AddRoleGrants(ctx context.Context, req *pbs.AddRoleGrantsRequest) (*pbs.AddRoleGrantsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateAddRoleGrantsRequest(req); err != nil {
return nil, err
}
r, err := s.addGrantsInRepo(ctx, req.GetRoleId(), req.GetGrantStrings(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.AddGrants)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.addGrantsInRepo(ctx, req.GetId(), req.GetGrantStrings(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -202,14 +204,14 @@ func (s Service) AddRoleGrants(ctx context.Context, req *pbs.AddRoleGrantsReques
// SetRoleGrants implements the interface pbs.RoleServiceServer.
func (s Service) SetRoleGrants(ctx context.Context, req *pbs.SetRoleGrantsRequest) (*pbs.SetRoleGrantsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateSetRoleGrantsRequest(req); err != nil {
return nil, err
}
r, err := s.setGrantsInRepo(ctx, req.GetRoleId(), req.GetGrantStrings(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.SetGrants)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.setGrantsInRepo(ctx, req.GetId(), req.GetGrantStrings(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -219,14 +221,14 @@ func (s Service) SetRoleGrants(ctx context.Context, req *pbs.SetRoleGrantsReques
// RemoveRoleGrants implements the interface pbs.RoleServiceServer.
func (s Service) RemoveRoleGrants(ctx context.Context, req *pbs.RemoveRoleGrantsRequest) (*pbs.RemoveRoleGrantsResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateRemoveRoleGrantsRequest(req); err != nil {
return nil, err
}
r, err := s.removeGrantsInRepo(ctx, req.GetRoleId(), req.GetGrantStrings(), req.GetVersion())
authResults := s.authResult(ctx, req.GetId(), action.RemoveGrants)
if authResults.Error != nil {
return nil, authResults.Error
}
r, err := s.removeGrantsInRepo(ctx, req.GetId(), req.GetGrantStrings(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -468,6 +470,45 @@ func (s Service) removeGrantsInRepo(ctx context.Context, roleId string, grants [
return toProto(out, pr, roleGrants), nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.Role), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
scp, err := repo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
r, _, _, err := repo.LookupRole(ctx, id)
if err != nil {
res.Error = err
return res
}
if r == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = r.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *iam.Role, principals []iam.PrincipalRole, grants []*iam.RoleGrant) *pb.Role {
out := pb.Role{
Id: in.GetPublicId(),
@@ -530,7 +571,7 @@ func validateGetRequest(req *pbs.GetRoleRequest) error {
return handlers.ValidateGetRequest(iam.RolePrefix, req, handlers.NoopValidatorFn)
}
func validateCreateRequest(req *pbs.CreateRoleRequest, s *scopes.ScopeInfo) error {
func validateCreateRequest(req *pbs.CreateRoleRequest) error {
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
badFields := map[string]string{}
item := req.GetItem()
@@ -539,8 +580,8 @@ func validateCreateRequest(req *pbs.CreateRoleRequest, s *scopes.ScopeInfo) erro
scope.Global.String() != item.GetScopeId() {
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() {
if item.GetGrantScopeId() != nil && handlers.ValidId(scope.Project.Prefix(), item.GetScopeId()) {
if item.GetGrantScopeId().GetValue() != item.GetScopeId() {
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
}
}
@@ -554,7 +595,7 @@ func validateCreateRequest(req *pbs.CreateRoleRequest, s *scopes.ScopeInfo) erro
})
}
func validateUpdateRequest(req *pbs.UpdateRoleRequest, s *scopes.ScopeInfo) error {
func validateUpdateRequest(req *pbs.UpdateRoleRequest) error {
return handlers.ValidateUpdateRequest(iam.RolePrefix, req, req.GetItem(), func() map[string]string {
badFields := map[string]string{}
if req.GetItem().GetPrincipalIds() != nil {
@@ -569,8 +610,8 @@ func validateUpdateRequest(req *pbs.UpdateRoleRequest, s *scopes.ScopeInfo) erro
if req.GetItem().GetGrantStrings() != nil {
badFields["grant_strings"] = "This is a read only field and cannot be specified in an update request."
}
if req.GetItem().GetGrantScopeId() != nil && s.GetType() == scope.Project.String() {
if req.GetItem().GetGrantScopeId().Value != s.GetId() {
if req.GetItem().GetGrantScopeId() != nil && handlers.ValidId(scope.Project.Prefix(), req.GetItem().GetScopeId()) {
if req.GetItem().GetGrantScopeId().GetValue() != req.GetItem().GetScopeId() {
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
}
}
@@ -595,7 +636,7 @@ func validateListRequest(req *pbs.ListRolesRequest) error {
func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -617,7 +658,7 @@ func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -636,7 +677,7 @@ func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error {
func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -653,7 +694,7 @@ func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) e
func validateAddRoleGrantsRequest(req *pbs.AddRoleGrantsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -670,7 +711,7 @@ func validateAddRoleGrantsRequest(req *pbs.AddRoleGrantsRequest) error {
func validateSetRoleGrantsRequest(req *pbs.SetRoleGrantsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -684,7 +725,7 @@ func validateSetRoleGrantsRequest(req *pbs.SetRoleGrantsRequest) error {
func validateRemoveRoleGrantsRequest(req *pbs.RemoveRoleGrantsRequest) error {
badFields := map[string]string{}
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
if !handlers.ValidId(iam.RolePrefix, req.GetId()) {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == 0 {
@@ -117,7 +117,7 @@ func TestGet(t *testing.T) {
name: "Get a non existant Role",
req: &pbs.GetRoleRequest{Id: iam.RolePrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -143,7 +143,7 @@ func TestGet(t *testing.T) {
scopeId: pr.GetScopeId(),
req: &pbs.GetRoleRequest{Id: iam.RolePrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Project Scoped Wrong id prefix",
@@ -284,10 +284,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteRoleRequest{
Id: iam.RolePrefix + "_doesntexis",
},
res: &pbs.DeleteRoleResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad Role Id formatting",
@@ -315,10 +312,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteRoleRequest{
Id: iam.RolePrefix + "_doesntexis",
},
res: &pbs.DeleteRoleResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
}
for _, tc := range cases {
@@ -346,8 +340,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteRole(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
projReq := &pbs.DeleteRoleRequest{
Id: pr.GetPublicId(),
@@ -357,8 +351,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteRole(ctx, projReq)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
@@ -823,8 +817,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant role should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing Role",
req: &pbs.UpdateRoleRequest{
@@ -837,7 +829,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -1033,7 +1025,7 @@ func TestAddPrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.AddRolePrincipalsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
PrincipalIds: append(tc.addUsers, tc.addGroups...),
}
@@ -1062,7 +1054,7 @@ func TestAddPrincipal(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.AddRolePrincipalsRequest{
RoleId: "bad id",
Id: "bad id",
Version: role.GetVersion(),
},
errCode: codes.InvalidArgument,
@@ -1159,7 +1151,7 @@ func TestSetPrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.SetRolePrincipalsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
PrincipalIds: append(tc.setUsers, tc.setGroups...),
}
@@ -1188,7 +1180,7 @@ func TestSetPrincipal(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.SetRolePrincipalsRequest{
RoleId: "bad id",
Id: "bad id",
Version: role.GetVersion(),
},
errCode: codes.InvalidArgument,
@@ -1297,7 +1289,7 @@ func TestRemovePrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.RemoveRolePrincipalsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
PrincipalIds: append(tc.removeUsers, tc.removeGroups...),
}
@@ -1326,7 +1318,7 @@ func TestRemovePrincipal(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.AddRolePrincipalsRequest{
RoleId: "bad id",
Id: "bad id",
Version: role.GetVersion(),
},
errCode: codes.InvalidArgument,
@@ -1406,7 +1398,7 @@ func TestAddGrants(t *testing.T) {
_ = iam.TestRoleGrant(t, conn, role.GetPublicId(), e)
}
req := &pbs.AddRoleGrantsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
}
scopeId := o.GetPublicId()
@@ -1435,7 +1427,7 @@ func TestAddGrants(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.AddRoleGrantsRequest{
RoleId: "bad id",
Id: "bad id",
GrantStrings: []string{"id=*;actions=create"},
Version: role.GetVersion(),
},
@@ -1504,7 +1496,7 @@ func TestSetGrants(t *testing.T) {
_ = iam.TestRoleGrant(t, conn, role.GetPublicId(), e)
}
req := &pbs.SetRoleGrantsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
}
scopeId := o.GetPublicId()
@@ -1535,7 +1527,7 @@ func TestSetGrants(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.SetRoleGrantsRequest{
RoleId: "bad id",
Id: "bad id",
GrantStrings: []string{"id=*;actions=create"},
Version: role.GetVersion(),
},
@@ -1603,7 +1595,7 @@ func TestRemoveGrants(t *testing.T) {
_ = iam.TestRoleGrant(t, conn, role.GetPublicId(), e)
}
req := &pbs.RemoveRoleGrantsRequest{
RoleId: role.GetPublicId(),
Id: role.GetPublicId(),
Version: role.GetVersion(),
}
scopeId := o.GetPublicId()
@@ -1635,7 +1627,7 @@ func TestRemoveGrants(t *testing.T) {
{
name: "Bad Role Id",
req: &pbs.RemoveRoleGrantsRequest{
RoleId: "bad id",
Id: "bad id",
GrantStrings: []string{"id=*;actions=create"},
Version: role.GetVersion(),
},
@@ -3,7 +3,6 @@ package scopes
import (
"context"
"fmt"
"regexp"
"sort"
"strings"
@@ -15,6 +14,8 @@ import (
"github.com/hashicorp/boundary/internal/iam/store"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -23,7 +24,6 @@ import (
var (
maskManager handlers.MaskManager
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
)
func init() {
@@ -35,7 +35,7 @@ func init() {
// Service handles requests as described by the pbs.ScopeServiceServer interface.
type Service struct {
repo common.IamRepoFactory
repoFn common.IamRepoFactory
}
// NewService returns a project service which handles project related requests to boundary.
@@ -43,7 +43,7 @@ func NewService(repo common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
return Service{repo: repo}, nil
return Service{repoFn: repo}, nil
}
var _ pbs.ScopeServiceServer = Service{}
@@ -53,14 +53,13 @@ func (s Service) ListScopes(ctx context.Context, req *pbs.ListScopesRequest) (*p
if req.GetScopeId() == "" {
req.ScopeId = scope.Global.String()
}
authResults := auth.Verify(ctx, auth.WithScopeId(req.GetScopeId()))
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
pl, err := s.listFromRepo(ctx, authResults.Scope.GetId())
if err != nil {
return nil, err
@@ -75,13 +74,13 @@ func (s Service) ListScopes(ctx context.Context, req *pbs.ListScopesRequest) (*p
// GetScopes implements the interface pbs.ScopeServiceServer.
func (s Service) GetScope(ctx context.Context, req *pbs.GetScopeRequest) (*pbs.GetScopeResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
p, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -95,7 +94,7 @@ func (s Service) CreateScope(ctx context.Context, req *pbs.CreateScopeRequest) (
if err := validateCreateRequest(req); err != nil {
return nil, err
}
authResults := auth.Verify(ctx, auth.WithScopeId(req.GetItem().GetScopeId()))
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -109,13 +108,13 @@ func (s Service) CreateScope(ctx context.Context, req *pbs.CreateScopeRequest) (
// UpdateScope implements the interface pbs.ScopeServiceServer.
func (s Service) UpdateScope(ctx context.Context, req *pbs.UpdateScopeRequest) (*pbs.UpdateScopeResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
p, err := s.updateInRepo(ctx, authResults.Scope, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -126,13 +125,13 @@ func (s Service) UpdateScope(ctx context.Context, req *pbs.UpdateScopeRequest) (
// DeleteScope implements the interface pbs.ScopeServiceServer.
func (s Service) DeleteScope(ctx context.Context, req *pbs.DeleteScopeRequest) (*pbs.DeleteScopeResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -141,7 +140,7 @@ func (s Service) DeleteScope(ctx context.Context, req *pbs.DeleteScopeRequest) (
}
func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Scope, error) {
repo, err := s.repo()
repo, err := s.repoFn()
if err != nil {
return nil, err
}
@@ -178,7 +177,7 @@ func (s Service) createInRepo(ctx context.Context, authResults auth.VerifyResult
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to build new scope for creation: %v.", err)
}
repo, err := s.repo()
repo, err := s.repoFn()
if err != nil {
return nil, err
}
@@ -218,7 +217,7 @@ func (s Service) updateInRepo(ctx context.Context, parentScope *scopes.ScopeInfo
if len(dbMask) == 0 {
return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
}
repo, err := s.repo()
repo, err := s.repoFn()
if err != nil {
return nil, err
}
@@ -233,7 +232,7 @@ func (s Service) updateInRepo(ctx context.Context, parentScope *scopes.ScopeInfo
}
func (s Service) deleteFromRepo(ctx context.Context, scopeId string) (bool, error) {
repo, err := s.repo()
repo, err := s.repoFn()
if err != nil {
return false, err
}
@@ -253,7 +252,7 @@ func SortScopes(scps []*pb.Scope) {
}
func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Scope, error) {
repo, err := s.repo()
repo, err := s.repoFn()
if err != nil {
return nil, err
}
@@ -279,6 +278,45 @@ func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Scope,
return outPl, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.Scope), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
s, err := repo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if s == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
s, err := repo.LookupScope(ctx, id)
if err != nil {
res.Error = err
return res
}
if s == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = s.GetParentId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func ToProto(in *iam.Scope) *pb.Scope {
out := pb.Scope{
Id: in.GetPublicId(),
@@ -307,11 +345,11 @@ func validateGetRequest(req *pbs.GetScopeRequest) error {
switch {
case id == "global":
case strings.HasPrefix(id, scope.Org.Prefix()):
if !validId(id, scope.Org.Prefix()+"_") {
if !handlers.ValidId(scope.Org.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
case strings.HasPrefix(id, scope.Project.Prefix()):
if !validId(id, scope.Project.Prefix()+"_") {
if !handlers.ValidId(scope.Project.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
default:
@@ -326,8 +364,8 @@ 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.GetScopeId() == "" {
badFields["scope_id"] = "Missing value for scope_id"
}
if item.GetId() != "" {
badFields["id"] = "This is a read only field."
@@ -353,11 +391,11 @@ func validateUpdateRequest(req *pbs.UpdateScopeRequest) error {
switch {
case id == "global":
case strings.HasPrefix(id, scope.Org.Prefix()):
if !validId(id, scope.Org.Prefix()+"_") {
if !handlers.ValidId(scope.Org.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
case strings.HasPrefix(id, scope.Project.Prefix()):
if !validId(id, scope.Project.Prefix()+"_") {
if !handlers.ValidId(scope.Project.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
default:
@@ -402,11 +440,11 @@ func validateDeleteRequest(req *pbs.DeleteScopeRequest) error {
case id == "global":
badFields["id"] = "Invalid to delete the global scope."
case strings.HasPrefix(id, scope.Org.Prefix()):
if !validId(id, scope.Org.Prefix()+"_") {
if !handlers.ValidId(scope.Org.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
case strings.HasPrefix(id, scope.Project.Prefix()):
if !validId(id, scope.Project.Prefix()+"_") {
if !handlers.ValidId(scope.Project.Prefix(), id) {
badFields["id"] = "Invalidly formatted scope id."
}
default:
@@ -425,11 +463,3 @@ func validateListRequest(req *pbs.ListScopesRequest) error {
}
return nil
}
func validId(id, prefix string) bool {
if !strings.HasPrefix(id, prefix) {
return false
}
id = strings.TrimPrefix(id, prefix)
return !reInvalidID.Match([]byte(id))
}
@@ -101,7 +101,7 @@ func TestGet(t *testing.T) {
scopeId: "global",
req: &pbs.GetScopeRequest{Id: "o_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Get an existing project",
@@ -115,7 +115,7 @@ func TestGet(t *testing.T) {
scopeId: org.GetPublicId(),
req: &pbs.GetScopeRequest{Id: "p_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -311,10 +311,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteScopeRequest{
Id: "p_doesntexis",
},
res: &pbs.DeleteScopeResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad Project Id formatting",
@@ -342,10 +339,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteScopeRequest{
Id: "p_doesntexis",
},
res: &pbs.DeleteScopeResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad Org Id formatting",
@@ -382,8 +376,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteScope(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
ctx = auth.DisabledAuthTestContext(auth.WithScopeId(scope.Global.String()))
req = &pbs.DeleteScopeRequest{
@@ -393,8 +387,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteScope(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -811,8 +805,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant project should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing Project",
scopeId: org.GetPublicId(),
@@ -826,7 +818,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",
@@ -9,11 +9,12 @@ import (
"github.com/hashicorp/boundary/internal/db"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/targets"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/store"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -33,17 +34,17 @@ func init() {
// Service handles request as described by the pbs.TargetServiceServer interface.
type Service struct {
repoFn func() (*target.Repository, error)
iamRepoFn func() (*iam.Repository, error)
repoFn common.TargetRepoFactory
iamRepoFn common.IamRepoFactory
}
// NewService returns a target service which handles target related requests to boundary.
func NewService(repoFn func() (*target.Repository, error), iamRepoFn func() (*iam.Repository, error)) (Service, error) {
func NewService(repoFn common.TargetRepoFactory, iamRepoFn common.IamRepoFactory) (Service, error) {
if repoFn == nil {
return Service{}, fmt.Errorf("nil target repository provided")
}
if iamRepoFn == nil {
return Service{}, fmt.Errorf("nil target repository provided")
return Service{}, fmt.Errorf("nil iam repository provided")
}
return Service{repoFn: repoFn, iamRepoFn: iamRepoFn}, nil
}
@@ -55,7 +56,7 @@ func (s Service) ListTargets(ctx context.Context, req *pbs.ListTargetsRequest) (
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.collectionAuthVerify(ctx, req.GetScopeId(), action.List)
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -74,7 +75,7 @@ func (s Service) GetTarget(ctx context.Context, req *pbs.GetTargetRequest) (*pbs
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.Read)
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -91,7 +92,7 @@ func (s Service) CreateTarget(ctx context.Context, req *pbs.CreateTargetRequest)
if err := validateCreateRequest(req); err != nil {
return nil, err
}
authResults := s.collectionAuthVerify(ctx, req.GetItem().GetScopeId(), action.Create)
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -108,7 +109,7 @@ func (s Service) UpdateTarget(ctx context.Context, req *pbs.UpdateTargetRequest)
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.Update)
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -125,7 +126,7 @@ func (s Service) DeleteTarget(ctx context.Context, req *pbs.DeleteTargetRequest)
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.Delete)
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -141,7 +142,7 @@ func (s Service) AddTargetHostSets(ctx context.Context, req *pbs.AddTargetHostSe
if err := validateAddRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.AddHostSets)
authResults := s.authResult(ctx, req.GetId(), action.AddHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -158,7 +159,7 @@ func (s Service) SetTargetHostSets(ctx context.Context, req *pbs.SetTargetHostSe
if err := validateSetRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.SetHostSets)
authResults := s.authResult(ctx, req.GetId(), action.SetHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -175,7 +176,7 @@ func (s Service) RemoveTargetHostSets(ctx context.Context, req *pbs.RemoveTarget
if err := validateRemoveRequest(req); err != nil {
return nil, err
}
authResults := s.authVerify(ctx, req.GetId(), action.RemoveHostSets)
authResults := s.authResult(ctx, req.GetId(), action.RemoveHostSets)
if authResults.Error != nil {
return nil, authResults.Error
}
@@ -348,48 +349,48 @@ func (s Service) removeInRepo(ctx context.Context, targetId string, hostSetIds [
return toProto(out, m), nil
}
func (s Service) collectionAuthVerify(ctx context.Context, parentId string, a action.Type) auth.VerifyResults {
var res auth.VerifyResults
iamRep, err := s.iamRepoFn()
if err != nil {
res.Error = err
return res
}
sc, err := iamRep.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if sc == nil {
res.Error = handlers.ForbiddenError()
return res
}
authResults := auth.Verify(ctx,
auth.WithScopeId(sc.GetPublicId()),
auth.WithAction(a))
return authResults
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
func (s Service) authVerify(ctx context.Context, id string, a action.Type) auth.VerifyResults {
var res auth.VerifyResults
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
var parentId string
opts := []auth.Option{auth.WithType(resource.Target), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
iamRepo, err := s.iamRepoFn()
if err != nil {
res.Error = err
return res
}
scp, err := iamRepo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
t, _, err := repo.LookupTarget(ctx, id)
if err != nil {
res.Error = err
return res
}
if t == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = t.GetScopeId()
opts = append(opts, auth.WithId(id))
}
tar, _, err := repo.LookupTarget(ctx, id)
if err != nil {
res.Error = err
return res
}
if tar == nil {
res.Error = handlers.ForbiddenError()
return res
}
authResults := auth.Verify(ctx,
auth.WithScopeId(tar.GetScopeId()),
auth.WithAction(a))
return authResults
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in target.Target, m []*target.TargetSet) *pb.Target {
@@ -11,7 +11,10 @@ import (
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/iam/store"
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -31,11 +34,11 @@ func init() {
// Service handles request as described by the pbs.UserServiceServer interface.
type Service struct {
repoFn func() (*iam.Repository, error)
repoFn common.IamRepoFactory
}
// NewService returns a user service which handles user related requests to boundary.
func NewService(repo func() (*iam.Repository, error)) (Service, error) {
func NewService(repo common.IamRepoFactory) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
@@ -46,13 +49,13 @@ var _ pbs.UserServiceServer = Service{}
// ListUsers implements the interface pbs.UserServiceServer.
func (s Service) ListUsers(ctx context.Context, req *pbs.ListUsersRequest) (*pbs.ListUsersResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateListRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetScopeId(), action.List)
if authResults.Error != nil {
return nil, authResults.Error
}
ul, err := s.listFromRepo(ctx, req.GetScopeId())
if err != nil {
return nil, err
@@ -65,13 +68,13 @@ func (s Service) ListUsers(ctx context.Context, req *pbs.ListUsersRequest) (*pbs
// GetUsers implements the interface pbs.UserServiceServer.
func (s Service) GetUser(ctx context.Context, req *pbs.GetUserRequest) (*pbs.GetUserResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Read)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -82,13 +85,13 @@ func (s Service) GetUser(ctx context.Context, req *pbs.GetUserRequest) (*pbs.Get
// CreateUser implements the interface pbs.UserServiceServer.
func (s Service) CreateUser(ctx context.Context, req *pbs.CreateUserRequest) (*pbs.CreateUserResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetItem().GetScopeId(), action.Create)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
if err != nil {
return nil, err
@@ -99,13 +102,13 @@ func (s Service) CreateUser(ctx context.Context, req *pbs.CreateUserRequest) (*p
// UpdateUser implements the interface pbs.UserServiceServer.
func (s Service) UpdateUser(ctx context.Context, req *pbs.UpdateUserRequest) (*pbs.UpdateUserResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateUpdateRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Update)
if authResults.Error != nil {
return nil, authResults.Error
}
u, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
if err != nil {
return nil, err
@@ -116,13 +119,13 @@ func (s Service) UpdateUser(ctx context.Context, req *pbs.UpdateUserRequest) (*p
// DeleteUser implements the interface pbs.UserServiceServer.
func (s Service) DeleteUser(ctx context.Context, req *pbs.DeleteUserRequest) (*pbs.DeleteUserResponse, error) {
authResults := auth.Verify(ctx)
if authResults.Error != nil {
return nil, authResults.Error
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
authResults := s.authResult(ctx, req.GetId(), action.Delete)
if authResults.Error != nil {
return nil, authResults.Error
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
@@ -237,6 +240,45 @@ func (s Service) listFromRepo(ctx context.Context, orgId string) ([]*pb.User, er
return outUl, nil
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
res := auth.VerifyResults{}
repo, err := s.repoFn()
if err != nil {
res.Error = err
return res
}
var parentId string
opts := []auth.Option{auth.WithType(resource.User), auth.WithAction(a)}
switch a {
case action.List, action.Create:
parentId = id
scp, err := repo.LookupScope(ctx, parentId)
if err != nil {
res.Error = err
return res
}
if scp == nil {
res.Error = handlers.ForbiddenError()
return res
}
default:
u, err := repo.LookupUser(ctx, id)
if err != nil {
res.Error = err
return res
}
if u == nil {
res.Error = handlers.ForbiddenError()
return res
}
parentId = u.GetScopeId()
opts = append(opts, auth.WithId(id))
}
opts = append(opts, auth.WithScopeId(parentId))
return auth.Verify(ctx, opts...)
}
func toProto(in *iam.User) *pb.User {
out := pb.User{
Id: in.GetPublicId(),
@@ -75,7 +75,7 @@ func TestGet(t *testing.T) {
name: "Get a non existant User",
req: &pbs.GetUserRequest{Id: iam.UserPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
errCode: codes.PermissionDenied,
},
{
name: "Wrong id prefix",
@@ -194,10 +194,7 @@ func TestDelete(t *testing.T) {
req: &pbs.DeleteUserRequest{
Id: iam.UserPrefix + "_doesntexis",
},
res: &pbs.DeleteUserResponse{
Existed: false,
},
errCode: codes.OK,
errCode: codes.PermissionDenied,
},
{
name: "Bad User Id formatting",
@@ -233,8 +230,8 @@ func TestDelete_twice(t *testing.T) {
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteUser(ctx, req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
assert.Error(gErr, "Second attempt")
assert.Equal(codes.PermissionDenied, status.Code(gErr), "Expected permission denied for the second delete.")
}
func TestCreate(t *testing.T) {
@@ -517,8 +514,6 @@ func TestUpdate(t *testing.T) {
},
errCode: codes.OK,
},
// TODO: Updating a non existant user should result in a NotFound exception but currently results in
// the repoFn returning an internal error.
{
name: "Update a Non Existing User",
req: &pbs.UpdateUserRequest{
@@ -531,7 +526,7 @@ func TestUpdate(t *testing.T) {
Description: &wrapperspb.StringValue{Value: "desc"},
},
},
errCode: codes.Internal,
errCode: codes.PermissionDenied,
},
{
name: "Cant change Id",