netbox-config-diff 2.15.0__tar.gz → 2.15.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/PKG-INFO +1 -1
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/__init__.py +2 -1
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/secrets.py +37 -21
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/PKG-INFO +1 -1
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/SOURCES.txt +1 -0
- netbox_config_diff-2.15.1/tests/test_secrets.py +135 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/LICENSE +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/MANIFEST.in +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/README.md +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/development/configuration.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-diff.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-error.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-list.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-missing-extra.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-ok.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-patch.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/config-temp-substitute.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-approve-button.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-approved.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-collecting-diff-button.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-completed.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-created.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-diffs-tab.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-job-log.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-schedule-button.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-scheduled.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-unapprove-button.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-unschedule-button.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/navbar.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/platformsetting.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/render-temp-substitute.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/script-list.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/script.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/substitute.png +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/api/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/api/serializers.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/api/urls.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/api/views.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/choices.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/base.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/utils.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/base.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/exceptions.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/factory.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/platforms.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/utils.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/constants.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/filtersets.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/forms/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/forms/general.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/enums.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/filters.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/schema.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/types.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/jobs.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0001_initial.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0002_add_script.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0003_configcompliance_actual_config_and_more.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0004_update_script.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0005_configcompliance_extra_missing.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0006_substitute.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0007_configurationrequest.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0008_alter_configcompliance_device.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0009_configcompliance_patch.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0010_create_script.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/0011_configurationrequest_owner.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/base.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/data_models.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/models.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/navigation.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/scripts/config_diff.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/search.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/static/netbox_config_diff/diff2html-ui.min.js +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/static/netbox_config_diff/diff2html.dark.min.css +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/static/netbox_config_diff/diff2html.min.css +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/tables.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configcompliance/config.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configcompliance/data.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configcompliance/missing_extra.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configcompliance.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configurationrequest/base.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configurationrequest/diffs.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/configurationrequest.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/inc/commands_card.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/inc/diff.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/inc/job_log.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/platformsetting.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templates/netbox_config_diff/substitute.html +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templatetags/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templatetags/string_filters.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/urls.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/__init__.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/base.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/compliance.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/configuration.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/dependency_links.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/requires.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/top_level.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/pyproject.toml +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/requirements/base.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/requirements/dev.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/requirements/test.txt +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/setup.cfg +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/conftest.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/factories.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/test_compliance.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/test_compliance_utils.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/test_configurtion_request.py +0 -0
- {netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/tests/test_urls.py +0 -0
|
@@ -2,7 +2,7 @@ from netbox.plugins import PluginConfig
|
|
|
2
2
|
|
|
3
3
|
__author__ = "Artem Kotik"
|
|
4
4
|
__email__ = "miaow2@yandex.ru"
|
|
5
|
-
__version__ = "2.15.
|
|
5
|
+
__version__ = "2.15.1"
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ConfigDiffConfig(PluginConfig):
|
|
@@ -21,6 +21,7 @@ class ConfigDiffConfig(PluginConfig):
|
|
|
21
21
|
"PASSWORD_SECRET_ROLE": "Password",
|
|
22
22
|
"SECOND_AUTH_SECRET_ROLE": "Second Auth",
|
|
23
23
|
"PATH_TO_SSH_CONFIG_FILE": "",
|
|
24
|
+
"SECRETS_PRECEDENCE": ["device", "role", "platform"],
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/secrets.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import base64
|
|
2
|
+
from operator import attrgetter
|
|
2
3
|
from typing import TYPE_CHECKING
|
|
3
4
|
|
|
4
5
|
from dcim.models import Device
|
|
@@ -34,8 +35,8 @@ class SecretsMixin:
|
|
|
34
35
|
sk = SessionKey.objects.get(userkey__user=self.request.user)
|
|
35
36
|
self.master_key = sk.get_master_key(self.session_key)
|
|
36
37
|
except Exception as e:
|
|
37
|
-
if
|
|
38
|
-
if
|
|
38
|
+
if hasattr(self, "logger"):
|
|
39
|
+
if hasattr(self.logger, "log_failure"):
|
|
39
40
|
self.logger.log_failure(f"Can't fetch master_key: {str(e)}")
|
|
40
41
|
else:
|
|
41
42
|
self.logger.error(f"Can't fetch master_key: {str(e)}")
|
|
@@ -49,28 +50,42 @@ class SecretsMixin:
|
|
|
49
50
|
return None
|
|
50
51
|
return secret.plaintext
|
|
51
52
|
|
|
53
|
+
def get_secret_value(self, objects: tuple[object | None, ...], role_name: str) -> str | None:
|
|
54
|
+
for obj in objects:
|
|
55
|
+
if not obj:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
secrets = getattr(obj, "secrets", None)
|
|
59
|
+
if not secrets:
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
if secret := secrets.filter(role__name=role_name).first():
|
|
63
|
+
if value := self.get_secret(secret):
|
|
64
|
+
return value
|
|
65
|
+
|
|
66
|
+
return None
|
|
67
|
+
|
|
52
68
|
def get_credentials(self, device: Device) -> tuple[str, str, str, str]:
|
|
53
|
-
if not self.netbox_secrets_installed:
|
|
69
|
+
if not self.netbox_secrets_installed or not self.secrets_precedence:
|
|
54
70
|
return self.username, self.password, self.auth_secondary, self.default_desired_privilege_level
|
|
55
71
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
default_desired_privilege_level = self.default_desired_privilege_level
|
|
72
|
+
secret_objects: list[object] = []
|
|
73
|
+
for entry in self.secrets_precedence:
|
|
74
|
+
if entry == "device":
|
|
75
|
+
secret_objects.append(device)
|
|
76
|
+
continue
|
|
77
|
+
try:
|
|
78
|
+
secret_objects.append(attrgetter(entry)(device))
|
|
79
|
+
except AttributeError:
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
username = self.get_secret_value(secret_objects, self.user_role) or self.username
|
|
83
|
+
password = self.get_secret_value(secret_objects, self.password_role) or self.password
|
|
84
|
+
auth_secondary = self.get_secret_value(secret_objects, self.auth_secondary_role) or self.auth_secondary
|
|
85
|
+
default_desired_privilege_level = (
|
|
86
|
+
self.get_secret_value(secret_objects, self.default_desired_privilege_level_role)
|
|
87
|
+
or self.default_desired_privilege_level
|
|
88
|
+
)
|
|
74
89
|
|
|
75
90
|
return username, password, auth_secondary, default_desired_privilege_level
|
|
76
91
|
|
|
@@ -83,6 +98,7 @@ class SecretsMixin:
|
|
|
83
98
|
self.default_desired_privilege_level_role = get_plugin_config(
|
|
84
99
|
"netbox_config_diff", "DEFAULT_DESIRED_PRIVILEGE_LEVEL_ROLE"
|
|
85
100
|
)
|
|
101
|
+
self.secrets_precedence = get_plugin_config("netbox_config_diff", "SECRETS_PRECEDENCE")
|
|
86
102
|
self.netbox_secrets_installed = True
|
|
87
103
|
|
|
88
104
|
self.username = get_plugin_config("netbox_config_diff", "USERNAME")
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
|
|
3
|
+
from netbox_config_diff.compliance.secrets import SecretsMixin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DummySecretsManager:
|
|
7
|
+
def __init__(self, by_role: dict[str, object]) -> None:
|
|
8
|
+
self.by_role = by_role
|
|
9
|
+
|
|
10
|
+
def filter(self, **kwargs):
|
|
11
|
+
return SimpleNamespace(first=lambda: self.by_role.get(kwargs["role__name"]))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DummySecretsMixin(SecretsMixin):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def build_mixin() -> DummySecretsMixin:
|
|
19
|
+
mixin = DummySecretsMixin()
|
|
20
|
+
mixin.netbox_secrets_installed = True
|
|
21
|
+
mixin.username = "default-user"
|
|
22
|
+
mixin.password = "default-pass"
|
|
23
|
+
mixin.auth_secondary = "default-secondary"
|
|
24
|
+
mixin.default_desired_privilege_level = "default-priv"
|
|
25
|
+
mixin.secrets_precedence = ["device", "role", "platform"]
|
|
26
|
+
|
|
27
|
+
mixin.user_role = "user-role"
|
|
28
|
+
mixin.password_role = "password-role"
|
|
29
|
+
mixin.auth_secondary_role = "secondary-role"
|
|
30
|
+
mixin.default_desired_privilege_level_role = "priv-role"
|
|
31
|
+
return mixin
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_get_credentials_prefers_device_then_role_then_platform() -> None:
|
|
35
|
+
mixin = build_mixin()
|
|
36
|
+
|
|
37
|
+
device = SimpleNamespace(
|
|
38
|
+
secrets=DummySecretsManager(
|
|
39
|
+
{
|
|
40
|
+
"user-role": SimpleNamespace(value="device-user"),
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
role=SimpleNamespace(
|
|
44
|
+
secrets=DummySecretsManager(
|
|
45
|
+
{
|
|
46
|
+
"user-role": SimpleNamespace(value="role-user"),
|
|
47
|
+
"password-role": SimpleNamespace(value="role-pass"),
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
),
|
|
51
|
+
platform=SimpleNamespace(
|
|
52
|
+
secrets=DummySecretsManager(
|
|
53
|
+
{
|
|
54
|
+
"user-role": SimpleNamespace(value="platform-user"),
|
|
55
|
+
"password-role": SimpleNamespace(value="platform-pass"),
|
|
56
|
+
"secondary-role": SimpleNamespace(value="platform-secondary"),
|
|
57
|
+
"priv-role": SimpleNamespace(value="platform-priv"),
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
mixin.get_secret = lambda secret: secret.value
|
|
63
|
+
|
|
64
|
+
assert mixin.get_credentials(device) == (
|
|
65
|
+
"device-user",
|
|
66
|
+
"role-pass",
|
|
67
|
+
"platform-secondary",
|
|
68
|
+
"platform-priv",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_get_credentials_skips_empty_secret_value() -> None:
|
|
73
|
+
mixin = build_mixin()
|
|
74
|
+
|
|
75
|
+
device = SimpleNamespace(
|
|
76
|
+
secrets=DummySecretsManager(
|
|
77
|
+
{
|
|
78
|
+
"password-role": SimpleNamespace(value=""),
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
role=SimpleNamespace(
|
|
82
|
+
secrets=DummySecretsManager(
|
|
83
|
+
{
|
|
84
|
+
"password-role": SimpleNamespace(value="role-pass"),
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
),
|
|
88
|
+
platform=SimpleNamespace(secrets=DummySecretsManager({})),
|
|
89
|
+
)
|
|
90
|
+
mixin.get_secret = lambda secret: secret.value
|
|
91
|
+
|
|
92
|
+
username, password, auth_secondary, default_desired_privilege_level = mixin.get_credentials(device)
|
|
93
|
+
|
|
94
|
+
assert username == "default-user"
|
|
95
|
+
assert password == "role-pass"
|
|
96
|
+
assert auth_secondary == "default-secondary"
|
|
97
|
+
assert default_desired_privilege_level == "default-priv"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_get_credentials_respects_custom_precedence() -> None:
|
|
101
|
+
mixin = build_mixin()
|
|
102
|
+
|
|
103
|
+
device = SimpleNamespace(
|
|
104
|
+
secrets=DummySecretsManager(
|
|
105
|
+
{
|
|
106
|
+
"password-role": SimpleNamespace(value="device-pass"),
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
role=SimpleNamespace(
|
|
110
|
+
secrets=DummySecretsManager(
|
|
111
|
+
{
|
|
112
|
+
"user-role": SimpleNamespace(value="role-user"),
|
|
113
|
+
"password-role": SimpleNamespace(value="role-pass"),
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
),
|
|
117
|
+
platform=SimpleNamespace(
|
|
118
|
+
secrets=DummySecretsManager(
|
|
119
|
+
{
|
|
120
|
+
"user-role": SimpleNamespace(value="platform-user"),
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
mixin.get_secret = lambda secret: secret.value
|
|
126
|
+
|
|
127
|
+
# Force precedence: platform -> device -> role
|
|
128
|
+
mixin.secrets_precedence = ["platform", "device", "role"]
|
|
129
|
+
|
|
130
|
+
assert mixin.get_credentials(device) == (
|
|
131
|
+
"platform-user",
|
|
132
|
+
"device-pass",
|
|
133
|
+
"default-secondary",
|
|
134
|
+
"default-priv",
|
|
135
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-diff.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-error.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-list.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-ok.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/compliance-patch.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-approve-button.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-approved.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-completed.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-created.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-diffs-tab.png
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-job-log.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/cr-scheduled.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/platformsetting.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/script-list.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/docs/media/screenshots/substitute.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/api/serializers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/__init__.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/base.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/compliance/utils.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/__init__.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/base.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/factory.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/platforms.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/configurator/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/forms/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/filters.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/graphql/schema.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/migrations/__init__.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/models/data_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/scripts/config_diff.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/templatetags/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/compliance.py
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff/views/configuration.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/requires.txt
RENAMED
|
File without changes
|
{netbox_config_diff-2.15.0 → netbox_config_diff-2.15.1}/netbox_config_diff.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|