Skip to content

Commit 8d07ed3

Browse files
authored
Bugfix/error messages (#72)
1 parent 19485a3 commit 8d07ed3

File tree

16 files changed

+262
-168
lines changed

16 files changed

+262
-168
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"c42eventextractor==0.3.0b1",
2525
"keyring==18.0.1",
2626
"keyrings.alt==3.2.0",
27-
"py42>=1.1.3",
27+
"py42>=1.2.0",
2828
],
2929
license="MIT",
3030
include_package_data=True,

src/code42cli/cmds/alerts/rules/user_rule.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from py42.exceptions import Py42InternalServerError
12
from py42.util import format_json
23

4+
5+
from code42cli.errors import InvalidRuleTypeError
36
from code42cli.util import format_to_table, find_format_width
47
from code42cli.bulk import run_bulk_process, CSVReader
58
from code42cli.logger import get_main_cli_logger
@@ -19,29 +22,55 @@
1922

2023
def add_user(sdk, profile, rule_id, username):
2124
user_id = get_user_id(sdk, username)
22-
sdk.alerts.rules.add_user(rule_id, user_id)
25+
rules = _get_rule_metadata(sdk, rule_id)
26+
try:
27+
if rules:
28+
sdk.alerts.rules.add_user(rule_id, user_id)
29+
except Py42InternalServerError as e:
30+
_check_if_system_rule(sdk, rules)
31+
raise
2332

2433

2534
def remove_user(sdk, profile, rule_id, username):
26-
if username:
27-
user_id = get_user_id(sdk, username)
28-
sdk.alerts.rules.remove_user(rule_id, user_id)
29-
else:
30-
sdk.alerts.rules.remove_all_users(rule_id)
35+
user_id = get_user_id(sdk, username)
36+
rules = _get_rule_metadata(sdk, rule_id)
37+
try:
38+
if rules:
39+
sdk.alerts.rules.remove_user(rule_id, user_id)
40+
except Py42InternalServerError as e:
41+
_check_if_system_rule(sdk, rules)
42+
raise
3143

3244

33-
def _get_rules_metadata(sdk, rule_id=None):
45+
def _get_all_rules_metadata(sdk):
3446
rules_generator = sdk.alerts.rules.get_all()
3547
selected_rules = [rule for rules in rules_generator for rule in rules[u"ruleMetadata"]]
36-
if rule_id:
37-
selected_rules = [rule for rule in selected_rules if rule[u"observerRuleId"] == rule_id]
38-
return selected_rules
48+
return _handle_rules_results(sdk, selected_rules)
49+
50+
51+
def _get_rule_metadata(sdk, rule_id):
52+
rules = sdk.alerts.rules.get_by_observer_id(rule_id)[u"ruleMetadata"]
53+
return _handle_rules_results(sdk, rules, rule_id)
54+
55+
56+
def _handle_rules_results(sdk, rules, rule_id=None):
57+
id_msg = u"with RuleId {} ".format(rule_id) if rule_id else u""
58+
msg = u"No alert rules {0}found.".format(id_msg)
59+
if not rules:
60+
get_main_cli_logger().print_and_log_info(msg)
61+
return rules
62+
63+
64+
def _check_if_system_rule(sdk, rules):
65+
if rules and rules[0][u"isSystem"]:
66+
raise InvalidRuleTypeError(rules[0][u"observerRuleId"], rules[0][u"ruleSource"])
3967

4068

4169
def get_rules(sdk, profile):
42-
selected_rules = _get_rules_metadata(sdk)
43-
rows, column_size = find_format_width(selected_rules, _HEADER_KEYS_MAP)
44-
format_to_table(rows, column_size)
70+
selected_rules = _get_all_rules_metadata(sdk)
71+
if selected_rules:
72+
rows, column_size = find_format_width(selected_rules, _HEADER_KEYS_MAP)
73+
format_to_table(rows, column_size)
4574

4675

4776
def add_bulk_users(sdk, profile, file_name):
@@ -59,9 +88,9 @@ def remove_bulk_users(sdk, profile, file_name):
5988

6089

6190
def show_rule(sdk, profile, rule_id):
62-
selected_rule = _get_rules_metadata(sdk, rule_id)
91+
selected_rule = _get_rule_metadata(sdk, rule_id)
6392
rule_detail = None
64-
if len(selected_rule):
93+
if selected_rule:
6594
rule_type = selected_rule[0][u"type"]
6695
if rule_type == AlertRuleTypes.EXFILTRATION:
6796
rule_detail = sdk.alerts.rules.exfiltration.get(rule_id)

