From 54f72c1be288040c07f2c337c9e1b331fafdbfd7 Mon Sep 17 00:00:00 2001 From: Anthony Fisher Date: Wed, 23 Aug 2017 14:59:59 -0500 Subject: [PATCH 01/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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)