Jeremy Stretch 4 месяцев назад
Родитель
Сommit
917a2c2618

+ 10 - 0
netbox/netbox/configuration_example.py

@@ -68,6 +68,16 @@ REDIS = {
 # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY
 # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY
 SECRET_KEY = ''
 SECRET_KEY = ''
 
 
+# Define a mapping of cryptographic peppers to use when hashing API tokens. A minimum of one pepper is required to
+# enable v2 API tokens (NetBox v4.5+). Define peppers as a mapping of numeric ID to pepper value, as shown below. Each
+# pepper must be at least 50 characters in length.
+#
+#     API_TOKEN_PEPPERS = {
+#         1: "<random string>",
+#         2: "<random string>",
+#     }
+API_TOKEN_PEPPERS = {}
+
 
 
 #########################
 #########################
 #                       #
 #                       #

+ 1 - 1
netbox/netbox/configuration_testing.py

@@ -46,7 +46,7 @@ DEFAULT_PERMISSIONS = {}
 ALLOW_TOKEN_RETRIEVAL = True
 ALLOW_TOKEN_RETRIEVAL = True
 
 
 API_TOKEN_PEPPERS = {
 API_TOKEN_PEPPERS = {
-    1: 'TEST-VALUE-DO-NOT-USE',
+    1: 'TEST-VALUE-DO-NOT-USE-TEST-VALUE-DO-NOT-USE-TEST-VALUE-DO-NOT-USE',
 }
 }
 
 
 LOGGING = {
 LOGGING = {

+ 4 - 4
netbox/netbox/settings.py

@@ -19,6 +19,7 @@ from netbox.plugins import PluginConfig
 from netbox.registry import registry
 from netbox.registry import registry
 import storages.utils  # type: ignore
 import storages.utils  # type: ignore
 from utilities.release import load_release_data
 from utilities.release import load_release_data
+from utilities.security import validate_peppers
 from utilities.string import trailing_slash
 from utilities.string import trailing_slash
 
 
 #
 #
@@ -217,10 +218,9 @@ if len(SECRET_KEY) < 50:
     )
     )
 
 
 # Validate API token peppers
 # Validate API token peppers
-for key in API_TOKEN_PEPPERS:
-    if type(key) is not int:
-        raise ImproperlyConfigured(f"Invalid API_TOKEN_PEPPERS key: {key}. All keys must be integers.")
-if not API_TOKEN_PEPPERS:
+if API_TOKEN_PEPPERS:
+    validate_peppers(API_TOKEN_PEPPERS)
+else:
     warnings.warn("API_TOKEN_PEPPERS is not defined. v2 API tokens cannot be used.")
     warnings.warn("API_TOKEN_PEPPERS is not defined. v2 API tokens cannot be used.")
 
 
 # Validate update repo URL and timeout
 # Validate update repo URL and timeout

+ 24 - 0
netbox/utilities/security.py

@@ -0,0 +1,24 @@
+from django.core.exceptions import ImproperlyConfigured
+
+__all__ = (
+    'validate_peppers',
+)
+
+
+def validate_peppers(peppers):
+    """
+    Validate the given dictionary of cryptographic peppers for type & sufficient length.
+    """
+    if type(peppers) is not dict:
+        raise ImproperlyConfigured("API_TOKEN_PEPPERS must be a dictionary.")
+    for key, pepper in peppers.items():
+        if type(key) is not int:
+            raise ImproperlyConfigured(f"Invalid API_TOKEN_PEPPERS key: {key}. All keys must be integers.")
+        if not 0 <= key <= 32767:
+            raise ImproperlyConfigured(
+                f"Invalid API_TOKEN_PEPPERS key: {key}. Key values must be between 0 and 32767, inclusive."
+            )
+        if type(pepper) is not str:
+            raise ImproperlyConfigured(f"Invalid pepper {key}: Pepper value must be a string.")
+        if len(pepper) < 50:
+            raise ImproperlyConfigured(f"Invalid pepper {key}: Pepper must be at least 50 characters in length.")