src/code42cli/cmds/detectionlists/__init__.py

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,11 @@
33
from code42cli.compat import str
44
from code42cli.cmds.detectionlists.commands import DetectionListCommandFactory
55
from code42cli.bulk import generate_template, run_bulk_process, CSVReader, FlatFileReader
6-
from code42cli.logger import get_main_cli_logger
6+
from code42cli.errors import UserAlreadyAddedError, UnknownRiskTagError, UserDoesNotExistError
77
from code42cli.bulk import BulkCommandType
88
from code42cli.cmds.detectionlists.enums import DetectionLists, DetectionListUserKeys, RiskTags
99

1010

11-
class UserAlreadyAddedError(Exception):
12-
def __init__(self, username, list_name):
13-
msg = u"'{}' is already on the {} list.".format(username, list_name)
14-
super(UserAlreadyAddedError, self).__init__(msg)
15-
16-
17-
class UnknownRiskTagError(Exception):
18-
def __init__(self, bad_tags):
19-
tags = u", ".join(bad_tags)
20-
super(UnknownRiskTagError, self).__init__(
21-
u"The following risk tags are unknown: '{}'.".format(tags)
22-
)
23-
24-
2511
def try_handle_user_already_added_error(bad_request_err, username_tried_adding, list_name):
2612
if _error_is_user_already_added(bad_request_err.response.text):
2713
raise UserAlreadyAddedError(username_tried_adding, list_name)
@@ -32,15 +18,6 @@ def _error_is_user_already_added(bad_request_error_text):
3218
return u"User already on list" in bad_request_error_text
3319

3420

35-
class UserDoesNotExistError(Exception):
36-
"""An error to represent a username that is not in our system. The CLI shows this error when
37-
the user tries to add or remove a user that does not exist. This error is not shown during
38-
bulk add or remove."""
39-
40-
def __init__(self, username):
41-
super(UserDoesNotExistError, self).__init__(u"User '{}' does not exist.".format(username))
42-
43-
4421
class DetectionListHandlers(object):
4522
"""Handlers DTO for passing in specific detection list functions.
4623
@@ -206,9 +183,7 @@ def get_user_id(sdk, username):
206183
"""
207184
users = sdk.users.get_by_username(username)[u"users"]
208185
if not users:
209-
ex = UserDoesNotExistError(username)
210-
get_main_cli_logger().print_and_log_error(str(ex))
211-
raise ex
186+
raise UserDoesNotExistError(username)
212187
return users[0][u"userUid"]
213188

214189

src/code42cli/cmds/search_shared/extraction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def begin_date_is_required(args, cursor_store):
1919

