diff --git a/pkg/iam/access_management_service.go b/pkg/iam/access_management_service.go deleted file mode 100644 index d48dd61cb..000000000 --- a/pkg/iam/access_management_service.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2025 Probo Inc . -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -// LEGACY ACCESS MANAGEMENT SERVICE - DEPRECATED -// -// This service implements the legacy authorization model that uses the Permissions -// map from permissions.go to check if a principal can perform an action. -// -// It is being replaced by Authorizer which uses a policy-based evaluation system. -// During migration, this service is still used for: -// - API key authorization (intersection semantics between user and API key roles) -// - Fallback for any unmapped legacy actions -// -// Once all actions are migrated and API key authorization is implemented in the -// new system, this service will be removed. -// -// Deprecated: Use Authorizer.Authorize() instead for new code. -package iam - -import ( - "context" - "errors" - "fmt" - - "go.gearno.de/kit/pg" - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/gid" -) - -type ( - AccessManagementService struct { - *Service - } -) - -func NewAccessManagementService(svc *Service) *AccessManagementService { - return &AccessManagementService{Service: svc} -} - -// Authorize implements Model 2 authorization: -// - principalID is the actor (Identity now; later service accounts) -// - credentialID is an optional credential (PersonalAPIKey now) -// - intersection semantics: actor must be allowed AND credential (if present) must be allowed. -// -// Entity scope: -// - Global/self-owned entities (Identity/Session/PersonalAPIKey) are authorized via ownership checks only (no global admin). -// - Organization-scoped entities are authorized via membership lookups that derive organization_id from entityID. -func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid.GID, credentialID *gid.GID, entityID gid.GID, action Action) error { - requiredRoles := GetPermissionsForAction(entityID.EntityType(), action) - if requiredRoles == nil { - entityModel, _ := coredata.EntityModel(entityID.EntityType()) - return NewNoPermissionsDefinedError(entityModel, action) - } - - switch principalID.EntityType() { - case coredata.IdentityEntityType: - // ok - default: - return NewUnsupportedPrincipalTypeError(principalID.EntityType()) - } - - return s.pg.WithConn(ctx, func(conn pg.Conn) error { - // Global/self-owned path - switch entityID.EntityType() { - case coredata.IdentityEntityType: - if entityID != principalID { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - return nil - - case coredata.SessionEntityType: - sess := &coredata.Session{} - if err := sess.LoadByID(ctx, conn, entityID); err != nil { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - if sess.IdentityID != principalID { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - return nil - - case coredata.PersonalAPIKeyEntityType: - key := &coredata.PersonalAPIKey{} - if err := key.LoadByID(ctx, conn, entityID); err != nil { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - if key.IdentityID != principalID { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - return nil - } - - // Organization-scoped path (derive org via joins) - scope := coredata.NewScope(entityID.TenantID()) - - actorRoleName, err := s.loadIdentityRoleForEntity(ctx, conn, scope, principalID, entityID) - if err != nil || !requiredRoleNamesContain(actorRoleName, requiredRoles) { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - - // Optional credential restriction (intersection) - if credentialID != nil { - switch credentialID.EntityType() { - case coredata.PersonalAPIKeyEntityType: - // Defensive check: credential must belong to actor - apiKey := &coredata.PersonalAPIKey{} - if err := apiKey.LoadByID(ctx, conn, *credentialID); err != nil { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - if apiKey.IdentityID != principalID { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - - keyRoleName, err := s.loadAPIKeyRoleForEntity(ctx, conn, scope, *credentialID, entityID) - if err != nil || !requiredRoleNamesContain(keyRoleName, requiredRoles) { - return NewInsufficientPermissionsError(principalID, entityID, action) - } - default: - return NewUnsupportedPrincipalTypeError(credentialID.EntityType()) - } - } - - return nil - }) -} - -func (s *AccessManagementService) loadIdentityRoleForEntity( - ctx context.Context, - conn pg.Conn, - scope coredata.Scoper, - identityID gid.GID, - entityID gid.GID, -) (Role, error) { - var m coredata.Membership - if err := m.LoadRoleByIdentityAndEntityID(ctx, conn, scope, identityID, entityID); err != nil { - // Do not leak existence details - if errors.Is(err, coredata.ErrResourceNotFound) { - return "", err - } - return "", err - } - return Role(m.Role.String()), nil -} - -func (s *AccessManagementService) loadAPIKeyRoleForEntity( - ctx context.Context, - conn pg.Conn, - scope coredata.Scoper, - apiKeyID gid.GID, - entityID gid.GID, -) (Role, error) { - // Load the API key to get the identity - apiKey := &coredata.PersonalAPIKey{} - if err := apiKey.LoadByID(ctx, conn, apiKeyID); err != nil { - return "", fmt.Errorf("cannot load api key: %w", err) - } - - // Use the Identity's membership role for authorization - var m coredata.Membership - if err := m.LoadRoleByIdentityAndEntityID(ctx, conn, scope, apiKey.IdentityID, entityID); err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return "", err - } - return "", err - } - return Role(m.Role.String()), nil -} - -// requiredRoleNamesContain is a temporary evaluator for the current in-code permissions registry -// (`Permissions` in `permissions.go`). In the future this becomes policy-document evaluation -// where the role name resolves to policy statements. -func requiredRoleNamesContain(roleName Role, required []Role) bool { - for _, r := range required { - if r == roleName { - return true - } - } - return false -} diff --git a/pkg/iam/authorizer.go b/pkg/iam/authorizer.go index 6d197d186..14471cecb 100644 --- a/pkg/iam/authorizer.go +++ b/pkg/iam/authorizer.go @@ -17,9 +17,7 @@ package iam import ( "context" "errors" - "fmt" "maps" - "slices" "go.gearno.de/kit/pg" "go.probo.inc/probo/pkg/coredata" @@ -27,21 +25,12 @@ import ( "go.probo.inc/probo/pkg/iam/policy" ) -// Authorizer handles authorization using the policy engine. type Authorizer struct { pg *pg.Client evaluator *policy.Evaluator policySet *PolicySet } -// NewAuthorizer creates a new authorizer. -// Services register their policies by calling RegisterPolicySet. -// -// Example: -// -// authorizer := iam.NewAuthorizer(pgClient) -// authorizer.RegisterPolicySet(iam.IAMPolicySet()) -// authorizer.RegisterPolicySet(probo.ProboPolicySet()) func NewAuthorizer(pgClient *pg.Client) *Authorizer { return &Authorizer{ pg: pgClient, @@ -50,87 +39,24 @@ func NewAuthorizer(pgClient *pg.Client) *Authorizer { } } -// RegisterPolicySet merges policies from another service into this authorizer. -// Services call this method to register their policies. func (a *Authorizer) RegisterPolicySet(policySet *PolicySet) { a.policySet.Merge(policySet) } -// AuthorizeParams contains all parameters for an authorization check. type AuthorizeParams struct { - // Principal is the user requesting access. - Principal gid.GID - - // Resource is the target resource. - Resource gid.GID - - // Action is the operation being performed (e.g., "iam:organization:get"). - Action string - - // ResourceAttributes provides additional context for condition evaluation. - // Keys like "user_id", "owner_id" are used for self-management checks. + Principal gid.GID + Resource gid.GID + Action string ResourceAttributes map[string]string } -func (a *Authorizer) GetPermissionsForMembership(ctx context.Context, identityID gid.GID, membershipID gid.GID) (map[string]map[Action]bool, error) { - var ( - scope = coredata.NewScopeFromObjectID(membershipID) - membership = &coredata.Membership{} - ) - - err := a.pg.WithConn( - ctx, - func(conn pg.Conn) error { - err := membership.LoadByID(ctx, conn, scope, membershipID) - if err != nil { - if err == coredata.ErrResourceNotFound { - return NewMembershipNotFoundError(membershipID) - } - - return fmt.Errorf("cannot load membership: %w", err) - } - - return nil - }, - ) - if err != nil { - return nil, err - } - - permissions := make(map[string]map[Action]bool) - - for entityType, actions := range Permissions { - entityTypeName, ok := coredata.EntityModel(entityType) - if !ok { - continue - } - - if permissions[entityTypeName] == nil { - permissions[entityTypeName] = make(map[Action]bool) - } - - for action, allowedRoles := range actions { - if slices.Contains(allowedRoles, Role(membership.Role)) { - permissions[entityTypeName][action] = true - } - } - } - - return permissions, nil -} - -// Authorize checks if the principal can perform the action on the resource. -// It combines self-management policies with role-based policies. func (a *Authorizer) Authorize(ctx context.Context, params AuthorizeParams) error { - // Validate principal type if params.Principal.EntityType() != coredata.IdentityEntityType { return NewUnsupportedPrincipalTypeError(params.Principal.EntityType()) } - // Build policies to evaluate policies := a.buildPolicies(ctx, params) - // Build condition context conditionCtx := policy.ConditionContext{ Principal: map[string]string{ "id": params.Principal.String(), @@ -142,7 +68,6 @@ func (a *Authorizer) Authorize(ctx context.Context, params AuthorizeParams) erro maps.Copy(conditionCtx.Resource, params.ResourceAttributes) - // Evaluate req := policy.AuthorizationRequest{ Principal: params.Principal, Resource: params.Resource, @@ -160,7 +85,6 @@ func (a *Authorizer) Authorize(ctx context.Context, params AuthorizeParams) erro return NewInsufficientPermissionsError(params.Principal, params.Resource, params.Action) } - // No match = implicit deny return NewInsufficientPermissionsError(params.Principal, params.Resource, params.Action) } diff --git a/pkg/iam/iam_actions.go b/pkg/iam/iam_actions.go index 08eda79f8..276b4200a 100644 --- a/pkg/iam/iam_actions.go +++ b/pkg/iam/iam_actions.go @@ -14,11 +14,8 @@ package iam -// Action represents a permission action string. -// Used for backward compatibility with the existing permission system. type Action = string -// IAM Service Actions const ( // Organization actions ActionIAMOrganizationCreate = "iam:organization:create" diff --git a/pkg/iam/service.go b/pkg/iam/service.go index 778ceaa92..acf7f661f 100644 --- a/pkg/iam/service.go +++ b/pkg/iam/service.go @@ -36,14 +36,13 @@ type ( privateKey *rsa.PrivateKey logger *log.Logger - AccountService *AccountService - OrganizationService *OrganizationService - SessionService *SessionService - AuthService *AuthService - SAMLService *saml.Service - APIKeyService *APIKeyService - LegacyAccessManagementService *AccessManagementService - Authorizer *Authorizer + AccountService *AccountService + OrganizationService *OrganizationService + SessionService *SessionService + AuthService *AuthService + SAMLService *saml.Service + APIKeyService *APIKeyService + Authorizer *Authorizer samlDomainVerifier *SAMLDomainVerifier } @@ -110,7 +109,6 @@ func NewService( svc.SessionService = NewSessionService(svc) svc.AuthService = NewAuthService(svc) svc.APIKeyService = NewAPIKeyService(svc) - svc.LegacyAccessManagementService = NewAccessManagementService(svc) svc.Authorizer = NewAuthorizer(pgClient) svc.Authorizer.RegisterPolicySet(IAMPolicySet()) diff --git a/pkg/probo/action_mapping.go b/pkg/probo/action_mapping.go deleted file mode 100644 index 838e6b36f..000000000 --- a/pkg/probo/action_mapping.go +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright (c) 2025 Probo Inc . -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -package probo - -import ( - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/iam" -) - -// legacyActionMapping maps entity types to a mapping of legacy actions to new namespaced actions. -// This is used during the migration period to translate old action strings to new policy actions. -var legacyActionMapping = map[uint16]map[iam.Action]iam.Action{ - coredata.OrganizationEntityType: { - iam.ActionGet: ActionOrganizationGet, - iam.ActionGetLogoUrl: ActionOrganizationGetLogoUrl, - iam.ActionGetHorizontalLogoUrl: ActionOrganizationGetHorizontalLogoUrl, - iam.ActionListDocuments: ActionDocumentList, - iam.ActionListSignableDocuments: ActionDocumentList, - iam.ActionPeoples: ActionPeopleList, - iam.ActionTotalCount: ActionOrganizationGet, - iam.ActionListFrameworks: ActionFrameworkList, - iam.ActionListControls: ActionControlList, - iam.ActionListVendors: ActionVendorList, - iam.ActionListPeople: ActionPeopleList, - iam.ActionListMeasures: ActionMeasureList, - iam.ActionListRisks: ActionRiskList, - iam.ActionListAssets: ActionAssetList, - iam.ActionListData: ActionDatumList, - iam.ActionListAudits: ActionAuditList, - iam.ActionListNonconformities: ActionNonconformityList, - iam.ActionListObligations: ActionObligationList, - iam.ActionListContinualImprovements: ActionContinualImprovementList, - iam.ActionListProcessingActivities: ActionProcessingActivityList, - iam.ActionListSnapshots: ActionSnapshotList, - iam.ActionAcceptInvitation: iam.ActionIAMInvitationAccept, - iam.ActionListTrustCenterFiles: ActionTrustCenterFileList, - iam.ActionGetTrustCenter: ActionTrustCenterGet, - iam.ActionMemberships: iam.ActionIAMOrganizationListMembers, - iam.ActionListMembers: iam.ActionIAMOrganizationListMembers, - iam.ActionListInvitations: iam.ActionIAMOrganizationListInvitations, - iam.ActionListSlackConnections: ActionSlackConnectionList, - iam.ActionGetCustomDomain: ActionCustomDomainGet, - iam.ActionListMeetings: ActionMeetingList, - iam.ActionListTasks: ActionTaskList, - iam.ActionUpdateOrganization: ActionOrganizationGet, - iam.ActionDeleteOrganizationHorizontalLogo: ActionOrganizationGet, - iam.ActionCreateTrustCenter: ActionTrustCenterGet, - iam.ActionInviteUser: iam.ActionIAMOrganizationInviteMember, - iam.ActionUpdateMembership: iam.ActionIAMMembershipUpdate, - iam.ActionCreatePeople: ActionPeopleCreate, - iam.ActionCreateVendor: ActionVendorCreate, - iam.ActionCreateFramework: ActionFrameworkCreate, - iam.ActionImportFramework: ActionFrameworkImport, - iam.ActionCreateControl: ActionControlCreate, - iam.ActionCreateMeasure: ActionMeasureCreate, - iam.ActionImportMeasure: ActionMeasureImport, - iam.ActionCreateMeeting: ActionMeetingCreate, - iam.ActionCreateTask: ActionTaskCreate, - iam.ActionCreateRisk: ActionRiskCreate, - iam.ActionCreateDocument: ActionDocumentCreate, - iam.ActionCreateAsset: ActionAssetCreate, - iam.ActionCreateDatum: ActionDatumCreate, - iam.ActionCreateAudit: ActionAuditCreate, - iam.ActionCreateNonconformity: ActionNonconformityCreate, - iam.ActionCreateObligation: ActionObligationCreate, - iam.ActionCreateContinualImprovement: ActionContinualImprovementCreate, - iam.ActionCreateProcessingActivity: ActionProcessingActivityCreate, - iam.ActionCreateSnapshot: ActionSnapshotCreate, - iam.ActionCreateTrustCenterFile: ActionTrustCenterFileCreate, - iam.ActionSendSigningNotifications: ActionDocumentSendSigningNotifications, - iam.ActionRemoveMember: iam.ActionIAMOrganizationRemoveMember, - iam.ActionCreateCustomDomain: ActionCustomDomainCreate, - iam.ActionDeleteCustomDomain: ActionCustomDomainDelete, - }, - coredata.TrustCenterEntityType: { - iam.ActionGet: ActionTrustCenterGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionUpdateTrustCenter: ActionTrustCenterUpdate, - iam.ActionUploadTrustCenterNDA: ActionTrustCenterNonDisclosureAgreementUpload, - iam.ActionDeleteTrustCenterNDA: ActionTrustCenterNonDisclosureAgreementDelete, - iam.ActionCreateTrustCenterAccess: ActionTrustCenterAccessCreate, - iam.ActionCreateTrustCenterReference: ActionTrustCenterReferenceCreate, - }, - coredata.TrustCenterAccessEntityType: { - iam.ActionUpdateTrustCenterAccess: ActionTrustCenterAccessUpdate, - iam.ActionDeleteTrustCenterAccess: ActionTrustCenterAccessDelete, - }, - coredata.TrustCenterReferenceEntityType: { - iam.ActionUpdateTrustCenterReference: ActionTrustCenterReferenceUpdate, - iam.ActionDeleteTrustCenterReference: ActionTrustCenterReferenceDelete, - }, - coredata.TrustCenterFileEntityType: { - iam.ActionUpdateTrustCenterFile: ActionTrustCenterFileUpdate, - iam.ActionDeleteTrustCenterFile: ActionTrustCenterFileDelete, - }, - coredata.IdentityEntityType: { - iam.ActionGet: iam.ActionIAMIdentityGet, - }, - coredata.MembershipEntityType: { - iam.ActionGet: iam.ActionIAMMembershipGet, - iam.ActionGetAuthMethod: iam.ActionIAMMembershipGet, - }, - coredata.InvitationEntityType: { - iam.ActionGet: iam.ActionIAMInvitationGet, - iam.ActionGetOrganization: iam.ActionIAMInvitationGet, - iam.ActionDeleteInvitation: iam.ActionIAMInvitationDelete, - }, - coredata.PeopleEntityType: { - iam.ActionGet: ActionPeopleGet, - iam.ActionUpdatePeople: ActionPeopleUpdate, - iam.ActionDeletePeople: ActionPeopleDelete, - }, - coredata.VendorEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionGetBusinessOwner: ActionPeopleGet, - iam.ActionGetSecurityOwner: ActionPeopleGet, - iam.ActionUpdateVendor: ActionVendorUpdate, - iam.ActionDeleteVendor: ActionVendorDelete, - iam.ActionCreateVendorContact: ActionVendorContactCreate, - iam.ActionCreateVendorService: ActionVendorServiceCreate, - iam.ActionUploadVendorComplianceReport: ActionVendorComplianceReportUpload, - iam.ActionUploadVendorBusinessAssociateAgreement: ActionVendorBusinessAssociateAgreementUpload, - iam.ActionDeleteVendorBusinessAssociateAgreement: ActionVendorBusinessAssociateAgreementDelete, - iam.ActionUploadVendorDataPrivacyAgreement: ActionVendorDataPrivacyAgreementUpload, - iam.ActionCreateVendorRiskAssessment: ActionVendorRiskAssessmentCreate, - iam.ActionAssessVendor: ActionVendorAssess, - }, - coredata.VendorComplianceReportEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetVendor: ActionVendorList, - iam.ActionDeleteVendorComplianceReport: ActionVendorComplianceReportDelete, - }, - coredata.VendorBusinessAssociateAgreementEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetVendor: ActionVendorList, - iam.ActionGetFileUrl: ActionFileDownloadUrl, - iam.ActionUpdateVendorBusinessAssociateAgreement: ActionVendorBusinessAssociateAgreementUpdate, - iam.ActionDeleteVendorBusinessAssociateAgreement: ActionVendorBusinessAssociateAgreementDelete, - }, - coredata.VendorContactEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetVendor: ActionVendorList, - iam.ActionUpdateVendorContact: ActionVendorContactUpdate, - iam.ActionDeleteVendorContact: ActionVendorContactDelete, - }, - coredata.VendorServiceEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetVendor: ActionVendorList, - iam.ActionUpdateVendorService: ActionVendorServiceUpdate, - iam.ActionDeleteVendorService: ActionVendorServiceDelete, - }, - coredata.VendorDataPrivacyAgreementEntityType: { - iam.ActionGet: ActionVendorList, - iam.ActionGetVendor: ActionVendorList, - iam.ActionGetFileUrl: ActionFileDownloadUrl, - iam.ActionUpdateVendorDataPrivacyAgreement: ActionVendorDataPrivacyAgreementUpdate, - iam.ActionDeleteVendorDataPrivacyAgreement: ActionVendorDataPrivacyAgreementDelete, - }, - coredata.VendorRiskAssessmentEntityType: { - iam.ActionGet: ActionVendorList, - }, - coredata.FrameworkEntityType: { - iam.ActionGet: ActionFrameworkGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionListControls: ActionControlList, - iam.ActionCreateControl: ActionControlCreate, - iam.ActionUpdateFramework: ActionFrameworkUpdate, - iam.ActionDeleteFramework: ActionFrameworkDelete, - iam.ActionGenerateFrameworkStateOfApplicability: ActionFrameworkStateOfApplicabilityGenerate, - iam.ActionExportFramework: ActionFrameworkExport, - }, - coredata.ControlEntityType: { - iam.ActionGet: ActionControlList, - iam.ActionGetFramework: ActionFrameworkGet, - iam.ActionListMeasures: ActionMeasureList, - iam.ActionListDocuments: ActionDocumentList, - iam.ActionListAudits: ActionAuditList, - iam.ActionListSnapshots: ActionSnapshotList, - iam.ActionUpdateControl: ActionControlUpdate, - iam.ActionDeleteControl: ActionControlDelete, - iam.ActionCreateControlMeasureMapping: ActionControlMeasureMappingCreate, - iam.ActionCreateControlDocumentMapping: ActionControlDocumentMappingCreate, - iam.ActionDeleteControlMeasureMapping: ActionControlMeasureMappingDelete, - iam.ActionDeleteControlDocumentMapping: ActionControlDocumentMappingDelete, - iam.ActionCreateControlAuditMapping: ActionControlAuditMappingCreate, - iam.ActionDeleteControlAuditMapping: ActionControlAuditMappingDelete, - iam.ActionCreateControlSnapshotMapping: ActionControlSnapshotMappingCreate, - iam.ActionDeleteControlSnapshotMapping: ActionControlSnapshotMappingDelete, - }, - coredata.MeasureEntityType: { - iam.ActionGet: ActionMeasureGet, - iam.ActionListTasks: ActionTaskList, - iam.ActionListEvidences: ActionEvidenceList, - iam.ActionListRisks: ActionRiskList, - iam.ActionListControls: ActionControlList, - iam.ActionTotalCount: ActionMeasureList, - iam.ActionUpdateMeasure: ActionMeasureUpdate, - iam.ActionDeleteMeasure: ActionMeasureDelete, - iam.ActionUploadMeasureEvidence: ActionMeasureEvidenceUpload, - }, - coredata.TaskEntityType: { - iam.ActionGet: ActionTaskGet, - iam.ActionGetAssignedTo: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionGetMeasure: ActionMeasureGet, - iam.ActionListEvidences: ActionEvidenceList, - iam.ActionUpdateTask: ActionTaskUpdate, - iam.ActionDeleteTask: ActionTaskDelete, - iam.ActionAssignTask: ActionTaskAssign, - iam.ActionUnassignTask: ActionTaskUnassign, - }, - coredata.EvidenceEntityType: { - iam.ActionGet: ActionEvidenceList, - iam.ActionGetFile: ActionFileGet, - iam.ActionGetTask: ActionTaskGet, - iam.ActionGetMeasure: ActionMeasureList, - iam.ActionDeleteEvidence: ActionEvidenceDelete, - }, - coredata.DocumentEntityType: { - iam.ActionGet: ActionDocumentGet, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionGetSigned: ActionDocumentList, - iam.ActionGetSignableDocument: ActionDocumentList, - iam.ActionListSignableDocumentVersion: ActionDocumentList, - iam.ActionBulkExportDocuments: ActionDocumentList, - iam.ActionTotalCount: ActionDocumentList, - iam.ActionListControls: ActionControlList, - iam.ActionListVersions: ActionDocumentVersionList, - iam.ActionUpdateDocument: ActionDocumentUpdate, - iam.ActionDeleteDocument: ActionDocumentDelete, - iam.ActionBulkDeleteDocuments: ActionDocumentDelete, - iam.ActionPublishDocumentVersion: ActionDocumentVersionPublish, - iam.ActionBulkPublishDocumentVersions: ActionDocumentVersionPublish, - iam.ActionGenerateDocumentChangelog: ActionDocumentChangelogGenerate, - iam.ActionCreateDraftDocumentVersion: ActionDocumentDraftVersionCreate, - iam.ActionDeleteDraftDocumentVersion: ActionDocumentVersionDeleteDraft, - iam.ActionUpdateDocumentVersion: ActionDocumentVersionUpdate, - iam.ActionRequestSignature: ActionDocumentVersionSignatureRequest, - iam.ActionBulkRequestSignatures: ActionDocumentVersionSignatureRequest, - iam.ActionSendSigningNotifications: ActionDocumentSendSigningNotifications, - iam.ActionCancelSignatureRequest: ActionDocumentVersionCancelSignature, - }, - coredata.DocumentVersionEntityType: { - iam.ActionGet: ActionDocumentVersionGet, - iam.ActionGetFile: ActionFileGet, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetDocument: ActionDocumentGet, - iam.ActionGetSigned: ActionDocumentVersionGet, - iam.ActionSignatures: ActionDocumentVersionSignatureList, - iam.ActionExportDocumentVersionPDF: ActionDocumentVersionExportPDF, - iam.ActionExportSignableVersionDocumentPDF: ActionDocumentVersionExportSignable, - iam.ActionSignDocument: ActionDocumentVersionSign, - iam.ActionUpdateDocumentVersion: ActionDocumentVersionUpdate, - iam.ActionRequestSignature: ActionDocumentVersionSignatureRequest, - iam.ActionDeleteDraftDocumentVersion: ActionDocumentVersionDeleteDraft, - }, - coredata.DocumentVersionSignatureEntityType: { - iam.ActionGet: ActionDocumentVersionSignatureList, - iam.ActionDocumentVersion: ActionDocumentVersionGet, - iam.ActionSignedBy: ActionPeopleGet, - }, - coredata.RiskEntityType: { - iam.ActionGet: ActionRiskList, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionTotalCount: ActionRiskList, - iam.ActionListControls: ActionControlList, - iam.ActionListMeasures: ActionMeasureList, - iam.ActionListDocuments: ActionDocumentList, - iam.ActionListObligations: ActionObligationList, - iam.ActionUpdateRisk: ActionRiskUpdate, - iam.ActionDeleteRisk: ActionRiskDelete, - iam.ActionCreateRiskMeasureMapping: ActionRiskMeasureMappingCreate, - iam.ActionDeleteRiskMeasureMapping: ActionRiskMeasureMappingDelete, - iam.ActionCreateRiskDocumentMapping: ActionRiskDocumentMappingCreate, - iam.ActionDeleteRiskDocumentMapping: ActionRiskDocumentMappingDelete, - iam.ActionCreateRiskObligationMapping: ActionRiskObligationMappingCreate, - iam.ActionDeleteRiskObligationMapping: ActionRiskObligationMappingDelete, - }, - coredata.AssetEntityType: { - iam.ActionGet: ActionAssetList, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionListVendors: ActionVendorList, - iam.ActionGetAssetType: ActionAssetList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionUpdateAsset: ActionAssetUpdate, - iam.ActionDeleteAsset: ActionAssetDelete, - }, - coredata.DatumEntityType: { - iam.ActionGet: ActionDatumList, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionListVendors: ActionVendorList, - iam.ActionUpdateDatum: ActionDatumUpdate, - iam.ActionDeleteDatum: ActionDatumDelete, - }, - coredata.AuditEntityType: { - iam.ActionGet: ActionAuditGet, - iam.ActionGetFile: ActionFileGet, - iam.ActionGetFramework: ActionFrameworkGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionReport: ActionAuditList, - iam.ActionReportUrl: ActionAuditList, - iam.ActionListControls: ActionControlList, - iam.ActionUpdateAudit: ActionAuditUpdate, - iam.ActionDeleteAudit: ActionAuditDelete, - iam.ActionUploadAuditReport: ActionAuditReportUpload, - iam.ActionDeleteAuditReport: ActionAuditReportDelete, - }, - coredata.ReportEntityType: { - iam.ActionGet: ActionReportGet, - iam.ActionGetAudit: ActionAuditGet, - iam.ActionGetFile: ActionFileGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionGetSnapshot: ActionSnapshotList, - iam.ActionDownloadUrl: ActionReportDownloadUrlGet, - }, - coredata.NonconformityEntityType: { - iam.ActionGet: ActionNonconformityList, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionAudit: ActionAuditList, - iam.ActionUpdateNonconformity: ActionNonconformityUpdate, - iam.ActionDeleteNonconformity: ActionNonconformityDelete, - }, - coredata.ObligationEntityType: { - iam.ActionGet: ActionObligationList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionListRisks: ActionRiskList, - iam.ActionUpdateObligation: ActionObligationUpdate, - iam.ActionDeleteObligation: ActionObligationDelete, - }, - coredata.ContinualImprovementEntityType: { - iam.ActionGet: ActionContinualImprovementList, - iam.ActionGetOwner: ActionPeopleGet, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionUpdateContinualImprovement: ActionContinualImprovementUpdate, - iam.ActionDeleteContinualImprovement: ActionContinualImprovementDelete, - }, - coredata.ProcessingActivityEntityType: { - iam.ActionGet: ActionProcessingActivityList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionListVendors: ActionVendorList, - iam.ActionUpdateProcessingActivity: ActionProcessingActivityUpdate, - iam.ActionDeleteProcessingActivity: ActionProcessingActivityDelete, - }, - coredata.SnapshotEntityType: { - iam.ActionGet: ActionSnapshotList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionListControls: ActionControlList, - iam.ActionDeleteSnapshot: ActionSnapshotDelete, - }, - coredata.CustomDomainEntityType: { - iam.ActionGet: ActionCustomDomainGet, - iam.ActionDeleteCustomDomain: ActionCustomDomainDelete, - }, - coredata.FileEntityType: { - iam.ActionGet: ActionFileGet, - iam.ActionDownloadUrl: ActionFileDownloadUrl, - }, - coredata.MeetingEntityType: { - iam.ActionGet: ActionMeetingList, - iam.ActionGetOrganization: ActionOrganizationGet, - iam.ActionTotalCount: ActionMeetingList, - iam.ActionUpdateMeeting: ActionMeetingUpdate, - iam.ActionDeleteMeeting: ActionMeetingDelete, - }, -} - -// MapLegacyAction converts a legacy action string to a new namespaced action. -// Returns the new action and true if found, or empty string and false if not mapped. -func MapLegacyAction(entityType uint16, legacyAction iam.Action) (iam.Action, bool) { - if entityActions, ok := legacyActionMapping[entityType]; ok { - if newAction, ok := entityActions[legacyAction]; ok { - return newAction, true - } - } - return "", false -} diff --git a/pkg/server/api/console/v1/resolver.go b/pkg/server/api/console/v1/resolver.go index 4b56844cb..e977a751f 100644 --- a/pkg/server/api/console/v1/resolver.go +++ b/pkg/server/api/console/v1/resolver.go @@ -309,15 +309,12 @@ func NewMux( } func (r *Resolver) ProboService(ctx context.Context, tenantID gid.TenantID) *probo.TenantService { - return GetTenantService(ctx, r.probo, tenantID) -} - -func GetTenantService(ctx context.Context, proboSvc *probo.Service, tenantID gid.TenantID) *probo.TenantService { - return proboSvc.WithTenant(tenantID) + return r.probo.WithTenant(tenantID) } func (r *Resolver) MustAuthorize(ctx context.Context, entityID gid.GID, action iam.Action) { - user := connect_v1.IdentityFromContext(ctx) + identity := connect_v1.IdentityFromContext(ctx) + // TODO: Add API key authorization // apiKey := connect_v1.APIKeyFromContext(ctx) // var credentialID *gid.GID @@ -328,7 +325,7 @@ func (r *Resolver) MustAuthorize(ctx context.Context, entityID gid.GID, action i err := r.iam.Authorizer.Authorize( ctx, iam.AuthorizeParams{ - Principal: user.ID, + Principal: identity.ID, Resource: entityID, Action: action, },