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.
- pycti/__init__.py +13 -1
- pycti/api/opencti_api_client.py +13 -0
- pycti/connector/opencti_connector_helper.py +24 -6
- pycti/entities/opencti_capability.py +52 -0
- pycti/entities/opencti_group.py +716 -0
- pycti/entities/opencti_indicator.py +6 -0
- pycti/entities/opencti_role.py +408 -0
- pycti/entities/opencti_settings.py +385 -0
- pycti/entities/opencti_user.py +803 -0
- pycti/utils/opencti_stix2.py +90 -22
- {pycti-6.5.11.dist-info → pycti-6.6.1.dist-info}/METADATA +1 -1
- {pycti-6.5.11.dist-info → pycti-6.6.1.dist-info}/RECORD +15 -10
- {pycti-6.5.11.dist-info → pycti-6.6.1.dist-info}/WHEEL +0 -0
- {pycti-6.5.11.dist-info → pycti-6.6.1.dist-info}/licenses/LICENSE +0 -0
- {pycti-6.5.11.dist-info → pycti-6.6.1.dist-info}/top_level.txt +0 -0
|
@@ -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
|