2020
# Ignore begin date when in incremental mode, it is not required, and it was passed an argument.
2121
if not is_required and args.begin:
22-
logger.print_info(
22+
logger.print_and_log_info(
2323
u"Ignoring --begin value as --incremental was passed and cursor checkpoint exists.\n"
2424
)
2525
args.begin = None

src/code42cli/date_helper.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,25 @@
33

44
from c42eventextractor.common import convert_datetime_to_timestamp
55

6-
7-
_FORMAT_VALUE_ERROR_MESSAGE = (
8-
u"input must be a date/time string (e.g. 'YYYY-MM-DD', "
9-
u"'YY-MM-DD HH:MM', 'YY-MM-DD HH:MM:SS'), or a short value in days, "
10-
u"hours, or minutes (e.g. 30d, 24h, 15m)"
11-
)
6+
from code42cli.errors import DateArgumentError
127

138
TIMESTAMP_REGEX = re.compile(u"(\d{4}-\d{2}-\d{2})\s*(.*)?")
149
MAGIC_TIME_REGEX = re.compile(u"(\d+)([dhm])$")
1510

1611

17-
class DateArgumentException(Exception):
18-
def __init__(self, message=_FORMAT_VALUE_ERROR_MESSAGE):
19-
super(DateArgumentException, self).__init__(message)
20-
21-
2212
def verify_timestamp_order(min_timestamp, max_timestamp):
2313
if min_timestamp is None or max_timestamp is None:
2414
return
2515
if min_timestamp >= max_timestamp:
26-
raise DateArgumentException(u"Begin date cannot be after end date")
16+
raise DateArgumentError(u"Begin date cannot be after end date")
2717

2818

2919
def parse_min_timestamp(begin_date_str, max_days_back=90):
3020
dt = _parse_timestamp(begin_date_str, _round_datetime_to_day_start)
3121

3222
boundary_date = _round_datetime_to_day_start(datetime.utcnow() - timedelta(days=max_days_back))
3323
if dt < boundary_date:
34-
raise DateArgumentException(u"'Begin date' must be within {0} days.".format(max_days_back))
24+
raise DateArgumentError(u"'Begin date' must be within {0} days.".format(max_days_back))
3525

3626
return convert_datetime_to_timestamp(dt)
3727

@@ -58,7 +48,7 @@ def _parse_timestamp(date_str, rounding_func):
5848
dt = rounding_func(dt)
5949

6050
else:
61-
raise DateArgumentException()
51+
raise DateArgumentError()
6252
return dt
6353

6454

@@ -72,7 +62,7 @@ def _get_dt_from_date_time_pair(date, time):
7262
try:
7363
dt = datetime.strptime(date_string, date_format)
7464
except ValueError:
75-
raise DateArgumentException()
65+
raise DateArgumentError()
7666
else:
7767
return dt
7868

@@ -86,7 +76,7 @@ def _get_dt_from_magic_time_pair(num, period):
8676
elif period == u"m":
8777
dt = datetime.utcnow() - timedelta(minutes=num)
8878
else:
89-
raise DateArgumentException(u"Couldn't parse magic time string: {}{}".format(num, period))
79+
raise DateArgumentError(u"Couldn't parse magic time string: {}{}".format(num, period))
9080
return dt
9181

9282

src/code42cli/errors.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,46 @@
11
ERRORED = False
2+
3+
_FORMAT_VALUE_ERROR_MESSAGE = (
4+
u"input must be a date/time string (e.g. 'YYYY-MM-DD', "
5+
u"'YY-MM-DD HH:MM', 'YY-MM-DD HH:MM:SS'), or a short value in days, "
6+
u"hours, or minutes (e.g. 30d, 24h, 15m)"
7+
)
8+
9+
10+
class Code42CLIError(Exception):
11+
pass
12+
13+
14+
class UserAlreadyAddedError(Code42CLIError):
15+
def __init__(self, username, list_name):
16+
msg = u"'{}' is already on the {} list.".format(username, list_name)
17+
super(UserAlreadyAddedError, self).__init__(msg)
18+
19+
20+
class UnknownRiskTagError(Code42CLIError):
21+
def __init__(self, bad_tags):
22+
tags = u", ".join(bad_tags)
23+
super(UnknownRiskTagError, self).__init__(
24+
u"The following risk tags are unknown: '{}'.".format(tags)
25+
)
26+
27+
28+
class InvalidRuleTypeError(Code42CLIError):
29+
def __init__(self, rule_id, source):
30+
msg = u"Only alert rules with a source of 'Alerting' can be targeted by this command. "
31+
msg += "Rule {0} has a source of '{1}'."
32+
super(InvalidRuleTypeError, self).__init__(msg.format(rule_id, source))
33+
34+
35+
class UserDoesNotExistError(Code42CLIError):
36+
"""An error to represent a username that is not in our system. The CLI shows this error when
37+
the user tries to add or remove a user that does not exist. This error is not shown during
38+
bulk add or remove."""
39+
40+
def __init__(self, username):
41+
super(UserDoesNotExistError, self).__init__(u"User '{}' does not exist.".format(username))
42+
43+
44+
class DateArgumentError(Code42CLIError):
45+
def __init__(self, message=_FORMAT_VALUE_ERROR_MESSAGE):
46+
super(DateArgumentError, self).__init__(message)

src/code42cli/invoker.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from py42.exceptions import Py42HTTPError, Py42ForbiddenError
44

5+
from code42cli.compat import str
6+
from code42cli.errors import Code42CLIError
57
from code42cli.parser import ArgumentParserError, CommandParser
68
from code42cli.logger import get_main_cli_logger
79

@@ -25,6 +27,9 @@ def run(self, input_args):
2527
path_parts = self._get_path_parts(input_args)
2628
command = self._commands.get(u" ".join(path_parts))
2729
self._try_run_command(command, path_parts, input_args)
30+
except Code42CLIError as err:
31+
logger = get_main_cli_logger()
32+
logger.print_and_log_error(str(err))
2833
except Py42ForbiddenError as err:
2934
logger = get_main_cli_logger()
3035
logger.log_verbose_error(invocation_str, err.response.request)

src/code42cli/worker.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from py42.exceptions import Py42HTTPError, Py42ForbiddenError
44

5+
from code42cli.compat import str
6+
from code42cli.errors import Code42CLIError
57
from code42cli.compat import queue
68
from code42cli.logger import get_main_cli_logger
79

@@ -77,6 +79,10 @@ def _process_queue(self):
7779
args = task[u"args"]
7880
kwargs = task[u"kwargs"]
7981
func(*args, **kwargs)
82+
except Code42CLIError as err:
83+
self._increment_total_errors()
84+
logger = get_main_cli_logger()
85+
logger.log_error(err)
8086
except Py42ForbiddenError as err:
8187
self._increment_total_errors()
8288
logger = get_main_cli_logger()

0 commit comments

Comments
 (0)