-
Notifications
You must be signed in to change notification settings - Fork 786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1960 deserialize config #2043
1960 deserialize config #2043
Changes from 58 commits
77804ca
d8ac441
e83995d
6b406ef
ffe8c34
095e49b
9286e86
86ed174
ab67853
0f848eb
aff5423
bba7139
6e951ed
81d3300
bff92ed
5a95aef
afeca66
ad0f694
05f640d
6d156b8
2ff2e5f
f9445a2
d59dd81
fb67586
b605f16
e1d5d25
ffd3464
858eb23
2eb1691
a3db414
7b4daaa
02cca3e
7bba711
e3cea20
5c73971
8605fd4
1f9a056
28250da
e4eee6a
6a92726
a1baaae
07d1d9c
4c47eae
ea02bec
fc9d854
94524d1
dbd0d3e
e2f365a
334d2a7
8cb045d
568eb4f
93ed7cf
84fc78c
b219ca0
33ec4f7
dc9b91d
8886ebc
4f7d8be
503a0a8
fefd2da
4b7ab05
7179f91
c080f03
232d6ba
bf1d360
90259c1
e6d3854
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from typing import List | ||
from typing import Any, List, Mapping | ||
|
||
from marshmallow import Schema, fields, post_load | ||
from marshmallow import Schema, fields | ||
from marshmallow.exceptions import MarshmallowError | ||
|
||
from .agent_sub_configuration_schemas import ( | ||
CustomPBAConfigurationSchema, | ||
|
@@ -15,6 +18,15 @@ | |
) | ||
|
||
|
||
class InvalidConfigurationError(Exception): | ||
pass | ||
|
||
|
||
INVALID_CONFIGURATION_ERROR_MESSAGE = ( | ||
"Cannot construct an AgentConfiguration object with the supplied, invalid data:" | ||
) | ||
|
||
|
||
@dataclass(frozen=True) | ||
class AgentConfiguration: | ||
keep_tunnel_open_time: float | ||
|
@@ -24,6 +36,57 @@ class AgentConfiguration: | |
payloads: List[PluginConfiguration] | ||
propagation: PropagationConfiguration | ||
|
||
def __post_init__(self): | ||
# This will raise an exception if the object is invalid. Calling this in __post__init() | ||
# makes it impossible to construct an invalid object | ||
try: | ||
AgentConfigurationSchema().dump(self) | ||
except Exception as err: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we expecting anything but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That I'm aware, it can raise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A better question is, "Is there any case where |
||
raise InvalidConfigurationError(f"{INVALID_CONFIGURATION_ERROR_MESSAGE}: {err}") | ||
|
||
@staticmethod | ||
def from_mapping(config_mapping: Mapping[str, Any]) -> AgentConfiguration: | ||
""" | ||
Construct an AgentConfiguration from a Mapping | ||
|
||
:param config_mapping: A Mapping that represents an AgentConfiguration | ||
:return: An AgentConfiguration | ||
:raises: InvalidConfigurationError if the provided Mapping does not represent a valid | ||
AgentConfiguration | ||
""" | ||
|
||
try: | ||
config_dict = AgentConfigurationSchema().load(config_mapping) | ||
return AgentConfiguration(**config_dict) | ||
except MarshmallowError as err: | ||
raise InvalidConfigurationError(f"{INVALID_CONFIGURATION_ERROR_MESSAGE}: {err}") | ||
|
||
@staticmethod | ||
def from_json(config_json: str) -> AgentConfiguration: | ||
""" | ||
Construct an AgentConfiguration from a JSON string | ||
|
||
:param config_json: A JSON string that represents an AgentConfiguration | ||
:return: An AgentConfiguration | ||
:raises: InvalidConfigurationError if the provided JSON does not represent a valid | ||
AgentConfiguration | ||
""" | ||
try: | ||
config_dict = AgentConfigurationSchema().loads(config_json) | ||
return AgentConfiguration(**config_dict) | ||
except MarshmallowError as err: | ||
raise InvalidConfigurationError(f"{INVALID_CONFIGURATION_ERROR_MESSAGE}: {err}") | ||
|
||
@staticmethod | ||
def to_json(config: AgentConfiguration) -> str: | ||
""" | ||
Serialize an AgentConfiguration to JSON | ||
|
||
:param config: An AgentConfiguration | ||
:return: A JSON string representing the AgentConfiguration | ||
""" | ||
return AgentConfigurationSchema().dumps(config) | ||
|
||
|
||
class AgentConfigurationSchema(Schema): | ||
keep_tunnel_open_time = fields.Float() | ||
|
@@ -32,7 +95,3 @@ class AgentConfigurationSchema(Schema): | |
credential_collectors = fields.List(fields.Nested(PluginConfigurationSchema)) | ||
payloads = fields.List(fields.Nested(PluginConfigurationSchema)) | ||
propagation = fields.Nested(PropagationConfigurationSchema) | ||
|
||
@post_load | ||
def _make_agent_configuration(self, data, **kwargs): | ||
return AgentConfiguration(**data) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from . import AgentConfiguration, AgentConfigurationSchema | ||
from . import AgentConfiguration | ||
|
||
DEFAULT_AGENT_CONFIGURATION_JSON = """{ | ||
"keep_tunnel_open_time": 30, | ||
|
@@ -204,5 +204,4 @@ | |
|
||
|
||
def build_default_agent_configuration() -> AgentConfiguration: | ||
schema = AgentConfigurationSchema() | ||
return schema.loads(DEFAULT_AGENT_CONFIGURATION_JSON) | ||
return AgentConfiguration.from_json(DEFAULT_AGENT_CONFIGURATION_JSON) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably specify the defaults in the marshmallow schema. We'll do it with validation, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, #2004. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,5 +38,7 @@ class DomainControllerNameFetchError(FailedExploitationError): | |
"""Raise on failed attempt to extract domain controller's name""" | ||
|
||
|
||
# TODO: This has been replaced by common.configuration.InvalidConfigurationError. Use that error | ||
# instead and remove this one. | ||
Comment on lines
+41
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not in this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it's out of scope. Other components are still using the old |
||
class InvalidConfigurationError(Exception): | ||
"""Raise when configuration is invalid""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have both
PluginConfiguration
andExploiterConfiguration
dataclasses which have the same member variables (link to file with definitions)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question!
ExploiterConfiguration
hadsupported_os
in it, until that was removed by #2038. Whensupported_os
was removed, everything that usedExploiterConfiguration
should have been changed toPluginConfiguration
. I'll add a task to #1960.