pycti 6.5.11__py3-none-any.whl → 6.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pycti might be problematic. Click here for more details.

@@ -0,0 +1,716 @@
1
+ from typing import Dict, List, Optional
2
+
3
+
4
+ class Group:
5
+ """Representation of a Group in OpenCTI
6
+
7
+ Groups have members and also have assigned roles. Roles attached to a group
8
+ determine what members of the group have permissions to do according to
9
+ the capabilities the role has.
10
+
11
+ Additionally, groups have a confidence level which informs the effective
12
+ confidence of members of the group.
13
+
14
+ Groups also have permissions on Marking Definitions. Assigned marking
15
+ definitions allow users to apply their capabilities on objects with those
16
+ definitions. Additionally, there are default markings added to all objects
17
+ created by members of a group, and max shareable definitions which
18
+ determine which objects users can export from the platform to share.
19
+
20
+ See the properties attribute to understand what properties are fetched by
21
+ default from GraphQL queries.
22
+ """
23
+
24
+ def __init__(self, opencti):
25
+ self.opencti = opencti
26
+ self.properties = """
27
+ id
28
+ standard_id
29
+ name
30
+ description
31
+ entity_type
32
+ parent_types
33
+ created_at
34
+ updated_at
35
+ default_assignation
36
+ no_creators
37
+ restrict_delete
38
+ default_hidden_types
39
+ auto_new_marking
40
+ allowed_marking {
41
+ id, standard_id, definition_type, definition
42
+ }
43
+ default_marking {
44
+ entity_type
45
+ values {
46
+ id, standard_id, definition_type, definition
47
+ }
48
+ }
49
+ not_shareable_marking_types
50
+ max_shareable_marking {
51
+ id, standard_id, definition_type, definition
52
+ }
53
+ group_confidence_level {
54
+ max_confidence
55
+ overrides {
56
+ entity_type
57
+ max_confidence
58
+ }
59
+ }
60
+ roles {
61
+ edges {
62
+ node {
63
+ id, name
64
+ capabilities {
65
+ id, name
66
+ }
67
+ }
68
+ }
69
+ }
70
+ members {
71
+ edges {
72
+ node {
73
+ id, individual_id, user_email, name
74
+ }
75
+ }
76
+ }
77
+ """
78
+
79
+ def list(self, **kwargs) -> List[Dict]:
80
+ """Lists groups based on a number of filters.
81
+
82
+ :param first: Retrieve this number of results. If 0
83
+ then fetches all results, defaults to 0.
84
+ :type first: int, optional
85
+ :param after: ID of the group to fetch results
86
+ after in the list of all results, defaults to None.
87
+ :type after: str, optional
88
+ :param orderBy: Field by which to order results.
89
+ Must be one of name, default_assignation, no_creators,
90
+ restrict_delete, auto_new_marking, created_at, updated_at,
91
+ group_confidence_level, and _score, defaults to "name".
92
+ :type orderBy: str, optional
93
+ :param orderMode: Direction of ordering. Must be
94
+ one of "asc" or "desc", defaults to "asc".
95
+ :type orderMode: str, optional
96
+ :param search: String to search groups for, defaults to None.
97
+ :type search: str, optional
98
+ :param filters: OpenCTI API FilterGroup object.
99
+ This is an advanced parameter. To learn more please search for
100
+ the FilterGroup object in the OpenCTI GraphQL Playground, defaults
101
+ to {}.
102
+ :type filters: dict, optional
103
+ :param customAttributes: Custom attributes to fetch from the GraphQL
104
+ query
105
+ :type customAttributes: str, optional
106
+ :param getAll: Defaults to False. Whether or not to get all results
107
+ from the search. If True then param first is ignored.
108
+ :type getAll: bool, optional
109
+ :param withPagination: Defaults to False. Whether to return pagination
110
+ info with results.
111
+ :type withPagination: bool, optional
112
+ :return: List of groups in dictionary representation.
113
+ :rtype: list[dict]
114
+ """
115
+ first = kwargs.get("first", 500)
116
+ after = kwargs.get("after", None)
117
+ order_by = kwargs.get("orderBy", None)
118
+ order_mode = kwargs.get("orderMode", None)
119
+ search = kwargs.get("search", None)
120
+ filters = kwargs.get("filters", None)
121
+ custom_attributes = kwargs.get("customAttributes", None)
122
+ get_all = kwargs.get("getAll", False)
123
+ with_pagination = kwargs.get("withPagination", False)
124
+
125
+ if get_all:
126
+ first = 100
127
+
128
+ self.opencti.admin_logger.info(
129
+ "Fetching groups with filters", {"filters": filters}
130
+ )
131
+ query = (
132
+ """
133
+ query Groups($first: Int, $after: ID, $orderBy: GroupsOrdering, $orderMode: OrderingMode, $search: String, $filters: FilterGroup) {
134
+ groups(first: $first, after: $after, orderBy: $orderBy, orderMode: $orderMode, search: $search, filters: $filters) {
135
+ edges {
136
+ node {
137
+ """
138
+ + (self.properties if custom_attributes is None else custom_attributes)
139
+ + """
140
+ }
141
+ }
142
+ pageInfo {
143
+ startCursor
144
+ endCursor
145
+ hasNextPage
146
+ hasPreviousPage
147
+ globalCount
148
+ }
149
+ }
150
+ }
151
+ """
152
+ )
153
+ result = self.opencti.query(
154
+ query,
155
+ {
156
+ "first": first,
157
+ "after": after,
158
+ "orderBy": order_by,
159
+ "orderMode": order_mode,
160
+ "search": search,
161
+ "filters": filters,
162
+ },
163
+ )
164
+
165
+ if get_all:
166
+ final_data = []
167
+ data = self.opencti.process_multiple(result["data"]["groups"])
168
+ final_data = final_data + data
169
+ while result["data"]["groups"]["pageInfo"]["hasNextPage"]:
170
+ after = result["data"]["groups"]["pageInfo"]["endCursor"]
171
+ result = self.opencti.query(
172
+ query,
173
+ {
174
+ "first": first,
175
+ "after": after,
176
+ "orderBy": order_by,
177
+ "orderMode": order_mode,
178
+ "search": search,
179
+ "filters": filters,
180
+ },
181
+ )
182
+ data = self.opencti.process_multiple(result["data"]["groups"])
183
+ final_data = final_data + data
184
+ return final_data
185
+ else:
186
+ return self.opencti.process_multiple(
187
+ result["data"]["groups"], with_pagination
188
+ )
189
+
190
+ def read(self, **kwargs) -> Optional[Dict]:
191
+ """Fetch a given group from OpenCTI
192
+
193
+ One of id or filters is required.
194
+
195
+ :param id: ID of the group to fetch
196
+ :type id: str, optional
197
+ :param filters: Filters to apply to find single group
198
+ :type filters: dict, optional
199
+ :param customAttributes: Custom attributes to fetch for the group
200
+ :type customAttributes: str
201
+ :return: Representation of a group.
202
+ :rtype: Optional[Dict]
203
+ """
204
+ id = kwargs.get("id", None)
205
+ filters = kwargs.get("filters", None)
206
+ search = kwargs.get("search", None)
207
+ custom_attributes = kwargs.get("customAttributes", None)
208
+ if id is not None:
209
+ self.opencti.admin_logger.info("Fetching group with ID", {"id": id})
210
+ query = (
211
+ """
212
+ query Group($id: String!) {
213
+ group(id: $id) {
214
+ """
215
+ + (self.properties if custom_attributes is None else custom_attributes)
216
+ + """
217
+ }
218
+ }
219
+ """
220
+ )
221
+ result = self.opencti.query(query, {"id": id})
222
+ return self.opencti.process_multiple_fields(result["data"]["group"])
223
+ elif filters is not None or search is not None:
224
+ results = self.list(
225
+ filters=filters, search=search, customAttributes=custom_attributes
226
+ )
227
+ return results[0] if results else None
228
+ else:
229
+ self.opencti.admin_logger.error(
230
+ "[opencti_group] Missing parameters: id or filters"
231
+ )
232
+ return None
233
+
234
+ def create(self, **kwargs) -> Optional[Dict]:
235
+ """Create a group with required details
236
+
237
+ Groups can be configured after creation using other functions.
238
+
239
+ :param name: Name of the group to create.
240
+ :type name: str
241
+ :param id_confidence_level: Confidence-level dictionary, with a
242
+ max_confidence member between 0 and 100 (incl) and an overrides
243
+ list with max_confidence and the entity_type it applies to.
244
+ :type id_confidence_level: dict
245
+ :param description: Description of the group
246
+ :type description: str, optional
247
+ :param default_assignation: Defaults to False. Whether or not to assign
248
+ this group by default to all new users.
249
+ :type default_assignation: bool, optional
250
+ :param no_creators: Defaults to False. Whether or not to create
251
+ authors for members of this group.
252
+ :type no_creators: bool, optional
253
+ :param restrict_delete: Defaults to False. Whether or not to restrict
254
+ members deleting entities that are not their own.
255
+ :type restrict_delete: bool, optional
256
+ :param auto_new_marking: Defaults to False. Whether or not to allow
257
+ members access to new markings automatically.
258
+ :type auto_new_marking: bool, optional
259
+ :param customAttributes: Attributes to retrieve from the new group
260
+ :type customAttributes: str, optional
261
+ :return: Representation of the group.
262
+ :rtype: Optional[Dict]
263
+ """
264
+ name = kwargs.get("name", None)
265
+ group_confidence_level = kwargs.get("group_confidence_level", None)
266
+ description = kwargs.get("description", None)
267
+ default_assignation = kwargs.get("default_assignation", False)
268
+ no_creators = kwargs.get("no_creators", False)
269
+ restrict_delete = kwargs.get("restrict_delete", False)
270
+ auto_new_marking = kwargs.get("auto_new_marking", False)
271
+ custom_attributes = kwargs.get("customAttributes", None)
272
+
273
+ if name is None or group_confidence_level is None:
274
+ self.opencti.admin_logger.error(
275
+ "[opencti_group] Missing parameters: name and group_confidence_level"
276
+ )
277
+ return None
278
+
279
+ self.opencti.admin_logger.info(
280
+ "Creating new group with parameters",
281
+ {
282
+ "name": name,
283
+ "group_confidence_level": group_confidence_level,
284
+ "description": description,
285
+ "default_assignation": default_assignation,
286
+ "no_creators": no_creators,
287
+ "restrict_delete": restrict_delete,
288
+ "auto_new_marking": auto_new_marking,
289
+ },
290
+ )
291
+ query = (
292
+ """
293
+ mutation GroupAdd($input: GroupAddInput!) {
294
+ groupAdd(input: $input) {
295
+ """
296
+ + (self.properties if custom_attributes is None else custom_attributes)
297
+ + """
298
+ }
299
+ }
300
+ """
301
+ )
302
+ result = self.opencti.query(
303
+ query,
304
+ {
305
+ "input": {
306
+ "name": name,
307
+ "description": description,
308
+ "default_assignation": default_assignation,
309
+ "no_creators": no_creators,
310
+ "restrict_delete": restrict_delete,
311
+ "auto_new_marking": auto_new_marking,
312
+ "group_confidence_level": group_confidence_level,
313
+ }
314
+ },
315
+ )
316
+ return self.opencti.process_multiple_fields(result["data"]["groupAdd"])
317
+
318
+ def delete(self, id: str):
319
+ """Delete a given group from OpenCTI
320
+
321
+ :param id: ID of the group to delete.
322
+ :type id: str
323
+ """
324
+ self.opencti.admin_logger.info("Deleting group", {"id": id})
325
+ query = """
326
+ mutation GroupDelete($id: ID!) {
327
+ groupEdit(id: $id) {
328
+ delete
329
+ }
330
+ }
331
+ """
332
+ self.opencti.query(query, {"id": id})
333
+
334
+ def update_field(self, **kwargs) -> Optional[Dict]:
335
+ """Update a group using fieldPatch
336
+
337
+ :param id: ID of the group to update
338
+ :type id: str
339
+ :param input: FieldPatchInput object to edit group
340
+ :type input: List[Dict]
341
+ :param customAttributes: Custom attributes to retrieve from group
342
+ :type customAttribues: str, optional
343
+ :return: Representation of a group
344
+ :rtype: Optional[Dict]
345
+ """
346
+ id = kwargs.get("id", None)
347
+ input = kwargs.get("input", None)
348
+ custom_attributes = kwargs.get("customAttributes", None)
349
+
350
+ if id is None or input is None:
351
+ self.opencti.admin_logger.error(
352
+ "[opencti_group] Missing parameters: id and input"
353
+ )
354
+ return None
355
+
356
+ self.opencti.admin_logger.info("Editing group with input", {"input": input})
357
+ query = (
358
+ """
359
+ mutation GroupEdit($id: ID!, $input:[EditInput]!) {
360
+ groupEdit(id: $id) {
361
+ fieldPatch(input: $input) {
362
+ """
363
+ + (self.properties if custom_attributes is None else custom_attributes)
364
+ + """
365
+ }
366
+ }
367
+ }
368
+ """
369
+ )
370
+ result = self.opencti.query(query, {"id": id, "input": input})
371
+ return self.opencti.process_multiple_fields(
372
+ result["data"]["groupEdit"]["fieldPatch"]
373
+ )
374
+
375
+ def add_member(self, **kwargs) -> Optional[Dict]:
376
+ """Add a member to a given group.
377
+
378
+ :param id: ID of the group to add a member to
379
+ :type id: str
380
+ :param user_id: ID to add to the group
381
+ :type user_id: str
382
+ :return: Representation of the relationship
383
+ :rtype: Optional[Dict]
384
+ """
385
+ id = kwargs.get("id", None)
386
+ user_id = kwargs.get("user_id", None)
387
+
388
+ if id is None or user_id is None:
389
+ self.opencti.admin_logger.error(
390
+ "[opencti_group] Missing parameters: id and user_id"
391
+ )
392
+ return None
393
+
394
+ self.opencti.admin_logger.info(
395
+ "Adding member to group", {"groupId": id, "userId": user_id}
396
+ )
397
+ query = """
398
+ mutation GroupEditMemberAdd($groupId: ID!, $userId: ID!) {
399
+ groupEdit(id: $groupId) {
400
+ relationAdd(input: {
401
+ fromId: $userId,
402
+ relationship_type: "member-of"
403
+ }) {
404
+ id, standard_id, entity_type, created_at, updated_at
405
+ from {
406
+ id, entity_type
407
+ }
408
+ to {
409
+ id, entity_type
410
+ }
411
+ }
412
+ }
413
+ }
414
+ """
415
+ result = self.opencti.query(query, {"groupId": id, "userId": user_id})
416
+ return self.opencti.process_multiple_fields(
417
+ result["data"]["groupEdit"]["relationAdd"]
418
+ )
419
+
420
+ def delete_member(self, **kwargs) -> Optional[Dict]:
421
+ """Remove a given user from a group
422
+
423
+ :param id: ID to remove a user from
424
+ :type id: str
425
+ :param user: ID to remove from the group
426
+ :type user: str
427
+ :return: Representation of the group after the member has been removed
428
+ :rtype: Optional[Dict]
429
+ """
430
+ id = kwargs.get("id", None)
431
+ user_id = kwargs.get("user_id", None)
432
+
433
+ if id is None or user_id is None:
434
+ self.opencti.admin_logger.error(
435
+ "[opencti_group] Missing parameters: id and user_id"
436
+ )
437
+ return None
438
+
439
+ self.opencti.admin_logger.info(
440
+ "Removing member from group", {"groupId": id, "userId": user_id}
441
+ )
442
+ query = (
443
+ """
444
+ mutation GroupEditMemberDelete ($groupId: ID!, $userId: StixRef!) {
445
+ groupEdit(id: $groupId) {
446
+ relationDelete(fromId: $userId, relationship_type: "member-of") {
447
+ """
448
+ + self.properties
449
+ + """
450
+ }
451
+ }
452
+ }
453
+ """
454
+ )
455
+ result = self.opencti.query(query, {"groupId": id, "userId": user_id})
456
+ return self.opencti.process_multiple_fields(
457
+ result["data"]["groupEdit"]["relationDelete"]
458
+ )
459
+
460
+ def add_role(self, **kwargs) -> Optional[Dict]:
461
+ """Add a role to a given group
462
+
463
+ :param id: ID to add a role to
464
+ :type id: str
465
+ :param role_id: Role ID to add to the group
466
+ :type role: str
467
+ :return: Representation of the group after a role has been added
468
+ :rtype: Optional[Dict]
469
+ """
470
+ id = kwargs.get("id", None)
471
+ role_id = kwargs.get("role_id", None)
472
+
473
+ if id is None or role_id is None:
474
+ self.opencti.admin_logger.error(
475
+ "[opencti_group] Missing parameters: id and role_id"
476
+ )
477
+ return None
478
+
479
+ self.opencti.admin_logger.info(
480
+ "Adding role to group", {"groupId": id, "roleId": role_id}
481
+ )
482
+ query = """
483
+ mutation GroupEditRoleAdd($groupId: ID!, $roleId: ID!) {
484
+ groupEdit(id: $groupId) {
485
+ relationAdd(input: {
486
+ toId: $roleId, relationship_type: "has-role"
487
+ }) {
488
+ id, standard_id, entity_type, created_at, updated_at
489
+ from {
490
+ id, entity_type
491
+ }
492
+ to {
493
+ id, entity_type
494
+ }
495
+ }
496
+ }
497
+ }
498
+ """
499
+ result = self.opencti.query(query, {"groupId": id, "roleId": role_id})
500
+ return self.opencti.process_multiple_fields(
501
+ result["data"]["groupEdit"]["relationAdd"]
502
+ )
503
+
504
+ def delete_role(self, **kwargs) -> Optional[Dict]:
505
+ """Removes a role from a given group
506
+
507
+ :param id: ID to remove role from
508
+ :type id: str
509
+ :param role_id: Role ID to remove from the group
510
+ :type role_id: str
511
+ :return: Representation of the group after role is removed
512
+ :rtype: Optional[Dict]
513
+ """
514
+ id = kwargs.get("id", None)
515
+ role_id = kwargs.get("role_id", None)
516
+
517
+ if id is None or role_id is None:
518
+ self.opencti.admin_logger.error(
519
+ "[opencti_group] Missing parameters: id and role_id"
520
+ )
521
+ return None
522
+
523
+ self.opencti.admin_logger.info(
524
+ "Removing role from group", {"groupId": id, "roleId": role_id}
525
+ )
526
+ query = (
527
+ """
528
+ mutation GroupEditRoleDelete($groupId: ID!, $roleId: StixRef!) {
529
+ groupEdit(id: $groupId) {
530
+ relationDelete(toId: $roleId, relationship_type: "has-role") {
531
+ """
532
+ + self.properties
533
+ + """
534
+ }
535
+ }
536
+ }
537
+ """
538
+ )
539
+ result = self.opencti.query(query, {"groupId": id, "roleId": role_id})
540
+ return self.opencti.process_multiple_fields(
541
+ result["data"]["groupEdit"]["relationDelete"]
542
+ )
543
+
544
+ def edit_default_marking(self, **kwargs) -> Optional[Dict]:
545
+ """Adds a default marking to the group.
546
+
547
+ :param id: ID of the group.
548
+ :type id: str
549
+ :param marking_ids: IDs of the markings to add, or an empty list to
550
+ remove all default markings
551
+ :type marking_ids: List[str]
552
+ :param entity: STIX entity type to add default
553
+ marking for. If set to "GLOBAL" applies to all entity types,
554
+ defaults to "GLOBAL".
555
+ :type entity: str, optional
556
+ :return: Group after adding the default marking.
557
+ :rtype: Optional[Dict]
558
+ """
559
+ id = kwargs.get("id", None)
560
+ marking_ids = kwargs.get("marking_ids", None)
561
+ entity_type = kwargs.get("entity_type", "GLOBAL")
562
+
563
+ if id is None or marking_ids is None:
564
+ self.opencti.admin_logger.error(
565
+ "[opencti_group] Missing parameters: id and marking_ids"
566
+ )
567
+ return None
568
+
569
+ self.opencti.admin_logger.info(
570
+ "Setting default markings for entity on group",
571
+ {"markings": marking_ids, "entity_type": entity_type, "groupId": id},
572
+ )
573
+ query = (
574
+ """
575
+ mutation GroupEditEditDefaultMarking($id: ID!, $entity_type: String!, $values: [String!]) {
576
+ groupEdit(id: $id) {
577
+ editDefaultMarking(input: {
578
+ entity_type: $entity_type,
579
+ values: $values
580
+ }) {
581
+ """
582
+ + self.properties
583
+ + """
584
+ }
585
+ }
586
+ }
587
+ """
588
+ )
589
+ result = self.opencti.query(
590
+ query, {"id": id, "entity_type": entity_type, "values": marking_ids}
591
+ )
592
+ return self.opencti.process_multiple_fields(
593
+ result["data"]["groupEdit"]["editDefaultMarking"]
594
+ )
595
+
596
+ def add_allowed_marking(self, **kwargs) -> Optional[Dict]:
597
+ """Allow a group to access a marking
598
+
599
+ :param id: ID of group to authorise
600
+ :type id: str
601
+ :param marking_id: ID of marking to authorise
602
+ :type marking_id: str
603
+ :return: Relationship from the group to the marking definition
604
+ :rtype: Optional[Dict]
605
+ """
606
+ id = kwargs.get("id", None)
607
+ marking_id = kwargs.get("marking_id", None)
608
+
609
+ if id is None or marking_id is None:
610
+ self.opencti.admin_logger.error(
611
+ "[opencti_group] Missing parameters: id and marking_id"
612
+ )
613
+ return None
614
+
615
+ self.opencti.admin_logger.info(
616
+ "Granting group access to marking definition",
617
+ {"groupId": id, "markingId": marking_id},
618
+ )
619
+ query = """
620
+ mutation GroupEditionMarkingsMarkingDefinitionsRelationAddMutation(
621
+ $id: ID!
622
+ $input: InternalRelationshipAddInput!
623
+ ) {
624
+ groupEdit(id: $id) {
625
+ relationAdd(input: $input) {
626
+ from {
627
+ __typename
628
+ ...GroupEditionMarkings_group
629
+ id
630
+ }
631
+ id
632
+ }
633
+ }
634
+ }
635
+
636
+ fragment GroupEditionMarkings_group on Group {
637
+ id
638
+ default_assignation
639
+ allowed_marking {
640
+ id
641
+ }
642
+ not_shareable_marking_types
643
+ max_shareable_marking {
644
+ id
645
+ definition
646
+ definition_type
647
+ x_opencti_order
648
+ }
649
+ default_marking {
650
+ entity_type
651
+ values {
652
+ id
653
+ }
654
+ }
655
+ }
656
+ """
657
+ result = self.opencti.query(
658
+ query,
659
+ {
660
+ "id": id,
661
+ "input": {"relationship_type": "accesses-to", "toId": marking_id},
662
+ },
663
+ )
664
+ return self.opencti.process_multiple_fields(
665
+ result["data"]["groupEdit"]["relationAdd"]
666
+ )
667
+
668
+ def delete_allowed_marking(self, **kwargs) -> Optional[Dict]:
669
+ """Removes access to a marking for a group
670
+
671
+ :param id: ID of group to forbid
672
+ :type id: str
673
+ :param marking_id: ID of marking to deny
674
+ :type marking_id: str
675
+ :return: Group after denying access to marking definition
676
+ :rtype: Optional[Dict]
677
+ """
678
+ id = kwargs.get("id", None)
679
+ marking_id = kwargs.get("marking_id", None)
680
+
681
+ if id is None or marking_id is None:
682
+ self.opencti.admin_logger.error(
683
+ "[opencti_group] Missing parameters: id and marking_id"
684
+ )
685
+ return None
686
+
687
+ self.opencti.admin_logger.info(
688
+ "Forbidding group access to marking definition",
689
+ {"groupId": id, "markingId": marking_id},
690
+ )
691
+ query = (
692
+ """
693
+ mutation GroupEditMarkingRemove($groupId: ID!, $markingId: StixRef!) {
694
+ groupEdit(id: $groupId) {
695
+ relationDelete(toId: $markingId, relationship_type: "accesses-to") {
696
+ """
697
+ + self.properties
698
+ + """
699
+ }
700
+ }
701
+ }
702
+ """
703
+ )
704
+ result = self.opencti.query(query, {"groupId": id, "markingId": marking_id})
705
+ return self.opencti.process_multiple_fields(
706
+ result["data"]["groupEdit"]["relationDelete"]
707
+ )
708
+
709
+ def process_multiple_fields(self, data):
710
+ if "roles" in data:
711
+ data["roles"] = self.opencti.process_multiple(data["roles"])
712
+ data["rolesIds"] = self.opencti.process_multiple_ids(data["roles"])
713
+ if "members" in data:
714
+ data["members"] = self.opencti.process_multiple(data["members"])
715
+ data["membersIds"] = self.opencti.process_multiple_ids(data["members"])
716
+ return data