Browse Source

Fixes #843: Implemented CORS headers for API

Jeremy Stretch 8 years ago
parent
commit
7ba6e320e7

+ 16 - 0
docs/configuration/optional-settings.md

@@ -38,6 +38,22 @@ BASE_PATH = 'netbox/'
 
 ---
 
+## CORS_ORIGIN_ALLOW_ALL
+
+Default: False
+
+If True, cross-origin resource sharing (CORS) requests will be accepted from all origins. If False, a whitelist will be used (see below).
+
+---
+
+## CORS_ORIGIN_WHITELIST
+
+## CORS_ORIGIN_REGEX_WHITELIST
+
+These settings specify a list of origins that are authorized to make cross-site API requests. Use `CORS_ORIGIN_WHITELIST` to define a list of exact hostnames, or `CORS_ORIGIN_REGEX_WHITELIST` to define a set of regular expressions. (These settings have no effect if `CORS_ORIGIN_ALLOW_ALL` is True.)
+
+---
+
 ## DEBUG
 
 Default: False

+ 29 - 18
netbox/netbox/configuration.example.py

@@ -38,6 +38,26 @@ ADMINS = [
     # ['John Doe', 'jdoe@example.com'],
 ]
 
+# Optionally display a persistent banner at the top and/or bottom of every page. To display the same content in both
+# banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP.
+BANNER_TOP = ''
+BANNER_BOTTOM = ''
+
+# Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set:
+# BASE_PATH = 'netbox/'
+BASE_PATH = ''
+
+# API Cross-Origin Resource Sharing (CORS) settings. If CORS_ORIGIN_ALLOW_ALL is set to True, all origins will be
+# allowed. Otherwise, define a list of allowed origins using either CORS_ORIGIN_WHITELIST or
+# CORS_ORIGIN_REGEX_WHITELIST. For more information, see https://github.com/ottoyiu/django-cors-headers
+CORS_ORIGIN_ALLOW_ALL = False
+CORS_ORIGIN_WHITELIST = [
+    # 'hostname.example.com',
+]
+CORS_ORIGIN_REGEX_WHITELIST = [
+    # r'^(https?://)?(\w+\.)?example\.com$',
+]
+
 # Email settings
 EMAIL = {
     'SERVER': 'localhost',
@@ -48,24 +68,28 @@ EMAIL = {
     'FROM_EMAIL': '',
 }
 
+# Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce unique IP space within the global table
+# (all prefixes and IP addresses not assigned to a VRF), set ENFORCE_GLOBAL_UNIQUE to True.
+ENFORCE_GLOBAL_UNIQUE = False
+
 # Setting this to True will permit only authenticated users to access any part of NetBox. By default, anonymous users
 # are permitted to access most data in NetBox (excluding secrets) but not make any changes.
 LOGIN_REQUIRED = False
 
-# Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set:
-# BASE_PATH = 'netbox/'
-BASE_PATH = ''
-
 # Setting this to True will display a "maintenance mode" banner at the top of every page.
 MAINTENANCE_MODE = False
 
-# Credentials that NetBox will use to access live devices.
+# Credentials that NetBox will use to access live devices (future use).
 NETBOX_USERNAME = ''
 NETBOX_PASSWORD = ''
 
 # Determine how many objects to display per page within a list. (Default: 50)
 PAGINATE_COUNT = 50
 
+# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
+# prefer IPv4 instead.
+PREFER_IPV4 = False
+
 # Time zone (default: UTC)
 TIME_ZONE = 'UTC'
 
@@ -77,16 +101,3 @@ TIME_FORMAT = 'g:i a'
 SHORT_TIME_FORMAT = 'H:i:s'
 DATETIME_FORMAT = 'N j, Y g:i a'
 SHORT_DATETIME_FORMAT = 'Y-m-d H:i'
-
-# Optionally display a persistent banner at the top and/or bottom of every page. To display the same content in both
-# banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP.
-BANNER_TOP = ''
-BANNER_BOTTOM = ''
-
-# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
-# prefer IPv4 instead.
-PREFER_IPV4 = False
-
-# Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce unique IP space within the global table
-# (all prefixes and IP addresses not assigned to a VRF), set ENFORCE_GLOBAL_UNIQUE to True.
-ENFORCE_GLOBAL_UNIQUE = False

+ 16 - 6
netbox/netbox/settings.py

@@ -8,19 +8,22 @@ from django.core.exceptions import ImproperlyConfigured
 try:
     from netbox import configuration
 except ImportError:
-    raise ImproperlyConfigured("Configuration file is not present. Please define netbox/netbox/configuration.py per "
-                               "the documentation.")
+    raise ImproperlyConfigured(
+        "Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation."
+    )
 
 
 VERSION = '2.0.0-dev'
 
 # Import local configuration
+ALLOWED_HOSTS = DATABASE = SECRET_KEY = None
 for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
     try:
         globals()[setting] = getattr(configuration, setting)
     except AttributeError:
-        raise ImproperlyConfigured("Mandatory setting {} is missing from configuration.py. Please define it per the "
-                                   "documentation.".format(setting))
+        raise ImproperlyConfigured(
+            "Mandatory setting {} is missing from configuration.py.".format(setting)
+        )
 
 # Default configurations
 ADMINS = getattr(configuration, 'ADMINS', [])
@@ -45,6 +48,9 @@ BANNER_TOP = getattr(configuration, 'BANNER_TOP', False)
 BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', False)
 PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
 ENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)
+CORS_ORIGIN_ALLOW_ALL = getattr(configuration, 'CORS_ORIGIN_ALLOW_ALL', False)
+CORS_ORIGIN_WHITELIST = getattr(configuration, 'CORS_ORIGIN_WHITELIST', [])
+CORS_ORIGIN_REGEX_WHITELIST = getattr(configuration, 'CORS_ORIGIN_REGEX_WHITELIST', [])
 CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
 
 # Attempt to import LDAP configuration if it has been defined
@@ -73,8 +79,10 @@ if LDAP_CONFIGURED:
         logger.addHandler(logging.StreamHandler())
         logger.setLevel(logging.DEBUG)
     except ImportError:
-        raise ImproperlyConfigured("LDAP authentication has been configured, but django-auth-ldap is not installed. "
-                                   "You can remove netbox/ldap_config.py to disable LDAP.")
+        raise ImproperlyConfigured(
+            "LDAP authentication has been configured, but django-auth-ldap is not installed. You can remove "
+            "netbox/ldap_config.py to disable LDAP."
+        )
 
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
@@ -102,6 +110,7 @@ INSTALLED_APPS = (
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'django.contrib.humanize',
+    'corsheaders',
     'debug_toolbar',
     'django_tables2',
     'mptt',
@@ -120,6 +129,7 @@ INSTALLED_APPS = (
 # Middleware
 MIDDLEWARE = (
     'debug_toolbar.middleware.DebugToolbarMiddleware',
+    'corsheaders.middleware.CorsMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',

+ 1 - 0
requirements.txt

@@ -1,6 +1,7 @@
 cffi>=1.8
 cryptography>=1.4
 Django>=1.10
+django-cors-headers>=2.0
 django-debug-toolbar>=1.6
 django-filter>=1.0.1
 django-mptt==0.8.7