Skip to content

Commit

Permalink
[backend] add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marieflorescontact committed Feb 7, 2025
1 parent 3f7ccd8 commit 8a92bf2
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 143 deletions.
24 changes: 15 additions & 9 deletions opencti-platform/opencti-graphql/src/utils/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,12 @@ const isEntityOrganizationsAllowed = (
entityInternalId: string,
entityOrganizations: string[],
user: AuthUser,
settings: BasicStoreSettings,
hasPlatformOrg: boolean,
opts: { useStandardId?: boolean } = {}
) => {
const { useStandardId = false } = opts;
// If platform organization is set
if (settings.platform_organization) {
if (hasPlatformOrg) {
const userOrganizations = user.organizations.map((o) => (useStandardId ? o.standard_id : o.internal_id));

// If user part of platform organization, is granted by default
Expand All @@ -479,9 +479,10 @@ const isEntityOrganizationsAllowed = (
return true;
};

export const isOrganizationAllowed = (element: BasicStoreCommon, user: AuthUser, settings: BasicStoreSettings) => {
export const isOrganizationAllowed = (element: BasicStoreCommon, user: AuthUser, platformOrganization: string) => {
const elementOrganizations = element[RELATION_GRANTED_TO] ?? [];
return isEntityOrganizationsAllowed(element.internal_id, elementOrganizations, user, settings);
const hasPlatformOrg = !!platformOrganization;
return isEntityOrganizationsAllowed(element.internal_id, elementOrganizations, user, hasPlatformOrg);
};

const isOrganizationUnrestrictedForEntityType = (entityType: string) => {
Expand Down Expand Up @@ -511,7 +512,7 @@ export const canRequestAccess = async (context: AuthContext, user: AuthUser, ele
const settings = await getEntityFromCache<BasicStoreSettings>(context, user, ENTITY_TYPE_SETTINGS);
const elementsThatRequiresAccess: Array<BasicStoreCommon> = [];
for (let i = 0; i < elements.length; i += 1) {
if (!isOrganizationAllowed(elements[i], user, settings)) {
if (!isOrganizationAllowed(elements[i], user, settings.platform_organization)) {
elementsThatRequiresAccess.push(elements[i]);
}
// TODO before removing ORGA_SHARING_REQUEST_FF: When it's ready check Authorized members
Expand Down Expand Up @@ -544,7 +545,7 @@ export const userFilterStoreElements = async (context: AuthContext, user: AuthUs
}
// Check restricted elements
// either allowed by orga sharing or has authorized members access if authorized_members are defined (bypass orga sharing)
return isOrganizationAllowed(element, user, settings)
return isOrganizationAllowed(element, user, settings.platform_organization)
|| (element.authorized_members && element.authorized_members.length > 0 && hasAuthorizedMemberAccess(user, element));
});
};
Expand All @@ -559,7 +560,7 @@ export const isUserCanAccessStoreElement = async (context: AuthContext, user: Au
return elements.length === 1;
};

export const isUserCanAccessStixElement = async (context: AuthContext, user: AuthUser, instance: StixObject) => {
export const checkUserCanAccessStixElement = async (context: AuthContext, user: AuthUser, instance: StixObject, hasPlatformOrg: boolean) => {
// If user have bypass, grant access to all
if (isBypassUser(user)) {
return true;
Expand All @@ -586,12 +587,17 @@ export const isUserCanAccessStixElement = async (context: AuthContext, user: Aut
return true;
}
// Check restricted elements
const settings = await getEntityFromCache<BasicStoreSettings>(context, user, ENTITY_TYPE_SETTINGS);
const elementOrganizations = instance.extensions?.[STIX_EXT_OCTI]?.granted_refs ?? [];
const organizationAllowed = isEntityOrganizationsAllowed(instance.id, elementOrganizations, user, settings, { useStandardId: true });
const organizationAllowed = isEntityOrganizationsAllowed(instance.id, elementOrganizations, user, hasPlatformOrg, { useStandardId: true });
// either allowed by organization or authorized members
return organizationAllowed || (authorized_members.length > 0 && authorizedMemberAllowed);
};

export const isUserCanAccessStixElement = async (context: AuthContext, user: AuthUser, instance: StixObject) => {
const settings = await getEntityFromCache<BasicStoreSettings>(context, user, ENTITY_TYPE_SETTINGS);
const hasPlatformOrg = !!settings.platform_organization;
return checkUserCanAccessStixElement(context, user, instance, hasPlatformOrg);
};
// end region

// region member access
Expand Down
128 changes: 0 additions & 128 deletions opencti-platform/opencti-graphql/tests/01-unit/database/utils-test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { describe, expect, it } from 'vitest';
import { extractObjectsRestrictionsFromInputs } from '../../../src/database/utils';
import { ENTITY_TYPE_CONTAINER_REPORT, ENTITY_TYPE_MALWARE } from '../../../src/schema/stixDomainObject';
import { testContext } from '../../utils/testQuery';
import { ADMINISTRATOR_ROLE, BYPASS, isUserCanAccessStixElement } from '../../../src/utils/access';

const inputs = [
{
Expand Down Expand Up @@ -136,121 +134,6 @@ const relInputs = [
}
];

const report = {
id: 'report--f3e554eb-60f5-587c-9191-4f25e9ba9f32',
spec_version: '2.1',
type: 'report',
extensions: {
'extension-definition--ea279b3e-5c71-4632-ac08-831c66a786ba': {
extension_type: 'property-extension',
id: 'f13cd64f-9268-4d77-9850-eb6fbe322463',
type: 'Report',
created_at: '2023-10-05T07:57:03.543Z',
updated_at: '2023-11-02T16:20:16.653Z',
files: [],
stix_ids: [
'report--a445d22a-db0c-4b5d-9ec8-e9ad0b6dbdd7'
],
is_inferred: false,
creator_ids: [
'88ec0c6a-13ce-5e39-b486-354fe4a7084f'
],
workflow_id: 'bd156107-1f9a-43df-9595-574c467e9e21',
content: '<p>dddddddrrrr</p>'
},
authorized_members: [
{
id: '88ec0c6a-13ce-5e39-b486-354fe4a7084f',
access_right: 'admin'
},
{
id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
access_right: 'view'
},
],
},
created: '2020-03-01T14:02:48.111Z',
modified: '2023-11-02T16:20:16.653Z',
revoked: false,
confidence: 3,
lang: 'en',
labels: [
'report'
],
object_marking_refs: [
'marking-definition--907bb632-e3c2-52fa-b484-cf166a7d377c'
],
created_by_ref: 'identity--18fe5225-fee1-5627-ad3e-20c14435b024',
external_references: [],
published: '2020-03-01T14:02:48.111Z',
object_refs: []
};

const user_is_allowed = {
administrated_organizations: [],
entity_type: 'User',
id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
internal_id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
individual_id: undefined,
organizations: [],
name: '',
user_email: '',
roles: [ADMINISTRATOR_ROLE],
groups: [],
capabilities: [{ name: BYPASS }],
all_marking: [],
inside_platform_organization: true,
allowed_marking: [],
default_marking: [],
origin: { referer: 'test', user_id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f' },
api_token: 'd434ce02-e58e-4cac-8b4c-42bf16748e56',
account_status: '',
account_lock_after_date: undefined,
effective_confidence_level: {
max_confidence: 100,
overrides: [],
},
user_confidence_level: {
max_confidence: 100,
overrides: [],
},
max_shareable_marking: [],
restrict_delete: false,
no_creators: false,
};

const user_is_not_allowed = {
administrated_organizations: [],
entity_type: 'User',
id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f',
internal_id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f',
individual_id: undefined,
organizations: [],
name: '',
user_email: '',
roles: [ADMINISTRATOR_ROLE],
groups: [],
capabilities: [{ name: BYPASS }],
all_marking: [],
inside_platform_organization: false,
allowed_marking: [],
default_marking: [],
origin: { referer: 'test', user_id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f' },
api_token: 'd434ce02-e58e-4cac-8b4c-42bf16748e48',
account_status: '',
account_lock_after_date: undefined,
effective_confidence_level: {
max_confidence: 100,
overrides: [],
},
user_confidence_level: {
max_confidence: 100,
overrides: [],
},
max_shareable_marking: [],
restrict_delete: false,
no_creators: false,
};
describe('extractObjectsRestrictionsFromInputs testing', () => {
it('should add inputs object-marking in stream when adding entity to a report', () => {
const relatedRestrictions = extractObjectsRestrictionsFromInputs(inputs, ENTITY_TYPE_CONTAINER_REPORT);
Expand All @@ -268,14 +151,3 @@ describe('extractObjectsRestrictionsFromInputs testing', () => {
expect(relatedRestrictions).toEqual(expected);
});
});

describe('isUserCanAccessStixElement testing', async () => {
it('user in auth members should access element', async () => {
const hasAccess = await isUserCanAccessStixElement(testContext, user_is_allowed, report);
expect(hasAccess).toEqual(true);
});
it('user not in auth members should not access element', async () => {
const hasAccess = await isUserCanAccessStixElement(testContext, user_is_not_allowed, report);
expect(hasAccess).toEqual(false);
});
});
116 changes: 110 additions & 6 deletions opencti-platform/opencti-graphql/tests/01-unit/utils/access-test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,106 @@
import { describe, it, expect } from 'vitest';
import { v4 as uuid } from 'uuid';
import { isMarkingAllowed, isOrganizationAllowed } from '../../../src/utils/access';
import { ADMINISTRATOR_ROLE, checkUserCanAccessStixElement, isMarkingAllowed, isOrganizationAllowed, KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS } from '../../../src/utils/access';
import type { BasicStoreCommon } from '../../../src/types/store';
import { MARKING_TLP_AMBER, MARKING_TLP_CLEAR, MARKING_TLP_GREEN, MARKING_TLP_RED } from '../../../src/schema/identifier';
import type { AuthUser } from '../../../src/types/user';
import type { BasicStoreSettings } from '../../../src/types/settings';
import { PLATFORM_ORGANIZATION, TEST_ORGANIZATION } from '../../utils/testQuery';
import { PLATFORM_ORGANIZATION, TEST_ORGANIZATION, testContext } from '../../utils/testQuery';
import { RELATION_GRANTED_TO } from '../../../src/schema/stixRefRelationship';
import type { BasicStoreEntityOrganization } from '../../../src/modules/organization/organization-types';
import type { StixObject } from '../../../src/types/stix-common';

const report = {
id: 'report--f3e554eb-60f5-587c-9191-4f25e9ba9f32',
spec_version: '2.1',
type: 'report',
extensions: {
'extension-definition--ea279b3e-5c71-4632-ac08-831c66a786ba': {
extension_type: 'property-extension',
id: 'f13cd64f-9268-4d77-9850-eb6fbe322463',
type: 'Report',
creator_ids: [
'88ec0c6a-13ce-5e39-b486-354fe4a7084f'
],
authorized_members: [
{
id: '88ec0c6a-13ce-5e39-b486-354fe4a7084f',
access_right: 'admin'
},
{
id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
access_right: 'view'
},
],
},
},
} as unknown as StixObject;

const user_is_allowed = {
administrated_organizations: [],
entity_type: 'User',
id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
internal_id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f',
individual_id: undefined,
organizations: [],
name: '',
user_email: '',
roles: [ADMINISTRATOR_ROLE],
groups: [],
capabilities: [{ name: KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS }],
all_marking: [],
inside_platform_organization: true,
allowed_marking: [],
default_marking: [],
origin: { referer: 'test', user_id: '55ec0c6a-13ce-5e39-b486-354fe4a7084f' },
api_token: 'd434ce02-e58e-4cac-8b4c-42bf16748e56',
account_status: '',
account_lock_after_date: undefined,
effective_confidence_level: {
max_confidence: 100,
overrides: [],
},
user_confidence_level: {
max_confidence: 100,
overrides: [],
},
max_shareable_marking: [],
restrict_delete: false,
no_creators: false,
};

const user_is_not_allowed = {
administrated_organizations: [],
entity_type: 'User',
id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f',
internal_id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f',
individual_id: undefined,
organizations: [],
name: '',
user_email: '',
roles: [ADMINISTRATOR_ROLE],
groups: [],
capabilities: [{ name: KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS, }],
all_marking: [],
inside_platform_organization: false,
allowed_marking: [],
default_marking: [],
origin: { referer: 'test', user_id: '48ec0c6a-13ce-5e39-b486-354fe4a7084f' },
api_token: 'd434ce02-e58e-4cac-8b4c-42bf16748e48',
account_status: '',
account_lock_after_date: undefined,
effective_confidence_level: {
max_confidence: 100,
overrides: [],
},
user_confidence_level: {
max_confidence: 100,
overrides: [],
},
max_shareable_marking: [],
restrict_delete: false,
no_creators: false,
};

describe('Check markings test coverage', () => {
it('should element with no marking be allowed', async () => {
Expand Down Expand Up @@ -66,7 +159,7 @@ describe('Check organization access for element.', () => {
platform_organization: undefined,
};

expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings as BasicStoreSettings)).toBeTruthy();
expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings.platform_organization as string)).toBeTruthy();
});

it('should element not shared be allowed to user in platform organization', async () => {
Expand All @@ -90,7 +183,7 @@ describe('Check organization access for element.', () => {
platform_organization: PLATFORM_ORGANIZATION.name,
};

expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings as BasicStoreSettings)).toBeTruthy();
expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings.platform_organization as string)).toBeTruthy();
});

it('should element not shared not be allowed to user in another organization', async () => {
Expand All @@ -114,7 +207,7 @@ describe('Check organization access for element.', () => {
platform_organization: PLATFORM_ORGANIZATION.name,
};

expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings as BasicStoreSettings)).toBeFalsy();
expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings.platform_organization as string)).toBeFalsy();
});

it('should element shared to user organization be allowed', async () => {
Expand All @@ -140,6 +233,17 @@ describe('Check organization access for element.', () => {
platform_organization: PLATFORM_ORGANIZATION.name,
};

expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings as BasicStoreSettings)).toBeTruthy();
expect(isOrganizationAllowed(element as BasicStoreCommon, user as AuthUser, settings.platform_organization as string)).toBeTruthy();
});
});

describe('checkUserCanAccessStixElement testing', async () => {
it('user in auth members should access element', async () => {
const hasAccess = await checkUserCanAccessStixElement(testContext, user_is_allowed, report, true);
expect(hasAccess).toEqual(true);
});
it('user not in auth members should not access element', async () => {
const hasAccess = await checkUserCanAccessStixElement(testContext, user_is_not_allowed, report, true);
expect(hasAccess).toEqual(false);
});
});

0 comments on commit 8a92bf2

Please sign in to comment.