Adding principal custom methods to roles handler. (#180)

* Adding Add/Set/Remove principals API calls.

* Add SDK custom methods.

Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com>
pull/176/head
Todd Knight 6 years ago committed by GitHub
parent 136e923583
commit 1ddc59f81e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,107 @@
package roles
import (
"context"
"fmt"
"github.com/hashicorp/watchtower/api"
)
func (s Role) AddPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in AddPrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:add-principals", s.Id), body)
if err != nil {
return nil, nil, fmt.Errorf("error creating AddPrincipals request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during AddPrincipals call: %w", err)
}
target := new(Role)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding AddPrincipals repsonse: %w", err)
}
target.Client = s.Client
return target, apiErr, nil
}
func (s Role) SetPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in SetPrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:set-principals", s.Id), body)
if err != nil {
return nil, nil, fmt.Errorf("error creating SetPrincipals request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during SetPrincipals call: %w", err)
}
target := new(Role)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding SetPrincipals repsonse: %w", err)
}
target.Client = s.Client
return target, apiErr, nil
}
func (s Role) RemovePrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in RemovePrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:remove-principals", s.Id), body)
if err != nil {
return nil, nil, fmt.Errorf("error creating RemovePrincipals request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during RemovePrincipals call: %w", err)
}
target := new(Role)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding RemovePrincipals repsonse: %w", err)
}
target.Client = s.Client
return target, apiErr, nil
}

