Skip to content

Commit

Permalink
fix: Add support for multiple operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Arun-KumarH committed Nov 21, 2023
1 parent 2678972 commit 5cad029
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 40 deletions.
32 changes: 13 additions & 19 deletions src/core/hierarchicalScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ export const checkHierarchicalScope = async (ruleTarget: Target,

const ctxResources = context.resources || [];
const reqTarget = request.target;
let currentResourceEntity: string;
let entityOrOperation: string;
// iterating through all targeted resources and retrieve relevant owners instances
for (let attribute of ruleTarget.resources || []) {
if (attribute?.id == urns.get('entity')) { // resource type found
logger.debug('Evaluating resource entity match');
currentResourceEntity = attribute?.value;
entityOrOperation = attribute?.value;

let entitiesMatch = false;
// iterating request resources to filter all resources of a given type
for (let requestAttribute of reqTarget.resources || []) {
if (requestAttribute?.id == attribute?.id && requestAttribute?.value == currentResourceEntity) {
if (requestAttribute?.id == attribute?.id && requestAttribute?.value == entityOrOperation) {
entitiesMatch = true; // a resource entity that matches the request and the rule's target
} else if (requestAttribute?.id == attribute?.id) {
// rule entity, get ruleNS and entityRegexValue for rule
const value = currentResourceEntity;
const value = entityOrOperation;
let pattern = value?.substring(value?.lastIndexOf(':') + 1);
let nsEntityArray = pattern?.split('.');
// firstElement could be either entity or namespace
Expand Down Expand Up @@ -104,7 +104,6 @@ export const checkHierarchicalScope = async (ruleTarget: Target,
const instanceID = requestAttribute?.value;
// found resource instance ID, iterating through the context to check if owners entities match the scoping entities
let ctxResource: Resource = _.find(ctxResources, ['instance.id', instanceID]);
// ctxResource = ctxResource.instance;
if (ctxResource) {
ctxResource = ctxResource?.instance;
} else {
Expand All @@ -122,38 +121,33 @@ export const checkHierarchicalScope = async (ruleTarget: Target,
logger.debug('Resource of targeted entity was not provided in context');
return false; // resource of targeted entity was not provided in context
}
// entitiesMatch = false;
}
}
} else if (attribute?.id === urns.get('operation')) {
logger.debug('Evaluating resource operation match');
currentResourceEntity = attribute?.value;
entityOrOperation = attribute?.value;
for (let reqAttribute of reqTarget.resources || []) {
// match Rule resource operation URN and operation name with request resource operation URN and operation name
if (reqAttribute?.id === attribute?.id && reqAttribute?.value === attribute?.value) {
if (ctxResources?.length === 1) {
let meta;
if (ctxResources[0]?.instance) {
meta = ctxResources[0]?.instance?.meta;
} else if (ctxResources[0]?.meta) {
meta = ctxResources[0].meta;
}

// find context resource based
let ctxResource: Resource = _.find(ctxResources, ['id', entityOrOperation]);
if (ctxResource) {
const meta = ctxResource.meta;
if (_.isEmpty(meta) || _.isEmpty(meta.owners)) {
logger.debug(`Owner information missing for hierarchical scope matching of operation ${attribute.value}, evaluation fails`);
logger.debug(`Owners information missing for hierarchical scope matching of entity ${attribute.value}, evaluation fails`);
return false; // no ownership was passed, evaluation fails
}
scopedRoles = updateScopedRoles(meta, scopedRoles, urns, totalScopingEntities);
} else {
logger.debug('Invalid resource passed', { resource: ctxResources });
return false;
logger.debug('Operation name was not provided in context');
return false; // Operation name was not provided in context
}
}
}
}
}

if (_.isNil(currentResourceEntity) || _.isEmpty(currentResourceEntity)) {
if (_.isNil(entityOrOperation) || _.isEmpty(entityOrOperation)) {
logger.debug('No Entity or operation name found');
return false; // no entity found
}
Expand Down
8 changes: 4 additions & 4 deletions test/core.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { createServiceConfig } from '@restorecommerce/service-config';
import { createLogger } from '@restorecommerce/logger';
import { Events } from '@restorecommerce/kafka-client';
import { createChannel, createClient } from '@restorecommerce/grpc-client';
import { UserServiceDefinition, UserServiceClient } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/user';
import { UserServiceDefinition, UserServiceClient } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/user';
import { Request, Response, Response_Decision } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/access_control';

const cfg = createServiceConfig(process.cwd() + '/test');
Expand Down Expand Up @@ -517,7 +517,7 @@ describe('Testing access control core', () => {
roleScopingEntity: 'urn:restorecommerce:acs:model:organization.Organization',
roleScopingInstance: 'Org1',
resourceType: 'mutation.executeTestMutation',
resourceID: 'TestMutate 1',
resourceID: 'mutation.executeTestMutation',
actionType: 'urn:restorecommerce:acs:names:action:execute',
ownerIndicatoryEntity: 'urn:restorecommerce:acs:model:organization.Organization',
ownerInstance: 'Org1'
Expand All @@ -531,7 +531,7 @@ describe('Testing access control core', () => {
roleScopingEntity: 'urn:restorecommerce:acs:model:organization.Organization',
roleScopingInstance: 'Org2',
resourceType: 'mutation.executeTestMutation',
resourceID: 'TestMutate 1',
resourceID: 'mutation.executeTestMutation',
actionType: 'urn:restorecommerce:acs:names:action:execute',
ownerIndicatoryEntity: 'urn:restorecommerce:acs:model:organization.Organization',
ownerInstance: 'Org1'
Expand All @@ -545,7 +545,7 @@ describe('Testing access control core', () => {
roleScopingEntity: 'urn:restorecommerce:acs:model:organization.Organization',
roleScopingInstance: 'Org1',
resourceType: 'mutation.executeTestMutation',
resourceID: 'TestMutate 1',
resourceID: 'mutation.executeTestMutation',
actionType: 'urn:restorecommerce:acs:names:action:execute',
ownerIndicatoryEntity: 'urn:restorecommerce:acs:model:organization.Organization',
ownerInstance: 'Org1'
Expand Down
47 changes: 47 additions & 0 deletions test/fixtures/multiple_operations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
policy_sets:
- id: policySet
name: Global policy set containing 2 policies
description: A policy set
combining_algorithm: urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides
policies:
- id: ExecutePolicy
name: Execute Policy
description: Policy with two rules targeting two Operations
combining_algorithm: urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides
rules:
- id: ruleAA1
name: Rule AA1
descripton: A rule targeting a execute action by a SimpleUser for `mutation.Test1`
target:
subjects:
- id: urn:restorecommerce:acs:names:role
value: SimpleUser
- id: urn:restorecommerce:acs:names:roleScopingEntity
value: urn:restorecommerce:acs:model:organization.Organization
resources:
- id: urn:restorecommerce:acs:names:operation
value: mutation.Test1
actions:
- id: urn:oasis:names:tc:xacml:1.0:action:action-id
value: urn:restorecommerce:acs:names:action:execute
effect: PERMIT
- id: ruleAA2
name: Rule AA2
descripton: A rule targeting a execute action by a SimpleUser for `mutation.Test2`
target:
subjects:
- id: urn:restorecommerce:acs:names:role
value: SimpleUser
- id: urn:restorecommerce:acs:names:roleScopingEntity
value: urn:restorecommerce:acs:model:organization.Organization
resources:
- id: urn:restorecommerce:acs:names:operation
value: mutation.Test1
actions:
- id: urn:oasis:names:tc:xacml:1.0:action:action-id
value: urn:restorecommerce:acs:names:action:execute
effect: PERMIT
- id: ruleAA3
name: Fallback rule
description: Always deny
effect: DENY
Loading

0 comments on commit 5cad029

Please sign in to comment.