|
1 |
| -"""NetBox configuration file.""" |
| 1 | +"""NetBox configuration.""" |
2 | 2 | import os
|
| 3 | +from distutils.util import strtobool |
| 4 | +from packaging import version |
| 5 | +from django.core.exceptions import ImproperlyConfigured |
| 6 | +from .settings import VERSION # pylint: disable=relative-beyond-top-level |
| 7 | + |
| 8 | + |
| 9 | +NETBOX_RELEASE_CURRENT = version.parse(VERSION) |
| 10 | +NETBOX_RELEASE_28 = version.parse("2.8") |
| 11 | +NETBOX_RELEASE_29 = version.parse("2.9") |
| 12 | +NETBOX_RELEASE_211 = version.parse("2.11") |
| 13 | + |
| 14 | +# Enforce required configuration parameters |
| 15 | +for key in [ |
| 16 | + "ALLOWED_HOSTS", |
| 17 | + "POSTGRES_DB", |
| 18 | + "POSTGRES_USER", |
| 19 | + "POSTGRES_HOST", |
| 20 | + "POSTGRES_PASSWORD", |
| 21 | + "REDIS_HOST", |
| 22 | + "REDIS_PASSWORD", |
| 23 | + "SECRET_KEY", |
| 24 | +]: |
| 25 | + if not os.environ.get(key): |
| 26 | + raise ImproperlyConfigured(f"Required environment variable {key} is missing.") |
| 27 | + |
| 28 | + |
| 29 | +def is_truthy(arg): |
| 30 | + """Convert "truthy" strings into Booleans. |
| 31 | +
|
| 32 | + Examples: |
| 33 | + >>> is_truthy('yes') |
| 34 | + True |
| 35 | + Args: |
| 36 | + arg (str): Truthy string (True values are y, yes, t, true, on and 1; false values are n, no, |
| 37 | + f, false, off and 0. Raises ValueError if val is anything else. |
| 38 | + """ |
| 39 | + if isinstance(arg, bool): |
| 40 | + return arg |
| 41 | + |
| 42 | + try: |
| 43 | + bool_val = strtobool(arg) |
| 44 | + except ValueError: |
| 45 | + raise ImproperlyConfigured(f"Unexpected variable value: {arg}") # pylint: disable=raise-missing-from |
| 46 | + |
| 47 | + return bool(bool_val) |
| 48 | + |
3 | 49 |
|
4 | 50 | # For reference see http://netbox.readthedocs.io/en/latest/configuration/mandatory-settings/
|
5 | 51 | # Based on https://github.com/digitalocean/netbox/blob/develop/netbox/netbox/configuration.example.py
|
|
16 | 62 | # access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name.
|
17 | 63 | #
|
18 | 64 | # Example: ALLOWED_HOSTS = ['netbox.example.com', 'netbox.internal.local']
|
19 |
| -ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "").split(" ") |
| 65 | +ALLOWED_HOSTS = os.environ["ALLOWED_HOSTS"].split(" ") |
20 | 66 |
|
21 | 67 | # PostgreSQL database configuration.
|
22 | 68 | DATABASE = {
|
23 |
| - "NAME": os.environ.get("DB_NAME", "netbox"), # Database name |
24 |
| - "USER": os.environ.get("DB_USER", ""), # PostgreSQL username |
25 |
| - "PASSWORD": os.environ.get("DB_PASSWORD", ""), |
| 69 | + "NAME": os.environ["POSTGRES_DB"], # Database name |
| 70 | + "USER": os.environ["POSTGRES_USER"], # PostgreSQL username |
| 71 | + "PASSWORD": os.environ["POSTGRES_PASSWORD"], |
26 | 72 | # PostgreSQL password
|
27 |
| - "HOST": os.environ.get("DB_HOST", "localhost"), # Database server |
28 |
| - "PORT": os.environ.get("DB_PORT", ""), # Database port (leave blank for default) |
| 73 | + "HOST": os.environ["POSTGRES_HOST"], # Database server |
| 74 | + "PORT": 5432 if "POSTGRES_PORT" not in os.environ else int(os.environ["POSTGRES_PORT"]), # Database port |
29 | 75 | }
|
30 | 76 |
|
31 | 77 | # This key is used for secure generation of random numbers and strings. It must never be exposed outside of this file.
|
32 | 78 | # For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and
|
33 | 79 | # symbols. NetBox will not run without this defined. For more information, see
|
34 | 80 | # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY
|
35 |
| -SECRET_KEY = os.environ.get("SECRET_KEY", "") |
| 81 | +SECRET_KEY = os.environ["SECRET_KEY"] |
36 | 82 |
|
37 | 83 | # Redis database settings. The Redis database is used for caching and background processing such as webhooks
|
38 | 84 | # Seperate sections for webhooks and caching allow for connecting to seperate Redis instances/datbases if desired.
|
39 | 85 | # Full connection details are required in both sections, even if they are the same.
|
40 | 86 | REDIS = {
|
41 | 87 | "caching": {
|
42 |
| - "HOST": os.environ.get("REDIS_HOST", "redis"), |
| 88 | + "HOST": os.environ["REDIS_HOST"], |
43 | 89 | "PORT": int(os.environ.get("REDIS_PORT", 6379)),
|
44 |
| - "PASSWORD": os.environ.get("REDIS_PASSWORD", ""), |
| 90 | + "PASSWORD": os.environ["REDIS_PASSWORD"], |
45 | 91 | "DATABASE": 1,
|
46 |
| - "SSL": bool(os.environ.get("REDIS_SSL", False)), |
| 92 | + "SSL": is_truthy(os.environ.get("REDIS_SSL", False)), |
47 | 93 | },
|
48 | 94 | "tasks": {
|
49 |
| - "HOST": os.environ.get("REDIS_HOST", "redis"), |
| 95 | + "HOST": os.environ["REDIS_HOST"], |
50 | 96 | "PORT": int(os.environ.get("REDIS_PORT", 6379)),
|
51 |
| - "PASSWORD": os.environ.get("REDIS_PASSWORD", ""), |
| 97 | + "PASSWORD": os.environ["REDIS_PASSWORD"], |
52 | 98 | "DATABASE": 0,
|
53 |
| - "SSL": bool(os.environ.get("REDIS_SSL", False)), |
| 99 | + "SSL": is_truthy(os.environ.get("REDIS_SSL", False)), |
54 | 100 | },
|
55 | 101 | }
|
56 | 102 |
|
57 |
| -RQ_DEFAULT_TIMEOUT = 300 |
58 |
| - |
| 103 | +if NETBOX_RELEASE_28 < NETBOX_RELEASE_CURRENT < NETBOX_RELEASE_29: |
| 104 | + # NetBox 2.8.x Specific Settings |
| 105 | + REDIS["caching"]["DEFAULT_TIMEOUT"] = 300 |
| 106 | + REDIS["tasks"]["DEFAULT_TIMEOUT"] = 300 |
| 107 | +elif NETBOX_RELEASE_CURRENT < NETBOX_RELEASE_211: |
| 108 | + RQ_DEFAULT_TIMEOUT = 300 |
| 109 | +else: |
| 110 | + raise ImproperlyConfigured(f"Version {NETBOX_RELEASE_CURRENT} of NetBox is unsupported at this time.") |
59 | 111 |
|
60 | 112 | #########################
|
61 | 113 | # #
|
|
71 | 123 |
|
72 | 124 | # Optionally display a persistent banner at the top and/or bottom of every page. HTML is allowed. To display the same
|
73 | 125 | # content in both banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP.
|
74 |
| -BANNER_TOP = os.environ.get("BANNER_TOP", None) |
75 |
| -BANNER_BOTTOM = os.environ.get("BANNER_BOTTOM", None) |
| 126 | +BANNER_TOP = os.environ.get("BANNER_TOP", "") |
| 127 | +BANNER_BOTTOM = os.environ.get("BANNER_BOTTOM", "") |
76 | 128 |
|
77 | 129 | # Text to include on the login page above the login form. HTML is allowed.
|
78 | 130 | BANNER_LOGIN = os.environ.get("BANNER_LOGIN", "")
|
|
87 | 139 | # API Cross-Origin Resource Sharing (CORS) settings. If CORS_ORIGIN_ALLOW_ALL is set to True, all origins will be
|
88 | 140 | # allowed. Otherwise, define a list of allowed origins using either CORS_ORIGIN_WHITELIST or
|
89 | 141 | # CORS_ORIGIN_REGEX_WHITELIST. For more information, see https://github.com/ottoyiu/django-cors-headers
|
90 |
| -CORS_ORIGIN_ALLOW_ALL = True |
| 142 | +CORS_ORIGIN_ALLOW_ALL = is_truthy(os.environ.get("CORS_ORIGIN_ALLOW_ALL", False)) |
91 | 143 | CORS_ORIGIN_WHITELIST = []
|
92 | 144 | CORS_ORIGIN_REGEX_WHITELIST = []
|
93 | 145 |
|
94 | 146 | # Set to True to enable server debugging. WARNING: Debugging introduces a substantial performance penalty and may reveal
|
95 | 147 | # sensitive information about your installation. Only enable debugging while performing testing. Never enable debugging
|
96 | 148 | # on a production system.
|
97 |
| -DEBUG = True |
98 |
| -DEVELOPER = True |
| 149 | +DEBUG = is_truthy(os.environ.get("DEBUG", False)) |
| 150 | +DEVELOPER = is_truthy(os.environ.get("DEVELOPER", False)) |
99 | 151 |
|
100 | 152 | # Email settings
|
101 | 153 | EMAIL = {
|
102 |
| - "SERVER": "localhost", |
103 |
| - "PORT": 25, |
104 |
| - "USERNAME": "", |
105 |
| - "PASSWORD": "", |
106 |
| - "TIMEOUT": 10, |
107 |
| - "FROM_EMAIL": "", |
| 154 | + "SERVER": os.environ.get("EMAIL_SERVER", "localhost"), |
| 155 | + "PORT": int(os.environ.get("EMAIL_PORT", 25)), |
| 156 | + "USERNAME": os.environ.get("EMAIL_USERNAME", ""), |
| 157 | + "PASSWORD": os.environ.get("EMAIL_PASSWORD", ""), |
| 158 | + "TIMEOUT": int(os.environ.get("EMAIL_TIMEOUT", 10)), # seconds |
| 159 | + "FROM_EMAIL": os.environ.get("EMAIL_FROM", ""), |
108 | 160 | }
|
109 | 161 |
|
110 | 162 | # Enforcement of unique IP space can be toggled on a per-VRF basis.
|
111 | 163 | # To enforce unique IP space within the global table (all prefixes and IP addresses not assigned to a VRF),
|
112 | 164 | # set ENFORCE_GLOBAL_UNIQUE to True.
|
113 |
| -ENFORCE_GLOBAL_UNIQUE = False |
| 165 | +ENFORCE_GLOBAL_UNIQUE = is_truthy(os.environ.get("ENFORCE_GLOBAL_UNIQUE", False)) |
| 166 | + |
| 167 | +# HTTP proxies NetBox should use when sending outbound HTTP requests (e.g. for webhooks). |
| 168 | +# HTTP_PROXIES = { |
| 169 | +# "http": "http://192.0.2.1:3128", |
| 170 | +# "https": "http://192.0.2.1:1080", |
| 171 | +# } |
| 172 | + |
| 173 | +# IP addresses recognized as internal to the system. The debugging toolbar will be available only to clients accessing |
| 174 | +# NetBox from an internal IP. |
| 175 | +INTERNAL_IPS = ("127.0.0.1", "::1") |
| 176 | + |
| 177 | +LOG_LEVEL = os.environ.get("LOG_LEVEL", "DEBUG" if DEBUG else "INFO") |
114 | 178 |
|
115 | 179 | # Enable custom logging. Please see the Django documentation for detailed guidance on configuring custom logs:
|
116 | 180 | # https://docs.djangoproject.com/en/1.11/topics/logging/
|
117 | 181 | LOGGING = {
|
118 | 182 | "version": 1,
|
119 | 183 | "disable_existing_loggers": False,
|
120 |
| - "formatters": {"rq_console": {"format": "%(asctime)s %(message)s", "datefmt": "%H:%M:%S",},}, |
121 |
| - "handlers": { |
122 |
| - "rq_console": { |
123 |
| - "level": "DEBUG", |
124 |
| - "class": "rq.utils.ColorizingStreamHandler", |
125 |
| - "formatter": "rq_console", |
126 |
| - "exclude": ["%(asctime)s"], |
| 184 | + "formatters": { |
| 185 | + "verbose": { |
| 186 | + "format": "{asctime} {levelname} {message} - {name} - {module} - {pathname}:{lineno}", |
| 187 | + "datefmt": "%H:%M:%S", |
| 188 | + "style": "{", |
127 | 189 | },
|
128 | 190 | },
|
129 |
| - "loggers": {"rq.worker": {"handlers": ["rq_console"], "level": "DEBUG"},}, |
| 191 | + "handlers": {"console": {"level": "DEBUG", "class": "rq.utils.ColorizingStreamHandler", "formatter": "verbose"}}, |
| 192 | + "root": {"handlers": ["console"], "level": LOG_LEVEL}, |
130 | 193 | }
|
131 | 194 |
|
132 | 195 | # Setting this to True will permit only authenticated users to access any part of NetBox. By default, anonymous users
|
133 | 196 | # are permitted to access most data in NetBox (excluding secrets) but not make any changes.
|
134 |
| -LOGIN_REQUIRED = False |
135 |
| - |
136 |
| -# Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set: |
137 |
| -# BASE_PATH = 'netbox/' |
138 |
| -BASE_PATH = os.environ.get("BASE_PATH", "") |
| 197 | +LOGIN_REQUIRED = is_truthy(os.environ.get("LOGIN_REQUIRED", False)) |
139 | 198 |
|
140 | 199 | # Setting this to True will display a "maintenance mode" banner at the top of every page.
|
141 |
| -MAINTENANCE_MODE = os.environ.get("MAINTENANCE_MODE", False) |
| 200 | +MAINTENANCE_MODE = is_truthy(os.environ.get("MAINTENANCE_MODE", False)) |
142 | 201 |
|
143 | 202 | # An API consumer can request an arbitrary number of objects =by appending the "limit" parameter to the URL (e.g.
|
144 | 203 | # "?limit=1000"). This setting defines the maximum limit. Setting it to 0 or None will allow an API consumer to request
|
|
149 | 208 | # the default value of this setting is derived from the installed location.
|
150 | 209 | MEDIA_ROOT = os.environ.get("MEDIA_ROOT", os.path.join(BASE_DIR, "media"))
|
151 | 210 |
|
| 211 | +# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics' |
| 212 | +METRICS_ENABLED = True |
| 213 | + |
152 | 214 | NAPALM_USERNAME = os.environ.get("NAPALM_USERNAME", "")
|
153 | 215 | NAPALM_PASSWORD = os.environ.get("NAPALM_PASSWORD", "")
|
154 | 216 |
|
155 | 217 | # NAPALM timeout (in seconds). (Default: 30)
|
156 |
| -NAPALM_TIMEOUT = os.environ.get("NAPALM_TIMEOUT", 30) |
| 218 | +NAPALM_TIMEOUT = int(os.environ.get("NAPALM_TIMEOUT", 30)) |
157 | 219 |
|
158 | 220 | # NAPALM optional arguments (see http://napalm.readthedocs.io/en/latest/support/#optional-arguments). Arguments must
|
159 | 221 | # be provided as a dictionary.
|
|
163 | 225 | }
|
164 | 226 |
|
165 | 227 | # Determine how many objects to display per page within a list. (Default: 50)
|
166 |
| -PAGINATE_COUNT = os.environ.get("PAGINATE_COUNT", 50) |
| 228 | +PAGINATE_COUNT = int(os.environ.get("PAGINATE_COUNT", 50)) |
167 | 229 |
|
168 | 230 | # Enable installed plugins. Add the name of each plugin to the list.
|
169 | 231 | PLUGINS = ["netbox_onboarding"]
|
170 | 232 |
|
171 |
| -PLUGINS_CONFIG = {"netbox_onboarding": {}} |
172 | 233 | # Plugins configuration settings. These settings are used by various plugins that the user may have installed.
|
173 | 234 | # Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
|
174 |
| -# PLUGINS_CONFIG = {} |
| 235 | +PLUGINS_CONFIG = {} |
175 | 236 |
|
176 | 237 | # When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
|
177 | 238 | # prefer IPv4 instead.
|
178 |
| -PREFER_IPV4 = os.environ.get("PREFER_IPV4", False) |
| 239 | +PREFER_IPV4 = is_truthy(os.environ.get("PREFER_IPV4", False)) |
179 | 240 |
|
180 | 241 | # Remote authentication support
|
181 | 242 | REMOTE_AUTH_ENABLED = False
|
182 |
| -REMOTE_AUTH_BACKEND = "netbox.authentication.RemoteUserBackend" |
183 | 243 | REMOTE_AUTH_HEADER = "HTTP_REMOTE_USER"
|
184 | 244 | REMOTE_AUTH_AUTO_CREATE_USER = True
|
185 | 245 | REMOTE_AUTH_DEFAULT_GROUPS = []
|
186 |
| -REMOTE_AUTH_DEFAULT_PERMISSIONS = {} |
| 246 | + |
| 247 | +if NETBOX_RELEASE_28 < NETBOX_RELEASE_CURRENT < NETBOX_RELEASE_29: |
| 248 | + # NetBox 2.8.x Specific Settings |
| 249 | + REMOTE_AUTH_BACKEND = "utilities.auth_backends.RemoteUserBackend" |
| 250 | + REMOTE_AUTH_DEFAULT_PERMISSIONS = [] |
| 251 | +elif NETBOX_RELEASE_CURRENT < NETBOX_RELEASE_211: |
| 252 | + REMOTE_AUTH_BACKEND = "netbox.authentication.RemoteUserBackend" |
| 253 | + REMOTE_AUTH_DEFAULT_PERMISSIONS = {} |
| 254 | +else: |
| 255 | + raise ImproperlyConfigured(f"Version {NETBOX_RELEASE_CURRENT} of NetBox is unsupported at this time.") |
187 | 256 |
|
188 | 257 | # This determines how often the GitHub API is called to check the latest release of NetBox. Must be at least 1 hour.
|
189 | 258 | RELEASE_CHECK_TIMEOUT = 24 * 3600
|
|
199 | 268 | # this setting is derived from the installed location.
|
200 | 269 | REPORTS_ROOT = os.environ.get("REPORTS_ROOT", os.path.join(BASE_DIR, "reports"))
|
201 | 270 |
|
| 271 | +# The file path where custom scripts will be stored. A trailing slash is not needed. Note that the default value of |
| 272 | +# this setting is derived from the installed location. |
| 273 | +SCRIPTS_ROOT = os.environ.get("SCRIPTS_ROOT", os.path.join(BASE_DIR, "scripts")) |
| 274 | + |
202 | 275 | # Time zone (default: UTC)
|
203 | 276 | TIME_ZONE = os.environ.get("TIME_ZONE", "UTC")
|
204 | 277 |
|
|
0 commit comments