@ -31,6 +31,18 @@ type Role struct {
UpdatedTime time.Time `json:"updated_time,omitempty"`
// Whether the resource is disabled
Disabled *bool `json:"disabled,omitempty"`
// The version can be used in subsiquent write requests to ensure this resource
// has not changed and to fail the write if it has.
// Output only.
Version *uint32 `json:"version,omitempty"`
// The principals that are assigned this role.
// Output only.
UserIds []string `json:"user_ids,omitempty"`
// Output only.
GroupIds []string `json:"group_ids,omitempty"`
// The grants that this role provides for it's principals.
// Output only.
Grants []string `json:"grants,omitempty"`
}
func (s *Role) SetDefault(key string) {

@ -7,8 +7,10 @@ import (
"testing"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/groups"
"github.com/hashicorp/watchtower/api/roles"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/api/users"
"github.com/hashicorp/watchtower/internal/iam"
"github.com/hashicorp/watchtower/internal/servers/controller"
"github.com/stretchr/testify/assert"
@ -16,6 +18,7 @@ import (
)
type roleCrud interface {
CreateGroup(context.Context, *groups.Group) (*groups.Group, *api.Error, error)
CreateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
ReadRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
UpdateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
@ -23,6 +26,83 @@ type roleCrud interface {
ListRoles(ctx context.Context) ([]*roles.Role, *api.Error, error)
}
func TestCustom(t *testing.T) {
tc := controller.NewTestController(t, nil)
defer tc.Shutdown()
client := tc.Client()
org := &scopes.Organization{
Client: client,
}
proj, apiErr, err := org.CreateProject(context.Background(), &scopes.Project{})
require.NoError(t, err)
require.Nil(t, apiErr)
user, apiErr, err := org.CreateUser(context.Background(), &users.User{})
require.NoError(t, err)
require.Nil(t, apiErr)
cases := []struct {
name string
scope roleCrud
}{
{
name: "org",
scope: org,
},
{
name: "proj",
scope: proj,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
require := require.New(t)
ctx := context.Background()
g, apiErr, err := tc.scope.CreateGroup(ctx, &groups.Group{})
require.NoError(err)
require.Nil(apiErr)
require.NotNil(g)
r, apiErr, err := tc.scope.CreateRole(ctx, &roles.Role{Name: api.String("foo")})
require.NoError(err)
require.Nil(apiErr)
require.NotNil(r)
updatedRole, apiErr, err := r.AddPrincipals(ctx, []string{g.Id}, nil)
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Contains(t, updatedRole.GroupIds, g.Id)
assert.Empty(t, updatedRole.UserIds)
r = updatedRole
updatedRole, apiErr, err = r.SetPrincipals(ctx, nil, []string{user.Id})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Empty(t, updatedRole.GroupIds)
assert.Contains(t, updatedRole.UserIds, user.Id)
r = updatedRole
updatedRole, apiErr, err = r.RemovePrincipals(ctx, nil, []string{user.Id})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Empty(t, updatedRole.GroupIds)
assert.Empty(t, updatedRole.UserIds)
})
}
}
func errorMessage(in *api.Error) string {
if in == nil {
return ""
}
return *in.Message
}
func TestRole_List(t *testing.T) {
assert := assert.New(t)
tc := controller.NewTestController(t, nil)

@ -33,7 +33,7 @@ type Options struct {
newOplogMsgs *[]*oplog.Message
// WithVersion must be accessible from other packages
WithVersion int
WithVersion uint32
withSkipVetForWrite bool
}
@ -121,7 +121,7 @@ func WithLimit(limit int) Option {
}
// WithVersion provides an option version number for update operations.
func WithVersion(version int) Option {
func WithVersion(version uint32) Option {
return func(o *Options) {
o.WithVersion = version
}

@ -2199,6 +2199,141 @@
]
}
},
"/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:add-principals": {
"post": {
"summary": "Adds Users and/or Groups to a Role",
"operationId": "RoleService_AddRolePrincipals2",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "project_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.AddRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:remove-principals": {
"post": {
"summary": "Removes the specified Users and/or Groups from a Role.",
"operationId": "RoleService_RemoveRolePrincipals2",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "project_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.RemoveRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/projects/{project_id}/roles/{role_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",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "project_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.SetRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/roles": {
"get": {
"summary": "Lists all Roles",
@ -2382,6 +2517,123 @@
]
}
},
"/v1/orgs/{org_id}/roles/{role_id}:add-principals": {
"post": {
"summary": "Adds Users and/or Groups to a Role",
"operationId": "RoleService_AddRolePrincipals",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.AddRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/roles/{role_id}:remove-principals": {
"post": {
"summary": "Removes the specified Users and/or Groups from a Role.",
"operationId": "RoleService_RemoveRolePrincipals",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.RemoveRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/roles/{role_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",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "role_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.SetRolePrincipalsRequest"
}
}
],
"tags": [
"controller.api.services.v1.RoleService"
]
}
},
"/v1/orgs/{org_id}/users": {
"get": {
"summary": "Lists all Users",
@ -2867,6 +3119,36 @@
"type": "boolean",
"format": "boolean",
"title": "Whether the resource is disabled"
},
"version": {
"type": "integer",
"format": "int64",
"description": "The version can be used in subsiquent write requests to ensure this resource\nhas not changed and to fail the write if it has.\nOutput only.",
"readOnly": true
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "The principals that are assigned this role.\nOutput only.",
"readOnly": true
},
"group_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Output only.",
"readOnly": true
},
"grants": {
"type": "array",
"items": {
"type": "string"
},
"description": "The grants that this role provides for it's principals.\nOutput only.",
"readOnly": true
}
},
"title": "Role contains all fields related to a Role resource"
@ -2974,6 +3256,45 @@
},
"title": "User contains all fields related to a User resource"
},
"controller.api.services.v1.AddRolePrincipalsRequest": {
"type": "object",
"properties": {
"org_id": {
"type": "string"
},
"project_id": {
"type": "string"
},
"role_id": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"controller.api.services.v1.AddRolePrincipalsResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"controller.api.services.v1.AddToHostSetResponse": {
"type": "object"
},
@ -3313,6 +3634,84 @@
"controller.api.services.v1.RemoveFromHostSetResponse": {
"type": "object"
},
"controller.api.services.v1.RemoveRolePrincipalsRequest": {
"type": "object",
"properties": {
"org_id": {
"type": "string"
},
"project_id": {
"type": "string"
},
"role_id": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"controller.api.services.v1.RemoveRolePrincipalsResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"controller.api.services.v1.SetRolePrincipalsRequest": {
"type": "object",
"properties": {
"org_id": {
"type": "string"
},
"project_id": {
"type": "string"
},
"role_id": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"controller.api.services.v1.SetRolePrincipalsResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.roles.v1.Role"
}
}
},
"controller.api.services.v1.UpdateGroupResponse": {
"type": "object",
"properties": {

@ -48,6 +48,18 @@ type Role struct {
UpdatedTime *timestamp.Timestamp `protobuf:"bytes,5,opt,name=updated_time,proto3" json:"updated_time,omitempty"`
// Whether the resource is disabled
Disabled *wrappers.BoolValue `protobuf:"bytes,6,opt,name=disabled,proto3" json:"disabled,omitempty"`
// The version can be used in subsiquent write requests to ensure this resource
// has not changed and to fail the write if it has.
// Output only.
Version uint32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"`
// The principals that are assigned this role.
// Output only.
UserIds []string `protobuf:"bytes,8,rep,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
// Output only.
GroupIds []string `protobuf:"bytes,9,rep,name=group_ids,json=groupIds,proto3" json:"group_ids,omitempty"`
// The grants that this role provides for it's principals.
// Output only.
Grants []string `protobuf:"bytes,10,rep,name=grants,proto3" json:"grants,omitempty"`
}
func (x *Role) Reset() {
@ -124,6 +136,34 @@ func (x *Role) GetDisabled() *wrappers.BoolValue {
return nil
}
func (x *Role) GetVersion() uint32 {
if x != nil {
return x.Version
}
return 0
}
func (x *Role) GetUserIds() []string {
if x != nil {
return x.UserIds
}
return nil
}
func (x *Role) GetGroupIds() []string {
if x != nil {
return x.GroupIds
}
return nil
}
func (x *Role) GetGrants() []string {
if x != nil {
return x.Grants
}
return nil
}
var File_controller_api_resources_roles_v1_role_proto protoreflect.FileDescriptor
var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{
@ -136,7 +176,7 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{
0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xc0, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x74, 0x6f, 0x22, 0xaa, 0x03, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
@ -156,13 +196,19 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{
0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x64, 0x69, 0x73,
0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61,
0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 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, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72,
0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
0x09, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72,
0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67,
0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42,
0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61,
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77,
0x65, 0x72, 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, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72,
0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

File diff suppressed because it is too large Load Diff

@ -1053,6 +1053,624 @@ func local_request_RoleService_DeleteRole_1(ctx context.Context, marshaler runti
}
func request_RoleService_AddRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AddRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_AddRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AddRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.AddRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
func request_RoleService_AddRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AddRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_AddRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AddRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.AddRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
func request_RoleService_SetRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SetRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_SetRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SetRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.SetRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
func request_RoleService_SetRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SetRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_SetRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SetRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.SetRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
func request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RemoveRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RemoveRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.RemoveRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
func request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RemoveRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RemoveRolePrincipalsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["project_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
}
protoReq.ProjectId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
}
val, ok = pathParams["role_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id")
}
protoReq.RoleId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err)
}
msg, err := server.RemoveRolePrincipals(ctx, &protoReq)
return msg, metadata, err
}
// RegisterRoleServiceHandlerServer registers the http handlers for service RoleService to "mux".
// UnaryRPC :call RoleServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -1258,6 +1876,126 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("POST", pattern_RoleService_AddRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_AddRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_AddRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_AddRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_AddRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_AddRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_SetRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_SetRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_SetRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_SetRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_SetRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_SetRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_RemoveRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_RemoveRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_RoleService_RemoveRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_RemoveRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1499,6 +2237,126 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("POST", pattern_RoleService_AddRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_AddRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_AddRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_AddRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_AddRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_AddRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_SetRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_SetRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_SetRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_SetRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_SetRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_SetRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_RemoveRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_RemoveRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RoleService_RemoveRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RoleService_RemoveRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1556,6 +2414,60 @@ func (m response_RoleService_UpdateRole_1) XXX_ResponseBody() interface{} {
return response.Item
}
type response_RoleService_AddRolePrincipals_0 struct {
proto.Message
}
func (m response_RoleService_AddRolePrincipals_0) XXX_ResponseBody() interface{} {
response := m.Message.(*AddRolePrincipalsResponse)
return response.Item
}
type response_RoleService_AddRolePrincipals_1 struct {
proto.Message
}
func (m response_RoleService_AddRolePrincipals_1) XXX_ResponseBody() interface{} {
response := m.Message.(*AddRolePrincipalsResponse)
return response.Item
}
type response_RoleService_SetRolePrincipals_0 struct {
proto.Message
}
func (m response_RoleService_SetRolePrincipals_0) XXX_ResponseBody() interface{} {
response := m.Message.(*SetRolePrincipalsResponse)
return response.Item
}
type response_RoleService_SetRolePrincipals_1 struct {
proto.Message
}
func (m response_RoleService_SetRolePrincipals_1) XXX_ResponseBody() interface{} {
response := m.Message.(*SetRolePrincipalsResponse)
return response.Item
}
type response_RoleService_RemoveRolePrincipals_0 struct {
proto.Message
}
func (m response_RoleService_RemoveRolePrincipals_0) XXX_ResponseBody() interface{} {
response := m.Message.(*RemoveRolePrincipalsResponse)
return response.Item
}
type response_RoleService_RemoveRolePrincipals_1 struct {
proto.Message
}
func (m response_RoleService_RemoveRolePrincipals_1) XXX_ResponseBody() interface{} {
response := m.Message.(*RemoveRolePrincipalsResponse)
return response.Item
}
var (
pattern_RoleService_GetRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true)))
@ -1576,6 +2488,18 @@ var (
pattern_RoleService_DeleteRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_DeleteRole_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_AddRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "add-principals", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_AddRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "add-principals", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_SetRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "set-principals", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_SetRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "set-principals", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_RemoveRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "remove-principals", runtime.AssumeColonVerbOpt(true)))
pattern_RoleService_RemoveRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "remove-principals", runtime.AssumeColonVerbOpt(true)))
)
var (
@ -1598,4 +2522,16 @@ var (
forward_RoleService_DeleteRole_0 = runtime.ForwardResponseMessage
forward_RoleService_DeleteRole_1 = runtime.ForwardResponseMessage
forward_RoleService_AddRolePrincipals_0 = runtime.ForwardResponseMessage
forward_RoleService_AddRolePrincipals_1 = runtime.ForwardResponseMessage
forward_RoleService_SetRolePrincipals_0 = runtime.ForwardResponseMessage
forward_RoleService_SetRolePrincipals_1 = runtime.ForwardResponseMessage
forward_RoleService_RemoveRolePrincipals_0 = runtime.ForwardResponseMessage
forward_RoleService_RemoveRolePrincipals_1 = runtime.ForwardResponseMessage
)

@ -13,7 +13,7 @@ import (
// roleVersion or an error will be returned. The roles and groups must be in
// the same scope. User can only be added to roles which are within the user's
// organization, or the role is within a project within the user's organization.
func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, error) {
func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, error) {
// NOTE - we are intentionally not going to check that the scopes are
// correct for the userIds and groupIds, given the roleId. We are going to
// rely on the database constraints and triggers to maintain the integrity
@ -64,7 +64,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV
}
updatedRole := allocRole()
updatedRole.PublicId = roleId
updatedRole.Version = uint32(roleVersion) + 1
updatedRole.Version = roleVersion + 1
var roleOplogMsg oplog.Message
rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion))
if err != nil {
@ -117,7 +117,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV
// principals as need to reconcile the existing principals with the principals
// requested. If both userIds and groupIds are empty, the principal roles will
// be cleared.
func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, int, error) {
func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, int, error) {
// NOTE - we are intentionally not going to check that the scopes are
// correct for the userIds and groupIds, given the roleId. We are going to
// rely on the database constraints and triggers to maintain the integrity
@ -179,7 +179,7 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV
}
updatedRole := allocRole()
updatedRole.PublicId = roleId
updatedRole.Version = uint32(roleVersion) + 1
updatedRole.Version = roleVersion + 1
var roleOplogMsg oplog.Message
rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion))
if err != nil {
@ -262,7 +262,7 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV
// DeletePrincipalRoles principals (userIds and/or groupIds) from a role
// (roleId). The role's current db version must match the roleVersion or an
// error will be returned.
func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) (int, error) {
func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) (int, error) {
if roleId == "" {
return db.NoRowsAffected, fmt.Errorf("delete principal roles: missing role id: %w", db.ErrInvalidParameter)
}
@ -305,7 +305,7 @@ func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, ro
}
updatedRole := allocRole()
updatedRole.PublicId = roleId
updatedRole.Version = uint32(roleVersion) + 1
updatedRole.Version = roleVersion + 1
var roleOplogMsg oplog.Message
rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion))
if err != nil {

@ -40,7 +40,7 @@ func TestRepository_AddPrincipalRoles(t *testing.T) {
}
type args struct {
roleId string
roleVersion int
roleVersion uint32
userIds []string
groupIds []string
opt []Option
@ -231,7 +231,7 @@ func TestRepository_ListPrincipalRoles(t *testing.T) {
g := TestGroup(t, conn, tt.createScopeId)
groupRoles = append(groupRoles, g.PublicId)
}
testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, int(role.Version), userRoles, groupRoles, tt.args.opt...)
testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, role.Version, userRoles, groupRoles, tt.args.opt...)
require.NoError(err)
assert.Equal(tt.createCnt, len(testRoles))
@ -452,7 +452,7 @@ func TestRepository_SetPrincipalRoles(t *testing.T) {
}
type args struct {
role *Role
roleVersion int
roleVersion uint32
userIds []string
groupIds []string
addToOrigUsers bool

@ -86,16 +86,36 @@ func (r *Repository) UpdateRole(ctx context.Context, role *Role, fieldMaskPaths
// LookupRole will look up a role in the repository. If the role is not
// found, it will return nil, nil.
func (r *Repository) LookupRole(ctx context.Context, withPublicId string, opt ...Option) (*Role, error) {
func (r *Repository) LookupRole(ctx context.Context, withPublicId string, opt ...Option) (*Role, []PrincipalRole, error) {
if withPublicId == "" {
return nil, fmt.Errorf("lookup role: missing public id %w", db.ErrNilParameter)
return nil, nil, fmt.Errorf("lookup role: missing public id %w", db.ErrNilParameter)
}
role := allocRole()
role.PublicId = withPublicId
if err := r.reader.LookupByPublicId(ctx, &role); err != nil {
return nil, fmt.Errorf("lookup role: failed %w for %s", err, withPublicId)
var pr []PrincipalRole
_, err := r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(read db.Reader, w db.Writer) error {
if err := read.LookupByPublicId(ctx, &role); err != nil {
return fmt.Errorf("lookup role: failed %w for %s", err, withPublicId)
}
repo, err := NewRepository(read, w, r.wrapper)
if err != nil {
return fmt.Errorf("lookup role: failed creating inner repo: %w for %s", err, withPublicId)
}
pr, err = repo.ListPrincipalRoles(ctx, withPublicId)
if err != nil {
return fmt.Errorf("lookup role: listing principal roles: %w for %s", err, withPublicId)
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return &role, nil
return &role, pr, nil
}
// DeleteRole will delete a role from the repository.

@ -160,7 +160,7 @@ func TestRepository_CreateRole(t *testing.T) {
assert.NotNil(grp.CreateTime)
assert.NotNil(grp.UpdateTime)
foundGrp, err := repo.LookupRole(context.Background(), grp.PublicId)
foundGrp, _, err := repo.LookupRole(context.Background(), grp.PublicId)
assert.NoError(err)
assert.True(proto.Equal(foundGrp, grp))
@ -421,7 +421,7 @@ func TestRepository_UpdateRole(t *testing.T) {
default:
assert.NotEqual(r.UpdateTime, roleAfterUpdate.UpdateTime)
}
foundRole, err := repo.LookupRole(context.Background(), r.PublicId)
foundRole, _, err := repo.LookupRole(context.Background(), r.PublicId)
assert.NoError(err)
assert.True(proto.Equal(roleAfterUpdate, foundRole))
dbassert := dbassert.New(t, rw)
@ -511,7 +511,7 @@ func TestRepository_DeleteRole(t *testing.T) {
}
assert.NoError(err)
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundRole, err := repo.LookupRole(context.Background(), tt.args.role.PublicId)
foundRole, _, err := repo.LookupRole(context.Background(), tt.args.role.PublicId)
assert.Error(err)
assert.Nil(foundRole)
assert.True(errors.Is(err, db.ErrRecordNotFound))

@ -29,4 +29,19 @@ message Role {
// Whether the resource is disabled
google.protobuf.BoolValue disabled = 6;
// The version can be used in subsiquent write requests to ensure this resource
// has not changed and to fail the write if it has.
// Output only.
uint32 version = 7;
// The principals that are assigned this role.
// Output only.
repeated string user_ids = 8;
// Output only.
repeated string group_ids = 9;
// The grants that this role provides for it's principals.
// Output only.
repeated string grants = 10;
}

@ -7,6 +7,7 @@ option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api
import "protoc-gen-swagger/options/annotations.proto";
import "google/api/annotations.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/wrappers.proto";
import "controller/api/resources/roles/v1/role.proto";
service RoleService {
@ -106,6 +107,68 @@ service RoleService {
summary: "Deletes a Role"
};
}
// AddRolePrincipals adds users and/or groups to a role. The provided request must include
// the org id and the role id which the users and/or groups will be added to. If the
// org id is missing, malformed or references a non existing organization,
// an error is returned.
rpc AddRolePrincipals(AddRolePrincipalsRequest) returns (AddRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}/roles/{role_id}:add-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:add-principals"
body: "*"
response_body: "item"
}
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Adds Users and/or Groups to a Role"
};
}
// SetRolePrincipals sets the role's users and/or groups. Any existing principals on
// the role are deleted if they are not included in this request. The provided
// request must include the org id and the role id which the users and/or groups
// will be set to. If the org id is missing, malformed or references a non
// existing organization, an error is returned.
rpc SetRolePrincipals(SetRolePrincipalsRequest) returns (SetRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}/roles/{role_id}:set-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:set-principals"
body: "*"
response_body: "item"
}
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Set Users and/or Groups to a Role, removing any principals that are not specified in the request."
};
}
// RemoveRolePrincipals removes the users and/or groups from the specified role.
// The provided request must include the org id and the role id which the users
// and/or groups will be removed from. If the org id is missing, malformed or references a non
// existing organization, an error is returned. It is not an error to have duplicate
// user/group ids.
rpc RemoveRolePrincipals(RemoveRolePrincipalsRequest) returns (RemoveRolePrincipalsResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}/roles/{role_id}:remove-principals"
body: "*"
response_body: "item"
additional_bindings {
post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:remove-principals"
body: "*"
response_body: "item"
}
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Removes the specified Users and/or Groups from a Role."
};
}
}
message GetRoleRequest {
@ -140,6 +203,7 @@ message CreateRoleResponse {
resources.roles.v1.Role item = 2;
}
// TODO: Add versions to Update and Delete role requests.
message UpdateRoleRequest {
string org_id = 1;
string project_id = 2;
@ -161,3 +225,48 @@ message DeleteRoleRequest {
message DeleteRoleResponse {
bool existed = 1;
}
message AddRolePrincipalsRequest {
string org_id = 1;
string project_id = 2;
string role_id = 3;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
}
message AddRolePrincipalsResponse {
resources.roles.v1.Role item = 1;
}
message SetRolePrincipalsRequest {
string org_id = 1;
string project_id = 2;
string role_id = 3;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
}
message SetRolePrincipalsResponse {
resources.roles.v1.Role item = 1;
}
message RemoveRolePrincipalsRequest {
string org_id = 1;
string project_id = 2;
string role_id = 3;
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
}
message RemoveRolePrincipalsResponse {
resources.roles.v1.Role item = 1;
}

@ -119,6 +119,47 @@ func TestGrpcGatewayRouting(t *testing.T) {
}
}
func TestGrpcGatewayRouting_CustomActions(t *testing.T) {
ctx := context.Background()
// The unimplemented result indicates the grpc routing is happening successfully otherwise it would return NotFound.
routed := http.StatusNotImplemented
cases := []struct {
name string
setup func(mux *runtime.ServeMux)
post_urls []string
}{
{
name: "roles",
setup: func(mux *runtime.ServeMux) {
require.NoError(t, services.RegisterRoleServiceHandlerServer(ctx, mux, &services.UnimplementedRoleServiceServer{}))
},
post_urls: []string{
"v1/orgs/someid/roles/r_anotherid:add-principals",
"v1/orgs/someid/roles/r_anotherid:set-principals",
"v1/orgs/someid/roles/r_anotherid:remove-principals",
"v1/orgs/someid/projects/p_something/roles/r_anotherid:add-principals",
"v1/orgs/someid/projects/p_something/roles/r_anotherid:set-principals",
"v1/orgs/someid/projects/p_something/roles/r_anotherid:remove-principals",
},
},
}
for _, tc := range cases {
for _, url := range tc.post_urls {
t.Run(tc.name+"_"+url, func(t *testing.T) {
mux := runtime.NewServeMux()
tc.setup(mux)
req := httptest.NewRequest("POST", fmt.Sprintf("http://localhost/%s", url), nil)
resp := httptest.NewRecorder()
mux.ServeHTTP(resp, req)
assert.Equal(t, routed, resp.Result().StatusCode, "Got response %v", resp)
})
}
}
}
func TestHandleGrpcGateway(t *testing.T) {
c := NewTestController(t, nil)
defer c.Shutdown()

@ -121,22 +121,64 @@ func (s Service) DeleteRole(ctx context.Context, req *pbs.DeleteRoleRequest) (*p
return &pbs.DeleteRoleResponse{Existed: existed}, nil
}
// AddRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipalsRequest) (*pbs.AddRolePrincipalsResponse, error) {
auth := handlers.ToTokenMetadata(ctx)
_ = auth
if err := validateAddRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.addPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
return &pbs.AddRolePrincipalsResponse{Item: r}, nil
}
// SetRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipalsRequest) (*pbs.SetRolePrincipalsResponse, error) {
auth := handlers.ToTokenMetadata(ctx)
_ = auth
if err := validateSetRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.setPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
return &pbs.SetRolePrincipalsResponse{Item: r}, nil
}
// RemoveRolePrincipals implements the interface pbs.RoleServiceServer.
func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePrincipalsRequest) (*pbs.RemoveRolePrincipalsResponse, error) {
auth := handlers.ToTokenMetadata(ctx)
_ = auth
if err := validateRemoveRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.removePrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
return &pbs.RemoveRolePrincipalsResponse{Item: r}, nil
}
func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
u, err := repo.LookupRole(ctx, id)
out, pr, err := repo.LookupRole(ctx, id)
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id)
}
return nil, err
}
if u == nil {
if out == nil {
return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id)
}
return toProto(u), nil
return toProto(out, pr), nil
}
func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Role) (*pb.Role, error) {
@ -162,7 +204,7 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Role
if out == nil {
return nil, status.Error(codes.Internal, "Unable to create role but no error returned from repository.")
}
return toProto(out), nil
return toProto(out, nil), nil
}
func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []string, item *pb.Role) (*pb.Role, error) {
@ -196,7 +238,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
if rowsUpdated == 0 {
return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id)
}
return toProto(out), nil
return toProto(out, nil), nil
}
func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) {
@ -225,11 +267,59 @@ func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Role,
}
var outRl []*pb.Role
for _, g := range rl {
outRl = append(outRl, toProto(g))
outRl = append(outRl, toProto(g, nil))
}
return outRl, nil
}
func (s Service) addPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, err = repo.AddPrincipalRoles(ctx, roleId, version, userIds, groupIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to add principles to role: %v.", err)
}
out, pr, err := repo.LookupRole(ctx, roleId)
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup role after adding principles to it.")
}
return toProto(out, pr), nil
}
func (s Service) setPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, _, err = repo.SetPrincipalRoles(ctx, roleId, version, userIds, groupIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to set principles on role: %v.", err)
}
out, pr, err := repo.LookupRole(ctx, roleId)
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup role after setting principles for it.")
}
return toProto(out, pr), nil
}
func (s Service) removePrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, err = repo.DeletePrincipalRoles(ctx, roleId, version, userIds, groupIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to remove principles from role: %v.", err)
}
out, pr, err := repo.LookupRole(ctx, roleId)
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup role after removing principles from it.")
}
return toProto(out, pr), nil
}
// toDbUpdateMask converts the wire format's FieldMask into a list of strings containing FieldMask paths used
func toDbUpdateMask(paths []string) ([]string, error) {
var dbPaths []string
@ -249,11 +339,12 @@ func toDbUpdateMask(paths []string) ([]string, error) {
return dbPaths, nil
}
func toProto(in *iam.Role) *pb.Role {
func toProto(in *iam.Role, principals []iam.PrincipalRole) *pb.Role {
out := pb.Role{
Id: in.GetPublicId(),
CreatedTime: in.GetCreateTime().GetTimestamp(),
UpdatedTime: in.GetUpdateTime().GetTimestamp(),
Version: in.GetVersion(),
}
if in.GetDescription() != "" {
out.Description = &wrapperspb.StringValue{Value: in.GetDescription()}
@ -261,6 +352,14 @@ func toProto(in *iam.Role) *pb.Role {
if in.GetName() != "" {
out.Name = &wrapperspb.StringValue{Value: in.GetName()}
}
for _, p := range principals {
switch p.GetType() {
case iam.UserRoleType.String():
out.UserIds = append(out.UserIds, p.GetPrincipalId())
case iam.GroupRoleType.String():
out.GroupIds = append(out.GroupIds, p.GetPrincipalId())
}
}
return &out
}
@ -348,6 +447,60 @@ func validateListRequest(req *pbs.ListRolesRequest) error {
return nil
}
func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
badFields := validateAncestors(req)
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == nil {
badFields["version"] = "Required field."
}
if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 {
badFields["user_ids"] = "Either user_ids or group_ids must be non empty."
badFields["group_ids"] = "Either user_ids or group_ids must be non empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
return nil
}
func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error {
badFields := validateAncestors(req)
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == nil {
badFields["version"] = "Required field."
}
if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 {
badFields["user_ids"] = "Either user_ids or group_ids must be non empty."
badFields["group_ids"] = "Either user_ids or group_ids must be non empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
return nil
}
func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) error {
badFields := validateAncestors(req)
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
badFields["id"] = "Incorrectly formatted identifier."
}
if req.GetVersion() == nil {
badFields["version"] = "Required field."
}
if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 {
badFields["user_ids"] = "Either user_ids or group_ids must be non empty."
badFields["group_ids"] = "Either user_ids or group_ids must be non empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
return nil
}
func validId(id, prefix string) bool {
if !strings.HasPrefix(id, prefix) {
return false

@ -3,10 +3,12 @@ package roles_test
import (
"context"
"fmt"
"sort"
"strings"
"testing"
"github.com/golang/protobuf/ptypes"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/watchtower/internal/db"
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/roles"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
@ -17,6 +19,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
@ -53,6 +56,7 @@ func TestGet(t *testing.T) {
Description: &wrapperspb.StringValue{Value: or.GetDescription()},
CreatedTime: or.CreateTime.GetTimestamp(),
UpdatedTime: or.UpdateTime.GetTimestamp(),
Version: or.GetVersion(),
}
wantProjRole := &pb.Role{
@ -61,6 +65,7 @@ func TestGet(t *testing.T) {
Description: &wrapperspb.StringValue{Value: pr.GetDescription()},
CreatedTime: pr.CreateTime.GetTimestamp(),
UpdatedTime: pr.UpdateTime.GetTimestamp(),
Version: pr.GetVersion(),
}
cases := []struct {
@ -151,12 +156,14 @@ func TestList(t *testing.T) {
Id: or.GetPublicId(),
CreatedTime: or.GetCreateTime().GetTimestamp(),
UpdatedTime: or.GetUpdateTime().GetTimestamp(),
Version: or.GetVersion(),
})
pr := iam.TestRole(t, conn, pWithRoles.GetPublicId())
wantProjRoles = append(wantProjRoles, &pb.Role{
Id: pr.GetPublicId(),
CreatedTime: pr.GetCreateTime().GetTimestamp(),
UpdatedTime: pr.GetUpdateTime().GetTimestamp(),
Version: pr.GetVersion(),
})
}
@ -408,6 +415,7 @@ func TestCreate(t *testing.T) {
Item: &pb.Role{
Name: &wrapperspb.StringValue{Value: "name"},
Description: &wrapperspb.StringValue{Value: "desc"},
Version: 1,
},
},
errCode: codes.OK,
@ -426,6 +434,7 @@ func TestCreate(t *testing.T) {
Item: &pb.Role{
Name: &wrapperspb.StringValue{Value: "name"},
Description: &wrapperspb.StringValue{Value: "desc"},
Version: 1,
},
},
errCode: codes.OK,
@ -773,8 +782,713 @@ func TestUpdate(t *testing.T) {
// Clear all values which are hard to compare against.
got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil
// TODO: Figure out the best way to test versions when updating roles
got.GetItem().Version = 0
}
assert.True(proto.Equal(got, tc.res), "UpdateRole(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
func TestAddPrincipal(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*iam.Repository, error) {
return iam.NewRepository(rw, rw, wrap)
}
o, p := iam.TestScopes(t, conn)
orUserEmpty := iam.TestRole(t, conn, o.GetPublicId())
prUserEmpty := iam.TestRole(t, conn, p.GetPublicId())
orGroupEmpty := iam.TestRole(t, conn, o.GetPublicId())
prGroupEmpty := iam.TestRole(t, conn, p.GetPublicId())
orWithUser := iam.TestRole(t, conn, o.GetPublicId())
assignedUser := iam.TestUser(t, conn, o.GetPublicId())
_ = iam.TestUserRole(t, conn, o.GetPublicId(), orWithUser.GetPublicId(), assignedUser.GetPublicId())
ou1 := iam.TestUser(t, conn, o.GetPublicId())
ou2 := iam.TestUser(t, conn, o.GetPublicId())
orWithGroup := iam.TestRole(t, conn, o.GetPublicId())
assignedOG := iam.TestGroup(t, conn, o.GetPublicId())
_ = iam.TestGroupRole(t, conn, o.GetPublicId(), orWithGroup.GetPublicId(), assignedOG.GetPublicId())
og1 := iam.TestGroup(t, conn, o.GetPublicId())
og2 := iam.TestGroup(t, conn, o.GetPublicId())
prWithUser := iam.TestRole(t, conn, p.GetPublicId())
_ = iam.TestUserRole(t, conn, p.GetPublicId(), prWithUser.GetPublicId(), assignedUser.GetPublicId())
prWithGroup := iam.TestRole(t, conn, p.GetPublicId())
assignedPG := iam.TestGroup(t, conn, p.GetPublicId())
_ = iam.TestGroupRole(t, conn, p.GetPublicId(), prWithGroup.GetPublicId(), assignedPG.GetPublicId())
pg1 := iam.TestGroup(t, conn, p.GetPublicId())
pg2 := iam.TestGroup(t, conn, p.GetPublicId())
s, err := roles.NewService(repoFn)
require.NoError(t, err, "Error when getting new role service.")
cases := []struct {
name string
req *pbs.AddRolePrincipalsRequest
res *pbs.AddRolePrincipalsResponse
errCode codes.Code
}{
{
name: "Add User Empty Org Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: orUserEmpty.GetScopeId(),
RoleId: orUserEmpty.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orUserEmpty.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: orUserEmpty.GetPublicId(),
CreatedTime: orUserEmpty.GetCreateTime().GetTimestamp(),
Version: orUserEmpty.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add User Populated Org Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: orWithUser.GetScopeId(),
RoleId: orWithUser.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orWithUser.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: orWithUser.GetPublicId(),
CreatedTime: orWithUser.GetCreateTime().GetTimestamp(),
Version: orWithUser.GetVersion() + 1,
UserIds: []string{assignedUser.GetPublicId(), ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add User Empty Project Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prUserEmpty.GetScopeId(),
RoleId: prUserEmpty.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prUserEmpty.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: prUserEmpty.GetPublicId(),
CreatedTime: prUserEmpty.GetCreateTime().GetTimestamp(),
Version: prUserEmpty.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add User Populated Project Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithUser.GetScopeId(),
RoleId: prWithUser.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithUser.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: prWithUser.GetPublicId(),
CreatedTime: prWithUser.GetCreateTime().GetTimestamp(),
Version: prWithUser.GetVersion() + 1,
UserIds: []string{assignedUser.GetPublicId(), ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add Group Empty Org Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: orGroupEmpty.GetScopeId(),
RoleId: orGroupEmpty.GetPublicId(),
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orGroupEmpty.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: orGroupEmpty.GetPublicId(),
CreatedTime: orGroupEmpty.GetCreateTime().GetTimestamp(),
Version: orGroupEmpty.GetVersion() + 1,
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add Group Populated Org Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: orWithGroup.GetScopeId(),
RoleId: orWithGroup.GetPublicId(),
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orWithGroup.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: orWithGroup.GetPublicId(),
CreatedTime: orWithGroup.GetCreateTime().GetTimestamp(),
Version: orWithGroup.GetVersion() + 1,
GroupIds: []string{assignedOG.GetPublicId(), og1.GetPublicId(), og2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add Group Empty Project Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prGroupEmpty.GetScopeId(),
RoleId: prGroupEmpty.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prGroupEmpty.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: prGroupEmpty.GetPublicId(),
CreatedTime: prGroupEmpty.GetCreateTime().GetTimestamp(),
Version: prGroupEmpty.GetVersion() + 1,
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Add Group Populated Project Role",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithGroup.GetScopeId(),
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: &pbs.AddRolePrincipalsResponse{
Item: &pb.Role{
Id: prWithGroup.GetPublicId(),
CreatedTime: prWithGroup.GetCreateTime().GetTimestamp(),
Version: prWithGroup.GetVersion() + 1,
GroupIds: []string{assignedPG.GetPublicId(), pg1.GetPublicId(), pg2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Bad Org Id",
req: &pbs.AddRolePrincipalsRequest{
OrgId: "",
ProjectId: prWithGroup.GetScopeId(),
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Project Id",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Role Id",
req: &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithGroup.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.AddRolePrincipals(context.Background(), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
if tc.res == nil {
require.Nil(t, got)
return
}
got.Item.UpdatedTime = nil
sort.Strings(got.Item.UserIds)
sort.Strings(got.Item.GroupIds)
sort.Strings(tc.res.Item.UserIds)
sort.Strings(tc.res.Item.GroupIds)
assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()),
"AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res)
})
}
}
func TestSetPrincipal(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*iam.Repository, error) {
return iam.NewRepository(rw, rw, wrap)
}
o, p := iam.TestScopes(t, conn)
orUserEmpty := iam.TestRole(t, conn, o.GetPublicId())
prUserEmpty := iam.TestRole(t, conn, p.GetPublicId())
orGroupEmpty := iam.TestRole(t, conn, o.GetPublicId())
prGroupEmpty := iam.TestRole(t, conn, p.GetPublicId())
orWithUser := iam.TestRole(t, conn, o.GetPublicId())
assignedUser := iam.TestUser(t, conn, o.GetPublicId())
_ = iam.TestUserRole(t, conn, o.GetPublicId(), orWithUser.GetPublicId(), assignedUser.GetPublicId())
ou1 := iam.TestUser(t, conn, o.GetPublicId())
ou2 := iam.TestUser(t, conn, o.GetPublicId())
orWithGroup := iam.TestRole(t, conn, o.GetPublicId())
assignedOG := iam.TestGroup(t, conn, o.GetPublicId())
_ = iam.TestGroupRole(t, conn, o.GetPublicId(), orWithGroup.GetPublicId(), assignedOG.GetPublicId())
og1 := iam.TestGroup(t, conn, o.GetPublicId())
og2 := iam.TestGroup(t, conn, o.GetPublicId())
prWithUser := iam.TestRole(t, conn, p.GetPublicId())
_ = iam.TestUserRole(t, conn, p.GetPublicId(), prWithUser.GetPublicId(), assignedUser.GetPublicId())
prWithGroup := iam.TestRole(t, conn, p.GetPublicId())
assignedPG := iam.TestGroup(t, conn, p.GetPublicId())
_ = iam.TestGroupRole(t, conn, p.GetPublicId(), prWithGroup.GetPublicId(), assignedPG.GetPublicId())
pg1 := iam.TestGroup(t, conn, p.GetPublicId())
pg2 := iam.TestGroup(t, conn, p.GetPublicId())
s, err := roles.NewService(repoFn)
require.NoError(t, err, "Error when getting new role service.")
cases := []struct {
name string
req *pbs.SetRolePrincipalsRequest
res *pbs.SetRolePrincipalsResponse
errCode codes.Code
}{
{
name: "Set User Empty Org Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: orUserEmpty.GetScopeId(),
RoleId: orUserEmpty.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orUserEmpty.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: orUserEmpty.GetPublicId(),
CreatedTime: orUserEmpty.GetCreateTime().GetTimestamp(),
Version: orUserEmpty.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set User Populated Org Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: orWithUser.GetScopeId(),
RoleId: orWithUser.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orWithUser.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: orWithUser.GetPublicId(),
CreatedTime: orWithUser.GetCreateTime().GetTimestamp(),
Version: orWithUser.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set User Empty Project Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prUserEmpty.GetScopeId(),
RoleId: prUserEmpty.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prUserEmpty.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: prUserEmpty.GetPublicId(),
CreatedTime: prUserEmpty.GetCreateTime().GetTimestamp(),
Version: prUserEmpty.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set User Populated Project Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithUser.GetScopeId(),
RoleId: prWithUser.GetPublicId(),
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithUser.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: prWithUser.GetPublicId(),
CreatedTime: prWithUser.GetCreateTime().GetTimestamp(),
Version: prWithUser.GetVersion() + 1,
UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set Group Empty Org Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: orGroupEmpty.GetScopeId(),
RoleId: orGroupEmpty.GetPublicId(),
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orGroupEmpty.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: orGroupEmpty.GetPublicId(),
CreatedTime: orGroupEmpty.GetCreateTime().GetTimestamp(),
Version: orGroupEmpty.GetVersion() + 1,
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set Group Populated Org Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: orWithGroup.GetScopeId(),
RoleId: orWithGroup.GetPublicId(),
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orWithGroup.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: orWithGroup.GetPublicId(),
CreatedTime: orWithGroup.GetCreateTime().GetTimestamp(),
Version: orWithGroup.GetVersion() + 1,
GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set Group Empty Project Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prGroupEmpty.GetScopeId(),
RoleId: prGroupEmpty.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prGroupEmpty.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: prGroupEmpty.GetPublicId(),
CreatedTime: prGroupEmpty.GetCreateTime().GetTimestamp(),
Version: prGroupEmpty.GetVersion() + 1,
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Set Group Populated Project Role",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithGroup.GetScopeId(),
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: &pbs.SetRolePrincipalsResponse{
Item: &pb.Role{
Id: prWithGroup.GetPublicId(),
CreatedTime: prWithGroup.GetCreateTime().GetTimestamp(),
Version: prWithGroup.GetVersion() + 1,
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Bad Org Id",
req: &pbs.SetRolePrincipalsRequest{
OrgId: "",
ProjectId: prWithGroup.GetScopeId(),
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Project Id",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: prWithGroup.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Role Id",
req: &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: prWithGroup.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.SetRolePrincipals(context.Background(), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
if tc.res == nil {
require.Nil(t, got)
return
}
got.Item.UpdatedTime = nil
sort.Strings(got.Item.UserIds)
sort.Strings(got.Item.GroupIds)
sort.Strings(tc.res.Item.UserIds)
sort.Strings(tc.res.Item.GroupIds)
assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()),
"AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res)
})
}
}
func TestRemovePrincipal(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*iam.Repository, error) {
return iam.NewRepository(rw, rw, wrap)
}
o, p := iam.TestScopes(t, conn)
orgEmptyRole := iam.TestRole(t, conn, o.GetPublicId())
orgUserRoles := iam.TestRole(t, conn, o.GetPublicId())
orgGroupRoles := iam.TestRole(t, conn, o.GetPublicId())
projEmptyRole := iam.TestRole(t, conn, p.GetPublicId())
projUserRoles := iam.TestRole(t, conn, p.GetPublicId())
projGroupRoles := iam.TestRole(t, conn, p.GetPublicId())
ou1 := iam.TestUser(t, conn, o.GetPublicId())
ou2 := iam.TestUser(t, conn, o.GetPublicId())
_ = iam.TestUserRole(t, conn, o.GetPublicId(), orgUserRoles.GetPublicId(), ou1.GetPublicId())
_ = iam.TestUserRole(t, conn, o.GetPublicId(), orgUserRoles.GetPublicId(), ou2.GetPublicId())
_ = iam.TestUserRole(t, conn, p.GetPublicId(), projUserRoles.GetPublicId(), ou1.GetPublicId())
_ = iam.TestUserRole(t, conn, p.GetPublicId(), projUserRoles.GetPublicId(), ou2.GetPublicId())
og1 := iam.TestGroup(t, conn, o.GetPublicId())
og2 := iam.TestGroup(t, conn, o.GetPublicId())
_ = iam.TestGroupRole(t, conn, o.GetPublicId(), orgGroupRoles.GetPublicId(), og1.GetPublicId())
_ = iam.TestGroupRole(t, conn, o.GetPublicId(), orgGroupRoles.GetPublicId(), og2.GetPublicId())
pg1 := iam.TestGroup(t, conn, p.GetPublicId())
pg2 := iam.TestGroup(t, conn, p.GetPublicId())
_ = iam.TestGroupRole(t, conn, p.GetPublicId(), projGroupRoles.GetPublicId(), pg1.GetPublicId())
_ = iam.TestGroupRole(t, conn, p.GetPublicId(), projGroupRoles.GetPublicId(), pg2.GetPublicId())
s, err := roles.NewService(repoFn)
require.NoError(t, err, "Error when getting new role service.")
cases := []struct {
name string
req *pbs.RemoveRolePrincipalsRequest
res *pbs.RemoveRolePrincipalsResponse
errCode codes.Code
}{
{
name: "Remove User From Org Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: orgUserRoles.GetScopeId(),
RoleId: orgUserRoles.GetPublicId(),
UserIds: []string{ou1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orgUserRoles.GetVersion()},
},
res: &pbs.RemoveRolePrincipalsResponse{
Item: &pb.Role{
Id: orgUserRoles.GetPublicId(),
CreatedTime: orgUserRoles.GetCreateTime().GetTimestamp(),
Version: orgUserRoles.GetVersion() + 1,
UserIds: []string{ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Remove User From Proj Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: projUserRoles.GetScopeId(),
RoleId: projUserRoles.GetPublicId(),
UserIds: []string{ou1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projUserRoles.GetVersion()},
},
res: &pbs.RemoveRolePrincipalsResponse{
Item: &pb.Role{
Id: projUserRoles.GetPublicId(),
CreatedTime: projUserRoles.GetCreateTime().GetTimestamp(),
Version: projUserRoles.GetVersion() + 1,
UserIds: []string{ou2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Remove Group From Org Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: orgGroupRoles.GetScopeId(),
RoleId: orgGroupRoles.GetPublicId(),
GroupIds: []string{og1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orgGroupRoles.GetVersion()},
},
res: &pbs.RemoveRolePrincipalsResponse{
Item: &pb.Role{
Id: orgGroupRoles.GetPublicId(),
CreatedTime: orgGroupRoles.GetCreateTime().GetTimestamp(),
Version: orgGroupRoles.GetVersion() + 1,
GroupIds: []string{og2.GetPublicId()},
},
},
errCode: codes.OK,
},
{
name: "Remove Group From Proj Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: projGroupRoles.GetScopeId(),
RoleId: projGroupRoles.GetPublicId(),
GroupIds: []string{pg1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()},
},
res: &pbs.RemoveRolePrincipalsResponse{
Item: &pb.Role{
Id: projGroupRoles.GetPublicId(),
CreatedTime: projGroupRoles.GetCreateTime().GetTimestamp(),
Version: projGroupRoles.GetVersion() + 1,
GroupIds: []string{pg2.GetPublicId()},
},
},
errCode: codes.OK,
},
// TODO: Should it be a silent noop to remove a principal from a role when the principal isn't on the role?
{
name: "Remove From Empty Org Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
RoleId: orgEmptyRole.GetPublicId(),
UserIds: []string{ou1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: orgEmptyRole.GetVersion()},
},
errCode: codes.Internal,
},
{
name: "Remove From Empty Project Role",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: projEmptyRole.GetScopeId(),
RoleId: projEmptyRole.GetPublicId(),
UserIds: []string{ou1.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projEmptyRole.GetVersion()},
},
errCode: codes.Internal,
},
{
name: "Bad Org Id",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: "",
ProjectId: projGroupRoles.GetScopeId(),
RoleId: projGroupRoles.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Project Id",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: projGroupRoles.GetPublicId(),
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Bad Role Id",
req: &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
ProjectId: projGroupRoles.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()},
Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()},
},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.RemoveRolePrincipals(context.Background(), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
if tc.res == nil {
require.Nil(t, got)
return
}
got.Item.UpdatedTime = nil
sort.Strings(got.Item.UserIds)
sort.Strings(got.Item.GroupIds)
sort.Strings(tc.res.Item.UserIds)
sort.Strings(tc.res.Item.GroupIds)
assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()),
"AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res)
})
}
}

Loading…
Cancel
Save