diff --git a/util/audit.py b/util/audit.py index 3a6132d27..903100b72 100644 --- a/util/audit.py +++ b/util/audit.py @@ -5,7 +5,7 @@ from urlparse import urlparse from flask import request -from app import analytics, userevents +from app import analytics, userevents, ip_resolver from data import model from auth.registry_jwt_auth import get_granted_entity from auth.auth_context import (get_authenticated_user, get_validated_token, @@ -85,6 +85,11 @@ def track_and_log(event_name, repo_obj, analytics_name=None, analytics_sample=1, analytics.track(analytics_id, analytics_name, extra_params) + # Add the resolved information to the metadata. + resolved_ip = ip_resolver.resolve_ip(request.remote_addr) + if resolved_ip is not None: + metadata['resolved_ip'] = resolved_ip._asdict() + # Log the action to the database. logger.debug('Logging the %s to logs system', event_name) model.log.log_action(event_name, namespace_name, performer=authenticated_user, diff --git a/util/ipresolver/__init__.py b/util/ipresolver/__init__.py index 270ff6074..7ecd106cb 100644 --- a/util/ipresolver/__init__.py +++ b/util/ipresolver/__init__.py @@ -1,5 +1,6 @@ import logging import json +import requests from cachetools import ttl_cache, lru_cache from collections import namedtuple, defaultdict @@ -12,6 +13,21 @@ ResolvedLocation = namedtuple('ResolvedLocation', ['provider', 'region', 'servic logger = logging.getLogger(__name__) +_DATA_FILES = {'aws-ip-ranges.json': 'https://ip-ranges.amazonaws.com/ip-ranges.json'} + +def update_resolver_datafiles(): + """ Performs an update of the data file(s) used by the IP Resolver. """ + for filename, url in _DATA_FILES.iteritems(): + logger.debug('Updating IP resolver data file "%s" from URL "%s"', filename, url) + with open('util/ipresolver/%s' % filename, 'w') as f: + response = requests.get(url) + logger.debug('Got %s response for URL %s', response.status_code, url) + if response.status_code / 2 != 100: + raise Exception('Got non-2XX status code for URL %s: %s' % (url, response.status_code)) + + f.write(response.text) + logger.debug('Successfully wrote %s', filename) + class IPResolver(object): def __init__(self, app, *args, **kwargs): self.app = app @@ -30,20 +46,20 @@ class IPResolver(object): @ttl_cache(maxsize=1, ttl=600) def _get_location_function(self): try: - with open('util/ipresolver/ip-ranges.json', 'r') as f: - ip_range_json = json.loads(f.read()) + with open('util/ipresolver/aws-ip-ranges.json', 'r') as f: + aws_ip_range_json = json.loads(f.read()) except IOError: - logger.exception('Could not load IP Ranges') + logger.exception('Could not load AWS IP Ranges') return None except ValueError: - logger.exception('Could not load IP Ranges') + logger.exception('Could not load AWS IP Ranges') return None except TypeError: - logger.exception('Could not load IP Ranges') + logger.exception('Could not load AWS IP Ranges') return None - sync_token = ip_range_json['syncToken'] - all_amazon, regions, services = IPResolver._parse_amazon_ranges(ip_range_json) + sync_token = aws_ip_range_json['syncToken'] + all_amazon, regions, services = IPResolver._parse_amazon_ranges(aws_ip_range_json) return IPResolver._build_location_function(sync_token, all_amazon, regions, services, self.geoip_db) @staticmethod