Skip to content

Commit

Permalink
[backend] Improve markings edition control
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-julien authored Feb 6, 2025
1 parent af2ab56 commit dd15d8f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
20 changes: 19 additions & 1 deletion opencti-platform/opencti-graphql/src/database/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ import {
storeLoadById
} from './middleware-loader';
import { checkRelationConsistency, isRelationConsistent } from '../utils/modelConsistency';
import { getEntitiesListFromCache, getEntityFromCache } from './cache';
import { getEntitiesListFromCache, getEntitiesMapFromCache, getEntityFromCache } from './cache';
import { ACTION_TYPE_SHARE, ACTION_TYPE_UNSHARE, createListTask } from '../domain/backgroundTask-common';
import { ENTITY_TYPE_VOCABULARY, vocabularyDefinitions } from '../modules/vocabulary/vocabulary-types';
import { getVocabulariesCategories, getVocabularyCategoryForField, isEntityFieldAnOpenVocabulary, updateElasticVocabularyValue } from '../modules/vocabulary/vocabulary-utils';
Expand Down Expand Up @@ -705,6 +705,24 @@ export const validateCreatedBy = async (context, user, createdById) => {
}
};

/**
* Verify that the Entity in Marking is one of user allowed
* @param context
* @param user
* @param markingId
*/
export const validateMarking = async (context, user, markingId) => {
if (isBypassUser(user)) {
return;
}
const markings = await getEntitiesMapFromCache(context, SYSTEM_USER, ENTITY_TYPE_MARKING_DEFINITION);
const userMarking = (user.allowed_marking || []).map((m) => markings.get(m.internal_id)).filter((m) => isNotEmptyField(m));
const userMarkingIds = userMarking.map((marking) => extractIdsFromStoreObject(marking)).flat();
if (!userMarkingIds.includes(markingId)) {
throw FunctionalError('User trying to create the data has missing markings', { id: markingId });
}
};

const inputResolveRefs = async (context, user, input, type, entitySetting) => {
const inputResolveRefsFn = async () => {
const fetchingIds = [];
Expand Down
19 changes: 13 additions & 6 deletions opencti-platform/opencti-graphql/src/domain/stixDomainObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
timeSeriesEntities,
updateAttribute,
updateAttributeFromLoadedWithRefs,
validateCreatedBy
validateCreatedBy,
validateMarking
} from '../database/middleware';
import { listAllToEntitiesThroughRelations, listEntities, listEntitiesThroughRelationsPaginated, storeLoadById } from '../database/middleware-loader';
import { elCount, elFindByIds } from '../database/engine';
Expand All @@ -25,7 +26,7 @@ import {
isStixDomainObjectLocation,
isStixDomainObjectThreatActor
} from '../schema/stixDomainObject';
import { ABSTRACT_STIX_CYBER_OBSERVABLE, ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey, INPUT_MARKINGS } from '../schema/general';
import { ABSTRACT_STIX_CYBER_OBSERVABLE, ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey, INPUT_CREATED_BY, INPUT_MARKINGS } from '../schema/general';
import { RELATION_CREATED_BY, RELATION_OBJECT_ASSIGNEE, } from '../schema/stixRefRelationship';
import { askEntityExport, askListExport, exportTransformFilters } from './stix';
import { RELATION_BASED_ON } from '../schema/stixCoreRelationship';
Expand Down Expand Up @@ -202,12 +203,19 @@ export const stixDomainObjectEditField = async (context, user, stixObjectId, inp
if (!stixDomainObject) {
throw FunctionalError('Cannot edit the field, Stix-Domain-Object cannot be found.');
}

const createdByKey = input.find((inputData) => inputData.key === 'createdBy');
// Validate specific relations, created by and markings
const markingsInput = input.find((inputData) => inputData.key === INPUT_MARKINGS);
if (markingsInput && markingsInput.value?.length > 0) {
for (let index = 0; index < markingsInput.value.length; index += 1) {
const markingId = markingsInput.value[index];
await validateMarking(context, user, markingId);
}
}
const createdByKey = input.find((inputData) => inputData.key === INPUT_CREATED_BY);
if (createdByKey && createdByKey.value?.length > 0) {
await validateCreatedBy(context, user, createdByKey.value[0]);
}

// Start the element edition
const { element: updatedElem } = await updateAttribute(context, user, stixObjectId, ABSTRACT_STIX_DOMAIN_OBJECT, input, opts);
// If indicator is score patched, we also patch the score of all observables attached to the indicator
if (stixDomainObject.entity_type === ENTITY_TYPE_INDICATOR && input.key === 'x_opencti_score') {
Expand Down Expand Up @@ -245,7 +253,6 @@ export const stixDomainObjectFileEdit = async (context, user, sdoId, { id, order
const { [INPUT_MARKINGS]: markingInput, ...nonResolvedFile } = f;
return nonResolvedFile;
});

const { element: updatedElement } = await updateAttributeFromLoadedWithRefs(context, user, stixDomainObject, { key: 'x_opencti_files', value: nonResolvedFiles });
return notify(BUS_TOPICS[ABSTRACT_STIX_DOMAIN_OBJECT].EDIT_TOPIC, updatedElement, user);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { READ_PLATFORM_INDICES, UPDATE_OPERATION_ADD, UPDATE_OPERATION_REMOVE }
import { type EntityOptions, storeLoadById } from '../database/middleware-loader';
import { ABSTRACT_STIX_OBJECT, ABSTRACT_STIX_REF_RELATIONSHIP, ABSTRACT_STIX_RELATIONSHIP } from '../schema/general';
import { FunctionalError, UnsupportedError } from '../config/errors';
import { isStixRefRelationship, RELATION_CREATED_BY } from '../schema/stixRefRelationship';
import { listThings, storeLoadByIdWithRefs, transformPatchToInput, updateAttributeFromLoadedWithRefs, validateCreatedBy } from '../database/middleware';
import { isStixRefRelationship, RELATION_CREATED_BY, RELATION_OBJECT_MARKING } from '../schema/stixRefRelationship';
import { listThings, storeLoadByIdWithRefs, transformPatchToInput, updateAttributeFromLoadedWithRefs, validateCreatedBy, validateMarking } from '../database/middleware';
import { notify } from '../database/redis';
import { BUS_TOPICS } from '../config/conf';
import type { AuthContext, AuthUser } from '../types/user';
Expand Down Expand Up @@ -51,12 +51,15 @@ export const stixObjectOrRelationshipAddRefRelation = async (
type: string,
opts = {}
): Promise<any> => { // TODO remove any when all resolvers in ts
const to = await findById(context, user, input.toId);

// Validate specific relations, created by and markings
if (input.relationship_type === RELATION_OBJECT_MARKING) {
await validateMarking(context, user, input.toId);
}
if (input.relationship_type === RELATION_CREATED_BY) {
await validateCreatedBy(context, user, input.toId);
}

// Add the relationship with patching
const to = await findById(context, user, input.toId);
const patchedFrom = await patchElementWithRefRelationships(context, user, stixObjectOrRelationshipId, type, input.relationship_type, [input.toId], UPDATE_OPERATION_ADD, opts);
const { element: refRelation } = await buildRelationData(context, user, { from: patchedFrom, to, relationship_type: input.relationship_type });
await notify(BUS_TOPICS[type as BusTopicsKeyType].EDIT_TOPIC, refRelation, user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ describe('Create dissemination list', () => {
const id = await deleteDisseminationList(testContext, TEST_DISSEMINATION_USER_SET, data.id);
expect(id, 'List deleted').toBe(data.id);
});
});
});

0 comments on commit dd15d8f

Please sign in to comment.