diff --git a/integration/test_alert_rules.py b/integration/test_alert_rules.py new file mode 100644 index 000000000..b6846a739 --- /dev/null +++ b/integration/test_alert_rules.py @@ -0,0 +1,57 @@ +import pytest +from integration import run_command + +ALERT_RULES_COMMAND = "code42 alert-rules" + + +@pytest.mark.integration +@pytest.mark.parametrize( + "command", + [ + "{} list".format(ALERT_RULES_COMMAND), + "{} show test-rule-id".format(ALERT_RULES_COMMAND), + "{} list -f CSV".format(ALERT_RULES_COMMAND), + "{} list -f TABLE".format(ALERT_RULES_COMMAND), + "{} list -f RAW-JSON".format(ALERT_RULES_COMMAND), + "{} list -f JSON".format(ALERT_RULES_COMMAND), + "{} list --format CSV".format(ALERT_RULES_COMMAND), + "{} list --format TABLE".format(ALERT_RULES_COMMAND), + "{} list --format JSON".format(ALERT_RULES_COMMAND), + "{} list --format RAW-JSON".format(ALERT_RULES_COMMAND), + ], +) +def test_alert_rules_command_returns_success_return_code(command): + return_code, response = run_command(command) + assert return_code == 0 + + +@pytest.mark.parametrize( + "command, error_msg", + [ + ( + "{} add-user --rule-id test-rule-id".format(ALERT_RULES_COMMAND), + "Missing option '-u' / '--username'.", + ), + ( + "{} remove-user --rule-id test-rule-id".format(ALERT_RULES_COMMAND), + "Missing option '-u' / '--username'.", + ), + ("{} add-user".format(ALERT_RULES_COMMAND), "Missing option '--rule-id'."), + ("{} remove-user".format(ALERT_RULES_COMMAND), "Missing option '--rule-id'."), + ("{} show".format(ALERT_RULES_COMMAND), "Missing argument 'RULE_ID'."), + ( + "{} bulk add".format(ALERT_RULES_COMMAND), + "Error: Missing argument 'CSV_FILE'.", + ), + ( + "{} bulk remove".format(ALERT_RULES_COMMAND), + "Error: Missing argument 'CSV_FILE'.", + ), + ], +) +def test_alert_rules_command_returns_error_exit_status_when_missing_required_parameters( + command, error_msg +): + return_code, response = run_command(command) + assert return_code == 2 + assert error_msg in "".join(response) diff --git a/integration/test_alerts.py b/integration/test_alerts.py index c559b1abe..57038f665 100644 --- a/integration/test_alerts.py +++ b/integration/test_alerts.py @@ -11,21 +11,48 @@ end_date_str = end_date.strftime("%Y-%m-%d") ALERT_COMMAND = "code42 alerts search -b {} -e {}".format(begin_date_str, end_date_str) +ADVANCED_QUERY = """{"groupClause":"AND", "groups":[{"filterClause":"AND", +"filters":[{"operator":"ON_OR_AFTER", "term":"eventTimestamp", "value":"2020-09-13T00:00:00.000Z"}, +{"operator":"ON_OR_BEFORE", "term":"eventTimestamp", "value":"2020-12-07T13:20:15.195Z"}]}], +"srtDir":"asc", "srtKey":"eventId", "pgNum":1, "pgSize":10000} +""" +ALERT_ADVANCED_QUERY_COMMAND = "code42 alerts search --advanced-query '{}'".format( + ADVANCED_QUERY +) +@pytest.mark.integration @pytest.mark.parametrize( "command", [ - ("{}".format(ALERT_COMMAND)), - ("{} --state OPEN".format(ALERT_COMMAND)), - ("{} --state RESOLVED".format(ALERT_COMMAND)), - ("{} --actor user@code42.com".format(ALERT_COMMAND)), - ("{} --rule-name 'File Upload Alert'".format(ALERT_COMMAND)), - ("{} --rule-id 962a6a1c-54f6-4477-90bd-a08cc74cbf71".format(ALERT_COMMAND)), - ("{} --rule-type FedEndpointExfiltration".format(ALERT_COMMAND)), - ("{} --description 'Alert on any file upload'".format(ALERT_COMMAND)), + ALERT_COMMAND, + "{} --state OPEN".format(ALERT_COMMAND), + "{} --state RESOLVED".format(ALERT_COMMAND), + "{} --actor user@code42.com".format(ALERT_COMMAND), + "{} --rule-name 'File Upload Alert'".format(ALERT_COMMAND), + "{} --rule-id 962a6a1c-54f6-4477-90bd-a08cc74cbf71".format(ALERT_COMMAND), + "{} --rule-type FedEndpointExfiltration".format(ALERT_COMMAND), + "{} --description 'Alert on any file upload'".format(ALERT_COMMAND), + "{} --exclude-rule-type 'FedEndpointExfiltration'".format(ALERT_COMMAND), + "{} --exclude-rule-id '962a6a1c-54f6-4477-90bd-a08cc74cbf71'".format( + ALERT_COMMAND + ), + "{} --exclude-rule-name 'File Upload Alert'".format(ALERT_COMMAND), + "{} --exclude-actor-contains 'user@code42.com'".format(ALERT_COMMAND), + "{} --exclude-actor 'user@code42.com'".format(ALERT_COMMAND), + "{} --actor-contains 'user@code42.com'".format(ALERT_COMMAND), + ALERT_ADVANCED_QUERY_COMMAND, ], ) -def test_alert_returns_success_return_code(command): +def test_alert_command_returns_success_return_code(command): return_code, response = run_command(command) assert return_code == 0 + + +@pytest.mark.parametrize( + "command", ["{} --advanced-query '{}'".format(ALERT_COMMAND, ADVANCED_QUERY)] +) +def test_begin_cant_be_used_with_advanced_query(command): + return_code, response = run_command(command) + assert return_code == 2 + assert "--begin can't be used with: --advanced-query" in response[0] diff --git a/integration/test_auditlogs.py b/integration/test_auditlogs.py index 047f4c219..cdf4b4bbe 100644 --- a/integration/test_auditlogs.py +++ b/integration/test_auditlogs.py @@ -4,12 +4,44 @@ import pytest from integration import run_command -BASE_COMMAND = "code42 audit-logs search -b" +SEARCH_COMMAND = "code42 audit-logs search" +BASE_COMMAND = "{} -b".format(SEARCH_COMMAND) begin_date = datetime.utcnow() - timedelta(days=-10) begin_date_str = begin_date.strftime("%Y-%m-%d %H:%M:%S") +end_date = datetime.utcnow() - timedelta(days=10) +end_date_str = end_date.strftime("%Y-%m-%d %H:%M:%S") -@pytest.mark.parametrize("command", [("{} '{}'".format(BASE_COMMAND, begin_date_str))]) -def test_auditlogs_search(command): +@pytest.mark.integration +@pytest.mark.parametrize( + "command", + [ + ("{} '{}'".format(BASE_COMMAND, begin_date_str)), + ("{} '{}' -e '{}'".format(BASE_COMMAND, begin_date_str, end_date_str)), + ("{} '{}' --end '{}'".format(BASE_COMMAND, begin_date_str, end_date_str)), + ("{} '{}' --event-type '{}'".format(BASE_COMMAND, begin_date_str, "test")), + ("{} '{}' --username '{}'".format(BASE_COMMAND, begin_date_str, "test")), + ("{} '{}' --user-id '{}'".format(BASE_COMMAND, begin_date_str, "123")), + ("{} '{}' --user-ip '{}'".format(BASE_COMMAND, begin_date_str, "0.0.0.0")), + ("{} '{}' --affected-user-id '{}'".format(BASE_COMMAND, begin_date_str, "123")), + ( + "{} '{}' --affected-username '{}'".format( + BASE_COMMAND, begin_date_str, "test" + ) + ), + ("{} '{}' -f {}".format(BASE_COMMAND, begin_date_str, "CSV")), + ("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "TABLE")), + ("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "JSON")), + ("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "RAW-JSON")), + ("{} '{}' --format {}".format(BASE_COMMAND, begin_date_str, "CSV")), + ("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "TABLE")), + ("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "JSON")), + ("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "RAW-JSON")), + ("{} --begin '{}'".format(SEARCH_COMMAND, begin_date_str)), + ("{} '{}' -d".format(BASE_COMMAND, begin_date_str)), + ("{} '{}' --debug".format(BASE_COMMAND, begin_date_str)), + ], +) +def test_auditlogs_search_command_returns_success_return_code(command): return_code, response = run_command(command) assert return_code == 0 diff --git a/integration/test_departing_employee.py b/integration/test_departing_employee.py new file mode 100644 index 000000000..7510b2933 --- /dev/null +++ b/integration/test_departing_employee.py @@ -0,0 +1,30 @@ +import pytest +from integration import run_command + +DEPARTING_EMPLOYEE_COMMAND = "code42 departing-employee" + + +@pytest.mark.parametrize( + "command, error_msg", + [ + ("{} add".format(DEPARTING_EMPLOYEE_COMMAND), "Missing argument 'USERNAME'."), + ( + "{} remove".format(DEPARTING_EMPLOYEE_COMMAND), + "Missing argument 'USERNAME'.", + ), + ( + "{} bulk add".format(DEPARTING_EMPLOYEE_COMMAND), + "Missing argument 'CSV_FILE'.", + ), + ( + "{} bulk remove".format(DEPARTING_EMPLOYEE_COMMAND), + "Missing argument 'FILE'.", + ), + ], +) +def test_departing_employee_command_returns_error_exit_status_when_missing_required_parameters( + command, error_msg +): + return_code, response = run_command(command) + assert return_code == 2 + assert error_msg in "".join(response) diff --git a/integration/test_high_risk_employee.py b/integration/test_high_risk_employee.py new file mode 100644 index 000000000..ff7ca7699 --- /dev/null +++ b/integration/test_high_risk_employee.py @@ -0,0 +1,29 @@ +import pytest +from integration import run_command + +HR_EMPLOYEE_COMMAND = "code42 high-risk-employee" + + +@pytest.mark.parametrize( + "command, error_msg", + [ + ("{} add".format(HR_EMPLOYEE_COMMAND), "Missing argument 'USERNAME'."), + ("{} remove".format(HR_EMPLOYEE_COMMAND), "Missing argument 'USERNAME'."), + ("{} bulk add".format(HR_EMPLOYEE_COMMAND), "Missing argument 'CSV_FILE'."), + ("{} bulk remove".format(HR_EMPLOYEE_COMMAND), "Missing argument 'FILE'."), + ( + "{} bulk add-risk-tags".format(HR_EMPLOYEE_COMMAND), + "Missing argument 'CSV_FILE'.", + ), + ( + "{} bulk remove-risk-tags".format(HR_EMPLOYEE_COMMAND), + "Missing argument 'CSV_FILE'.", + ), + ], +) +def test_hr_employee_command_returns_error_exit_status_when_missing_required_parameters( + command, error_msg +): + return_code, response = run_command(command) + assert return_code == 2 + assert error_msg in "".join(response) diff --git a/integration/test_legal_hold.py b/integration/test_legal_hold.py new file mode 100644 index 000000000..8d3f9238e --- /dev/null +++ b/integration/test_legal_hold.py @@ -0,0 +1,63 @@ +import pytest +from integration import run_command + +LEGAL_HOLD_COMMAND = "code42 legal-hold" + + +@pytest.mark.integration +@pytest.mark.parametrize( + "command", + [ + "{} list".format(LEGAL_HOLD_COMMAND), + "{} show 984140047896012577".format(LEGAL_HOLD_COMMAND), + "{} list -f CSV".format(LEGAL_HOLD_COMMAND), + "{} list -f TABLE".format(LEGAL_HOLD_COMMAND), + "{} list -f RAW-JSON".format(LEGAL_HOLD_COMMAND), + "{} list -f JSON".format(LEGAL_HOLD_COMMAND), + "{} list --format CSV".format(LEGAL_HOLD_COMMAND), + "{} list --format TABLE".format(LEGAL_HOLD_COMMAND), + "{} list --format JSON".format(LEGAL_HOLD_COMMAND), + "{} list --format RAW-JSON".format(LEGAL_HOLD_COMMAND), + ], +) +def test_alert_rules_command_returns_success_return_code(command): + return_code, response = run_command(command) + assert return_code == 0 + + +@pytest.mark.parametrize( + "command, error_msg", + [ + ( + "{} add-user --matter-id test-matter-id".format(LEGAL_HOLD_COMMAND), + "Missing option '-u' / '--username'.", + ), + ( + "{} remove-user --matter-id test-matter-id".format(LEGAL_HOLD_COMMAND), + "Missing option '-u' / '--username'.", + ), + ( + "{} add-user".format(LEGAL_HOLD_COMMAND), + "Missing option '-m' / '--matter-id'.", + ), + ( + "{} remove-user".format(LEGAL_HOLD_COMMAND), + "Missing option '-m' / '--matter-id'.", + ), + ("{} show".format(LEGAL_HOLD_COMMAND), "Missing argument 'MATTER_ID'."), + ( + "{} bulk add".format(LEGAL_HOLD_COMMAND), + "Error: Missing argument 'CSV_FILE'.", + ), + ( + "{} bulk remove".format(LEGAL_HOLD_COMMAND), + "Error: Missing argument 'CSV_FILE'.", + ), + ], +) +def test_alert_rules_command_returns_error_exit_status_when_missing_required_parameters( + command, error_msg +): + return_code, response = run_command(command) + assert return_code == 2 + assert error_msg in "".join(response) diff --git a/run_integration.py b/run_integration.py deleted file mode 100644 index da21ee8a5..000000000 --- a/run_integration.py +++ /dev/null @@ -1,13 +0,0 @@ -import os -import sys - -if __name__ == "__main__": - if sys.argv[1] and sys.argv[2]: - os.environ["C42_USER"] = sys.argv[1] - os.environ["C42_PW"] = sys.argv[2] - rc = os.system("pytest ./integration -v -rsxX -l --tb=short --strict") - sys.exit(rc) - else: - print( - "username and password were not supplied. Integration tests will be skipped." - ) diff --git a/tox.ini b/tox.ini index 6031d7c65..6154ee5ea 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ deps = pytest == 4.6.11 pytest-mock == 2.0.0 pytest-cov == 2.10.0 + pexpect == 4.8.0 commands = # -v: verbose @@ -17,7 +18,7 @@ commands = # -l: show locals in tracebacks # --tb=short: short traceback print mode # --strict: marks not registered in configuration file raise errors - pytest --cov=code42cli --cov-report xml -v -rsxX -l --tb=short --strict + pytest --cov=code42cli --cov-report xml -v -rsxX -l --tb=short --strict -m "not integration" [testenv:docs] deps = @@ -44,3 +45,7 @@ deps = pytest-cov == 2.10.0 git+https://github.com/code42/py42.git@master#egg=py42 git+ssh://git@github.com/code42/c42eventextractor.git@master#egg=c42eventextractor + +[pytest] +markers = + integration: mark test as a integration test.