diff --git a/SoftLayer/CLI/event_log/__init__.py b/SoftLayer/CLI/event_log/__init__.py new file mode 100644 index 000000000..a10576f5f --- /dev/null +++ b/SoftLayer/CLI/event_log/__init__.py @@ -0,0 +1 @@ +"""Event Logs.""" diff --git a/SoftLayer/CLI/event_log/get.py b/SoftLayer/CLI/event_log/get.py new file mode 100644 index 000000000..b505a4502 --- /dev/null +++ b/SoftLayer/CLI/event_log/get.py @@ -0,0 +1,66 @@ +"""Get Event Logs.""" +# :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', 'object', 'type', 'date', 'username'] + + +@click.command() +@click.option('--date-min', '-d', + help='The earliest date we want to search for event logs in mm/dd/yyyy format.') +@click.option('--date-max', '-D', + help='The latest date we want to search for event logs in mm/dd/yyyy format.') +@click.option('--obj-event', '-e', + help="The event we want to get event logs for") +@click.option('--obj-id', '-i', + help="The id of the object we want to get event logs for") +@click.option('--obj-type', '-t', + help="The type of the object we want to get event logs for") +@click.option('--utc-offset', '-z', + help="UTC Offset for searching with dates. The default is -0000") +@click.option('--metadata/--no-metadata', default=False, + help="Display metadata if present") +@environment.pass_env +def cli(env, date_min, date_max, obj_event, obj_id, obj_type, utc_offset, metadata): + """Get Event Logs""" + mgr = SoftLayer.EventLogManager(env.client) + usrmgr = SoftLayer.UserManager(env.client) + request_filter = mgr.build_filter(date_min, date_max, obj_event, obj_id, obj_type, utc_offset) + logs = mgr.get_event_logs(request_filter) + + if logs is None: + env.fout('None available.') + return + + if metadata and 'metadata' not in COLUMNS: + COLUMNS.append('metadata') + + table = formatting.Table(COLUMNS) + if metadata: + table.align['metadata'] = "l" + + for log in logs: + user = log['userType'] + if user == "CUSTOMER": + user = usrmgr.get_user(log['userId'], "mask[username]")['username'] + if metadata: + try: + metadata_data = json.dumps(json.loads(log['metaData']), indent=4, sort_keys=True) + if env.format == "table": + metadata_data = metadata_data.strip("{}\n\t") + except ValueError: + metadata_data = log['metaData'] + + table.add_row([log['eventName'], log['label'], log['objectName'], + log['eventCreateDate'], user, metadata_data]) + else: + table.add_row([log['eventName'], log['label'], log['objectName'], + log['eventCreateDate'], user]) + env.fout(table) diff --git a/SoftLayer/CLI/event_log/types.py b/SoftLayer/CLI/event_log/types.py new file mode 100644 index 000000000..4bb377e99 --- /dev/null +++ b/SoftLayer/CLI/event_log/types.py @@ -0,0 +1,26 @@ +"""Get Event 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 Event 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 51914c30b..cc6a86abe 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -97,6 +97,10 @@ ('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'), + ('event-log:types', 'SoftLayer.CLI.event_log.types:cli'), + ('file', 'SoftLayer.CLI.file'), ('file:access-authorize', 'SoftLayer.CLI.file.access.authorize:cli'), ('file:access-list', 'SoftLayer.CLI.file.access.list:cli'), @@ -256,6 +260,7 @@ 'SoftLayer.CLI.securitygroup.interface:add'), ('securitygroup:interface-remove', 'SoftLayer.CLI.securitygroup.interface:remove'), + ('securitygroup:event-log', 'SoftLayer.CLI.securitygroup.event_log:get_by_request_id'), ('sshkey', 'SoftLayer.CLI.sshkey'), ('sshkey:add', 'SoftLayer.CLI.sshkey.add:cli'), diff --git a/SoftLayer/CLI/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/CLI/securitygroup/interface.py b/SoftLayer/CLI/securitygroup/interface.py index a2f33ee87..db07ae851 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') @@ -90,11 +92,16 @@ def add(env, securitygroup_id, network_component, server, interface): mgr = SoftLayer.NetworkManager(env.client) component_id = _get_component_id(env, network_component, server, interface) - success = mgr.attach_securitygroup_component(securitygroup_id, - component_id) - if not success: + ret = mgr.attach_securitygroup_component(securitygroup_id, + component_id) + if not ret: raise exceptions.CLIAbort("Could not attach network component") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([ret['requestId']]) + + env.fout(table) + @click.command() @click.argument('securitygroup_id') @@ -113,11 +120,16 @@ def remove(env, securitygroup_id, network_component, server, interface): mgr = SoftLayer.NetworkManager(env.client) component_id = _get_component_id(env, network_component, server, interface) - success = mgr.detach_securitygroup_component(securitygroup_id, - component_id) - if not success: + ret = mgr.detach_securitygroup_component(securitygroup_id, + component_id) + if not ret: raise exceptions.CLIAbort("Could not detach network component") + table = formatting.Table(REQUEST_COLUMNS) + table.add_row([ret['requestId']]) + + 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 815262313..6d6c33c62 100644 --- a/SoftLayer/CLI/securitygroup/rule.py +++ b/SoftLayer/CLI/securitygroup/rule.py @@ -19,6 +19,9 @@ 'createDate', 'modifyDate'] +REQUEST_BOOL_COLUMNS = ['requestId', 'response'] +REQUEST_RULES_COLUMNS = ['requestId', 'rules'] + @click.command() @click.argument('securitygroup_id') @@ -109,6 +112,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_RULES_COLUMNS) + table.add_row([ret['requestId'], str(ret['rules'])]) + + env.fout(table) + @click.command() @click.argument('securitygroup_id') @@ -149,9 +157,16 @@ 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_BOOL_COLUMNS) + table.add_row([ret['requestId']]) + + env.fout(table) + @click.command() @click.argument('securitygroup_id') @@ -160,5 +175,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_BOOL_COLUMNS) + table.add_row([ret['requestId']]) + + env.fout(table) diff --git a/SoftLayer/CLI/user/detail.py b/SoftLayer/CLI/user/detail.py index 498874482..11b55546a 100644 --- a/SoftLayer/CLI/user/detail.py +++ b/SoftLayer/CLI/user/detail.py @@ -23,7 +23,7 @@ @click.option('--logins', '-l', is_flag=True, default=False, help="Show login history of this user for the last 30 days") @click.option('--events', '-e', is_flag=True, default=False, - help="Show audit log for this user.") + help="Show event log for this user.") @environment.pass_env def cli(env, identifier, keys, permissions, hardware, virtual, logins, events): """User details.""" diff --git a/SoftLayer/fixtures/SoftLayer_Event_Log.py b/SoftLayer/fixtures/SoftLayer_Event_Log.py index 8d9ce1e4a..840e84890 100644 --- a/SoftLayer/fixtures/SoftLayer_Event_Log.py +++ b/SoftLayer/fixtures/SoftLayer_Event_Log.py @@ -1,22 +1,164 @@ getAllObjects = [ { - "accountId": 1234, - "eventCreateDate": "2018-05-15T14:37:13.378291-06:00", - "eventName": "Login Successful", - "ipAddress": "1.2.3.4", - "label": "sl1234-aaa", - "metaData": "", - "objectId": 6657767, - "objectName": "User", - "openIdConnectUserName": "a@b.com", - "resource": { - "accountId": 307608, - "address1": "4849 Alpha Rd", - "city": "Dallas" - }, - "traceId": "5afb44f95c61f", - "userId": 6657767, - "userType": "CUSTOMER", - "username": "sl1234-aaa" + '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' + } +] + +getAllEventObjectNames = [ + { + 'value': "Account" + }, + { + 'value': "CDN" + }, + { + 'value': "User" + }, + { + 'value': "Bare Metal Instance" + }, + { + 'value': "API Authentication" + }, + { + 'value': "Server" + }, + { + 'value': "CCI" + }, + { + 'value': "Image" + }, + { + 'value': "Bluemix LB" + }, + { + 'value': "Facility" + }, + { + 'value': "Cloud Object Storage" + }, + { + 'value': "Security Group" } ] diff --git a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py index aa202ab9c..8d4b73283 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py +++ b/SoftLayer/fixtures/SoftLayer_Network_SecurityGroup.py @@ -39,8 +39,15 @@ 'createDate': '2017-05-05T12:44:43-06:00'} editObject = True deleteObject = True -addRules = True -editRules = True -removeRules = True -attachNetworkComponents = True -detachNetworkComponents = True +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/SoftLayer/managers/__init__.py b/SoftLayer/managers/__init__.py index 02e54b30e..d93b810de 100644 --- a/SoftLayer/managers/__init__.py +++ b/SoftLayer/managers/__init__.py @@ -11,6 +11,7 @@ from SoftLayer.managers.cdn import CDNManager from SoftLayer.managers.dedicated_host import DedicatedHostManager 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 @@ -36,6 +37,7 @@ 'CDNManager', 'DedicatedHostManager', '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..4e37e6d67 --- /dev/null +++ b/SoftLayer/managers/event_log.py @@ -0,0 +1,104 @@ +""" + SoftLayer.event_log + ~~~~~~~~~~~~~~~~~ + Network Manager/helpers + + :license: MIT, see LICENSE for more details. +""" + +from SoftLayer import utils + + +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.event_log = client['Event_Log'] + + 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.event_log.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.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 4223143ae..48edbefa7 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', @@ -544,6 +547,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 96efac342..5c68f7c49 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 new file mode 100644 index 000000000..a7ff0dcb1 --- /dev/null +++ b/tests/CLI/modules/event_log_tests.py @@ -0,0 +1,372 @@ +""" + SoftLayer.tests.CLI.modules.event_log_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + :license: MIT, see LICENSE for more details. +""" + +import json + +from SoftLayer.CLI import formatting +from SoftLayer import testing + + +class EventLogTests(testing.TestCase): + def test_get_event_log_with_metadata(self): + expected = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'object': 'test.softlayer.com', + 'username': 'SYSTEM', + 'type': 'CCI', + 'metadata': '' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"100"}],"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba",' + '"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"2abda7ca97e5a1444cae0b9",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"6b9a87a9ab8ac9a22e87a00"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"0a293c1c3e59e4471da6495",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + } + ] + + result = self.run_command(['event-log', 'get', '--metadata']) + + self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) + + def test_get_event_log_without_metadata(self): + expected = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'username': 'SYSTEM', + 'type': 'CCI', + 'object': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'username': 'SL12345-test', + 'type': 'CCI', + 'object': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'username': 'SL12345-test', + 'type': 'CCI', + 'object': 'test.softlayer.com' + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'object': 'test_SG' + } + ] + + result = self.run_command(['event-log', 'get']) + + self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) + + def test_get_event_table(self): + table_fix = formatting.Table(['event', 'object', 'type', 'date', 'username', 'metadata']) + table_fix.align['metadata'] = "l" + expected = [ + { + 'date': '2017-10-23T14:22:36.221541-05:00', + 'event': 'Disable Port', + 'object': 'test.softlayer.com', + 'username': 'SYSTEM', + 'type': 'CCI', + 'metadata': '' + }, + { + 'date': '2017-10-18T09:40:41.830338-05:00', + 'event': 'Security Group Rule Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"53d0b91d392864e062f4958",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"100"}],"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T09:40:32.238869-05:00', + 'event': 'Security Group Added', + 'object': 'test.softlayer.com', + 'username': 'SL12345-test', + 'type': 'CCI', + 'metadata': json.dumps(json.loads( + '{"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"96c9b47b9e102d2e1d81fba",' + '"securityGroupId":"200",' + '"securityGroupName":"test_SG"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:13.089536-05:00', + 'event': 'Security Group Rule(s) Removed', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"2abda7ca97e5a1444cae0b9",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:42:11.679736-05:00', + 'event': 'Network Component Removed from Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"6b9a87a9ab8ac9a22e87a00"}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:49.802498-05:00', + 'event': 'Security Group Rule(s) Added', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"requestId":"0a293c1c3e59e4471da6495",' + '"rules":[{"direction":"ingress",' + '"ethertype":"IPv4",' + '"portRangeMax":2001,"portRangeMin":2000,"protocol":"tcp",' + '"remoteGroupId":null,"remoteIp":null,"ruleId":"800"}]}' + ), + indent=4, + sort_keys=True + ) + }, + { + 'date': '2017-10-18T10:41:42.176328-05:00', + 'event': 'Network Component Added to Security Group', + 'object': 'test_SG', + 'username': 'SL12345-test', + 'type': 'Security Group', + 'metadata': json.dumps(json.loads( + '{"fullyQualifiedDomainName":"test.softlayer.com",' + '"networkComponentId":"100",' + '"networkInterfaceType":"public",' + '"requestId":"4709e02ad42c83f80345904"}' + ), + indent=4, + sort_keys=True + ) + } + ] + + for log in expected: + table_fix.add_row([log['event'], log['object'], log['type'], log['date'], + log['username'], log['metadata'].strip("{}\n\t")]) + expected_output = formatting.format_output(table_fix) + '\n' + + result = self.run_command(args=['event-log', 'get', '--metadata'], fmt='table') + + self.assert_no_fail(result) + self.assertEqual(expected_output, result.output) + + def test_get_event_log_empty(self): + mock = self.set_mock('SoftLayer_Event_Log', 'getAllObjects') + mock.return_value = None + + result = self.run_command(['event-log', 'get']) + + self.assertEqual(mock.call_count, 1) + self.assert_no_fail(result) + self.assertEqual('"None available."\n', result.output) + + def test_get_event_log_types(self): + expected = [ + { + "types": {"value": "Account"} + }, + { + "types": {"value": "CDN"} + }, + { + "types": {"value": "User"} + }, + { + "types": {"value": "Bare Metal Instance"} + }, + { + "types": {"value": "API Authentication"} + }, + { + "types": {"value": "Server"} + }, + { + "types": {"value": "CCI"} + }, + { + "types": {"value": "Image"} + }, + { + "types": {"value": "Bluemix LB"} + }, + { + "types": {"value": "Facility"} + }, + { + "types": {"value": "Cloud Object Storage"} + }, + { + "types": {"value": "Security Group"} + } + ] + + result = self.run_command(['event-log', 'types']) + + self.assert_no_fail(result) + self.assertEqual(expected, json.loads(result.output)) diff --git a/tests/CLI/modules/securitygroup_tests.py b/tests/CLI/modules/securitygroup_tests.py index 9b7e4c6a7..4ce0cd564 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']) @@ -127,11 +132,21 @@ def test_securitygroup_rule_add(self): result = self.run_command(['sg', 'rule-add', '100', '--direction=ingress']) + 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", + "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') fixture.return_value = False @@ -151,6 +166,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 @@ -168,6 +185,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') @@ -205,6 +224,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') @@ -225,6 +246,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') @@ -234,3 +257,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', 'event-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 e78b91f1a..f9f5ed308 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 @@ -466,3 +468,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)