From 54f72c1be288040c07f2c337c9e1b331fafdbfd7 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Wed, 23 Aug 2017 14:59:59 -0500 Subject: [PATCH 01/28] security-groups-request-ids : Add output for RequestIDs The python api will now output a table with requestIDs for specific calls to security groups apis --- SoftLayer/CLI/securitygroup/interface.py | 12 ++++++++++ SoftLayer/CLI/securitygroup/rule.py | 28 ++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/interface.py b/SoftLayer/CLI/securitygroup/interface.py index a2f33ee87..b08f7daa6 100644 --- a/SoftLayer/CLI/securitygroup/interface.py +++ b/SoftLayer/CLI/securitygroup/interface.py @@ -14,6 +14,8 @@ 'interface', 'ipAddress', ] +REQUEST_COLUMNS = ['requestId'] + @click.command() @click.argument('securitygroup_id') @@ -95,6 +97,11 @@ def add(env, securitygroup_id, network_component, server, interface): if not success: raise exceptions.CLIAbort("Could not attach network component") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([success['id']]) + + env.fout(table) + @click.command() @click.argument('securitygroup_id') @@ -118,6 +125,11 @@ def remove(env, securitygroup_id, network_component, server, interface): if not success: raise exceptions.CLIAbort("Could not detach network component") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([success['id']]) + + env.fout(table) + def _validate_args(network_component, server, interface): use_server = bool(server and interface and not network_component) diff --git a/SoftLayer/CLI/securitygroup/rule.py b/SoftLayer/CLI/securitygroup/rule.py index dfbc93ed9..7a9a0fd8e 100644 --- a/SoftLayer/CLI/securitygroup/rule.py +++ b/SoftLayer/CLI/securitygroup/rule.py @@ -17,6 +17,8 @@ 'portRangeMax', 'protocol'] +REQUEST_COLUMNS = ['requestId'] + @click.command() @click.argument('securitygroup_id') @@ -85,6 +87,11 @@ def add(env, securitygroup_id, remote_ip, remote_group, if not ret: raise exceptions.CLIAbort("Failed to add security group rule") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([ret['id']]) + + env.fout(table) + @click.command() @click.argument('securitygroup_id') @@ -125,9 +132,18 @@ def edit(env, securitygroup_id, rule_id, remote_ip, remote_group, if protocol: data['protocol'] = protocol - if not mgr.edit_securitygroup_rule(securitygroup_id, rule_id, **data): + ret = mgr.edit_securitygroup_rule(securitygroup_id, rule_id, **data) + + if not ret: raise exceptions.CLIAbort("Failed to edit security group rule") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([ret['id']]) + + env.fout(table) + + + @click.command() @click.argument('securitygroup_id') @@ -136,5 +152,13 @@ def edit(env, securitygroup_id, rule_id, remote_ip, remote_group, def remove(env, securitygroup_id, rule_id): """Remove a rule from a security group.""" mgr = SoftLayer.NetworkManager(env.client) - if not mgr.remove_securitygroup_rule(securitygroup_id, rule_id): + + ret = mgr.remove_securitygroup_rule(securitygroup_id, rule_id) + + if not ret: raise exceptions.CLIAbort("Failed to remove security group rule") + + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([ret['id']]) + + env.fout(table) From 4c0badf5b13be7f9f2346e9dc2aef78a7df14067 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Fri, 25 Aug 2017 10:31:08 -0500 Subject: [PATCH 02/28] security-groups-request-ids : Add output for RequestIDs Fix unit tests Fix code style issues --- SoftLayer/CLI/securitygroup/rule.py | 2 -- SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py | 10 +++++----- tests/CLI/modules/securitygroup_tests.py | 10 ++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/rule.py b/SoftLayer/CLI/securitygroup/rule.py index 7a9a0fd8e..2500bdc22 100644 --- a/SoftLayer/CLI/securitygroup/rule.py +++ b/SoftLayer/CLI/securitygroup/rule.py @@ -143,8 +143,6 @@ def edit(env, securitygroup_id, rule_id, remote_ip, remote_group, env.fout(table) - - @click.command() @click.argument('securitygroup_id') @click.argument('rule_id') diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index 7e79560f7..48cc05bdd 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -39,8 +39,8 @@ 'createDate': '2017-05-05T12:44:43-06:00'}] editObjects = True deleteObjects = True -addRules = True -editRules = True -removeRules = True -attachNetworkComponents = True -detachNetworkComponents = True +addRules = {'id': 'addRules'} +editRules = {'id': 'editRules'} +removeRules = {'id': 'removeRules'} +attachNetworkComponents = {'id': 'interfaceAdd'} +detachNetworkComponents = {'id': 'interfaceRemove'} diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index b234941d6..ba366dfab 100644 --- a/tests/CLI/modules/securitygroup_tests.py +++ b/tests/CLI/modules/securitygroup_tests.py @@ -129,6 +129,8 @@ def test_securitygroup_rule_add(self): identifier='100', args=([{'direction': 'ingress'}],)) + self.assertEqual([{'requestId': 'addRules'}], json.loads(result.output)) + def test_securitygroup_rule_add_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'addRules') fixture.return_value = False @@ -148,6 +150,8 @@ def test_securitygroup_rule_edit(self): args=([{'id': '520', 'direction': 'ingress'}],)) + self.assertEqual([{'requestId': 'editRules'}], json.loads(result.output)) + def test_securitygroup_rule_edit_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'editRules') fixture.return_value = False @@ -165,6 +169,8 @@ def test_securitygroup_rule_remove(self): 'removeRules', identifier='100', args=(['520'],)) + self.assertEqual([{'requestId': 'removeRules'}], json.loads(result.output)) + def test_securitygroup_rule_remove_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'removeRules') @@ -202,6 +208,8 @@ def test_securitygroup_interface_add(self): identifier='100', args=(['1000'],)) + self.assertEqual([{'requestId': 'interfaceAdd'}], json.loads(result.output)) + def test_securitygroup_interface_add_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'attachNetworkComponents') @@ -222,6 +230,8 @@ def test_securitygroup_interface_remove(self): identifier='100', args=(['500'],)) + self.assertEqual([{'requestId': 'interfaceRemove'}], json.loads(result.output)) + def test_securitygroup_interface_remove_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'detachNetworkComponents') From 7768a83e2624cdd1bb91482c0c7d6ef77e7c8995 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Fri, 6 Oct 2017 15:20:58 -0500 Subject: [PATCH 03/28] security-groups-request-ids : Add output for RequestIDs Add new return format --- SoftLayer/CLI/securitygroup/rule.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/rule.py b/SoftLayer/CLI/securitygroup/rule.py index 2500bdc22..609332258 100644 --- a/SoftLayer/CLI/securitygroup/rule.py +++ b/SoftLayer/CLI/securitygroup/rule.py @@ -17,7 +17,8 @@ 'portRangeMax', 'protocol'] -REQUEST_COLUMNS = ['requestId'] +REQUEST_BOOL_COLUMNS = ['requestId', 'response'] +REQUEST_RULES_COLUMNS = ['requestId', 'rules'] @click.command() @@ -84,11 +85,13 @@ def add(env, securitygroup_id, remote_ip, remote_group, direction, ethertype, port_max, port_min, protocol) + print ret + if not ret: raise exceptions.CLIAbort("Failed to add security group rule") - table = formatting.Table(REQUEST_COLUMNS) - table.add_row([ret['id']]) + table = formatting.Table(REQUEST_RULES_COLUMNS) + table.add_row([ret['requestId'], str(ret['rules'])]) env.fout(table) @@ -137,8 +140,9 @@ def edit(env, securitygroup_id, rule_id, remote_ip, remote_group, if not ret: raise exceptions.CLIAbort("Failed to edit security group rule") - table = formatting.Table(REQUEST_COLUMNS) - table.add_row([ret['id']]) + table = formatting.Table(REQUEST_BOOL_COLUMNS) + table.add_row([ret['requestId']]) + table.add_row([ret['response']]) env.fout(table) @@ -156,7 +160,8 @@ def remove(env, securitygroup_id, rule_id): if not ret: raise exceptions.CLIAbort("Failed to remove security group rule") - table = formatting.Table(REQUEST_COLUMNS) - table.add_row([ret['id']]) + table = formatting.Table(REQUEST_BOOL_COLUMNS) + table.add_row([ret['requestId']]) + table.add_row([ret['response']]) env.fout(table) From d3650de390746f1ac4791b67d85d96b3f9d855cc Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Mon, 23 Oct 2017 11:14:50 -0500 Subject: [PATCH 04/28] security-groups-request-ids : Add output for RequestIDs Add functionality to get event logs to slcli --- SoftLayer/CLI/event_log/__init__.py | 1 + SoftLayer/CLI/event_log/get.py | 52 +++++++++++++++++++++++++++++ SoftLayer/CLI/routes.py | 3 ++ SoftLayer/managers/network.py | 19 +++++++++++ 4 files changed, 75 insertions(+) create mode 100644 SoftLayer/CLI/event_log/__init__.py create mode 100644 SoftLayer/CLI/event_log/get.py diff --git a/SoftLayer/CLI/event_log/__init__.py b/SoftLayer/CLI/event_log/__init__.py new file mode 100644 index 000000000..7fef4f43d --- /dev/null +++ b/SoftLayer/CLI/event_log/__init__.py @@ -0,0 +1 @@ +"""Event Logs.""" \ No newline at end of file diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py new file mode 100644 index 000000000..cc11f2efb --- /dev/null +++ b/SoftLayer/CLI/event_log/get.py @@ -0,0 +1,52 @@ +"""Get Event Logs.""" +# :license: MIT, see LICENSE for more details. + +import click +import json + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import exceptions +from SoftLayer.CLI import formatting + +COLUMNS = ['event', 'label', 'date', 'metadata'] + +@click.command() +@click.option('--obj_id', '-i', + help="The id of the object we want to get event logs for") +@click.option('--obj_type', '-t', + help="The type of the object we want to get event logs for") +@environment.pass_env + +def cli(env, obj_id, obj_type): + """Get Event Logs""" + mgr = SoftLayer.NetworkManager(env.client) + + filter = _build_filter(obj_id, obj_type) + + logs = mgr.get_event_logs(filter) + + table = formatting.Table(COLUMNS) + table.align['metadata'] = "l" + + for log in logs: + metadata = json.loads(log['metaData']) + + table.add_row([log['eventName'], log['label'], log['eventCreateDate'], json.dumps(metadata, indent=4, sort_keys=True)]) + + env.fout(table) + + +def _build_filter(obj_id, obj_type): + if not obj_id and not obj_type: + return None + + filter = {} + + if obj_id: + filter['objectId'] = {'operation': obj_id} + + if obj_type: + filter['objectName'] = {'operation': obj_type} + + return filter diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index eae0c763d..42d0a4792 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -83,6 +83,9 @@ ('block:volume-order', 'SoftLayer.CLI.block.order:cli'), ('block:volume-set-lun-id', 'SoftLayer.CLI.block.lun:cli'), + ('event-log', 'SoftLayer.CLI.event_log'), + ('event-log:get', 'SoftLayer.CLI.event_log.get:cli'), + ('file', 'SoftLayer.CLI.file'), ('file:access-authorize', 'SoftLayer.CLI.file.access.authorize:cli'), ('file:access-list', 'SoftLayer.CLI.file.access.list:cli'), diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py index 0e44d7b38..963c6a040 100644 --- a/SoftLayer/managers/network.py +++ b/SoftLayer/managers/network.py @@ -34,6 +34,14 @@ 'virtualGuests', ]) +CCI_SECURITY_GROUP_EVENT_NAMES = [ + 'Security Group Added', + 'Security Group Rule Added', + 'Security Group Rule Edited', + 'Security Group Rule Removed', + 'Security Group Removed' +] + class NetworkManager(object): """Manage SoftLayer network objects: VLANs, subnets, IPs and rwhois @@ -639,3 +647,14 @@ def get_nas_credentials(self, identifier, **kwargs): """ result = self.network_storage.getObject(id=identifier, **kwargs) return result + + def get_event_logs(self, filter): + """Returns a list of event logs + + :param dict filter: filter dict + :returns: List of event logs + """ + results = self.client.call("Event_Log", + 'getAllObjects', + filter=filter) + return results From f4bc42fee7f2398354782b81aa73cc87622dd7bd Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Mon, 23 Oct 2017 14:01:28 -0500 Subject: [PATCH 05/28] security-groups-request-ids : Add output for RequestIDs Fix Security Group unit tests --- SoftLayer/CLI/securitygroup/interface.py | 4 ++-- SoftLayer/CLI/securitygroup/rule.py | 4 ---- SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py | 10 +++++----- tests/CLI/modules/securitygroup_tests.py | 7 ++++++- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/interface.py b/SoftLayer/CLI/securitygroup/interface.py index b08f7daa6..f95c34402 100644 --- a/SoftLayer/CLI/securitygroup/interface.py +++ b/SoftLayer/CLI/securitygroup/interface.py @@ -98,7 +98,7 @@ def add(env, securitygroup_id, network_component, server, interface): raise exceptions.CLIAbort("Could not attach network component") table = formatting.Table(REQUEST_COLUMNS) - table.add_row([success['id']]) + table.add_row([success['requestId']]) env.fout(table) @@ -126,7 +126,7 @@ def remove(env, securitygroup_id, network_component, server, interface): raise exceptions.CLIAbort("Could not detach network component") table = formatting.Table(REQUEST_COLUMNS) - table.add_row([success['id']]) + table.add_row([success['requestId']]) env.fout(table) diff --git a/SoftLayer/CLI/securitygroup/rule.py b/SoftLayer/CLI/securitygroup/rule.py index 609332258..be9b4909d 100644 --- a/SoftLayer/CLI/securitygroup/rule.py +++ b/SoftLayer/CLI/securitygroup/rule.py @@ -85,8 +85,6 @@ def add(env, securitygroup_id, remote_ip, remote_group, direction, ethertype, port_max, port_min, protocol) - print ret - if not ret: raise exceptions.CLIAbort("Failed to add security group rule") @@ -142,7 +140,6 @@ def edit(env, securitygroup_id, rule_id, remote_ip, remote_group, table = formatting.Table(REQUEST_BOOL_COLUMNS) table.add_row([ret['requestId']]) - table.add_row([ret['response']]) env.fout(table) @@ -162,6 +159,5 @@ def remove(env, securitygroup_id, rule_id): table = formatting.Table(REQUEST_BOOL_COLUMNS) table.add_row([ret['requestId']]) - table.add_row([ret['response']]) env.fout(table) diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index 48cc05bdd..c01bbe7b6 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -39,8 +39,8 @@ 'createDate': '2017-05-05T12:44:43-06:00'}] editObjects = True deleteObjects = True -addRules = {'id': 'addRules'} -editRules = {'id': 'editRules'} -removeRules = {'id': 'removeRules'} -attachNetworkComponents = {'id': 'interfaceAdd'} -detachNetworkComponents = {'id': 'interfaceRemove'} +addRules = {"requestId": "addRules", "rules": "[{'direction': 'ingress', 'portRangeMax': '', 'portRangeMin': '', 'ethertype': 'IPv4', 'securityGroupId': 100, 'remoteGroupId': '', 'id': 100}]"} +editRules = {'requestId': 'editRules'} +removeRules = {'requestId': 'removeRules'} +attachNetworkComponents = {'requestId': 'interfaceAdd'} +detachNetworkComponents = {'requestId': 'interfaceRemove'} diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index ba366dfab..653405474 100644 --- a/tests/CLI/modules/securitygroup_tests.py +++ b/tests/CLI/modules/securitygroup_tests.py @@ -4,6 +4,7 @@ :license: MIT, see LICENSE for more details. """ import json +import pprint from SoftLayer import testing @@ -124,12 +125,16 @@ def test_securitygroup_rule_add(self): result = self.run_command(['sg', 'rule-add', '100', '--direction=ingress']) + print result.output + + json.loads(result.output) + self.assert_no_fail(result) self.assert_called_with('SoftLayer_Network_SecurityGroup', 'addRules', identifier='100', args=([{'direction': 'ingress'}],)) - self.assertEqual([{'requestId': 'addRules'}], json.loads(result.output)) + self.assertEqual([{"requestId": "addRules", "rules": "[{'direction': 'ingress', 'portRangeMax': '', 'portRangeMin': '', 'ethertype': 'IPv4', 'securityGroupId': 100, 'remoteGroupId': '', 'id': 100}]"}], json.loads(result.output)) def test_securitygroup_rule_add_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'addRules') From d7a736f4dbcb96a2d3027063fb83be4886c9c4fd Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 24 Oct 2017 11:09:22 -0500 Subject: [PATCH 06/28] security-groups-request-ids : Add output for RequestIDs Refactor Event Log Code Fix Unit Tests Add Unit Tests Fix Code Styling --- SoftLayer/CLI/event_log/__init__.py | 2 +- SoftLayer/CLI/event_log/get.py | 28 ++-- SoftLayer/fixtures/SoftLayer_Event_Log.py | 125 ++++++++++++++++ .../SoftLayer_Network_SecurityGroup.py | 9 +- SoftLayer/managers/__init__.py | 2 + SoftLayer/managers/event_log.py | 28 ++++ SoftLayer/managers/network.py | 11 -- tests/CLI/modules/event_log_tests.py | 135 ++++++++++++++++++ tests/CLI/modules/securitygroup_tests.py | 11 +- 9 files changed, 321 insertions(+), 30 deletions(-) create mode 100644 SoftLayer/fixtures/SoftLayer_Event_Log.py create mode 100644 SoftLayer/managers/event_log.py create mode 100644 tests/CLI/modules/event_log_tests.py diff --git a/SoftLayer/CLI/event_log/__init__.py b/SoftLayer/CLI/event_log/__init__.py index 7fef4f43d..a10576f5f 100644 --- a/SoftLayer/CLI/event_log/__init__.py +++ b/SoftLayer/CLI/event_log/__init__.py @@ -1 +1 @@ -"""Event Logs.""" \ No newline at end of file +"""Event Logs.""" diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index cc11f2efb..6487698f1 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -1,38 +1,40 @@ """Get Event Logs.""" # :license: MIT, see LICENSE for more details. -import click import json +import click import SoftLayer from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions from SoftLayer.CLI import formatting COLUMNS = ['event', 'label', 'date', 'metadata'] + @click.command() @click.option('--obj_id', '-i', help="The id of the object we want to get event logs for") @click.option('--obj_type', '-t', help="The type of the object we want to get event logs for") @environment.pass_env - def cli(env, obj_id, obj_type): """Get Event Logs""" - mgr = SoftLayer.NetworkManager(env.client) + mgr = SoftLayer.EventLogManager(env.client) - filter = _build_filter(obj_id, obj_type) + request_filter = _build_filter(obj_id, obj_type) - logs = mgr.get_event_logs(filter) + logs = mgr.get_event_logs(request_filter) table = formatting.Table(COLUMNS) table.align['metadata'] = "l" for log in logs: - metadata = json.loads(log['metaData']) + try: + metadata = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) + except ValueError: + metadata = log['metaData'] - table.add_row([log['eventName'], log['label'], log['eventCreateDate'], json.dumps(metadata, indent=4, sort_keys=True)]) + table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata]) env.fout(table) @@ -40,13 +42,13 @@ def cli(env, obj_id, obj_type): def _build_filter(obj_id, obj_type): if not obj_id and not obj_type: return None - - filter = {} + + request_filter = {} if obj_id: - filter['objectId'] = {'operation': obj_id} + request_filter['objectId'] = {'operation': obj_id} if obj_type: - filter['objectName'] = {'operation': obj_type} + request_filter['objectName'] = {'operation': obj_type} - return filter + return request_filter diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py new file mode 100644 index 000000000..98f6dea40 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -0,0 +1,125 @@ +getAllObjects = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-23T14:22:36.221541-05:00', + 'eventName': 'Disable Port', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '100', + 'userId': '', + 'userType': 'SYSTEM' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:41.830338-05:00', + 'eventName': 'Security Group Rule Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"ruleId":"100",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e9c2184', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:13.089536-05:00', + 'eventName': 'Security Group Rule(s) Removed', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"2abda7ca97e5a1444cae0b9",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7765515e28', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:11.679736-05:00', + 'eventName': 'Network Component Removed from Security Group', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"6b9a87a9ab8ac9a22e87a00",' + '"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public"}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e77653a1e5f', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:41:49.802498-05:00', + 'eventName': 'Security Group Rule(s) Added', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"0a293c1c3e59e4471da6495",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7763dc3f1c', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:41:42.176328-05:00', + 'eventName': 'Network Component Added to Security Group', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"4709e02ad42c83f80345904",' + '"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public"}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e77636261e7', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } +] diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index c01bbe7b6..ade908688 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -39,7 +39,14 @@ 'createDate': '2017-05-05T12:44:43-06:00'}] editObjects = True deleteObjects = True -addRules = {"requestId": "addRules", "rules": "[{'direction': 'ingress', 'portRangeMax': '', 'portRangeMin': '', 'ethertype': 'IPv4', 'securityGroupId': 100, 'remoteGroupId': '', 'id': 100}]"} +addRules = {"requestId": "addRules", + "rules": "[{'direction': 'ingress', " + "'portRangeMax': '', " + "'portRangeMin': '', " + "'ethertype': 'IPv4', " + "'securityGroupId': 100, " + "'remoteGroupId': '', " + "'id': 100}]"} editRules = {'requestId': 'editRules'} removeRules = {'requestId': 'removeRules'} attachNetworkComponents = {'requestId': 'interfaceAdd'} diff --git a/SoftLayer/managers/__init__.py b/SoftLayer/managers/__init__.py index f404d7b9b..0fe0d66e7 100644 --- a/SoftLayer/managers/__init__.py +++ b/SoftLayer/managers/__init__.py @@ -10,6 +10,7 @@ from SoftLayer.managers.block import BlockStorageManager from SoftLayer.managers.cdn import CDNManager from SoftLayer.managers.dns import DNSManager +from SoftLayer.managers.event_log import EventLogManager from SoftLayer.managers.file import FileStorageManager from SoftLayer.managers.firewall import FirewallManager from SoftLayer.managers.hardware import HardwareManager @@ -30,6 +31,7 @@ 'BlockStorageManager', 'CDNManager', 'DNSManager', + 'EventLogManager', 'FileStorageManager', 'FirewallManager', 'HardwareManager', diff --git a/SoftLayer/managers/event_log.py b/SoftLayer/managers/event_log.py new file mode 100644 index 000000000..29adacae2 --- /dev/null +++ b/SoftLayer/managers/event_log.py @@ -0,0 +1,28 @@ +""" + SoftLayer.network + ~~~~~~~~~~~~~~~~~ + Network Manager/helpers + + :license: MIT, see LICENSE for more details. +""" + + +class EventLogManager(object): + """Provides an interface for the SoftLayer Event Log Service. + + See product information here: + http://sldn.softlayer.com/reference/services/SoftLayer_Event_Log + """ + def __init__(self, client): + self.client = client + + def get_event_logs(self, request_filter): + """Returns a list of event logs + + :param dict request_filter: filter dict + :returns: List of event logs + """ + results = self.client.call("Event_Log", + 'getAllObjects', + filter=request_filter) + return results diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py index 963c6a040..344c3171d 100644 --- a/SoftLayer/managers/network.py +++ b/SoftLayer/managers/network.py @@ -647,14 +647,3 @@ def get_nas_credentials(self, identifier, **kwargs): """ result = self.network_storage.getObject(id=identifier, **kwargs) return result - - def get_event_logs(self, filter): - """Returns a list of event logs - - :param dict filter: filter dict - :returns: List of event logs - """ - results = self.client.call("Event_Log", - 'getAllObjects', - filter=filter) - return results diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py new file mode 100644 index 000000000..d2b49411c --- /dev/null +++ b/tests/CLI/modules/event_log_tests.py @@ -0,0 +1,135 @@ +""" + SoftLayer.tests.CLI.modules.event_log_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + :license: MIT, see LICENSE for more details. +""" + +import json + +from SoftLayer.CLI.event_log import get as event_log_get +from SoftLayer import testing + + +class EventLogTests(testing.TestCase): + + def test_get_event_log(self): + result = self.run_command(['event-log', 'get']) + + self.assert_no_fail(result) + + correctResponse = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'label': 'test.softlayer.com', + 'metadata': '' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'label': 'test.softlayer.com', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"100"}],"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'label': 'test.softlayer.com', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba",' + '"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"requestId":"2abda7ca97e5a1444cae0b9",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"6b9a87a9ab8ac9a22e87a00"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"requestId":"0a293c1c3e59e4471da6495",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + } + ] + + self.assertEqual(correctResponse, json.loads(result.output)) + + def test_get_event_log_id(self): + test_filter = event_log_get._build_filter(1, None) + + self.assertEqual(test_filter, {'objectId': {'operation': 1}}) + + def test_get_event_log_type(self): + test_filter = event_log_get._build_filter(None, 'CCI') + + self.assertEqual(test_filter, {'objectName': {'operation': 'CCI'}}) + + def test_get_event_log_id_type(self): + test_filter = event_log_get._build_filter(1, 'CCI') + + self.assertEqual(test_filter, {'objectId': {'operation': 1}, 'objectName': {'operation': 'CCI'}}) diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index 653405474..dae64d562 100644 --- a/tests/CLI/modules/securitygroup_tests.py +++ b/tests/CLI/modules/securitygroup_tests.py @@ -4,7 +4,6 @@ :license: MIT, see LICENSE for more details. """ import json -import pprint from SoftLayer import testing @@ -125,8 +124,6 @@ def test_securitygroup_rule_add(self): result = self.run_command(['sg', 'rule-add', '100', '--direction=ingress']) - print result.output - json.loads(result.output) self.assert_no_fail(result) @@ -134,7 +131,13 @@ def test_securitygroup_rule_add(self): identifier='100', args=([{'direction': 'ingress'}],)) - self.assertEqual([{"requestId": "addRules", "rules": "[{'direction': 'ingress', 'portRangeMax': '', 'portRangeMin': '', 'ethertype': 'IPv4', 'securityGroupId': 100, 'remoteGroupId': '', 'id': 100}]"}], json.loads(result.output)) + self.assertEqual([{"requestId": "addRules", + "rules": "[{'direction': 'ingress', " + "'portRangeMax': '', " + "'portRangeMin': '', " + "'ethertype': 'IPv4', " + "'securityGroupId': 100, 'remoteGroupId': '', " + "'id': 100}]"}], json.loads(result.output)) def test_securitygroup_rule_add_fail(self): fixture = self.set_mock('SoftLayer_Network_SecurityGroup', 'addRules') From d851de680fca36c848c64d912a4582bc93b01a04 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 24 Oct 2017 13:32:40 -0500 Subject: [PATCH 07/28] security-groups-request-ids : Add output for RequestIDs Remove unneeded code left over from refactoring Fix incorrect package name --- SoftLayer/managers/event_log.py | 2 +- SoftLayer/managers/network.py | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/SoftLayer/managers/event_log.py b/SoftLayer/managers/event_log.py index 29adacae2..346eb1fa2 100644 --- a/SoftLayer/managers/event_log.py +++ b/SoftLayer/managers/event_log.py @@ -1,5 +1,5 @@ """ - SoftLayer.network + SoftLayer.event_log ~~~~~~~~~~~~~~~~~ Network Manager/helpers diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py index 344c3171d..0e44d7b38 100644 --- a/SoftLayer/managers/network.py +++ b/SoftLayer/managers/network.py @@ -34,14 +34,6 @@ 'virtualGuests', ]) -CCI_SECURITY_GROUP_EVENT_NAMES = [ - 'Security Group Added', - 'Security Group Rule Added', - 'Security Group Rule Edited', - 'Security Group Rule Removed', - 'Security Group Removed' -] - class NetworkManager(object): """Manage SoftLayer network objects: VLANs, subnets, IPs and rwhois From 4228058114376f6fe6807f2cca1cf0876eabaeaf Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 24 Oct 2017 13:40:13 -0500 Subject: [PATCH 08/28] security-groups-request-ids : Add output for RequestIDs Code Styling changes --- SoftLayer/CLI/event_log/get.py | 1 + .../fixtures/SoftLayer_Network_SecurityGroup.py | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 6487698f1..66b72107b 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -2,6 +2,7 @@ # :license: MIT, see LICENSE for more details. import json + import click import SoftLayer diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index ade908688..e00372361 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -41,12 +41,12 @@ deleteObjects = True addRules = {"requestId": "addRules", "rules": "[{'direction': 'ingress', " - "'portRangeMax': '', " - "'portRangeMin': '', " - "'ethertype': 'IPv4', " - "'securityGroupId': 100, " - "'remoteGroupId': '', " - "'id': 100}]"} + "'portRangeMax': '', " + "'portRangeMin': '', " + "'ethertype': 'IPv4', " + "'securityGroupId': 100, " + "'remoteGroupId': '', " + "'id': 100}]"} editRules = {'requestId': 'editRules'} removeRules = {'requestId': 'removeRules'} attachNetworkComponents = {'requestId': 'interfaceAdd'} From 9d04a8e4638453c5e2bbc32c99a28c1c3b0961b8 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 24 Oct 2017 14:21:16 -0500 Subject: [PATCH 09/28] security-groups-request-ids : Add output for RequestIDs Change public facing name to Audit Logs Add functionality to get event log types --- SoftLayer/CLI/event_log/__init__.py | 2 +- SoftLayer/CLI/event_log/get.py | 8 +++---- SoftLayer/CLI/event_log/types.py | 26 +++++++++++++++++++++++ SoftLayer/CLI/routes.py | 5 +++-- SoftLayer/fixtures/SoftLayer_Event_Log.py | 2 ++ SoftLayer/managers/event_log.py | 10 +++++++++ tests/CLI/modules/event_log_tests.py | 18 +++++++++++++++- 7 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 SoftLayer/CLI/event_log/types.py diff --git a/SoftLayer/CLI/event_log/__init__.py b/SoftLayer/CLI/event_log/__init__.py index a10576f5f..35973ae26 100644 --- a/SoftLayer/CLI/event_log/__init__.py +++ b/SoftLayer/CLI/event_log/__init__.py @@ -1 +1 @@ -"""Event Logs.""" +"""Audit Logs.""" diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 66b72107b..a615a093d 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -1,4 +1,4 @@ -"""Get Event Logs.""" +"""Get Audit Logs.""" # :license: MIT, see LICENSE for more details. import json @@ -14,12 +14,12 @@ @click.command() @click.option('--obj_id', '-i', - help="The id of the object we want to get event logs for") + help="The id of the object we want to get audit logs for") @click.option('--obj_type', '-t', - help="The type of the object we want to get event logs for") + help="The type of the object we want to get audit logs for") @environment.pass_env def cli(env, obj_id, obj_type): - """Get Event Logs""" + """Get Audit Logs""" mgr = SoftLayer.EventLogManager(env.client) request_filter = _build_filter(obj_id, obj_type) diff --git a/SoftLayer/CLI/event_log/types.py b/SoftLayer/CLI/event_log/types.py new file mode 100644 index 000000000..561fcc708 --- /dev/null +++ b/SoftLayer/CLI/event_log/types.py @@ -0,0 +1,26 @@ +"""Get Audit Log Types.""" +# :license: MIT, see LICENSE for more details. + +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting + +COLUMNS = ['types'] + + +@click.command() +@environment.pass_env +def cli(env): + """Get Audit Log Types""" + mgr = SoftLayer.EventLogManager(env.client) + + event_log_types = mgr.get_event_log_types() + + table = formatting.Table(COLUMNS) + + for event_log_type in event_log_types: + table.add_row([event_log_type]) + + env.fout(table) diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 42d0a4792..aab5d912f 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -83,8 +83,9 @@ ('block:volume-order', 'SoftLayer.CLI.block.order:cli'), ('block:volume-set-lun-id', 'SoftLayer.CLI.block.lun:cli'), - ('event-log', 'SoftLayer.CLI.event_log'), - ('event-log:get', 'SoftLayer.CLI.event_log.get:cli'), + ('audit-log', 'SoftLayer.CLI.event_log'), + ('audit-log:get', 'SoftLayer.CLI.event_log.get:cli'), + ('audit-log:types', 'SoftLayer.CLI.event_log.types:cli'), ('file', 'SoftLayer.CLI.file'), ('file:access-authorize', 'SoftLayer.CLI.file.access.authorize:cli'), diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py index 98f6dea40..8b6a3f746 100644 --- a/SoftLayer/fixtures/SoftLayer_Event_Log.py +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -123,3 +123,5 @@ 'username': 'user' } ] + +getAllEventObjectNames = ['CCI', 'Security Group'] diff --git a/SoftLayer/managers/event_log.py b/SoftLayer/managers/event_log.py index 346eb1fa2..7b7e39d54 100644 --- a/SoftLayer/managers/event_log.py +++ b/SoftLayer/managers/event_log.py @@ -26,3 +26,13 @@ def get_event_logs(self, request_filter): 'getAllObjects', filter=request_filter) return results + + def get_event_log_types(self): + """Returns a list of event log types + + :returns: List of event log types + """ + results = self.client.call("Event_Log", + 'getAllEventObjectNames') + + return results diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index d2b49411c..622753e4f 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -13,7 +13,7 @@ class EventLogTests(testing.TestCase): def test_get_event_log(self): - result = self.run_command(['event-log', 'get']) + result = self.run_command(['audit-log', 'get']) self.assert_no_fail(result) @@ -133,3 +133,19 @@ def test_get_event_log_id_type(self): test_filter = event_log_get._build_filter(1, 'CCI') self.assertEqual(test_filter, {'objectId': {'operation': 1}, 'objectName': {'operation': 'CCI'}}) + + def test_get_event_log_types(self): + result = self.run_command(['audit-log', 'types']) + + self.assert_no_fail(result) + + correctResponse = [ + { + 'types': 'CCI' + }, + { + 'types': 'Security Group' + } + ] + + self.assertEqual(correctResponse, json.loads(result.output)) From a3406a19871914d41031894ff3facfc926d53640 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 24 Oct 2017 14:29:35 -0500 Subject: [PATCH 10/28] security-groups-request-ids : Add output for RequestIDs Fix ordering of test expecations to be Actual then Expected --- tests/CLI/modules/event_log_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 622753e4f..c552535a0 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -117,7 +117,7 @@ def test_get_event_log(self): } ] - self.assertEqual(correctResponse, json.loads(result.output)) + self.assertEqual(json.loads(result.output), correctResponse) def test_get_event_log_id(self): test_filter = event_log_get._build_filter(1, None) @@ -148,4 +148,4 @@ def test_get_event_log_types(self): } ] - self.assertEqual(correctResponse, json.loads(result.output)) + self.assertEqual(json.loads(result.output), correctResponse) From 884d117b002a5954eeb4a3b21515f061f070e531 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Wed, 25 Oct 2017 10:13:24 -0500 Subject: [PATCH 11/28] security-groups-request-ids : Add output for RequestIDs Add functionality to filter by eventName --- SoftLayer/CLI/event_log/get.py | 13 +++++++++---- tests/CLI/modules/event_log_tests.py | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index a615a093d..f5765287c 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -13,16 +13,18 @@ @click.command() +@click.option('--obj_event', '-e', + help="The event we want to get audit logs for") @click.option('--obj_id', '-i', help="The id of the object we want to get audit logs for") @click.option('--obj_type', '-t', help="The type of the object we want to get audit logs for") @environment.pass_env -def cli(env, obj_id, obj_type): +def cli(env, obj_event, obj_id, obj_type): """Get Audit Logs""" mgr = SoftLayer.EventLogManager(env.client) - request_filter = _build_filter(obj_id, obj_type) + request_filter = _build_filter(obj_event, obj_id, obj_type) logs = mgr.get_event_logs(request_filter) @@ -40,12 +42,15 @@ def cli(env, obj_id, obj_type): env.fout(table) -def _build_filter(obj_id, obj_type): - if not obj_id and not obj_type: +def _build_filter(obj_event, obj_id, obj_type): + if not obj_event and not obj_id and not obj_type: return None request_filter = {} + if obj_event: + request_filter['eventName'] = {'operation': obj_event} + if obj_id: request_filter['objectId'] = {'operation': obj_id} diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index c552535a0..9f7b829d6 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -119,20 +119,35 @@ def test_get_event_log(self): self.assertEqual(json.loads(result.output), correctResponse) + def test_get_event_log_event(self): + test_filter = event_log_get._build_filter('Security Group Rule Added', None, None) + + self.assertEqual(test_filter, {'eventName': {'operation': 'Security Group Rule Added'}}) + def test_get_event_log_id(self): - test_filter = event_log_get._build_filter(1, None) + test_filter = event_log_get._build_filter(None, 1, None) self.assertEqual(test_filter, {'objectId': {'operation': 1}}) def test_get_event_log_type(self): - test_filter = event_log_get._build_filter(None, 'CCI') + test_filter = event_log_get._build_filter(None, None, 'CCI') self.assertEqual(test_filter, {'objectName': {'operation': 'CCI'}}) - def test_get_event_log_id_type(self): - test_filter = event_log_get._build_filter(1, 'CCI') + def test_get_event_log_event_id_type(self): + test_filter = event_log_get._build_filter('Security Group Rule Added', 1, 'CCI') - self.assertEqual(test_filter, {'objectId': {'operation': 1}, 'objectName': {'operation': 'CCI'}}) + self.assertEqual(test_filter, { + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) def test_get_event_log_types(self): result = self.run_command(['audit-log', 'types']) From 7c25d97969738910619cfd1da2b79eea313b5662 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Thu, 26 Oct 2017 14:37:08 -0500 Subject: [PATCH 12/28] security-groups-request-ids : Add output for RequestIDs Add functionality to filter by dates --- SoftLayer/CLI/event_log/get.py | 68 ++++++- tests/CLI/modules/event_log_tests.py | 264 ++++++++++++++++++++++++++- 2 files changed, 323 insertions(+), 9 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index f5765287c..6dddc0d18 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -2,6 +2,7 @@ # :license: MIT, see LICENSE for more details. import json +from datetime import datetime import click @@ -13,18 +14,24 @@ @click.command() +@click.option('--date_min', '-d', + help='The earliest date we want to search for audit logs in mm/dd/yyy format.') +@click.option('--date_max', '-D', + help='The latest date we want to search for audit logs in mm/dd/yyy format.') @click.option('--obj_event', '-e', help="The event we want to get audit logs for") @click.option('--obj_id', '-i', help="The id of the object we want to get audit logs for") @click.option('--obj_type', '-t', help="The type of the object we want to get audit logs for") +@click.option('--utc_offset', '-z', + help="UTC Offset for seatching with dates. The default is -0500") @environment.pass_env -def cli(env, obj_event, obj_id, obj_type): +def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): """Get Audit Logs""" mgr = SoftLayer.EventLogManager(env.client) - request_filter = _build_filter(obj_event, obj_id, obj_type) + request_filter = _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) logs = mgr.get_event_logs(request_filter) @@ -42,12 +49,50 @@ def cli(env, obj_event, obj_id, obj_type): env.fout(table) -def _build_filter(obj_event, obj_id, obj_type): - if not obj_event and not obj_id and not obj_type: +def _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset): + if not date_min and not date_max and not obj_event and not obj_id and not obj_type: return None request_filter = {} + if date_min and date_max: + request_filter['eventCreateDate'] = { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': [_parse_date(date_min, utc_offset)] + }, + { + 'name': 'endDate', + 'value': [_parse_date(date_max, utc_offset)] + } + ] + } + + else: + if date_min: + request_filter['eventCreateDate'] = { + 'operation': 'greaterThanDate', + 'options': [ + { + 'name': 'date', + 'value': [_parse_date(date_min, utc_offset)] + } + ] + } + + if date_max: + request_filter['eventCreateDate'] = { + 'operation': 'lessThanDate', + 'options': [ + { + 'name': 'date', + 'value': [_parse_date(date_max, utc_offset)] + } + ] + } + if obj_event: request_filter['eventName'] = {'operation': obj_event} @@ -58,3 +103,18 @@ def _build_filter(obj_event, obj_id, obj_type): request_filter['objectName'] = {'operation': obj_type} return request_filter + + +def _parse_date(date_string, utc_offset): + user_date_format = "%m/%d/%Y" + + user_date = datetime.strptime(date_string, user_date_format) + dirty_time = user_date.isoformat() + + if utc_offset is None: + utc_offset = "-0500" + + iso_time_zone = utc_offset[:3] + ':' + utc_offset[3:] + clean_time = "{}.000000{}".format(dirty_time, iso_time_zone) + + return clean_time diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 9f7b829d6..fe175ed6f 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -119,25 +119,279 @@ def test_get_event_log(self): self.assertEqual(json.loads(result.output), correctResponse) + def test_get_event_log_date_min(self): + test_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, None) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-30T00:00:00.000000-05:00'] + }] + } + }) + + def test_get_event_log_date_max(self): + test_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, None) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-31T00:00:00.000000-05:00'] + }] + } + }) + + def test_get_event_log_date_min_max(self): + test_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, None) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': ['2017-10-30T00:00:00.000000-05:00'] + }, + { + 'name': 'endDate', + 'value': ['2017-10-31T00:00:00.000000-05:00'] + } + ] + } + }) + + def test_get_event_log_date_min_utc_offset(self): + test_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, "-0600") + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-30T00:00:00.000000-06:00'] + }] + } + }) + + def test_get_event_log_date_max_utc_offset(self): + test_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, "-0600") + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-31T00:00:00.000000-06:00'] + }] + } + }) + + def test_get_event_log_date_min_max_utc_offset(self): + test_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, "-0600") + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': ['2017-10-30T00:00:00.000000-06:00'] + }, + { + 'name': 'endDate', + 'value': ['2017-10-31T00:00:00.000000-06:00'] + } + ] + } + }) + def test_get_event_log_event(self): - test_filter = event_log_get._build_filter('Security Group Rule Added', None, None) + test_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', None, None, None) self.assertEqual(test_filter, {'eventName': {'operation': 'Security Group Rule Added'}}) def test_get_event_log_id(self): - test_filter = event_log_get._build_filter(None, 1, None) + test_filter = event_log_get._build_filter(None, None, None, 1, None, None) self.assertEqual(test_filter, {'objectId': {'operation': 1}}) def test_get_event_log_type(self): - test_filter = event_log_get._build_filter(None, None, 'CCI') + test_filter = event_log_get._build_filter(None, None, None, None, 'CCI', None) self.assertEqual(test_filter, {'objectName': {'operation': 'CCI'}}) - def test_get_event_log_event_id_type(self): - test_filter = event_log_get._build_filter('Security Group Rule Added', 1, 'CCI') + def test_get_event_log_event_all_args(self): + test_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', 1, 'CCI', None) + + self.assertEqual(test_filter, { + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_min_date(self): + test_filter = event_log_get._build_filter('10/30/2017', None, 'Security Group Rule Added', 1, 'CCI', None) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-30T00:00:00.000000-05:00'] + }] + }, + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_max_date(self): + test_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', None) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-31T00:00:00.000000-05:00'] + }] + }, + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_min_max_date(self): + test_filter = event_log_get._build_filter( + '10/30/2017', + '10/31/2017', + 'Security Group Rule Added', + 1, + 'CCI', + None + ) self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': ['2017-10-30T00:00:00.000000-05:00'] + }, + { + 'name': 'endDate', + 'value': ['2017-10-31T00:00:00.000000-05:00'] + } + ] + }, + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_min_date_utc_offset(self): + test_filter = event_log_get._build_filter( + '10/30/2017', + None, + 'Security Group Rule Added', + 1, + 'CCI', + '-0600' + ) + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-30T00:00:00.000000-06:00'] + }] + }, + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_max_date_utc_offset(self): + test_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', '-0600') + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [{ + 'name': 'date', + 'value': ['2017-10-31T00:00:00.000000-06:00'] + }] + }, + 'eventName': { + 'operation': 'Security Group Rule Added' + }, + 'objectId': { + 'operation': 1 + }, + 'objectName': { + 'operation': 'CCI' + } + }) + + def test_get_event_log_event_all_args_min_max_date_utc_offset(self): + test_filter = event_log_get._build_filter( + '10/30/2017', + '10/31/2017', + 'Security Group Rule Added', + 1, + 'CCI', + '-0600') + + self.assertEqual(test_filter, { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': ['2017-10-30T00:00:00.000000-06:00'] + }, + { + 'name': 'endDate', + 'value': ['2017-10-31T00:00:00.000000-06:00'] + } + ] + }, 'eventName': { 'operation': 'Security Group Rule Added' }, From 265460ad73d8b7ef238196c42076c5167da21485 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Fri, 27 Oct 2017 10:41:43 -0500 Subject: [PATCH 13/28] security-groups-request-ids : Add output for RequestIDs Add request id search functionality --- SoftLayer/CLI/event_log/get.py | 45 ++++++- tests/CLI/modules/event_log_tests.py | 168 +++++++++++++++++++-------- 2 files changed, 160 insertions(+), 53 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 6dddc0d18..fa190a6a9 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -22,18 +22,22 @@ help="The event we want to get audit logs for") @click.option('--obj_id', '-i', help="The id of the object we want to get audit logs for") +@click.option('--request_id', '-r', + help="The request id we want to look for. If this is set, we will ignore all other arguments.") @click.option('--obj_type', '-t', help="The type of the object we want to get audit logs for") @click.option('--utc_offset', '-z', help="UTC Offset for seatching with dates. The default is -0500") @environment.pass_env -def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): +def cli(env, date_min, date_max, obj_event, obj_id, request_id, obj_type, utc_offset): """Get Audit Logs""" mgr = SoftLayer.EventLogManager(env.client) - request_filter = _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) - - logs = mgr.get_event_logs(request_filter) + if request_id is not None: + logs = _get_event_logs_by_request_id(mgr, request_id) + else: + request_filter = _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) + logs = mgr.get_event_logs(request_filter) table = formatting.Table(COLUMNS) table.align['metadata'] = "l" @@ -105,6 +109,39 @@ def _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset): return request_filter +def _get_event_logs_by_request_id(mgr, request_id): + cci_filter = { + 'objectName': { + 'operation': 'CCI' + } + } + + cci_logs = mgr.get_event_logs(cci_filter) + + security_group_filter = { + 'objectName': { + 'operation': 'Security Group' + } + } + + security_group_logs = mgr.get_event_logs(security_group_filter) + + unfiltered_logs = cci_logs + security_group_logs + + filtered_logs = [] + + for unfiltered_log in unfiltered_logs: + try: + metadata = json.loads(unfiltered_log['metaData']) + if 'requestId' in metadata: + if metadata['requestId'] == request_id: + filtered_logs.append(unfiltered_log) + except ValueError: + continue + + return filtered_logs + + def _parse_date(date_string, utc_offset): user_date_format = "%m/%d/%Y" diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index fe175ed6f..8393c42c4 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -17,7 +17,7 @@ def test_get_event_log(self): self.assert_no_fail(result) - correctResponse = [ + expected_esponse = [ { 'date': '2017-10-23T14:22:36.221541-05:00', 'event': 'Disable Port', @@ -117,12 +117,50 @@ def test_get_event_log(self): } ] - self.assertEqual(json.loads(result.output), correctResponse) + self.assertEqual(expected_esponse, json.loads(result.output)) + + def test_get_event_log_request_id(self): + result = self.run_command(['audit-log', 'get', '--request_id=4709e02ad42c83f80345904']) + + # Because filtering doesn't work on the test data recieved from the server we stand up, + # and we call getAllObjects twice, the dataset we work over has duplicates + expected_esponse = [ + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + } + ] + + self.assertEqual(expected_esponse, json.loads(result.output)) def test_get_event_log_date_min(self): - test_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, None) + observed_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, None) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'greaterThanDate', 'options': [{ @@ -130,12 +168,14 @@ def test_get_event_log_date_min(self): 'value': ['2017-10-30T00:00:00.000000-05:00'] }] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_date_max(self): - test_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, None) + observed_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, None) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'lessThanDate', 'options': [{ @@ -143,12 +183,14 @@ def test_get_event_log_date_max(self): 'value': ['2017-10-31T00:00:00.000000-05:00'] }] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_date_min_max(self): - test_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, None) + observed_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, None) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'betweenDate', 'options': [ @@ -162,12 +204,14 @@ def test_get_event_log_date_min_max(self): } ] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_date_min_utc_offset(self): - test_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, "-0600") + observed_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, "-0600") - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'greaterThanDate', 'options': [{ @@ -175,12 +219,14 @@ def test_get_event_log_date_min_utc_offset(self): 'value': ['2017-10-30T00:00:00.000000-06:00'] }] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_date_max_utc_offset(self): - test_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, "-0600") + observed_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, "-0600") - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'lessThanDate', 'options': [{ @@ -188,12 +234,14 @@ def test_get_event_log_date_max_utc_offset(self): 'value': ['2017-10-31T00:00:00.000000-06:00'] }] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_date_min_max_utc_offset(self): - test_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, "-0600") + observed_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, "-0600") - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'betweenDate', 'options': [ @@ -207,27 +255,35 @@ def test_get_event_log_date_min_max_utc_offset(self): } ] } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event(self): - test_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', None, None, None) + observed_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', None, None, None) + + expected_filter = {'eventName': {'operation': 'Security Group Rule Added'}} - self.assertEqual(test_filter, {'eventName': {'operation': 'Security Group Rule Added'}}) + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_id(self): - test_filter = event_log_get._build_filter(None, None, None, 1, None, None) + observed_filter = event_log_get._build_filter(None, None, None, 1, None, None) + + expected_filter = {'objectId': {'operation': 1}} - self.assertEqual(test_filter, {'objectId': {'operation': 1}}) + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_type(self): - test_filter = event_log_get._build_filter(None, None, None, None, 'CCI', None) + observed_filter = event_log_get._build_filter(None, None, None, None, 'CCI', None) - self.assertEqual(test_filter, {'objectName': {'operation': 'CCI'}}) + expected_filter = {'objectName': {'operation': 'CCI'}} + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args(self): - test_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', 1, 'CCI', None) + observed_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', 1, 'CCI', None) - self.assertEqual(test_filter, { + expected_filter = { 'eventName': { 'operation': 'Security Group Rule Added' }, @@ -237,12 +293,14 @@ def test_get_event_log_event_all_args(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_min_date(self): - test_filter = event_log_get._build_filter('10/30/2017', None, 'Security Group Rule Added', 1, 'CCI', None) + observed_filter = event_log_get._build_filter('10/30/2017', None, 'Security Group Rule Added', 1, 'CCI', None) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'greaterThanDate', 'options': [{ @@ -259,12 +317,14 @@ def test_get_event_log_event_all_args_min_date(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_max_date(self): - test_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', None) + observed_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', None) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'lessThanDate', 'options': [{ @@ -281,10 +341,12 @@ def test_get_event_log_event_all_args_max_date(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_min_max_date(self): - test_filter = event_log_get._build_filter( + observed_filter = event_log_get._build_filter( '10/30/2017', '10/31/2017', 'Security Group Rule Added', @@ -293,7 +355,7 @@ def test_get_event_log_event_all_args_min_max_date(self): None ) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'betweenDate', 'options': [ @@ -316,10 +378,12 @@ def test_get_event_log_event_all_args_min_max_date(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_min_date_utc_offset(self): - test_filter = event_log_get._build_filter( + observed_filter = event_log_get._build_filter( '10/30/2017', None, 'Security Group Rule Added', @@ -328,7 +392,7 @@ def test_get_event_log_event_all_args_min_date_utc_offset(self): '-0600' ) - self.assertEqual(test_filter, { + expected_filter = { 'eventCreateDate': { 'operation': 'greaterThanDate', 'options': [{ @@ -345,12 +409,14 @@ def test_get_event_log_event_all_args_min_date_utc_offset(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_max_date_utc_offset(self): - test_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', '-0600') + observed_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', '-0600') - self.assertEqual(test_filter, { + correct_filter = { 'eventCreateDate': { 'operation': 'lessThanDate', 'options': [{ @@ -367,10 +433,12 @@ def test_get_event_log_event_all_args_max_date_utc_offset(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(correct_filter, observed_filter) def test_get_event_log_event_all_args_min_max_date_utc_offset(self): - test_filter = event_log_get._build_filter( + observed_filter = event_log_get._build_filter( '10/30/2017', '10/31/2017', 'Security Group Rule Added', @@ -378,7 +446,7 @@ def test_get_event_log_event_all_args_min_max_date_utc_offset(self): 'CCI', '-0600') - self.assertEqual(test_filter, { + correct_filter = { 'eventCreateDate': { 'operation': 'betweenDate', 'options': [ @@ -401,14 +469,16 @@ def test_get_event_log_event_all_args_min_max_date_utc_offset(self): 'objectName': { 'operation': 'CCI' } - }) + } + + self.assertEqual(correct_filter, observed_filter) def test_get_event_log_types(self): result = self.run_command(['audit-log', 'types']) self.assert_no_fail(result) - correctResponse = [ + expected_esponse = [ { 'types': 'CCI' }, @@ -417,4 +487,4 @@ def test_get_event_log_types(self): } ] - self.assertEqual(json.loads(result.output), correctResponse) + self.assertEqual(expected_esponse, json.loads(result.output)) From 01ee7710a2f089f02b3b58e89c05149f0748b617 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Tue, 9 Jan 2018 10:11:41 -0600 Subject: [PATCH 14/28] security-groups-request-ids : Add output for RequestIDs Fix fixtures from merge --- SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index cb67de60e..8d4b73283 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -33,16 +33,12 @@ 'rules': getRules } -createObjects = [{'id': 100, - 'name': 'secgroup1', - 'description': 'Securitygroup1', - 'createDate': '2017-05-05T12:44:43-06:00'}] createObject = {'id': 100, 'name': 'secgroup1', 'description': 'Securitygroup1', 'createDate': '2017-05-05T12:44:43-06:00'} -editObjects = True -deleteObjects = True +editObject = True +deleteObject = True addRules = {"requestId": "addRules", "rules": "[{'direction': 'ingress', " "'portRangeMax': '', " From 3a72d7f379b32563ec3830179ef004bba778746f Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Thu, 1 Feb 2018 14:05:59 -0600 Subject: [PATCH 15/28] security-groups-request-ids : Add output for RequestIDs Fix tox issues --- SoftLayer/CLI/event_log/get.py | 2 +- tests/CLI/modules/event_log_tests.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index fa190a6a9..ef741318c 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -1,8 +1,8 @@ """Get Audit Logs.""" # :license: MIT, see LICENSE for more details. -import json from datetime import datetime +import json import click diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 8393c42c4..f95f3bccd 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -414,7 +414,14 @@ def test_get_event_log_event_all_args_min_date_utc_offset(self): self.assertEqual(expected_filter, observed_filter) def test_get_event_log_event_all_args_max_date_utc_offset(self): - observed_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', '-0600') + observed_filter = event_log_get._build_filter( + None, + '10/31/2017', + 'Security Group Rule Added', + 1, + 'CCI', + '-0600' + ) correct_filter = { 'eventCreateDate': { From 633368713bc9239257671a2efce3df81345b3358 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Thu, 8 Feb 2018 16:22:51 -0600 Subject: [PATCH 16/28] Major refactoring of audit log code change date_min to date-min in click args change date_max to date-max in click args change how the event log client is initialized move filter building code into event log manager set default utc offset to +0000 move date parsing code into utils add ability to get event logs by type add ability to get event logs by name move requestID searching into Security Groups code Overhaul unit tests --- SoftLayer/CLI/event_log/get.py | 126 +------- SoftLayer/CLI/routes.py | 1 + SoftLayer/CLI/securitygroup/event_log.py | 32 ++ SoftLayer/managers/event_log.py | 80 ++++- SoftLayer/managers/network.py | 40 +++ SoftLayer/utils.py | 64 ++++ tests/CLI/modules/event_log_tests.py | 383 +---------------------- tests/CLI/modules/securitygroup_tests.py | 87 +++++ tests/managers/event_log_tests.py | 295 +++++++++++++++++ tests/managers/network_tests.py | 200 ++++++++++++ 10 files changed, 809 insertions(+), 499 deletions(-) create mode 100644 SoftLayer/CLI/securitygroup/event_log.py create mode 100644 tests/managers/event_log_tests.py diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index ef741318c..7bfb329ce 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -1,7 +1,6 @@ """Get Audit Logs.""" # :license: MIT, see LICENSE for more details. -from datetime import datetime import json import click @@ -14,30 +13,25 @@ @click.command() -@click.option('--date_min', '-d', - help='The earliest date we want to search for audit logs in mm/dd/yyy format.') -@click.option('--date_max', '-D', - help='The latest date we want to search for audit logs in mm/dd/yyy format.') +@click.option('--date-min', '-d', + help='The earliest date we want to search for audit logs in mm/dd/yyyy format.') +@click.option('--date-max', '-D', + help='The latest date we want to search for audit logs in mm/dd/yyyy format.') @click.option('--obj_event', '-e', help="The event we want to get audit logs for") @click.option('--obj_id', '-i', help="The id of the object we want to get audit logs for") -@click.option('--request_id', '-r', - help="The request id we want to look for. If this is set, we will ignore all other arguments.") @click.option('--obj_type', '-t', help="The type of the object we want to get audit logs for") @click.option('--utc_offset', '-z', - help="UTC Offset for seatching with dates. The default is -0500") + help="UTC Offset for seatching with dates. The default is -0000") @environment.pass_env -def cli(env, date_min, date_max, obj_event, obj_id, request_id, obj_type, utc_offset): +def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): """Get Audit Logs""" mgr = SoftLayer.EventLogManager(env.client) - if request_id is not None: - logs = _get_event_logs_by_request_id(mgr, request_id) - else: - request_filter = _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) - logs = mgr.get_event_logs(request_filter) + request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) + logs = mgr.get_event_logs(request_filter) table = formatting.Table(COLUMNS) table.align['metadata'] = "l" @@ -51,107 +45,3 @@ def cli(env, date_min, date_max, obj_event, obj_id, request_id, obj_type, utc_of table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata]) env.fout(table) - - -def _build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset): - if not date_min and not date_max and not obj_event and not obj_id and not obj_type: - return None - - request_filter = {} - - if date_min and date_max: - request_filter['eventCreateDate'] = { - 'operation': 'betweenDate', - 'options': [ - { - 'name': 'startDate', - 'value': [_parse_date(date_min, utc_offset)] - }, - { - 'name': 'endDate', - 'value': [_parse_date(date_max, utc_offset)] - } - ] - } - - else: - if date_min: - request_filter['eventCreateDate'] = { - 'operation': 'greaterThanDate', - 'options': [ - { - 'name': 'date', - 'value': [_parse_date(date_min, utc_offset)] - } - ] - } - - if date_max: - request_filter['eventCreateDate'] = { - 'operation': 'lessThanDate', - 'options': [ - { - 'name': 'date', - 'value': [_parse_date(date_max, utc_offset)] - } - ] - } - - if obj_event: - request_filter['eventName'] = {'operation': obj_event} - - if obj_id: - request_filter['objectId'] = {'operation': obj_id} - - if obj_type: - request_filter['objectName'] = {'operation': obj_type} - - return request_filter - - -def _get_event_logs_by_request_id(mgr, request_id): - cci_filter = { - 'objectName': { - 'operation': 'CCI' - } - } - - cci_logs = mgr.get_event_logs(cci_filter) - - security_group_filter = { - 'objectName': { - 'operation': 'Security Group' - } - } - - security_group_logs = mgr.get_event_logs(security_group_filter) - - unfiltered_logs = cci_logs + security_group_logs - - filtered_logs = [] - - for unfiltered_log in unfiltered_logs: - try: - metadata = json.loads(unfiltered_log['metaData']) - if 'requestId' in metadata: - if metadata['requestId'] == request_id: - filtered_logs.append(unfiltered_log) - except ValueError: - continue - - return filtered_logs - - -def _parse_date(date_string, utc_offset): - user_date_format = "%m/%d/%Y" - - user_date = datetime.strptime(date_string, user_date_format) - dirty_time = user_date.isoformat() - - if utc_offset is None: - utc_offset = "-0500" - - iso_time_zone = utc_offset[:3] + ':' + utc_offset[3:] - clean_time = "{}.000000{}".format(dirty_time, iso_time_zone) - - return clean_time diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 71d52d0ae..83419bda8 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -252,6 +252,7 @@ 'SoftLayer.CLI.securitygroup.interface:add'), ('securitygroup:interface-remove', 'SoftLayer.CLI.securitygroup.interface:remove'), + ('securitygroup:audit-log', 'SoftLayer.CLI.securitygroup.event_log:get_by_request_id'), ('sshkey', 'SoftLayer.CLI.sshkey'), ('sshkey:add', 'SoftLayer.CLI.sshkey.add:cli'), diff --git a/SoftLayer/CLI/securitygroup/event_log.py b/SoftLayer/CLI/securitygroup/event_log.py new file mode 100644 index 000000000..fbf109d9b --- /dev/null +++ b/SoftLayer/CLI/securitygroup/event_log.py @@ -0,0 +1,32 @@ +"""Get event logs relating to security groups""" +# :license: MIT, see LICENSE for more details. + +import json + +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting + +COLUMNS = ['event', 'label', 'date', 'metadata'] + + +@click.command() +@click.argument('request_id') +@environment.pass_env +def get_by_request_id(env, request_id): + """Search for event logs by request id""" + mgr = SoftLayer.NetworkManager(env.client) + + logs = mgr.get_event_logs_by_request_id(request_id) + + table = formatting.Table(COLUMNS) + table.align['metadata'] = "l" + + for log in logs: + metadata = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) + + table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata]) + + env.fout(table) diff --git a/SoftLayer/managers/event_log.py b/SoftLayer/managers/event_log.py index 7b7e39d54..4e37e6d67 100644 --- a/SoftLayer/managers/event_log.py +++ b/SoftLayer/managers/event_log.py @@ -6,6 +6,8 @@ :license: MIT, see LICENSE for more details. """ +from SoftLayer import utils + class EventLogManager(object): """Provides an interface for the SoftLayer Event Log Service. @@ -13,8 +15,9 @@ class EventLogManager(object): See product information here: http://sldn.softlayer.com/reference/services/SoftLayer_Event_Log """ + def __init__(self, client): - self.client = client + self.event_log = client['Event_Log'] def get_event_logs(self, request_filter): """Returns a list of event logs @@ -22,9 +25,7 @@ def get_event_logs(self, request_filter): :param dict request_filter: filter dict :returns: List of event logs """ - results = self.client.call("Event_Log", - 'getAllObjects', - filter=request_filter) + results = self.event_log.getAllObjects(filter=request_filter) return results def get_event_log_types(self): @@ -32,7 +33,72 @@ def get_event_log_types(self): :returns: List of event log types """ - results = self.client.call("Event_Log", - 'getAllEventObjectNames') - + results = self.event_log.getAllEventObjectNames() return results + + def get_event_logs_by_type(self, event_type): + """Returns a list of event logs, filtered on the 'objectName' field + + :param string event_type: The event type we want to filter on + :returns: List of event logs, filtered on the 'objectName' field + """ + request_filter = {} + request_filter['objectName'] = {'operation': event_type} + + return self.event_log.getAllObjects(filter=request_filter) + + def get_event_logs_by_event_name(self, event_name): + """Returns a list of event logs, filtered on the 'eventName' field + + :param string event_type: The event type we want to filter on + :returns: List of event logs, filtered on the 'eventName' field + """ + request_filter = {} + request_filter['eventName'] = {'operation': event_name} + + return self.event_log.getAllObjects(filter=request_filter) + + @staticmethod + def build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset): + """Returns a query filter that can be passed into EventLogManager.get_event_logs + + :param string date_min: Lower bound date in MM/DD/YYYY format + :param string date_max: Upper bound date in MM/DD/YYYY format + :param string obj_event: The name of the events we want to filter by + :param int obj_id: The id of the event we want to filter by + :param string obj_type: The type of event we want to filter by + :param string utc_offset: The UTC offset we want to use when converting date_min and date_max. + (default '+0000') + + :returns: dict: The generated query filter + """ + + if not date_min and not date_max and not obj_event and not obj_id and not obj_type: + return None + + request_filter = {} + + if date_min and date_max: + request_filter['eventCreateDate'] = utils.event_log_filter_between_date(date_min, date_max, utc_offset) + else: + if date_min: + request_filter['eventCreateDate'] = utils.event_log_filter_greater_than_date( + date_min, + utc_offset + ) + elif date_max: + request_filter['eventCreateDate'] = utils.event_log_filter_less_than_date( + date_max, + utc_offset + ) + + if obj_event: + request_filter['eventName'] = {'operation': obj_event} + + if obj_id: + request_filter['objectId'] = {'operation': obj_id} + + if obj_type: + request_filter['objectName'] = {'operation': obj_type} + + return request_filter diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py index 2513a912f..10c887ece 100644 --- a/SoftLayer/managers/network.py +++ b/SoftLayer/managers/network.py @@ -6,10 +6,13 @@ :license: MIT, see LICENSE for more details. """ import collections +import json from SoftLayer import exceptions from SoftLayer import utils +from SoftLayer.managers import event_log + DEFAULT_SUBNET_MASK = ','.join(['hardware', 'datacenter', 'ipAddressCount', @@ -540,6 +543,43 @@ def remove_securitygroup_rules(self, group_id, rules): """ return self.security_group.removeRules(rules, id=group_id) + def get_event_logs_by_request_id(self, request_id): + """Gets all event logs by the given request id + + :param string request_id: The request id we want to filter on + """ + + # Get all relevant event logs + unfiltered_logs = self._get_cci_event_logs() + self._get_security_group_event_logs() + + # Grab only those that have the specific request id + filtered_logs = [] + + for unfiltered_log in unfiltered_logs: + try: + metadata = json.loads(unfiltered_log['metaData']) + if 'requestId' in metadata: + if metadata['requestId'] == request_id: + filtered_logs.append(unfiltered_log) + except ValueError: + continue + + return filtered_logs + + def _get_cci_event_logs(self): + # Load the event log manager + event_log_mgr = event_log.EventLogManager(self.client) + + # Get CCI Event Logs + return event_log_mgr.get_event_logs_by_type('CCI') + + def _get_security_group_event_logs(self): + # Load the event log manager + event_log_mgr = event_log.EventLogManager(self.client) + + # Get CCI Event Logs + return event_log_mgr.get_event_logs_by_type('Security Group') + def resolve_global_ip_ids(self, identifier): """Resolve global ip ids.""" return utils.resolve_ids(identifier, diff --git a/SoftLayer/utils.py b/SoftLayer/utils.py index 07eb72edb..1e643ffd9 100644 --- a/SoftLayer/utils.py +++ b/SoftLayer/utils.py @@ -127,6 +127,70 @@ def query_filter_date(start, end): } +def format_event_log_date(date_string, utc): + """Gets a date in the format that the SoftLayer_EventLog object likes. + + :param string date_string: date in mm/dd/yyyy format + :param string utc: utc offset. Defaults to '+0000' + """ + user_date_format = "%m/%d/%Y" + + user_date = datetime.datetime.strptime(date_string, user_date_format) + dirty_time = user_date.isoformat() + + if utc is None: + utc = "+0000" + + iso_time_zone = utc[:3] + ':' + utc[3:] + clean_time = "{}.000000{}".format(dirty_time, iso_time_zone) + + return clean_time + + +def event_log_filter_between_date(start, end, utc): + """betweenDate Query filter that SoftLayer_EventLog likes + + :param string start: lower bound date in mm/dd/yyyy format + :param string end: upper bound date in mm/dd/yyyy format + :param string utc: utc offset. Defaults to '+0000' + """ + return { + 'operation': 'betweenDate', + 'options': [ + {'name': 'startDate', 'value': [format_event_log_date(start, utc)]}, + {'name': 'endDate', 'value': [format_event_log_date(end, utc)]} + ] + } + + +def event_log_filter_greater_than_date(date, utc): + """greaterThanDate Query filter that SoftLayer_EventLog likes + + :param string date: lower bound date in mm/dd/yyyy format + :param string utc: utc offset. Defaults to '+0000' + """ + return { + 'operation': 'greaterThanDate', + 'options': [ + {'name': 'date', 'value': [format_event_log_date(date, utc)]} + ] + } + + +def event_log_filter_less_than_date(date, utc): + """lessThanDate Query filter that SoftLayer_EventLog likes + + :param string date: upper bound date in mm/dd/yyyy format + :param string utc: utc offset. Defaults to '+0000' + """ + return { + 'operation': 'lessThanDate', + 'options': [ + {'name': 'date', 'value': [format_event_log_date(date, utc)]} + ] + } + + class IdentifierMixin(object): """Mixin used to resolve ids from other names of objects. diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index f95f3bccd..8cb58cb72 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -6,18 +6,12 @@ import json -from SoftLayer.CLI.event_log import get as event_log_get from SoftLayer import testing class EventLogTests(testing.TestCase): - def test_get_event_log(self): - result = self.run_command(['audit-log', 'get']) - - self.assert_no_fail(result) - - expected_esponse = [ + expected = [ { 'date': '2017-10-23T14:22:36.221541-05:00', 'event': 'Disable Port', @@ -117,375 +111,13 @@ def test_get_event_log(self): } ] - self.assertEqual(expected_esponse, json.loads(result.output)) - - def test_get_event_log_request_id(self): - result = self.run_command(['audit-log', 'get', '--request_id=4709e02ad42c83f80345904']) - - # Because filtering doesn't work on the test data recieved from the server we stand up, - # and we call getAllObjects twice, the dataset we work over has duplicates - expected_esponse = [ - { - 'date': '2017-10-18T10:41:42.176328-05:00', - 'event': 'Network Component Added to Security Group', - 'label': 'test_SG', - 'metadata': json.dumps(json.loads( - '{"fullyQualifiedDomainName":"test.softlayer.com",' - '"networkComponentId":"100",' - '"networkInterfaceType":"public",' - '"requestId":"4709e02ad42c83f80345904"}' - ), - indent=4, - sort_keys=True - ) - }, - { - 'date': '2017-10-18T10:41:42.176328-05:00', - 'event': 'Network Component Added to Security Group', - 'label': 'test_SG', - 'metadata': json.dumps(json.loads( - '{"fullyQualifiedDomainName":"test.softlayer.com",' - '"networkComponentId":"100",' - '"networkInterfaceType":"public",' - '"requestId":"4709e02ad42c83f80345904"}' - ), - indent=4, - sort_keys=True - ) - } - ] - - self.assertEqual(expected_esponse, json.loads(result.output)) - - def test_get_event_log_date_min(self): - observed_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, None) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'greaterThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-30T00:00:00.000000-05:00'] - }] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_date_max(self): - observed_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, None) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'lessThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-31T00:00:00.000000-05:00'] - }] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_date_min_max(self): - observed_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, None) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'betweenDate', - 'options': [ - { - 'name': 'startDate', - 'value': ['2017-10-30T00:00:00.000000-05:00'] - }, - { - 'name': 'endDate', - 'value': ['2017-10-31T00:00:00.000000-05:00'] - } - ] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_date_min_utc_offset(self): - observed_filter = event_log_get._build_filter('10/30/2017', None, None, None, None, "-0600") - - expected_filter = { - 'eventCreateDate': { - 'operation': 'greaterThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-30T00:00:00.000000-06:00'] - }] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_date_max_utc_offset(self): - observed_filter = event_log_get._build_filter(None, '10/31/2017', None, None, None, "-0600") - - expected_filter = { - 'eventCreateDate': { - 'operation': 'lessThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-31T00:00:00.000000-06:00'] - }] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_date_min_max_utc_offset(self): - observed_filter = event_log_get._build_filter('10/30/2017', '10/31/2017', None, None, None, "-0600") - - expected_filter = { - 'eventCreateDate': { - 'operation': 'betweenDate', - 'options': [ - { - 'name': 'startDate', - 'value': ['2017-10-30T00:00:00.000000-06:00'] - }, - { - 'name': 'endDate', - 'value': ['2017-10-31T00:00:00.000000-06:00'] - } - ] - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event(self): - observed_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', None, None, None) - - expected_filter = {'eventName': {'operation': 'Security Group Rule Added'}} - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_id(self): - observed_filter = event_log_get._build_filter(None, None, None, 1, None, None) - - expected_filter = {'objectId': {'operation': 1}} - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_type(self): - observed_filter = event_log_get._build_filter(None, None, None, None, 'CCI', None) - - expected_filter = {'objectName': {'operation': 'CCI'}} - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args(self): - observed_filter = event_log_get._build_filter(None, None, 'Security Group Rule Added', 1, 'CCI', None) - - expected_filter = { - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args_min_date(self): - observed_filter = event_log_get._build_filter('10/30/2017', None, 'Security Group Rule Added', 1, 'CCI', None) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'greaterThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-30T00:00:00.000000-05:00'] - }] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args_max_date(self): - observed_filter = event_log_get._build_filter(None, '10/31/2017', 'Security Group Rule Added', 1, 'CCI', None) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'lessThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-31T00:00:00.000000-05:00'] - }] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args_min_max_date(self): - observed_filter = event_log_get._build_filter( - '10/30/2017', - '10/31/2017', - 'Security Group Rule Added', - 1, - 'CCI', - None - ) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'betweenDate', - 'options': [ - { - 'name': 'startDate', - 'value': ['2017-10-30T00:00:00.000000-05:00'] - }, - { - 'name': 'endDate', - 'value': ['2017-10-31T00:00:00.000000-05:00'] - } - ] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args_min_date_utc_offset(self): - observed_filter = event_log_get._build_filter( - '10/30/2017', - None, - 'Security Group Rule Added', - 1, - 'CCI', - '-0600' - ) - - expected_filter = { - 'eventCreateDate': { - 'operation': 'greaterThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-30T00:00:00.000000-06:00'] - }] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(expected_filter, observed_filter) - - def test_get_event_log_event_all_args_max_date_utc_offset(self): - observed_filter = event_log_get._build_filter( - None, - '10/31/2017', - 'Security Group Rule Added', - 1, - 'CCI', - '-0600' - ) - - correct_filter = { - 'eventCreateDate': { - 'operation': 'lessThanDate', - 'options': [{ - 'name': 'date', - 'value': ['2017-10-31T00:00:00.000000-06:00'] - }] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(correct_filter, observed_filter) - - def test_get_event_log_event_all_args_min_max_date_utc_offset(self): - observed_filter = event_log_get._build_filter( - '10/30/2017', - '10/31/2017', - 'Security Group Rule Added', - 1, - 'CCI', - '-0600') - - correct_filter = { - 'eventCreateDate': { - 'operation': 'betweenDate', - 'options': [ - { - 'name': 'startDate', - 'value': ['2017-10-30T00:00:00.000000-06:00'] - }, - { - 'name': 'endDate', - 'value': ['2017-10-31T00:00:00.000000-06:00'] - } - ] - }, - 'eventName': { - 'operation': 'Security Group Rule Added' - }, - 'objectId': { - 'operation': 1 - }, - 'objectName': { - 'operation': 'CCI' - } - } - - self.assertEqual(correct_filter, observed_filter) - - def test_get_event_log_types(self): - result = self.run_command(['audit-log', 'types']) + result = self.run_command(['audit-log', 'get']) self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) - expected_esponse = [ + def test_get_event_log_types(self): + expected = [ { 'types': 'CCI' }, @@ -494,4 +126,7 @@ def test_get_event_log_types(self): } ] - self.assertEqual(expected_esponse, json.loads(result.output)) + result = self.run_command(['audit-log', 'types']) + + self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index 2a14e8434..3377e4d15 100644 --- a/tests/CLI/modules/securitygroup_tests.py +++ b/tests/CLI/modules/securitygroup_tests.py @@ -4,11 +4,16 @@ :license: MIT, see LICENSE for more details. """ import json +import mock +import SoftLayer from SoftLayer import testing class SecurityGroupTests(testing.TestCase): + def set_up(self): + self.network = SoftLayer.NetworkManager(self.client) + def test_list_securitygroup(self): result = self.run_command(['sg', 'list']) @@ -250,3 +255,85 @@ def test_securitygroup_interface_remove_fail(self): '--network-component=500']) self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.NetworkManager.get_event_logs_by_request_id') + def test_securitygroup_get_by_request_id(self, event_mock): + event_mock.return_value = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:13.089536-05:00', + 'eventName': 'Security Group Rule(s) Removed', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"96c9b47b9e102d2e1d81fba",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7765515e28', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + expected = [ + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'label': 'test.softlayer.com', + 'metadata': json.dumps(json.loads( + '{"networkComponentId": "100",' + '"networkInterfaceType": "public",' + '"requestId": "96c9b47b9e102d2e1d81fba",' + '"securityGroupId": "200",' + '"securityGroupName": "test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'label': 'test_SG', + 'metadata': json.dumps(json.loads( + '{"requestId": "96c9b47b9e102d2e1d81fba",' + '"rules": [{"direction": "ingress",' + '"ethertype": "IPv4",' + '"portRangeMax": 2001,' + '"portRangeMin": 2000,' + '"protocol": "tcp",' + '"remoteGroupId": null,' + '"remoteIp": null,' + '"ruleId": "800"}]}' + ), + indent=4, + sort_keys=True + ) + } + ] + + result = self.run_command(['sg', 'audit-log', '96c9b47b9e102d2e1d81fba']) + + self.assertEqual(expected, json.loads(result.output)) diff --git a/tests/managers/event_log_tests.py b/tests/managers/event_log_tests.py new file mode 100644 index 000000000..9a933e0d8 --- /dev/null +++ b/tests/managers/event_log_tests.py @@ -0,0 +1,295 @@ +""" + SoftLayer.tests.managers.event_log_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" +import SoftLayer +from SoftLayer import fixtures +from SoftLayer import testing + + +class EventLogTests(testing.TestCase): + + def set_up(self): + self.event_log = SoftLayer.EventLogManager(self.client) + + def test_get_event_logs(self): + result = self.event_log.get_event_logs(None) + + expected = fixtures.SoftLayer_Event_Log.getAllObjects + self.assertEqual(expected, result) + + def test_get_event_log_types(self): + result = self.event_log.get_event_log_types() + + expected = fixtures.SoftLayer_Event_Log.getAllEventObjectNames + self.assertEqual(expected, result) + + def test_get_event_logs_by_type(self): + expected = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-23T14:22:36.221541-05:00', + 'eventName': 'Disable Port', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '100', + 'userId': '', + 'userType': 'SYSTEM' + } + ] + + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = expected + + result = self.event_log.get_event_logs_by_type('CCI') + + self.assertEqual(expected, result) + + def test_get_event_logs_by_event_name(self): + expected = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = expected + + result = self.event_log.get_event_logs_by_event_name('Security Group Added') + + self.assertEqual(expected, result) + + def test_build_filter_no_args(self): + result = self.event_log.build_filter(None, None, None, None, None, None) + + self.assertEqual(result, None) + + def test_build_filter_min_date(self): + expected = { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-30T00:00:00.000000+00:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', None, None, None, None, None) + + self.assertEqual(expected, result) + + def test_build_filter_max_date(self): + expected = { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-31T00:00:00.000000+00:00' + ] + } + ] + } + } + + result = self.event_log.build_filter(None, '10/31/2017', None, None, None, None) + + self.assertEqual(expected, result) + + def test_build_filter_min_max_date(self): + expected = { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': [ + '2017-10-30T00:00:00.000000+00:00' + ] + }, + { + 'name': 'endDate', + 'value': [ + '2017-10-31T00:00:00.000000+00:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', '10/31/2017', None, None, None, None) + + self.assertEqual(expected, result) + + def test_build_filter_min_date_pos_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-30T00:00:00.000000+05:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', None, None, None, None, '+0500') + + self.assertEqual(expected, result) + + def test_build_filter_max_date_pos_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-31T00:00:00.000000+05:00' + ] + } + ] + } + } + + result = self.event_log.build_filter(None, '10/31/2017', None, None, None, '+0500') + + self.assertEqual(expected, result) + + def test_build_filter_min_max_date_pos_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': [ + '2017-10-30T00:00:00.000000+05:00' + ] + }, + { + 'name': 'endDate', + 'value': [ + '2017-10-31T00:00:00.000000+05:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', '10/31/2017', None, None, None, '+0500') + + self.assertEqual(expected, result) + + def test_build_filter_min_date_neg_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'greaterThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-30T00:00:00.000000-03:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', None, None, None, None, '-0300') + + self.assertEqual(expected, result) + + def test_build_filter_max_date_neg_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'lessThanDate', + 'options': [ + { + 'name': 'date', + 'value': [ + '2017-10-31T00:00:00.000000-03:00' + ] + } + ] + } + } + + result = self.event_log.build_filter(None, '10/31/2017', None, None, None, '-0300') + + self.assertEqual(expected, result) + + def test_build_filter_min_max_date_neg_utc(self): + expected = { + 'eventCreateDate': { + 'operation': 'betweenDate', + 'options': [ + { + 'name': 'startDate', + 'value': [ + '2017-10-30T00:00:00.000000-03:00' + ] + }, + { + 'name': 'endDate', + 'value': [ + '2017-10-31T00:00:00.000000-03:00' + ] + } + ] + } + } + + result = self.event_log.build_filter('10/30/2017', '10/31/2017', None, None, None, '-0300') + + self.assertEqual(expected, result) + + def test_build_filter_name(self): + expected = {'eventName': {'operation': 'Add Security Group'}} + + result = self.event_log.build_filter(None, None, 'Add Security Group', None, None, None) + + self.assertEqual(expected, result) + + def test_build_filter_id(self): + expected = {'objectId': {'operation': 1}} + + result = self.event_log.build_filter(None, None, None, 1, None, None) + + self.assertEqual(expected, result) + + def test_build_filter_type(self): + expected = {'objectName': {'operation': 'CCI'}} + + result = self.event_log.build_filter(None, None, None, None, 'CCI', None) + + self.assertEqual(expected, result) diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py index cf38e730f..53e4f2ac0 100644 --- a/tests/managers/network_tests.py +++ b/tests/managers/network_tests.py @@ -4,6 +4,8 @@ :license: MIT, see LICENSE for more details. """ +import mock + import SoftLayer from SoftLayer import fixtures from SoftLayer.managers import network @@ -449,3 +451,201 @@ def test_unassign_global_ip(self): self.assert_called_with('SoftLayer_Network_Subnet_IpAddress_Global', 'unroute', identifier=9876) + + def test_get_event_logs_by_request_id(self): + expected = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:13.089536-05:00', + 'eventName': 'Security Group Rule(s) Removed', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"96c9b47b9e102d2e1d81fba",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7765515e28', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + with mock.patch.object(self.network, '_get_cci_event_logs') as cci_mock: + with mock.patch.object(self.network, '_get_security_group_event_logs') as sg_mock: + cci_mock.return_value = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-23T14:22:36.221541-05:00', + 'eventName': 'Disable Port', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '100', + 'userId': '', + 'userType': 'SYSTEM' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:41.830338-05:00', + 'eventName': 'Security Group Rule Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"ruleId":"100",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e9c2184', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + sg_mock.return_value = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:13.089536-05:00', + 'eventName': 'Security Group Rule(s) Removed', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"96c9b47b9e102d2e1d81fba",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7765515e28', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + }, + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:11.679736-05:00', + 'eventName': 'Network Component Removed from Security Group', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"6b9a87a9ab8ac9a22e87a00",' + '"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public"}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e77653a1e5f', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + result = self.network.get_event_logs_by_request_id('96c9b47b9e102d2e1d81fba') + + self.assertEqual(expected, result) + + def test_get_security_group_event_logs(self): + expected = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T10:42:13.089536-05:00', + 'eventName': 'Security Group Rule(s) Removed', + 'ipAddress': '192.168.0.1', + 'label': 'test_SG', + 'metaData': '{"requestId":"96c9b47b9e102d2e1d81fba",' + '"rules":[{"ruleId":"800",' + '"remoteIp":null,"remoteGroupId":null,"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMin":2000,"portRangeMax":2001,"protocol":"tcp"}]}', + 'objectId': 700, + 'objectName': 'Security Group', + 'traceId': '59e7765515e28', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = expected + + result = self.network._get_security_group_event_logs() + + self.assertEqual(expected, result) + + def test__get_cci_event_logs(self): + expected = [ + { + 'accountId': 100, + 'eventCreateDate': '2017-10-18T09:40:32.238869-05:00', + 'eventName': 'Security Group Added', + 'ipAddress': '192.168.0.1', + 'label': 'test.softlayer.com', + 'metaData': '{"securityGroupId":"200",' + '"securityGroupName":"test_SG",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba"}', + 'objectId': 300, + 'objectName': 'CCI', + 'traceId': '59e767e03a57e', + 'userId': 400, + 'userType': 'CUSTOMER', + 'username': 'user' + } + ] + + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = expected + + result = self.network._get_cci_event_logs() + + self.assertEqual(expected, result) From 6ae681408db48b4bdd1b250084073977498bb1ad Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 11:46:52 -0600 Subject: [PATCH 17/28] Updated fixture. --- SoftLayer/fixtures/SoftLayer_Event_Log.py | 39 ++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py index 8b6a3f746..bbb043d0b 100644 --- a/SoftLayer/fixtures/SoftLayer_Event_Log.py +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -124,4 +124,41 @@ } ] -getAllEventObjectNames = ['CCI', 'Security Group'] +getAllEventObjectNames = [ + { + 'value': 'CCI' + }, + { + 'value':'Security Group' + } + { + 'value': "User" + }, + { + 'value': "Bare Metal Instance" + }, + { + 'value': "API Authentication" + }, + { + 'value': "Server" + }, + { + 'value': "CCI" + }, + { + 'value': "Image" + }, + { + 'value': "Bluemix LB" + }, + { + 'value': "Facility" + }, + { + 'value': "Cloud Object Storage" + }, + { + 'value': "Security Group" + } +] From e2648c6c008817d3162f5410298a2da8adad1489 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 12:33:39 -0600 Subject: [PATCH 18/28] Fixing typos and refactoring work. --- SoftLayer/CLI/event_log/get.py | 10 +++++----- tests/managers/network_tests.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 7bfb329ce..a141a0823 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -17,14 +17,14 @@ help='The earliest date we want to search for audit logs in mm/dd/yyyy format.') @click.option('--date-max', '-D', help='The latest date we want to search for audit logs in mm/dd/yyyy format.') -@click.option('--obj_event', '-e', +@click.option('--obj-event', '-e', help="The event we want to get audit logs for") -@click.option('--obj_id', '-i', +@click.option('--obj-id', '-i', help="The id of the object we want to get audit logs for") -@click.option('--obj_type', '-t', +@click.option('--obj-type', '-t', help="The type of the object we want to get audit logs for") -@click.option('--utc_offset', '-z', - help="UTC Offset for seatching with dates. The default is -0000") +@click.option('--utc-offset', '-z', + help="UTC Offset for searching with dates. The default is -0000") @environment.pass_env def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): """Get Audit Logs""" diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py index 4f95b170e..f9f5ed308 100644 --- a/tests/managers/network_tests.py +++ b/tests/managers/network_tests.py @@ -638,7 +638,7 @@ def test_get_security_group_event_logs(self): self.assertEqual(expected, result) - def test__get_cci_event_logs(self): + def test_get_cci_event_logs(self): expected = [ { 'accountId': 100, From 5a406b49e638b9e06270b594e2fc4cf3c7999b1b Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 12:44:30 -0600 Subject: [PATCH 19/28] More refactoring. --- SoftLayer/CLI/securitygroup/interface.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/interface.py b/SoftLayer/CLI/securitygroup/interface.py index f95c34402..e131269d2 100644 --- a/SoftLayer/CLI/securitygroup/interface.py +++ b/SoftLayer/CLI/securitygroup/interface.py @@ -92,13 +92,13 @@ def add(env, securitygroup_id, network_component, server, interface): mgr = SoftLayer.NetworkManager(env.client) component_id = _get_component_id(env, network_component, server, interface) - success = mgr.attach_securitygroup_component(securitygroup_id, + ret = mgr.attach_securitygroup_component(securitygroup_id, component_id) - if not success: + if not ret: raise exceptions.CLIAbort("Could not attach network component") table = formatting.Table(REQUEST_COLUMNS) - table.add_row([success['requestId']]) + table.add_row([ret['requestId']]) env.fout(table) @@ -120,13 +120,13 @@ def remove(env, securitygroup_id, network_component, server, interface): mgr = SoftLayer.NetworkManager(env.client) component_id = _get_component_id(env, network_component, server, interface) - success = mgr.detach_securitygroup_component(securitygroup_id, + ret = mgr.detach_securitygroup_component(securitygroup_id, component_id) - if not success: + if not ret: raise exceptions.CLIAbort("Could not detach network component") table = formatting.Table(REQUEST_COLUMNS) - table.add_row([success['requestId']]) + table.add_row([ret['requestId']]) env.fout(table) From 8bbbe7849a65914ede6ddc899ee1455ac2c93bb8 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 12:53:05 -0600 Subject: [PATCH 20/28] Formating changes. --- SoftLayer/CLI/securitygroup/interface.py | 4 +-- SoftLayer/CLI/virt/placementgroup/__init__.py | 1 - SoftLayer/fixtures/SoftLayer_Event_Log.py | 28 +++++++++---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/SoftLayer/CLI/securitygroup/interface.py b/SoftLayer/CLI/securitygroup/interface.py index e131269d2..db07ae851 100644 --- a/SoftLayer/CLI/securitygroup/interface.py +++ b/SoftLayer/CLI/securitygroup/interface.py @@ -93,7 +93,7 @@ def add(env, securitygroup_id, network_component, server, interface): component_id = _get_component_id(env, network_component, server, interface) ret = mgr.attach_securitygroup_component(securitygroup_id, - component_id) + component_id) if not ret: raise exceptions.CLIAbort("Could not attach network component") @@ -121,7 +121,7 @@ def remove(env, securitygroup_id, network_component, server, interface): component_id = _get_component_id(env, network_component, server, interface) ret = mgr.detach_securitygroup_component(securitygroup_id, - component_id) + component_id) if not ret: raise exceptions.CLIAbort("Could not detach network component") diff --git a/SoftLayer/CLI/virt/placementgroup/__init__.py b/SoftLayer/CLI/virt/placementgroup/__init__.py index 02d5da986..aa748a5b1 100644 --- a/SoftLayer/CLI/virt/placementgroup/__init__.py +++ b/SoftLayer/CLI/virt/placementgroup/__init__.py @@ -44,4 +44,3 @@ def get_command(self, ctx, cmd_name): @click.group(cls=PlacementGroupCommands, context_settings=CONTEXT) def cli(): """Base command for all capacity related concerns""" - pass diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py index bbb043d0b..f375a377e 100644 --- a/SoftLayer/fixtures/SoftLayer_Event_Log.py +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -126,39 +126,39 @@ getAllEventObjectNames = [ { - 'value': 'CCI' - }, + 'value': 'CCI' + }, { - 'value':'Security Group' - } + 'value': 'Security Group' + }, { - 'value': "User" + 'value': "User" }, { - 'value': "Bare Metal Instance" + 'value': "Bare Metal Instance" }, { - 'value': "API Authentication" + 'value': "API Authentication" }, { - 'value': "Server" + 'value': "Server" }, { - 'value': "CCI" + 'value': "CCI" }, { - 'value': "Image" + 'value': "Image" }, { - 'value': "Bluemix LB" + 'value': "Bluemix LB" }, { - 'value': "Facility" + 'value': "Facility" }, { - 'value': "Cloud Object Storage" + 'value': "Cloud Object Storage" }, { - 'value': "Security Group" + 'value': "Security Group" } ] From 82574e0ac893734cbab04d1de35e404424dcdb68 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 13:49:54 -0600 Subject: [PATCH 21/28] Updates to fixture and unit test. --- SoftLayer/fixtures/SoftLayer_Event_Log.py | 4 +-- tests/CLI/modules/event_log_tests.py | 34 +++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py index f375a377e..840e84890 100644 --- a/SoftLayer/fixtures/SoftLayer_Event_Log.py +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -126,10 +126,10 @@ getAllEventObjectNames = [ { - 'value': 'CCI' + 'value': "Account" }, { - 'value': 'Security Group' + 'value': "CDN" }, { 'value': "User" diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 8cb58cb72..06ab4a1ae 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -119,10 +119,40 @@ def test_get_event_log(self): def test_get_event_log_types(self): expected = [ { - 'types': 'CCI' + "types": {"value": "Account"} }, { - 'types': 'Security Group' + "types": {"value": "CDN"} + }, + { + "types": {"value": "User"} + }, + { + "types": {"value": "Bare Metal Instance"} + }, + { + "types": {"value": "API Authentication"} + }, + { + "types": {"value": "Server"} + }, + { + "types": {"value": "CCI"} + }, + { + "types": {"value": "Image"} + }, + { + "types": {"value": "Bluemix LB"} + }, + { + "types": {"value": "Facility"} + }, + { + "types": {"value": "Cloud Object Storage"} + }, + { + "types": {"value": "Security Group"} } ] From 5320df050285118effd2502ca25dbe8e80f916b9 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Tue, 5 Feb 2019 14:16:59 -0600 Subject: [PATCH 22/28] Refactoring. Audi-log is no more. All references has been changed to event-log which matches the API and function names. --- SoftLayer/CLI/event_log/__init__.py | 2 +- SoftLayer/CLI/event_log/get.py | 14 +++++++------- SoftLayer/CLI/event_log/types.py | 4 ++-- SoftLayer/CLI/routes.py | 8 ++++---- SoftLayer/CLI/user/detail.py | 2 +- tests/CLI/modules/event_log_tests.py | 4 ++-- tests/CLI/modules/securitygroup_tests.py | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/SoftLayer/CLI/event_log/__init__.py b/SoftLayer/CLI/event_log/__init__.py index 35973ae26..a10576f5f 100644 --- a/SoftLayer/CLI/event_log/__init__.py +++ b/SoftLayer/CLI/event_log/__init__.py @@ -1 +1 @@ -"""Audit Logs.""" +"""Event Logs.""" diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index a141a0823..84c98f4a6 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -1,4 +1,4 @@ -"""Get Audit Logs.""" +"""Get Event Logs.""" # :license: MIT, see LICENSE for more details. import json @@ -14,20 +14,20 @@ @click.command() @click.option('--date-min', '-d', - help='The earliest date we want to search for audit logs in mm/dd/yyyy format.') + help='The earliest date we want to search for event logs in mm/dd/yyyy format.') @click.option('--date-max', '-D', - help='The latest date we want to search for audit logs in mm/dd/yyyy format.') + help='The latest date we want to search for event logs in mm/dd/yyyy format.') @click.option('--obj-event', '-e', - help="The event we want to get audit logs for") + help="The event we want to get event logs for") @click.option('--obj-id', '-i', - help="The id of the object we want to get audit logs for") + help="The id of the object we want to get event logs for") @click.option('--obj-type', '-t', - help="The type of the object we want to get audit logs for") + help="The type of the object we want to get event logs for") @click.option('--utc-offset', '-z', help="UTC Offset for searching with dates. The default is -0000") @environment.pass_env def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): - """Get Audit Logs""" + """Get Event Logs""" mgr = SoftLayer.EventLogManager(env.client) request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) diff --git a/SoftLayer/CLI/event_log/types.py b/SoftLayer/CLI/event_log/types.py index 561fcc708..4bb377e99 100644 --- a/SoftLayer/CLI/event_log/types.py +++ b/SoftLayer/CLI/event_log/types.py @@ -1,4 +1,4 @@ -"""Get Audit Log Types.""" +"""Get Event Log Types.""" # :license: MIT, see LICENSE for more details. import click @@ -13,7 +13,7 @@ @click.command() @environment.pass_env def cli(env): - """Get Audit Log Types""" + """Get Event Log Types""" mgr = SoftLayer.EventLogManager(env.client) event_log_types = mgr.get_event_log_types() diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 3e9dfd86e..cc6a86abe 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -97,9 +97,9 @@ ('block:volume-order', 'SoftLayer.CLI.block.order:cli'), ('block:volume-set-lun-id', 'SoftLayer.CLI.block.lun:cli'), - ('audit-log', 'SoftLayer.CLI.event_log'), - ('audit-log:get', 'SoftLayer.CLI.event_log.get:cli'), - ('audit-log:types', 'SoftLayer.CLI.event_log.types:cli'), + ('event-log', 'SoftLayer.CLI.event_log'), + ('event-log:get', 'SoftLayer.CLI.event_log.get:cli'), + ('event-log:types', 'SoftLayer.CLI.event_log.types:cli'), ('file', 'SoftLayer.CLI.file'), ('file:access-authorize', 'SoftLayer.CLI.file.access.authorize:cli'), @@ -260,7 +260,7 @@ 'SoftLayer.CLI.securitygroup.interface:add'), ('securitygroup:interface-remove', 'SoftLayer.CLI.securitygroup.interface:remove'), - ('securitygroup:audit-log', 'SoftLayer.CLI.securitygroup.event_log:get_by_request_id'), + ('securitygroup:event-log', 'SoftLayer.CLI.securitygroup.event_log:get_by_request_id'), ('sshkey', 'SoftLayer.CLI.sshkey'), ('sshkey:add', 'SoftLayer.CLI.sshkey.add:cli'), diff --git a/SoftLayer/CLI/user/detail.py b/SoftLayer/CLI/user/detail.py index 498874482..11b55546a 100644 --- a/SoftLayer/CLI/user/detail.py +++ b/SoftLayer/CLI/user/detail.py @@ -23,7 +23,7 @@ @click.option('--logins', '-l', is_flag=True, default=False, help="Show login history of this user for the last 30 days") @click.option('--events', '-e', is_flag=True, default=False, - help="Show audit log for this user.") + help="Show event log for this user.") @environment.pass_env def cli(env, identifier, keys, permissions, hardware, virtual, logins, events): """User details.""" diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 06ab4a1ae..e1ba13f11 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -111,7 +111,7 @@ def test_get_event_log(self): } ] - result = self.run_command(['audit-log', 'get']) + result = self.run_command(['event-log', 'get']) self.assert_no_fail(result) self.assertEqual(expected, json.loads(result.output)) @@ -156,7 +156,7 @@ def test_get_event_log_types(self): } ] - result = self.run_command(['audit-log', 'types']) + result = self.run_command(['event-log', 'types']) self.assert_no_fail(result) self.assertEqual(expected, json.loads(result.output)) diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index 3baabc3e7..4ce0cd564 100644 --- a/tests/CLI/modules/securitygroup_tests.py +++ b/tests/CLI/modules/securitygroup_tests.py @@ -336,6 +336,6 @@ def test_securitygroup_get_by_request_id(self, event_mock): } ] - result = self.run_command(['sg', 'audit-log', '96c9b47b9e102d2e1d81fba']) + result = self.run_command(['sg', 'event-log', '96c9b47b9e102d2e1d81fba']) self.assertEqual(expected, json.loads(result.output)) From bb1717c2cca8097dbc80f4b8058e34bf28001dab Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Wed, 6 Feb 2019 12:47:56 -0600 Subject: [PATCH 23/28] Made the metadata field optional, and handles empty responses. --- SoftLayer/CLI/event_log/get.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 84c98f4a6..95b1d82bd 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -9,7 +9,7 @@ from SoftLayer.CLI import environment from SoftLayer.CLI import formatting -COLUMNS = ['event', 'label', 'date', 'metadata'] +COLUMNS = ['event', 'label', 'date'] @click.command() @@ -25,23 +25,35 @@ help="The type of the object we want to get event logs for") @click.option('--utc-offset', '-z', help="UTC Offset for searching with dates. The default is -0000") +@click.option('--metadata/--no-metadata', default=False, + help="Display metadata if present") @environment.pass_env -def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset): +def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metadata): """Get Event Logs""" mgr = SoftLayer.EventLogManager(env.client) - request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) logs = mgr.get_event_logs(request_filter) + if logs == None: + env.fout('None available.') + return + + if metadata: + COLUMNS.append('metadata') + table = formatting.Table(COLUMNS) - table.align['metadata'] = "l" + env.out("Table size: " + str(len(table.columns))) + if metadata: + table.align['metadata'] = "l" for log in logs: - try: - metadata = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) - except ValueError: - metadata = log['metaData'] - - table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata]) - + if metadata: + try: + metadata_data = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) + except ValueError: + metadata_data = log['metaData'] + + table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata_data]) + else: + table.add_row([log['eventName'], log['label'], log['eventCreateDate']]) env.fout(table) From 8bb2b1e2ae80dd832692c7bc67e3d2a86fa93bcc Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Wed, 6 Feb 2019 14:32:54 -0600 Subject: [PATCH 24/28] Updated unit tests. --- SoftLayer/CLI/event_log/get.py | 7 ++-- tests/CLI/modules/event_log_tests.py | 56 +++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 95b1d82bd..33a9476c3 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -26,7 +26,7 @@ @click.option('--utc-offset', '-z', help="UTC Offset for searching with dates. The default is -0000") @click.option('--metadata/--no-metadata', default=False, - help="Display metadata if present") + help="Display metadata if present") @environment.pass_env def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metadata): """Get Event Logs""" @@ -34,15 +34,14 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metada request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) logs = mgr.get_event_logs(request_filter) - if logs == None: + if logs is None: env.fout('None available.') return if metadata: COLUMNS.append('metadata') - + table = formatting.Table(COLUMNS) - env.out("Table size: " + str(len(table.columns))) if metadata: table.align['metadata'] = "l" diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index e1ba13f11..95409f070 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -10,7 +10,7 @@ class EventLogTests(testing.TestCase): - def test_get_event_log(self): + def test_get_event_log_with_metadata(self): expected = [ { 'date': '2017-10-23T14:22:36.221541-05:00', @@ -111,11 +111,65 @@ def test_get_event_log(self): } ] + result = self.run_command(['event-log', 'get', '--metadata']) + + self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) + + def test_get_event_log_without_metadata(self): + expected = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'label': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'label': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'label': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'label': 'test_SG' + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'label': 'test_SG' + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'label': 'test_SG' + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'label': 'test_SG' + } + ] + result = self.run_command(['event-log', 'get']) self.assert_no_fail(result) self.assertEqual(expected, json.loads(result.output)) + def test_get_event_log_empty(self): + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = None + + result = self.run_command(['event-log', 'get']) + + self.assertEqual(mock.call_count, 1) + self.assert_no_fail(result) + self.assertEqual('"None available."\n', result.output) + def test_get_event_log_types(self): expected = [ { From 004e5afcc3dd16efdfef5a345b99954932ee5db8 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Wed, 6 Feb 2019 15:50:26 -0600 Subject: [PATCH 25/28] Strips out leading and trailing curly-brackets from metadata if displayed as a table. --- SoftLayer/CLI/event_log/get.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 33a9476c3..c99db5e3d 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -49,6 +49,8 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metada if metadata: try: metadata_data = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) + if env.format == "table": + metadata_data = metadata_data.strip("{}\n\t") except ValueError: metadata_data = log['metaData'] From d21cbd1d0d1f28d92c43f09402503ee2e9b660b1 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Thu, 7 Feb 2019 11:19:19 -0600 Subject: [PATCH 26/28] Added and renamed fields. --- SoftLayer/CLI/event_log/get.py | 12 ++++-- tests/CLI/modules/event_log_tests.py | 56 +++++++++++++++++++++------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index c99db5e3d..42224a315 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -9,7 +9,7 @@ from SoftLayer.CLI import environment from SoftLayer.CLI import formatting -COLUMNS = ['event', 'label', 'date'] +COLUMNS = ['event', 'object', 'type', 'date', 'username'] @click.command() @@ -31,6 +31,7 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metadata): """Get Event Logs""" mgr = SoftLayer.EventLogManager(env.client) + usrmgr = SoftLayer.UserManager(env.client) request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) logs = mgr.get_event_logs(request_filter) @@ -46,6 +47,9 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metada table.align['metadata'] = "l" for log in logs: + user = log['userType'] + if user == "CUSTOMER": + user = usrmgr.get_user(log['userId'], "mask[username]")['username'] if metadata: try: metadata_data = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) @@ -54,7 +58,9 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metada except ValueError: metadata_data = log['metaData'] - table.add_row([log['eventName'], log['label'], log['eventCreateDate'], metadata_data]) + table.add_row([log['eventName'], log['label'], log['objectName'], + log['eventCreateDate'], user, metadata_data]) else: - table.add_row([log['eventName'], log['label'], log['eventCreateDate']]) + table.add_row([log['eventName'], log['label'], log['objectName'], + log['eventCreateDate'], user]) env.fout(table) diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 95409f070..2164a57f5 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -15,13 +15,17 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-23T14:22:36.221541-05:00', 'event': 'Disable Port', - 'label': 'test.softlayer.com', + 'object': 'test.softlayer.com', + 'username': 'SYSTEM', + 'type': 'CCI', 'metadata': '' }, { 'date': '2017-10-18T09:40:41.830338-05:00', 'event': 'Security Group Rule Added', - 'label': 'test.softlayer.com', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', 'metadata': json.dumps(json.loads( '{"networkComponentId":"100",' '"networkInterfaceType":"public",' @@ -39,7 +43,9 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-18T09:40:32.238869-05:00', 'event': 'Security Group Added', - 'label': 'test.softlayer.com', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', 'metadata': json.dumps(json.loads( '{"networkComponentId":"100",' '"networkInterfaceType":"public",' @@ -54,7 +60,9 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-18T10:42:13.089536-05:00', 'event': 'Security Group Rule(s) Removed', - 'label': 'test_SG', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', 'metadata': json.dumps(json.loads( '{"requestId":"2abda7ca97e5a1444cae0b9",' '"rules":[{"direction":"ingress",' @@ -69,7 +77,9 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-18T10:42:11.679736-05:00', 'event': 'Network Component Removed from Security Group', - 'label': 'test_SG', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', 'metadata': json.dumps(json.loads( '{"fullyQualifiedDomainName":"test.softlayer.com",' '"networkComponentId":"100",' @@ -83,7 +93,9 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-18T10:41:49.802498-05:00', 'event': 'Security Group Rule(s) Added', - 'label': 'test_SG', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', 'metadata': json.dumps(json.loads( '{"requestId":"0a293c1c3e59e4471da6495",' '"rules":[{"direction":"ingress",' @@ -98,7 +110,9 @@ def test_get_event_log_with_metadata(self): { 'date': '2017-10-18T10:41:42.176328-05:00', 'event': 'Network Component Added to Security Group', - 'label': 'test_SG', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', 'metadata': json.dumps(json.loads( '{"fullyQualifiedDomainName":"test.softlayer.com",' '"networkComponentId":"100",' @@ -121,37 +135,51 @@ def test_get_event_log_without_metadata(self): { 'date': '2017-10-23T14:22:36.221541-05:00', 'event': 'Disable Port', - 'label': 'test.softlayer.com' + 'username': 'SYSTEM', + 'type': 'CCI', + 'object': 'test.softlayer.com' }, { 'date': '2017-10-18T09:40:41.830338-05:00', 'event': 'Security Group Rule Added', - 'label': 'test.softlayer.com' + 'username': 'SL12345-test', + 'type': 'CCI', + 'object': 'test.softlayer.com' }, { 'date': '2017-10-18T09:40:32.238869-05:00', 'event': 'Security Group Added', - 'label': 'test.softlayer.com' + 'username': 'SL12345-test', + 'type': 'CCI', + 'object': 'test.softlayer.com' }, { 'date': '2017-10-18T10:42:13.089536-05:00', 'event': 'Security Group Rule(s) Removed', - 'label': 'test_SG' + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' }, { 'date': '2017-10-18T10:42:11.679736-05:00', 'event': 'Network Component Removed from Security Group', - 'label': 'test_SG' + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' }, { 'date': '2017-10-18T10:41:49.802498-05:00', 'event': 'Security Group Rule(s) Added', - 'label': 'test_SG' + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' }, { 'date': '2017-10-18T10:41:42.176328-05:00', 'event': 'Network Component Added to Security Group', - 'label': 'test_SG' + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' } ] From 6a160767866d522aaf410ee7c59077336003a9be Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Sun, 10 Feb 2019 13:38:53 -0600 Subject: [PATCH 27/28] Finished unit test. --- SoftLayer/CLI/event_log/get.py | 2 +- tests/CLI/modules/event_log_tests.py | 132 ++++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py index 42224a315..b505a4502 100644 --- a/SoftLayer/CLI/event_log/get.py +++ b/SoftLayer/CLI/event_log/get.py @@ -39,7 +39,7 @@ def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metada env.fout('None available.') return - if metadata: + if metadata and 'metadata' not in COLUMNS: COLUMNS.append('metadata') table = formatting.Table(COLUMNS) diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 2164a57f5..1d22ddc1d 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -7,7 +7,7 @@ import json from SoftLayer import testing - +from SoftLayer.CLI import formatting class EventLogTests(testing.TestCase): def test_get_event_log_with_metadata(self): @@ -188,6 +188,136 @@ def test_get_event_log_without_metadata(self): self.assert_no_fail(result) self.assertEqual(expected, json.loads(result.output)) + def test_get_event_table(self): + table_fix = formatting.Table(['event', 'object', 'type', 'date', 'username', 'metadata']) + table_fix.align['metadata'] = "l" + expected = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'object': 'test.softlayer.com', + 'username': 'SYSTEM', + 'type': 'CCI', + 'metadata': '' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"100"}],"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba",' + '"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"2abda7ca97e5a1444cae0b9",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"6b9a87a9ab8ac9a22e87a00"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"0a293c1c3e59e4471da6495",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + } + ] + + for log in expected: + table_fix.add_row([log['event'], log['object'], log['type'], log['date'], log['username'], log['metadata'].strip("{}\n\t")]) + expected_output = formatting.format_output(table_fix) + '\n' + + #print("Output: " + expected_output) + + result = self.run_command(args=['event-log', 'get', '--metadata'], fmt='table') + + #print("Result: " + result.output) + + self.assert_no_fail(result) + self.assertEqual(expected_output, result.output) + def test_get_event_log_empty(self): mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') mock.return_value = None From 62e66b75ca72dfac4311950747902c51183e1a51 Mon Sep 17 00:00:00 2001 From: Erick Sapp Date: Sun, 10 Feb 2019 15:11:09 -0600 Subject: [PATCH 28/28] Formating changes. --- tests/CLI/modules/event_log_tests.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/CLI/modules/event_log_tests.py b/tests/CLI/modules/event_log_tests.py index 1d22ddc1d..a7ff0dcb1 100644 --- a/tests/CLI/modules/event_log_tests.py +++ b/tests/CLI/modules/event_log_tests.py @@ -6,8 +6,9 @@ import json -from SoftLayer import testing from SoftLayer.CLI import formatting +from SoftLayer import testing + class EventLogTests(testing.TestCase): def test_get_event_log_with_metadata(self): @@ -304,17 +305,14 @@ def test_get_event_table(self): ) } ] - + for log in expected: - table_fix.add_row([log['event'], log['object'], log['type'], log['date'], log['username'], log['metadata'].strip("{}\n\t")]) + table_fix.add_row([log['event'], log['object'], log['type'], log['date'], + log['username'], log['metadata'].strip("{}\n\t")]) expected_output = formatting.format_output(table_fix) + '\n' - #print("Output: " + expected_output) - result = self.run_command(args=['event-log', 'get', '--metadata'], fmt='table') - #print("Result: " + result.output) - self.assert_no_fail(result) self.assertEqual(expected_output, result.output)