From 9248edccb5cca51dc77e4de915be43d9c220f4ee Mon Sep 17 00:00:00 2001 From: Angelique Date: Wed, 25 Sep 2024 17:48:14 +0200 Subject: [PATCH 01/10] First step of implementing chunk1 for sensitive conf protection(#8284) --- .../roles/RoleEditionCapabilities.tsx | 23 +++++++++++++++++++ .../src/schema/relay.schema.graphql | 2 ++ .../utils/hooks/useSensitiveModifications.ts | 12 ++++++++++ .../opencti-graphql/config/default.json | 3 ++- .../config/schema/opencti.graphql | 2 ++ .../opencti-graphql/src/domain/grant.js | 16 ++++++++++++- .../opencti-graphql/src/domain/user.js | 17 +++++++++++++- .../opencti-graphql/src/generated/graphql.ts | 4 ++++ .../internalObject-registrationAttributes.ts | 1 + .../opencti-graphql/src/types/user.d.ts | 1 + 10 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx index 373038a4ba5e..b50b105f0b4f 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx @@ -15,6 +15,8 @@ import { RoleEditionCapabilitiesLinesSearchQuery } from './__generated__/RoleEdi import { RoleEditionCapabilities_role$data } from './__generated__/RoleEditionCapabilities_role.graphql'; import useApiMutation from '../../../../utils/hooks/useApiMutation'; import { SETTINGS } from '../../../../utils/hooks/useGranted'; +import useHelper from '../../../../utils/hooks/useHelper'; +import useSensitiveModifications from '../../../../utils/hooks/useSensitiveModifications'; const roleEditionAddCapability = graphql` mutation RoleEditionCapabilitiesAddCapabilityMutation( @@ -101,9 +103,30 @@ const RoleEditionCapabilitiesComponent: FunctionComponent + {ffenabled && ( + + + + + + + handleToggle('1234', event)} + checked={isSensitiveModifAllowed} + disabled={false} + /> + + + )} {capabilities.edges.map((edge) => { const capability = edge?.node; if (capability) { diff --git a/opencti-platform/opencti-front/src/schema/relay.schema.graphql b/opencti-platform/opencti-front/src/schema/relay.schema.graphql index 4e9f7707f735..3ebb565a92fe 100644 --- a/opencti-platform/opencti-front/src/schema/relay.schema.graphql +++ b/opencti-platform/opencti-front/src/schema/relay.schema.graphql @@ -1608,6 +1608,7 @@ type MeUser implements BasicObject & InternalObject { submenu_show_icons: Boolean submenu_auto_collapse: Boolean monochrome_labels: Boolean + is_sensitive_changes_allow: Boolean } type SessionDetail { @@ -1694,6 +1695,7 @@ type Role implements BasicObject & InternalObject { updated_at: DateTime! capabilities: [Capability] editContext: [EditUserContext!] + is_sensitive_changes_allow: Boolean } input RoleAddInput { diff --git a/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts new file mode 100644 index 000000000000..a3fff03b4344 --- /dev/null +++ b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts @@ -0,0 +1,12 @@ +import useAuth from './useAuth'; +import useScale from './useScale'; + +const PROTECT_SENSITIVE_CHANGES_FF = 'PROTECT_SENSITIVE_CHANGES'; + +const useSensitiveModifications = () => { + const { me } = useAuth(); + // with FF & me.sensitve truc; + return {ffenabled: true, isSensitiveModifAllowed: true}; +}; + +export default useSensitiveModifications; \ No newline at end of file diff --git a/opencti-platform/opencti-graphql/config/default.json b/opencti-platform/opencti-graphql/config/default.json index 998cc081d4c5..c739050970c9 100644 --- a/opencti-platform/opencti-graphql/config/default.json +++ b/opencti-platform/opencti-graphql/config/default.json @@ -11,7 +11,8 @@ "NEW_IMPORT_SCREENS", "FILIGRAN_LOADER", "CONTAINERS_AUTHORIZED_MEMBERS", - "TELEMETRY_COUNT_ACTIVE_USERS" + "TELEMETRY_COUNT_ACTIVE_USERS", + "PROTECT_SENSITIVE_CHANGES" ], "https_cert": { "ca": [], diff --git a/opencti-platform/opencti-graphql/config/schema/opencti.graphql b/opencti-platform/opencti-graphql/config/schema/opencti.graphql index 10e732102a24..61cb13b33e5b 100644 --- a/opencti-platform/opencti-graphql/config/schema/opencti.graphql +++ b/opencti-platform/opencti-graphql/config/schema/opencti.graphql @@ -1542,6 +1542,7 @@ type MeUser implements BasicObject & InternalObject { submenu_show_icons: Boolean submenu_auto_collapse: Boolean monochrome_labels: Boolean + is_sensitive_changes_allow: Boolean } type SessionDetail { id: ID! @@ -1624,6 +1625,7 @@ type Role implements BasicObject & InternalObject { updated_at: DateTime! capabilities: [Capability] editContext: [EditUserContext!] + is_sensitive_changes_allow: Boolean } input RoleAddInput { name: String! @constraint(minLength: 2, format: "not-blank") diff --git a/opencti-platform/opencti-graphql/src/domain/grant.js b/opencti-platform/opencti-graphql/src/domain/grant.js index 0e1bfea7b192..2708380ee7dd 100644 --- a/opencti-platform/opencti-graphql/src/domain/grant.js +++ b/opencti-platform/opencti-graphql/src/domain/grant.js @@ -5,6 +5,8 @@ import { ENTITY_TYPE_CAPABILITY, ENTITY_TYPE_GROUP, ENTITY_TYPE_ROLE } from '../ import { RELATION_HAS_CAPABILITY } from '../schema/internalRelationship'; import { generateStandardId } from '../schema/identifier'; import { publishUserAction } from '../listener/UserActionListener'; +import {isFeatureEnabled} from '../config/conf'; +import {PROTECT_SENSITIVE_CHANGES_FF} from './user'; export const addCapability = async (context, user, capability) => { return createEntity(context, user, capability, ENTITY_TYPE_CAPABILITY); @@ -16,7 +18,19 @@ export const addRole = async (context, user, role) => { assoc('description', role.description ? role.description : ''), dissoc('capabilities'), )(role); - const { element, isCreation } = await createEntity(context, user, roleToCreate, ENTITY_TYPE_ROLE, { complete: true }); + + let completeRoleToCreate; + if(isFeatureEnabled((PROTECT_SENSITIVE_CHANGES_FF))){ + completeRoleToCreate = { + ...roleToCreate, + is_sensitive_changes_allow: true + } + } else { + completeRoleToCreate = { + ...roleToCreate + } + } + const { element, isCreation } = await createEntity(context, user, completeRoleToCreate, ENTITY_TYPE_ROLE, { complete: true }); const relationPromises = capabilities.map(async (capabilityName) => { const generateToId = generateStandardId(ENTITY_TYPE_CAPABILITY, { name: capabilityName }); return createRelation(context, user, { fromId: element.id, toId: generateToId, relationship_type: RELATION_HAS_CAPABILITY }); diff --git a/opencti-platform/opencti-graphql/src/domain/user.js b/opencti-platform/opencti-graphql/src/domain/user.js index de391be31a06..0b18ef842abf 100644 --- a/opencti-platform/opencti-graphql/src/domain/user.js +++ b/opencti-platform/opencti-graphql/src/domain/user.js @@ -9,7 +9,7 @@ import { ACCOUNT_STATUSES, BUS_TOPICS, DEFAULT_ACCOUNT_STATUS, - ENABLED_DEMO_MODE, + ENABLED_DEMO_MODE, isFeatureEnabled, logApp, OPENCTI_SESSION, PLATFORM_VERSION, @@ -1280,6 +1280,13 @@ const getStackTrace = () => { Error.captureStackTrace(obj, getStackTrace); return obj.stack; }; + + +export const PROTECT_SENSITIVE_CHANGES_FF='PROTECT_SENSITIVE_CHANGES'; +const isSensitiveChangesAllowed = async (context) => { + return true; +}; + export const buildCompleteUser = async (context, client) => { if (!client) { return undefined; @@ -1330,8 +1337,14 @@ export const buildCompleteUser = async (context, client) => { const no_creators = groups.filter((g) => g.no_creators).length === groups.length; const restrict_delete = !isByPass && groups.filter((g) => g.restrict_delete).length === groups.length; + let ff = null; + if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)){ + ff = {is_sensitive_changes_allow: isSensitiveChangesAllowed(context)} + } + return { ...client, + ...ff, roles, capabilities, default_hidden_types, @@ -1349,6 +1362,8 @@ export const buildCompleteUser = async (context, client) => { no_creators, restrict_delete, }; + + }; export const resolveUserByIdFromCache = async (context, id) => { diff --git a/opencti-platform/opencti-graphql/src/generated/graphql.ts b/opencti-platform/opencti-graphql/src/generated/graphql.ts index 9309000d7371..6188fe8afad6 100644 --- a/opencti-platform/opencti-graphql/src/generated/graphql.ts +++ b/opencti-platform/opencti-graphql/src/generated/graphql.ts @@ -12761,6 +12761,7 @@ export type MeUser = BasicObject & InternalObject & { groups?: Maybe; id: Scalars['ID']['output']; individual_id?: Maybe; + is_sensitive_changes_allow?: Maybe; language?: Maybe; lastname?: Maybe; max_shareable_marking?: Maybe>; @@ -22317,6 +22318,7 @@ export type Role = BasicObject & InternalObject & { editContext?: Maybe>; entity_type: Scalars['String']['output']; id: Scalars['ID']['output']; + is_sensitive_changes_allow?: Maybe; name: Scalars['String']['output']; parent_types: Array>; standard_id: Scalars['String']['output']; @@ -35669,6 +35671,7 @@ export type MeUserResolvers, ParentType, ContextType, Partial>; id?: Resolver; individual_id?: Resolver, ParentType, ContextType>; + is_sensitive_changes_allow?: Resolver, ParentType, ContextType>; language?: Resolver, ParentType, ContextType>; lastname?: Resolver, ParentType, ContextType>; max_shareable_marking?: Resolver>, ParentType, ContextType>; @@ -37827,6 +37830,7 @@ export type RoleResolvers>, ParentType, ContextType>; entity_type?: Resolver; id?: Resolver; + is_sensitive_changes_allow?: Resolver, ParentType, ContextType>; name?: Resolver; parent_types?: Resolver>, ParentType, ContextType>; standard_id?: Resolver; diff --git a/opencti-platform/opencti-graphql/src/modules/attributes/internalObject-registrationAttributes.ts b/opencti-platform/opencti-graphql/src/modules/attributes/internalObject-registrationAttributes.ts index 2b65e8f389e6..f07ca9a5201a 100644 --- a/opencti-platform/opencti-graphql/src/modules/attributes/internalObject-registrationAttributes.ts +++ b/opencti-platform/opencti-graphql/src/modules/attributes/internalObject-registrationAttributes.ts @@ -347,6 +347,7 @@ const internalObjectsAttributes: { [k: string]: Array } = { [ENTITY_TYPE_ROLE]: [ { name: 'name', label: 'Name', type: 'string', format: 'short', mandatoryType: 'external', editDefault: true, multiple: false, upsert: false, isFilterable: true }, { name: 'description', label: 'Description', type: 'string', format: 'text', mandatoryType: 'no', editDefault: false, multiple: false, upsert: false, isFilterable: true }, + { name: 'is_sensitive_changes_allow', label: 'Is sensitive changes allowed', type: 'boolean', mandatoryType: 'no', editDefault: false, multiple: false, upsert: false, isFilterable: false }, ], [ENTITY_TYPE_RULE]: [ { name: 'active', label: 'Status', type: 'boolean', mandatoryType: 'no', editDefault: false, multiple: false, upsert: true, isFilterable: true } diff --git a/opencti-platform/opencti-graphql/src/types/user.d.ts b/opencti-platform/opencti-graphql/src/types/user.d.ts index cbbddf13e074..6ad91878ec5a 100644 --- a/opencti-platform/opencti-graphql/src/types/user.d.ts +++ b/opencti-platform/opencti-graphql/src/types/user.d.ts @@ -4,6 +4,7 @@ import type { ConfidenceLevel } from '../generated/graphql'; interface UserRole extends BasicStoreIdentifier { name: string; + patate: boolean; } interface UserCapability { From c301dd581a5aac2f046bef4b4189d87f84f1837b Mon Sep 17 00:00:00 2001 From: "A. Jard" Date: Wed, 25 Sep 2024 17:50:35 +0200 Subject: [PATCH 02/10] Apply suggestions from code review --- opencti-platform/opencti-graphql/src/types/user.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/opencti-platform/opencti-graphql/src/types/user.d.ts b/opencti-platform/opencti-graphql/src/types/user.d.ts index 6ad91878ec5a..cbbddf13e074 100644 --- a/opencti-platform/opencti-graphql/src/types/user.d.ts +++ b/opencti-platform/opencti-graphql/src/types/user.d.ts @@ -4,7 +4,6 @@ import type { ConfidenceLevel } from '../generated/graphql'; interface UserRole extends BasicStoreIdentifier { name: string; - patate: boolean; } interface UserCapability { From d7c589ef56e08eb645bfb7824f671a0b35724ad8 Mon Sep 17 00:00:00 2001 From: Angelique Date: Thu, 26 Sep 2024 11:18:38 +0200 Subject: [PATCH 03/10] Add update of is_sensitive_changes_allow field in progress --- .../opencti-front/src/private/Root.tsx | 1 + .../roles/RoleEditionCapabilities.tsx | 37 ++- .../utils/hooks/useSensitiveModifications.ts | 6 +- .../opencti-graphql/src/domain/user.js | 30 ++- .../tests/01-unit/domain/user-test.ts | 77 ------ .../tests/01-unit/domain/user-unit-test.ts | 244 ++++++++++++++++++ 6 files changed, 309 insertions(+), 86 deletions(-) delete mode 100644 opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts create mode 100644 opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts diff --git a/opencti-platform/opencti-front/src/private/Root.tsx b/opencti-platform/opencti-front/src/private/Root.tsx index 9fba89c5d75f..898c0dc1f011 100644 --- a/opencti-platform/opencti-front/src/private/Root.tsx +++ b/opencti-platform/opencti-front/src/private/Root.tsx @@ -141,6 +141,7 @@ const meUserFragment = graphql` id name } + is_sensitive_changes_allow } `; diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx index b50b105f0b4f..c8bf24e2e8eb 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx @@ -47,6 +47,21 @@ const roleEditionRemoveCapability = graphql` } `; +const roleEditionPatchAllowSensitiveConf = graphql` + mutation RoleEditionCapabilitiesPatchAllowSensitiveChangesMutation( + $id: ID! + $input: [EditInput]! + ) { + roleEdit(id: $id) { + fieldPatch(input: $input) { + is_sensitive_changes_allow + } + } + } +`; + + + export const roleEditionCapabilitiesLinesSearch = graphql` query RoleEditionCapabilitiesLinesSearchQuery { capabilities(first: 500) { @@ -77,6 +92,7 @@ const RoleEditionCapabilitiesComponent: FunctionComponent, @@ -103,6 +119,21 @@ const RoleEditionCapabilitiesComponent: FunctionComponent, + ) => { + const roleId = role.id; + commitPatchAllowSensitiveConf({ + variables: { + id: roleId, + input: { + key:'is_sensitive_changes_allow', + value: event.target.checked, + }, + }, + }); + }; + const {ffenabled, isSensitiveModifAllowed} = useSensitiveModifications(); if (capabilities && capabilities.edges) { @@ -120,9 +151,9 @@ const RoleEditionCapabilitiesComponent: FunctionComponent handleToggle('1234', event)} - checked={isSensitiveModifAllowed} - disabled={false} + onChange={(event) => handleSensitiveToggle(event)} + checked={isSensitiveModifAllowed} + disabled={false} /> diff --git a/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts index a3fff03b4344..90314f242612 100644 --- a/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts +++ b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts @@ -1,12 +1,12 @@ import useAuth from './useAuth'; -import useScale from './useScale'; +import useHelper from './useHelper'; const PROTECT_SENSITIVE_CHANGES_FF = 'PROTECT_SENSITIVE_CHANGES'; const useSensitiveModifications = () => { const { me } = useAuth(); - // with FF & me.sensitve truc; - return {ffenabled: true, isSensitiveModifAllowed: true}; + const { isFeatureEnable } = useHelper(); + return {ffenabled: isFeatureEnable(PROTECT_SENSITIVE_CHANGES_FF), isSensitiveModifAllowed: me.is_sensitive_changes_allow ? me.is_sensitive_changes_allow: true}; }; export default useSensitiveModifications; \ No newline at end of file diff --git a/opencti-platform/opencti-graphql/src/domain/user.js b/opencti-platform/opencti-graphql/src/domain/user.js index 0b18ef842abf..472de06e3a4d 100644 --- a/opencti-platform/opencti-graphql/src/domain/user.js +++ b/opencti-platform/opencti-graphql/src/domain/user.js @@ -943,6 +943,11 @@ export const userDelete = async (context, user, userId) => { }; export const userAddRelation = async (context, user, userId, input) => { + logApp.info('ANGIE - input:', input); + if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)) { + logApp.info('ANGIE - input:', input); + } + const userData = await storeLoadById(context, user, userId, ENTITY_TYPE_USER); if (!userData) { throw FunctionalError(`Cannot add the relation, ${ENTITY_TYPE_USER} cannot be found.`); @@ -973,6 +978,11 @@ export const userAddRelation = async (context, user, userId, input) => { }; export const userDeleteRelation = async (context, user, targetUser, toId, relationshipType) => { + logApp.info('ANGIE - userDeleteRelation input:', input); + if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)) { + logApp.info('ANGIE - userDeleteRelation input:', input); + } + if (!isInternalRelationship(relationshipType)) { throw FunctionalError(`Only ${ABSTRACT_INTERNAL_RELATIONSHIP} can be deleted through this method.`); } @@ -1283,8 +1293,22 @@ const getStackTrace = () => { export const PROTECT_SENSITIVE_CHANGES_FF='PROTECT_SENSITIVE_CHANGES'; -const isSensitiveChangesAllowed = async (context) => { - return true; +export const isSensitiveChangesAllowed = (roles) => { + + let hasExplicitAllowSensitiveChangeFalse = 0; + console.log(`ANGIE - roles.length:${roles.length}`); + for (let i = 0; i { @@ -1339,7 +1363,7 @@ export const buildCompleteUser = async (context, client) => { let ff = null; if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)){ - ff = {is_sensitive_changes_allow: isSensitiveChangesAllowed(context)} + ff = {is_sensitive_changes_allow: isSensitiveChangesAllowed(roles)} } return { diff --git a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts deleted file mode 100644 index edc8f017ed9f..000000000000 --- a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { testContext } from '../../utils/testQuery'; -import { checkPasswordInlinePolicy } from '../../../src/domain/user'; - -describe('password checker', () => { - it('should no policy applied', async () => { - const policy = {}; - expect(checkPasswordInlinePolicy(testContext, policy, '').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, policy, 'a').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, policy, '!').length).toBe(0); - }); - it('should password_policy_min_length policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_length: 4 }, '123').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_length: 4 }, '1234').length).toBe(0); - }); - it('should password_policy_max_length policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 0 }, '123').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 2 }, '123').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 4 }, '1234').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 4 }, '12345').length).toBe(1); - }); - it('should password_policy_min_symbols policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_symbols: 4 }, '123é').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_symbols: 4 }, '1!2!3$4$').length).toBe(0); - }); - it('should password_policy_min_numbers policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_numbers: 1 }, 'aaa').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_numbers: 4 }, 'a1a2a3a4').length).toBe(0); - }); - it('should password_policy_min_words policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello-world').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello|world').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello_world').length).toBe(0); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello world').length).toBe(0); - }); - it('should password_policy_min_lowercase policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_lowercase: 4 }, 'AAAA').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_lowercase: 4 }, 'aaaa').length).toBe(0); - }); - it('should password_policy_min_uppercase policy applied', async () => { - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_uppercase: 4 }, 'aXaaXa').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, { password_policy_min_uppercase: 4 }, 'AxAxAxA)').length).toBe(0); - }); - it('should complex policy applied', async () => { - const policy01 = { - password_policy_min_length: 10, - password_policy_min_symbols: 2, - password_policy_min_numbers: 3, - password_policy_min_words: 3, - password_policy_min_lowercase: 2, - password_policy_min_uppercase: 2, - }; - expect(checkPasswordInlinePolicy(testContext, policy01, 'aXa77&&2aXa').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, policy01, 'ab-CD-&^123').length).toBe(0); - const policy02 = { - password_policy_min_length: 4, - password_policy_min_symbols: 1, - password_policy_min_numbers: 2, - password_policy_min_words: 0, - password_policy_min_lowercase: 0, - password_policy_min_uppercase: 0, - }; - expect(checkPasswordInlinePolicy(testContext, policy02, 'test!').length).toBe(1); - const policy03 = { - password_policy_min_length: 2, - password_policy_max_length: 5, - password_policy_min_symbols: 1, - password_policy_min_numbers: 0, - password_policy_min_words: 0, - password_policy_min_lowercase: 2, - password_policy_min_uppercase: 1, - }; - expect(checkPasswordInlinePolicy(testContext, policy03, 'julA').length).toBe(1); - expect(checkPasswordInlinePolicy(testContext, policy03, 'ju!lA').length).toBe(0); - }); -}); diff --git a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts new file mode 100644 index 000000000000..67be9b013479 --- /dev/null +++ b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts @@ -0,0 +1,244 @@ +import { describe, expect, it } from 'vitest'; +import { testContext } from '../../utils/testQuery'; +import {checkPasswordInlinePolicy, isSensitiveChangesAllowed} from '../../../src/domain/user'; + +describe.skip('password checker', () => { + it('should no policy applied', async () => { + const policy = {}; + expect(checkPasswordInlinePolicy(testContext, policy, '').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, policy, 'a').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, policy, '!').length).toBe(0); + }); + it('should password_policy_min_length policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_length: 4 }, '123').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_length: 4 }, '1234').length).toBe(0); + }); + it('should password_policy_max_length policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 0 }, '123').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 2 }, '123').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 4 }, '1234').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, { password_policy_max_length: 4 }, '12345').length).toBe(1); + }); + it('should password_policy_min_symbols policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_symbols: 4 }, '123é').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_symbols: 4 }, '1!2!3$4$').length).toBe(0); + }); + it('should password_policy_min_numbers policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_numbers: 1 }, 'aaa').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_numbers: 4 }, 'a1a2a3a4').length).toBe(0); + }); + it('should password_policy_min_words policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello-world').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello|world').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello_world').length).toBe(0); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_words: 2 }, 'hello world').length).toBe(0); + }); + it('should password_policy_min_lowercase policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_lowercase: 4 }, 'AAAA').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_lowercase: 4 }, 'aaaa').length).toBe(0); + }); + it('should password_policy_min_uppercase policy applied', async () => { + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_uppercase: 4 }, 'aXaaXa').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, { password_policy_min_uppercase: 4 }, 'AxAxAxA)').length).toBe(0); + }); + it('should complex policy applied', async () => { + const policy01 = { + password_policy_min_length: 10, + password_policy_min_symbols: 2, + password_policy_min_numbers: 3, + password_policy_min_words: 3, + password_policy_min_lowercase: 2, + password_policy_min_uppercase: 2, + }; + expect(checkPasswordInlinePolicy(testContext, policy01, 'aXa77&&2aXa').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, policy01, 'ab-CD-&^123').length).toBe(0); + const policy02 = { + password_policy_min_length: 4, + password_policy_min_symbols: 1, + password_policy_min_numbers: 2, + password_policy_min_words: 0, + password_policy_min_lowercase: 0, + password_policy_min_uppercase: 0, + }; + expect(checkPasswordInlinePolicy(testContext, policy02, 'test!').length).toBe(1); + const policy03 = { + password_policy_min_length: 2, + password_policy_max_length: 5, + password_policy_min_symbols: 1, + password_policy_min_numbers: 0, + password_policy_min_words: 0, + password_policy_min_lowercase: 2, + password_policy_min_uppercase: 1, + }; + expect(checkPasswordInlinePolicy(testContext, policy03, 'julA').length).toBe(1); + expect(checkPasswordInlinePolicy(testContext, policy03, 'ju!lA').length).toBe(0); + }); +}); + +describe('isSensitiveChangesAllowed use case coverage', () => { + it('should user with one role and not is_sensitive_changes_allow set be allow change sensitive conf', async () => { + + //subset of role data + const roles = + [ { + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z" + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role without is_sensitive_changes_allow field should be isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + it('should user with one role is_sensitive_changes_allow=true be allow change sensitive conf', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": true + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role with is_sensitive_changes_allow field true should be isSensitiveChangesAllowed=true').toBeTruthy(); + + }); + + it('should user with one role is_sensitive_changes_allow=false not be allow change sensitive conf', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role with is_sensitive_changes_allow field false should be isSensitiveChangesAllowed=false').toBeFalsy(); + }); + + it('should user with 2 roles one without is_sensitive_changes_allow, the other is false', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + }, + { + "_index": "opencti_internal_objects-000001", + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role with one is_sensitive_changes_allow true should be isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + it('should user with 2 roles one without is_sensitive_changes_allow, the other is true', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + }, + { + "_index": "opencti_internal_objects-000001", + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": true + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role with one is_sensitive_changes_allow true should be isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + it('should user with 2 roles all with is_sensitive_changes_allow set to false', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + }, + { + "_index": "opencti_internal_objects-000001", + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + } + ] + + const result = isSensitiveChangesAllowed(roles); + expect(result, 'Role with all is_sensitive_changes_allow field false should be isSensitiveChangesAllowed=false').toBeFalsy(); + }); + +}); \ No newline at end of file From c0868374319809cca93ec5ed8fe8d6a05a7600f1 Mon Sep 17 00:00:00 2001 From: Angelique Date: Thu, 26 Sep 2024 12:21:43 +0200 Subject: [PATCH 04/10] Add a bypass for infra admin --- .../roles/RoleEditionCapabilities.tsx | 1 + .../utils/hooks/useSensitiveModifications.ts | 3 +- .../opencti-graphql/src/domain/user.js | 23 +---- .../tests/01-unit/domain/user-unit-test.ts | 98 +++++++++++++++++-- 4 files changed, 100 insertions(+), 25 deletions(-) diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx index c8bf24e2e8eb..cb22e316365c 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx @@ -132,6 +132,7 @@ const RoleEditionCapabilitiesComponent: FunctionComponent { const { me } = useAuth(); const { isFeatureEnable } = useHelper(); - return {ffenabled: isFeatureEnable(PROTECT_SENSITIVE_CHANGES_FF), isSensitiveModifAllowed: me.is_sensitive_changes_allow ? me.is_sensitive_changes_allow: true}; + //When is_sensitive_changes_allow is not set then it's allowed. + return {ffenabled: isFeatureEnable(PROTECT_SENSITIVE_CHANGES_FF), isSensitiveModifAllowed: me.is_sensitive_changes_allow ?? true}; }; export default useSensitiveModifications; \ No newline at end of file diff --git a/opencti-platform/opencti-graphql/src/domain/user.js b/opencti-platform/opencti-graphql/src/domain/user.js index 472de06e3a4d..e25815c71e81 100644 --- a/opencti-platform/opencti-graphql/src/domain/user.js +++ b/opencti-platform/opencti-graphql/src/domain/user.js @@ -943,11 +943,6 @@ export const userDelete = async (context, user, userId) => { }; export const userAddRelation = async (context, user, userId, input) => { - logApp.info('ANGIE - input:', input); - if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)) { - logApp.info('ANGIE - input:', input); - } - const userData = await storeLoadById(context, user, userId, ENTITY_TYPE_USER); if (!userData) { throw FunctionalError(`Cannot add the relation, ${ENTITY_TYPE_USER} cannot be found.`); @@ -978,11 +973,6 @@ export const userAddRelation = async (context, user, userId, input) => { }; export const userDeleteRelation = async (context, user, targetUser, toId, relationshipType) => { - logApp.info('ANGIE - userDeleteRelation input:', input); - if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)) { - logApp.info('ANGIE - userDeleteRelation input:', input); - } - if (!isInternalRelationship(relationshipType)) { throw FunctionalError(`Only ${ABSTRACT_INTERNAL_RELATIONSHIP} can be deleted through this method.`); } @@ -1293,21 +1283,18 @@ const getStackTrace = () => { export const PROTECT_SENSITIVE_CHANGES_FF='PROTECT_SENSITIVE_CHANGES'; -export const isSensitiveChangesAllowed = (roles) => { - +export const isSensitiveChangesAllowed = (userId, roles) => { + if(userId === OPENCTI_ADMIN_UUID) { + return true; + } let hasExplicitAllowSensitiveChangeFalse = 0; - console.log(`ANGIE - roles.length:${roles.length}`); for (let i = 0; i { let ff = null; if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)){ - ff = {is_sensitive_changes_allow: isSensitiveChangesAllowed(roles)} + ff = {is_sensitive_changes_allow: isSensitiveChangesAllowed(client.id, roles)} } return { diff --git a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts index 67be9b013479..64d6f4945ae3 100644 --- a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts +++ b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest'; import { testContext } from '../../utils/testQuery'; import {checkPasswordInlinePolicy, isSensitiveChangesAllowed} from '../../../src/domain/user'; +import {OPENCTI_ADMIN_UUID} from '../../../src/schema/general'; describe.skip('password checker', () => { it('should no policy applied', async () => { @@ -77,6 +78,9 @@ describe.skip('password checker', () => { }); describe('isSensitiveChangesAllowed use case coverage', () => { + + const NOT_INFRA_ADMIN_USER_ID = '1c0925fe-ab65-42a1-8e96-ee6dc7fab4fa'; + it('should user with one role and not is_sensitive_changes_allow set be allow change sensitive conf', async () => { //subset of role data @@ -94,7 +98,7 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID, roles); expect(result, 'Role without is_sensitive_changes_allow field should be isSensitiveChangesAllowed=true').toBeTruthy(); }); @@ -115,7 +119,7 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); expect(result, 'Role with is_sensitive_changes_allow field true should be isSensitiveChangesAllowed=true').toBeTruthy(); }); @@ -137,7 +141,7 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); expect(result, 'Role with is_sensitive_changes_allow field false should be isSensitiveChangesAllowed=false').toBeFalsy(); }); @@ -170,7 +174,7 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); expect(result, 'Role with one is_sensitive_changes_allow true should be isSensitiveChangesAllowed=true').toBeTruthy(); }); @@ -203,7 +207,7 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); expect(result, 'Role with one is_sensitive_changes_allow true should be isSensitiveChangesAllowed=true').toBeTruthy(); }); @@ -237,8 +241,90 @@ describe('isSensitiveChangesAllowed use case coverage', () => { } ] - const result = isSensitiveChangesAllowed(roles); + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); expect(result, 'Role with all is_sensitive_changes_allow field false should be isSensitiveChangesAllowed=false').toBeFalsy(); }); + it('should INFRA admin bypass sensitive conf', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + }, + { + "_index": "opencti_internal_objects-000001", + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": false + } + ] + + const result = isSensitiveChangesAllowed(OPENCTI_ADMIN_UUID,roles); + expect(result, 'OPENCTI_ADMIN_UUID should be always isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + it('should INFRA user with 2 roles one without is_sensitive_changes_allow, the other is true', async () => { + //subset of role data + const roles = + [{ + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + }, + { + "_index": "opencti_internal_objects-000001", + "base_type": "ENTITY", + "confidence": 100, + "created_at": "2024-08-06T13:30:04.478Z", + "description": "Administrator role that bypass every capabilities", + "entity_type": "Role", + "id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "internal_id": "57312f0e-f276-44f8-97d3-88191ee57e1a", + "name": "Administrator", + "updated_at": "2024-08-06T13:30:04.478Z", + "is_sensitive_changes_allow": true + } + ] + + const result = isSensitiveChangesAllowed(OPENCTI_ADMIN_UUID,roles); + expect(result, 'OPENCTI_ADMIN_UUID should be always isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + + it('should INFRA admin bypass sensitive conf with zero role', async () => { + //subset of role data + const roles: any[] = []; + const result = isSensitiveChangesAllowed(OPENCTI_ADMIN_UUID,roles); + expect(result, 'OPENCTI_ADMIN_UUID should be always isSensitiveChangesAllowed=true').toBeTruthy(); + }); + + it('should a user with zero role be isSensitiveChangesAllowed=false', async () => { + //subset of role data + const roles: any[] = []; + const result = isSensitiveChangesAllowed(NOT_INFRA_ADMIN_USER_ID,roles); + expect(result, 'A user with no role should be isSensitiveChangesAllowed=false').toBeFalsy(); + }); + }); \ No newline at end of file From fcf091be8b93737bab5bfa7249206a053346242d Mon Sep 17 00:00:00 2001 From: Angelique Date: Thu, 26 Sep 2024 13:54:03 +0200 Subject: [PATCH 05/10] Make deepscan happy --- .../components/settings/roles/RoleEditionCapabilities.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx index cb22e316365c..7c11ec895b12 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx @@ -15,7 +15,6 @@ import { RoleEditionCapabilitiesLinesSearchQuery } from './__generated__/RoleEdi import { RoleEditionCapabilities_role$data } from './__generated__/RoleEditionCapabilities_role.graphql'; import useApiMutation from '../../../../utils/hooks/useApiMutation'; import { SETTINGS } from '../../../../utils/hooks/useGranted'; -import useHelper from '../../../../utils/hooks/useHelper'; import useSensitiveModifications from '../../../../utils/hooks/useSensitiveModifications'; const roleEditionAddCapability = graphql` From a051825e211bd8891821cab21d086452477478c7 Mon Sep 17 00:00:00 2001 From: Angelique Date: Fri, 27 Sep 2024 09:24:38 +0200 Subject: [PATCH 06/10] Add conf allow to false for new platform on Admin and Connector --- .../src/database/data-initialization.js | 30 +++++++++++++++---- .../opencti-graphql/src/domain/grant.js | 10 +++---- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/opencti-platform/opencti-graphql/src/database/data-initialization.js b/opencti-platform/opencti-graphql/src/database/data-initialization.js index 693110ca46f7..59cf87f046b7 100644 --- a/opencti-platform/opencti-graphql/src/database/data-initialization.js +++ b/opencti-platform/opencti-graphql/src/database/data-initialization.js @@ -1,4 +1,4 @@ -import { logApp } from '../config/conf'; +import {isFeatureEnabled, logApp} from '../config/conf'; import { addSettings } from '../domain/settings'; import { BYPASS, ROLE_ADMINISTRATOR, ROLE_DEFAULT, SYSTEM_USER } from '../utils/access'; import { initCreateEntitySettings } from '../modules/entitySetting/entitySetting-domain'; @@ -12,7 +12,7 @@ import { addVocabulary } from '../modules/vocabulary/vocabulary-domain'; import { addAllowedMarkingDefinition } from '../domain/markingDefinition'; import { addCapability, addGroup, addRole } from '../domain/grant'; import { GROUP_DEFAULT, groupAddRelation } from '../domain/group'; -import { TAXIIAPI } from '../domain/user'; +import {PROTECT_SENSITIVE_CHANGES_FF, TAXIIAPI} from '../domain/user'; import { KNOWLEDGE_COLLABORATION, KNOWLEDGE_DELETE, KNOWLEDGE_MANAGE_AUTH_MEMBERS, KNOWLEDGE_UPDATE } from '../schema/general'; // region Platform capabilities definition @@ -247,12 +247,21 @@ const createBasicRolesAndCapabilities = async (context) => { description: 'Default role associated to the default group', capabilities: [KNOWLEDGE_CAPABILITY], }); - await addRole(context, SYSTEM_USER, { + + let administratorRoleInput = { name: ROLE_ADMINISTRATOR, description: 'Administrator role that bypass every capabilities', capabilities: [BYPASS], - }); - const connectorRole = await addRole(context, SYSTEM_USER, { + }; + if(isFeatureEnabled((PROTECT_SENSITIVE_CHANGES_FF))){ + administratorRoleInput = { + ...administratorRoleInput, + is_sensitive_changes_allow: false + } + } + await addRole(context, SYSTEM_USER, administratorRoleInput); + + let connectorRoleInput = { name: 'Connector', description: 'Connector role that has the recommended capabilities', capabilities: [ @@ -270,7 +279,16 @@ const createBasicRolesAndCapabilities = async (context) => { 'SETTINGS_SETMARKINGS', 'SETTINGS_SETLABELS', ], - }); + }; + + if(isFeatureEnabled((PROTECT_SENSITIVE_CHANGES_FF))){ + connectorRoleInput = { + ...connectorRoleInput, + is_sensitive_changes_allow: false + } + } + + const connectorRole = await addRole(context, SYSTEM_USER, connectorRoleInput); // Create default group with default role const defaultGroup = await addGroup(context, SYSTEM_USER, { name: GROUP_DEFAULT, diff --git a/opencti-platform/opencti-graphql/src/domain/grant.js b/opencti-platform/opencti-graphql/src/domain/grant.js index 2708380ee7dd..6a6a753028b9 100644 --- a/opencti-platform/opencti-graphql/src/domain/grant.js +++ b/opencti-platform/opencti-graphql/src/domain/grant.js @@ -20,11 +20,11 @@ export const addRole = async (context, user, role) => { )(role); let completeRoleToCreate; - if(isFeatureEnabled((PROTECT_SENSITIVE_CHANGES_FF))){ - completeRoleToCreate = { - ...roleToCreate, - is_sensitive_changes_allow: true - } + if(isFeatureEnabled(PROTECT_SENSITIVE_CHANGES_FF)) { + completeRoleToCreate = { + ...roleToCreate, + is_sensitive_changes_allow: role.is_sensitive_changes_allow ?? true, //default when undefined is true + } } else { completeRoleToCreate = { ...roleToCreate From a306c6f7a38d6a36a846f2729bd27d4fae2ff043 Mon Sep 17 00:00:00 2001 From: marie flores Date: Fri, 27 Sep 2024 11:58:32 +0200 Subject: [PATCH 07/10] [frontend] wip:prtect groups and roles --- .../components/settings/groups/Group.tsx | 32 +++++++-- .../components/settings/roles/Role.tsx | 66 +++++++++++++++++-- .../roles/RoleEditionCapabilities.tsx | 36 +++++----- .../utils/hooks/useSensitiveModifications.ts | 10 +-- 4 files changed, 113 insertions(+), 31 deletions(-) diff --git a/opencti-platform/opencti-front/src/private/components/settings/groups/Group.tsx b/opencti-platform/opencti-front/src/private/components/settings/groups/Group.tsx index bcac75be9cc5..389649a0722d 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/groups/Group.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/groups/Group.tsx @@ -30,6 +30,7 @@ import ItemIcon from '../../../../components/ItemIcon'; import GroupHiddenTypesChipList from './GroupHiddenTypesChipList'; import ExpandableMarkdown from '../../../../components/ExpandableMarkdown'; import { checkIsMarkingAllowed } from '../../../../utils/markings/markingsFiltering'; +import useSensitiveModifications from '../../../../utils/hooks/useSensitiveModifications'; // Deprecated - https://mui.com/system/styles/basics/ // Do not use it for new code. @@ -123,6 +124,7 @@ const Group = ({ groupData }: { groupData: Group_group$key }) => { const classes = useStyles(); const { t_i18n } = useFormatter(); const group = useFragment(groupFragment, groupData); + const { ffenabled, isSensitiveModifAllowed } = useSensitiveModifications(); const markingsSort = R.sortWith([ R.ascend(R.propOr('TLP', 'definition_type')), R.descend(R.propOr(0, 'x_opencti_order')), @@ -153,9 +155,19 @@ const Group = ({ groupData }: { groupData: Group_group$key }) => { > {group.name} -
- -
+ {ffenabled && ( + isSensitiveModifAllowed + ?
+ +
+ : <> + )} + {!ffenabled && ( +
+ +
+ ) + }
{ - + {ffenabled && ( + isSensitiveModifAllowed + ?
+ +
+ : <> + )} + {!ffenabled && ( +
+ +
+ ) + }
); }; diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx index 525dad9df88d..69dd28769a77 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx @@ -8,6 +8,10 @@ import ListItem from '@mui/material/ListItem'; import { Link } from 'react-router-dom'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; +import VerifiedUserIcon from '@mui/icons-material/VerifiedUser'; +import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; +import Checkbox from '@mui/material/Checkbox'; +import List from '@mui/material/List'; import AccessesMenu from '../AccessesMenu'; import { useFormatter } from '../../../../components/i18n'; import { Role_role$data, Role_role$key } from './__generated__/Role_role.graphql'; @@ -24,6 +28,7 @@ import { groupsSearchQuery } from '../Groups'; import { GroupsSearchQuery } from '../__generated__/GroupsSearchQuery.graphql'; import ItemIcon from '../../../../components/ItemIcon'; import ExpandableMarkdown from '../../../../components/ExpandableMarkdown'; +import useSensitiveModifications from '../../../../utils/hooks/useSensitiveModifications'; // Deprecated - https://mui.com/system/styles/basics/ // Do not use it for new code. @@ -61,6 +66,7 @@ const roleFragment = graphql` name description } + is_sensitive_changes_allow } `; @@ -81,6 +87,7 @@ const Role = ({ : null)) .filter((n) => n !== null && n !== undefined); }; + const { ffenabled, isSensitiveModifAllowed } = useSensitiveModifications(); const role = useFragment(roleFragment, roleData); const queryRef = useQueryLoading( roleEditionCapabilitiesLinesSearch, @@ -96,10 +103,20 @@ const Role = ({ > {role.name} -
- -
-
+ {ffenabled && ( + isSensitiveModifAllowed + ?
+ +
+ : <> + )} + {!ffenabled && ( +
+ +
+ ) + } +
+ + + {t_i18n('Allow modification of sensitive configuration')} + + + + + {ffenabled && ( + + + + + + + + + + + + )} + + + + { if (props && props.role) { + if (ffenabled) { + return ( + isSensitiveModifAllowed + ? + : <> + ); + } return ( , + event: React.ChangeEvent, ) => { const roleId = role.id; - commitPatchAllowSensitiveConf({ - variables: { - id: roleId, - input: { - key:'is_sensitive_changes_allow', - value: event.target.checked, - }, + commitPatchAllowSensitiveConf({ + variables: { + id: roleId, + input: { + key: 'is_sensitive_changes_allow', + value: event.target.checked, }, - }); - // And invalid me ?? or invalidSession + }, + }); + // And invalid me ?? or invalidSession }; - const {ffenabled, isSensitiveModifAllowed} = useSensitiveModifications(); + const { ffenabled } = useSensitiveModifications(); if (capabilities && capabilities.edges) { return ( {ffenabled && ( - + handleSensitiveToggle(event)} - checked={isSensitiveModifAllowed} + checked={role.is_sensitive_changes_allow} disabled={false} /> @@ -209,6 +208,7 @@ const RoleEditionCapabilities = createFragmentContainer( role: graphql` fragment RoleEditionCapabilities_role on Role { id + is_sensitive_changes_allow capabilities { id name diff --git a/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts index 00a0ec6dcce0..f97fdbc6d623 100644 --- a/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts +++ b/opencti-platform/opencti-front/src/utils/hooks/useSensitiveModifications.ts @@ -4,10 +4,10 @@ import useHelper from './useHelper'; const PROTECT_SENSITIVE_CHANGES_FF = 'PROTECT_SENSITIVE_CHANGES'; const useSensitiveModifications = () => { - const { me } = useAuth(); - const { isFeatureEnable } = useHelper(); - //When is_sensitive_changes_allow is not set then it's allowed. - return {ffenabled: isFeatureEnable(PROTECT_SENSITIVE_CHANGES_FF), isSensitiveModifAllowed: me.is_sensitive_changes_allow ?? true}; + const { me } = useAuth(); + const { isFeatureEnable } = useHelper(); + // When is_sensitive_changes_allow is not set then it's allowed. + return { ffenabled: isFeatureEnable(PROTECT_SENSITIVE_CHANGES_FF), isSensitiveModifAllowed: me.is_sensitive_changes_allow ?? true }; }; -export default useSensitiveModifications; \ No newline at end of file +export default useSensitiveModifications; From 121d71cc6fb72cbcbd41633c26f91d785491398b Mon Sep 17 00:00:00 2001 From: Angelique Date: Fri, 27 Sep 2024 13:59:32 +0200 Subject: [PATCH 08/10] user test back to old name --- .../tests/01-unit/domain/{user-unit-test.ts => user-test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename opencti-platform/opencti-graphql/tests/01-unit/domain/{user-unit-test.ts => user-test.ts} (100%) diff --git a/opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts b/opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts similarity index 100% rename from opencti-platform/opencti-graphql/tests/01-unit/domain/user-unit-test.ts rename to opencti-platform/opencti-graphql/tests/01-unit/domain/user-test.ts From 511719bcfdc8c65646baf5d55a0686323b1f2b48 Mon Sep 17 00:00:00 2001 From: marie flores Date: Fri, 27 Sep 2024 14:28:09 +0200 Subject: [PATCH 09/10] [frontend] wip:prtect groups and roles --- .../src/private/components/settings/roles/Role.tsx | 2 +- .../components/settings/roles/RoleEditionCapabilities.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx index 69dd28769a77..61be59ff1ae6 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx @@ -200,7 +200,7 @@ const Role = ({ diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx index fffe8c17e2f1..5e45422def2f 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/RoleEditionCapabilities.tsx @@ -151,7 +151,7 @@ const RoleEditionCapabilitiesComponent: FunctionComponent handleSensitiveToggle(event)} - checked={role.is_sensitive_changes_allow} + checked={role.is_sensitive_changes_allow ? role.is_sensitive_changes_allow : false} disabled={false} /> From a210cff15f8f3e074de0a493dfd273c360c46a52 Mon Sep 17 00:00:00 2001 From: marie flores Date: Fri, 27 Sep 2024 17:33:10 +0200 Subject: [PATCH 10/10] [frontend] fix UI and add translation --- .../opencti-front/lang/front/de.json | 1 + .../opencti-front/lang/front/en.json | 1 + .../opencti-front/lang/front/es.json | 1 + .../opencti-front/lang/front/fr.json | 1 + .../opencti-front/lang/front/ja.json | 1 + .../opencti-front/lang/front/ko.json | 1 + .../opencti-front/lang/front/zh.json | 1 + .../settings/roles/CapabilitiesList.tsx | 19 ++++++++++ .../components/settings/roles/Role.tsx | 36 ------------------- .../roles/RoleEditionCapabilities.tsx | 3 +- 10 files changed, 27 insertions(+), 38 deletions(-) diff --git a/opencti-platform/opencti-front/lang/front/de.json b/opencti-platform/opencti-front/lang/front/de.json index 7d260d41bad5..95292ee881eb 100644 --- a/opencti-platform/opencti-front/lang/front/de.json +++ b/opencti-platform/opencti-front/lang/front/de.json @@ -135,6 +135,7 @@ "All types of relationship": "Alle Arten von Beziehungen", "All types of target": "Alle Arten von Ziel", "All years": "Alle Jahre", + "Allow modification of sensitive configuration": "Änderung der sensiblen Konfiguration zulassen", "Allowed marking definitions": "Erlaubte Markierungsdefinitionen", "Allowed markings": "Erlaubte Markierungen", "Already in plat.": "Bereits in plat.", diff --git a/opencti-platform/opencti-front/lang/front/en.json b/opencti-platform/opencti-front/lang/front/en.json index 7161031945a1..db5dec5e7a23 100644 --- a/opencti-platform/opencti-front/lang/front/en.json +++ b/opencti-platform/opencti-front/lang/front/en.json @@ -135,6 +135,7 @@ "All types of relationship": "All types of relationship", "All types of target": "All types of target", "All years": "All years", + "Allow modification of sensitive configuration": "Allow modification of sensitive configuration", "Allowed marking definitions": "Allowed marking definitions", "Allowed markings": "Allowed markings", "Already in plat.": "Already in plat.", diff --git a/opencti-platform/opencti-front/lang/front/es.json b/opencti-platform/opencti-front/lang/front/es.json index 275937f3efd4..d8c47a428862 100644 --- a/opencti-platform/opencti-front/lang/front/es.json +++ b/opencti-platform/opencti-front/lang/front/es.json @@ -135,6 +135,7 @@ "All types of relationship": "Todos los tipos de relación", "All types of target": "Todo los tipos de objetivo", "All years": "Todos los años", + "Allow modification of sensitive configuration": "Permitir la modificación de la configuración sensible", "Allowed marking definitions": "Definiciones de marcado permitidas", "Allowed markings": "Marcas permitidas", "Already in plat.": "Ya está en la plataforma.", diff --git a/opencti-platform/opencti-front/lang/front/fr.json b/opencti-platform/opencti-front/lang/front/fr.json index ea7a0e50058e..604f350d5be3 100644 --- a/opencti-platform/opencti-front/lang/front/fr.json +++ b/opencti-platform/opencti-front/lang/front/fr.json @@ -135,6 +135,7 @@ "All types of relationship": "Tous les types de relation", "All types of target": "Tous les types de cible", "All years": "Toutes les années", + "Allow modification of sensitive configuration": "Permettre la modification d'une configuration sensible", "Allowed marking definitions": "Définitions de marquage autorisées", "Allowed markings": "Marquages autorisés", "Already in plat.": "Déjà dans la plat.", diff --git a/opencti-platform/opencti-front/lang/front/ja.json b/opencti-platform/opencti-front/lang/front/ja.json index 7b13e7235677..879ba986b124 100644 --- a/opencti-platform/opencti-front/lang/front/ja.json +++ b/opencti-platform/opencti-front/lang/front/ja.json @@ -135,6 +135,7 @@ "All types of relationship": "全てのリレーションシップの種別", "All types of target": "あらゆる種類のターゲット", "All years": "すべての年", + "Allow modification of sensitive configuration": "機密設定の変更を許可する", "Allowed marking definitions": "許可されたマーキング定義", "Allowed markings": "許可されるマーキング", "Already in plat.": "すでにプラットフォームに存在します", diff --git a/opencti-platform/opencti-front/lang/front/ko.json b/opencti-platform/opencti-front/lang/front/ko.json index 4623f77e88aa..5100e2759812 100644 --- a/opencti-platform/opencti-front/lang/front/ko.json +++ b/opencti-platform/opencti-front/lang/front/ko.json @@ -135,6 +135,7 @@ "All types of relationship": "모든 관계 유형", "All types of target": "모든 대상 유형", "All years": "모든 연도", + "Allow modification of sensitive configuration": "민감한 구성의 수정 허용", "Allowed marking definitions": "허용된 마킹 정의", "Allowed markings": "허용된 마킹", "Already in plat.": "이미 플랫폼에 있음", diff --git a/opencti-platform/opencti-front/lang/front/zh.json b/opencti-platform/opencti-front/lang/front/zh.json index a1ccce25ac00..f7defa0fc6c0 100644 --- a/opencti-platform/opencti-front/lang/front/zh.json +++ b/opencti-platform/opencti-front/lang/front/zh.json @@ -135,6 +135,7 @@ "All types of relationship": "关系的所有类型", "All types of target": "所有类型的目标", "All years": "所有年份", + "Allow modification of sensitive configuration": "允许修改敏感配置", "Allowed marking definitions": "允许的标记定义", "Allowed markings": "允许的标记", "Already in plat.": "已经在平台", diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/CapabilitiesList.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/CapabilitiesList.tsx index 3e2f6b2bfdc6..47b4962ca936 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/CapabilitiesList.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/CapabilitiesList.tsx @@ -4,11 +4,15 @@ import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; +import Checkbox from '@mui/material/Checkbox'; +import LocalPoliceOutlined from '@mui/icons-material/LocalPoliceOutlined'; import { useFormatter } from '../../../../components/i18n'; import { roleEditionCapabilitiesLinesSearch } from './RoleEditionCapabilities'; import { RoleEditionCapabilitiesLinesSearchQuery } from './__generated__/RoleEditionCapabilitiesLinesSearchQuery.graphql'; import { Role_role$data } from './__generated__/Role_role.graphql'; import ItemIcon from '../../../../components/ItemIcon'; +import useSensitiveModifications from '../../../../utils/hooks/useSensitiveModifications'; interface CapabilitiesListProps { queryRef: PreloadedQuery; @@ -27,8 +31,23 @@ const CapabilitiesList: FunctionComponent = ({ roleEditionCapabilitiesLinesSearch, queryRef, ); + const { ffenabled } = useSensitiveModifications(); + return ( + {ffenabled && ( + + + + + + + )} {capabilities?.edges?.map((edge, i) => { const capability = edge?.node; if (capability) { diff --git a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx index 61be59ff1ae6..312082d393ba 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/roles/Role.tsx @@ -8,10 +8,6 @@ import ListItem from '@mui/material/ListItem'; import { Link } from 'react-router-dom'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; -import VerifiedUserIcon from '@mui/icons-material/VerifiedUser'; -import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; -import Checkbox from '@mui/material/Checkbox'; -import List from '@mui/material/List'; import AccessesMenu from '../AccessesMenu'; import { useFormatter } from '../../../../components/i18n'; import { Role_role$data, Role_role$key } from './__generated__/Role_role.graphql'; @@ -179,38 +175,6 @@ const Role = ({ - - - {t_i18n('Allow modification of sensitive configuration')} - - - - - {ffenabled && ( - - - - - - - - - - - - )} - - - - - +