Files
bridge/internal/service/process.go
2023-07-11 21:56:39 +00:00

139 lines
3.9 KiB
Go

package service
import (
"context"
"go.infratographer.com/x/events"
"go.infratographer.com/x/gidx"
)
func (s *service) processRelationships(ctx context.Context, subjectType string, relationships []Relationship) {
var err error
for _, rel := range relationships {
err = s.publisher.PublishChange(ctx, subjectType, events.ChangeMessage{
SubjectID: rel.Resource.PrefixedID(),
EventType: string(events.CreateChangeType),
AdditionalSubjectIDs: []gidx.PrefixedID{
rel.RelatedResource.PrefixedID(),
},
})
if err != nil {
s.logger.Errorw("error publishing change",
"subject_type", subjectType,
"resource.id", rel.Resource.PrefixedID(),
"related_resource.id", rel.RelatedResource.PrefixedID(),
"error", err,
)
}
}
}
func (s *service) processMemberships(ctx context.Context, memberships []ResourceMemberships) {
resourceRoleID := make(map[gidx.PrefixedID]map[string]gidx.PrefixedID)
resourceRoleMembers := make(map[gidx.PrefixedID]map[string]map[gidx.PrefixedID]bool)
roleActions := make(map[string][]string)
for _, membership := range memberships {
resourceID := membership.Resource.PrefixedID()
role := membership.Role
memberID := membership.Member.PrefixedID()
if _, ok := resourceRoleMembers[resourceID]; !ok {
resourceRoleID[resourceID] = make(map[string]gidx.PrefixedID)
resourceRoleMembers[resourceID] = make(map[string]map[gidx.PrefixedID]bool)
}
if _, ok := resourceRoleMembers[resourceID][role]; !ok {
resourceRoleMembers[resourceID][role] = make(map[gidx.PrefixedID]bool)
roleActions[role] = s.roles[role]
}
resourceRoleID[resourceID][role] = gidx.NullPrefixedID
resourceRoleMembers[resourceID][role][memberID] = true
}
resourceRoleAssignments := make(map[gidx.PrefixedID]map[gidx.PrefixedID]map[gidx.PrefixedID]bool)
for resourceID, roles := range resourceRoleID {
resourceRoleAssignments[resourceID] = make(map[gidx.PrefixedID]map[gidx.PrefixedID]bool)
for role := range roles {
actions := roleActions[role]
resourceRole, err := s.perms.FindResourceRoleByActions(ctx, resourceID, actions)
if err != nil {
s.logger.Warnw("failed to find role by actions for resource", "resource.id", resourceID, "role", role, "actions", actions, "error", err)
continue
}
resourceRoleID[resourceID][role] = resourceRole.ID
resourceRoleAssignments[resourceID][resourceRole.ID] = make(map[gidx.PrefixedID]bool)
assignments, err := s.perms.ListRoleAssignments(ctx, resourceRole.ID)
if err != nil {
s.logger.Warnw("failed to get role assignments for resource", "resource.id", resourceID, "role", role, "error", err)
continue
}
for _, assignment := range assignments {
resourceRoleAssignments[resourceID][resourceRole.ID][assignment] = true
}
}
}
for resourceID, roles := range resourceRoleMembers {
for role, members := range roles {
roleID := resourceRoleID[resourceID][role]
actions := roleActions[role]
logger := s.logger.With("resource.id", resourceID, "role.name", role, "actions", actions)
var createdRole bool
if roleID == gidx.NullPrefixedID {
logger.Infow("creating role for resource")
resourceRoleID, err := s.perms.CreateRole(ctx, resourceID, actions)
if err != nil {
logger.Errorw("failed to create role for resource", "error", err)
continue
}
createdRole = true
roleID = resourceRoleID
}
logger = logger.With("role.id", roleID)
assignments := make(map[gidx.PrefixedID]bool)
if !createdRole {
assignments = resourceRoleAssignments[resourceID][roleID]
}
for memberID := range members {
mlogger := logger.With("member.id", memberID)
if _, ok := assignments[memberID]; ok {
mlogger.Infow("skipping already assigned member")
continue
}
if err := s.perms.AssignRole(ctx, roleID, memberID); err != nil {
mlogger.Errorw("failed to assign member to role", "error", err)
continue
}
mlogger.Infow("role assigned to member")
}
}
}
}