Skip to content

Commit bb9317d

Browse files
authored
Closes #35: Add ability to define password for accessing priviliged exec mode
2 parents d8987ba + 715283a commit bb9317d

File tree

24 files changed

+164
-117
lines changed

24 files changed

+164
-117
lines changed

.github/workflows/commit.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ jobs:
2121
python -m pip install --upgrade pip
2222
python -m pip install --upgrade setuptools wheel
2323
python -m pip install -r requirements/dev.txt
24-
- name: Run black
25-
run: black --check --diff --color .
24+
- name: Run ruff format
25+
run: ruff format .
2626
- name: Run ruff
2727
run: ruff .
2828

.pre-commit-config.yaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ repos:
55
- id: check-yaml
66
- id: end-of-file-fixer
77
- id: trailing-whitespace
8-
- repo: https://github.com/psf/black
9-
rev: 23.1.0
10-
hooks:
11-
- id: black
12-
args: [--check, --diff, --color, .]
138
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.0.280
9+
rev: v0.1.2
1510
hooks:
1611
- id: ruff
1712
args: [netbox_config_diff]
13+
- id: ruff-format
14+
exclude: migrations

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
[![NetBox version](https://img.shields.io/badge/NetBox-3.5|3.6-blue.svg)](https://github.com/netbox-community/netbox)
22
[![Supported Versions](https://img.shields.io/pypi/pyversions/netbox-config-diff.svg)](https://pypi.org/project/netbox-config-diff/)
33
[![PyPI version](https://badge.fury.io/py/netbox-config-diff.svg)](https://badge.fury.io/py/netbox-config-diff)
4-
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
54
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
65
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
76
[![CI](https://github.com/miaow2/netbox-config-diff/actions/workflows/commit.yaml/badge.svg?branch=develop)](https://github.com/miaow2/netbox-config-diff/actions)
@@ -78,6 +77,7 @@ PLUGINS_CONFIG = {
7877
"netbox_config_diff": {
7978
"USERNAME": "foo",
8079
"PASSWORD": "bar",
80+
"AUTH_SECONDARY": "foobar", # define here password for accessing Privileged EXEC mode, this variable is optional
8181
},
8282
}
8383
```
@@ -120,6 +120,14 @@ No diff
120120

121121
![Screenshot of the compliance ok](docs/media/screenshots/compliance-ok.png)
122122

123+
Configuration request
124+
125+
![Screenshot of the CR](docs/media/screenshots/cr-created.png)
126+
127+
Completed Configuration request
128+
129+
![Screenshot of the completed CR](docs/media/screenshots/cr-completed.png)
130+
123131
## Credits
124132

125133
Based on the NetBox plugin tutorial:

docs/changelog.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## 2.1.0 (2023-10-26)
4+
5+
* [#35](https://github.com/miaow2/netbox-config-diff/issues/35) Add ability to define password for accessing priviliged exec mode
6+
* [#37](https://github.com/miaow2/netbox-config-diff/issues/37) Add `DeviceRole` field to `CollectDiffScript`
7+
* [#38](https://github.com/miaow2/netbox-config-diff/issues/38) Remove config template filter for devices filed in forms
8+
* [#39](https://github.com/miaow2/netbox-config-diff/issues/39) Add `Status` field to `CollectDiffScript`
9+
* [#43](https://github.com/miaow2/netbox-config-diff/issues/43) `ConfigDiffScript` does not create empty changelog entries
10+
11+
## 2.0.1 (2023-10-22)
12+
13+
* [#33](https://github.com/miaow2/netbox-config-diff/issues/33) Fix failing migrations on fresh database install
14+
315
## 2.0.0 (2023-10-18)
416

517
* [#25](https://github.com/miaow2/netbox-config-diff/issues/25) Add configuration management
47.3 KB
Loading

docs/media/screenshots/cr-created.png

41.3 KB
Loading

docs/secrets.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ You can store credentials for devices authentification in NetBox secrets [plugin
44

55
Read NetBox secrets docs for more info.
66

7-
In plugin variables define secrets roles for username (`USER_SECRET_ROLE`) and password (`PASSWORD_SECRET_ROLE`).
7+
In plugin variables define secrets roles for username (`USER_SECRET_ROLE`), password (`PASSWORD_SECRET_ROLE`) and
8+
password (`SECOND_AUTH_SECRET_ROLE`) for Privileged EXEC mode.
89

910
Default values for this variables are:
1011

@@ -13,6 +14,7 @@ PLUGINS_CONFIG = {
1314
"netbox_config_diff": {
1415
"USER_SECRET_ROLE": "Username",
1516
"PASSWORD_SECRET_ROLE": "Password",
17+
"SECOND_AUTH_SECRET_ROLE": "Second Auth",
1618
},
1719
}
1820
```

netbox_config_diff/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
__author__ = "Artem Kotik"
44
__email__ = "miaow2@yandex.ru"
5-
__version__ = "2.0.1"
5+
__version__ = "2.1.0"
66

77

88
class ConfigDiffConfig(PluginConfig):
@@ -18,6 +18,7 @@ class ConfigDiffConfig(PluginConfig):
1818
default_settings = {
1919
"USER_SECRET_ROLE": "Username",
2020
"PASSWORD_SECRET_ROLE": "Password",
21+
"SECOND_AUTH_SECRET_ROLE": "Second Auth",
2122
}
2223

2324

netbox_config_diff/compliance/base.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from netutils.config.compliance import diff_network_config
1515
from utilities.exceptions import AbortScript
1616

17-
from .models import DeviceDataClass
17+
from netbox_config_diff.models import ConplianceDeviceDataClass
18+
1819
from .secrets import SecretsMixin
1920
from .utils import PLATFORM_MAPPING, CustomChoiceVar, exclude_lines, get_unified_diff
2021

@@ -106,24 +107,24 @@ def validate_data(self, data: dict) -> Iterable[Device]:
106107
self.log_info(f"Working with device(s): {', '.join(d.name for d in devices)}")
107108
return devices
108109

109-
def update_in_db(self, devices: list[DeviceDataClass]) -> None:
110+
def update_in_db(self, devices: list[ConplianceDeviceDataClass]) -> None:
110111
for device in devices:
111112
self.log_results(device)
112113
device.send_to_db()
113114

114-
def log_results(self, device: DeviceDataClass) -> None:
115+
def log_results(self, device: ConplianceDeviceDataClass) -> None:
115116
if device.error:
116117
self.log_failure(f"{device.name} errored")
117118
elif device.diff:
118119
self.log_warning(f"{device.name} has diff between intented and actual configurations")
119120
else:
120121
self.log_success(f"{device.name} no diff")
121122

122-
def get_devices_with_rendered_configs(self, devices: Iterable[Device]) -> Iterator[DeviceDataClass]:
123+
def get_devices_with_rendered_configs(self, devices: Iterable[Device]) -> Iterator[ConplianceDeviceDataClass]:
123124
self.check_netbox_secrets()
124125
self.substitutes = {}
125126
for device in devices:
126-
username, password = self.get_credentials(device)
127+
username, password, auth_secondary = self.get_credentials(device)
127128
rendered_config = None
128129
error = None
129130
context_data = device.get_config_context()
@@ -142,7 +143,7 @@ def get_devices_with_rendered_configs(self, devices: Iterable[Device]) -> Iterat
142143
if substitutes := device.platform.platform_setting.substitutes.all():
143144
self.substitutes[platform] = [s.regexp for s in substitutes]
144145

145-
yield DeviceDataClass(
146+
yield ConplianceDeviceDataClass(
146147
pk=device.pk,
147148
name=device.name,
148149
mgmt_ip=str(device.primary_ip.address.ip),
@@ -151,11 +152,12 @@ def get_devices_with_rendered_configs(self, devices: Iterable[Device]) -> Iterat
151152
exclude_regex=device.platform.platform_setting.exclude_regex,
152153
username=username,
153154
password=password,
155+
auth_secondary=auth_secondary,
154156
rendered_config=rendered_config,
155157
error=error,
156158
)
157159

158-
def get_config_from_datasource(self, devices: list[DeviceDataClass]) -> None:
160+
def get_config_from_datasource(self, devices: list[ConplianceDeviceDataClass]) -> None:
159161
for device in devices:
160162
if df := DataFile.objects.filter(source=self.data["data_source"], path__icontains=device.name).first():
161163
if config := df.data_as_string:
@@ -165,14 +167,14 @@ def get_config_from_datasource(self, devices: list[DeviceDataClass]) -> None:
165167
else:
166168
device.error = f"Not found file in DataSource for device {device.name}"
167169

168-
def get_actual_configs(self, devices: list[DeviceDataClass]) -> None:
170+
def get_actual_configs(self, devices: list[ConplianceDeviceDataClass]) -> None:
169171
if self.data["data_source"]:
170172
self.get_config_from_datasource(devices)
171173
else:
172174
loop = asyncio.get_event_loop()
173175
loop.run_until_complete(asyncio.gather(*(d.get_actual_config() for d in devices)))
174176

175-
def get_diff(self, devices: list[DeviceDataClass]) -> None:
177+
def get_diff(self, devices: list[ConplianceDeviceDataClass]) -> None:
176178
for device in devices:
177179
if device.error is not None:
178180
continue

netbox_config_diff/compliance/secrets.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class SecretsMixin:
1515

1616
def get_session_key(self) -> None:
1717
if "netbox_secrets_sessionid" in self.request.COOKIES:
18-
self.session_key = base64.b64decode(self.request.COOKIES['netbox_secrets_sessionid'])
18+
self.session_key = base64.b64decode(self.request.COOKIES["netbox_secrets_sessionid"])
1919
elif "HTTP_X_SESSION_KEY" in self.request.META:
20-
self.session_key = base64.b64decode(self.request.META['HTTP_X_SESSION_KEY'])
20+
self.session_key = base64.b64decode(self.request.META["HTTP_X_SESSION_KEY"])
2121
else:
2222
self.session_key = None
2323

@@ -45,24 +45,33 @@ def get_secret(self, secret: "Secret") -> str | None:
4545
return None
4646
return secret.plaintext
4747

48-
def get_credentials(self, device: Device) -> tuple[str, str]:
49-
if self.netbox_secrets_installed:
50-
if secret := device.secrets.filter(role__name=self.user_role).first():
51-
if value := self.get_secret(secret):
52-
username = value
53-
if secret := device.secrets.filter(role__name=self.password_role).first():
54-
if value := self.get_secret(secret):
55-
password = value
56-
return username, password
48+
def get_credentials(self, device: Device) -> tuple[str, str, str]:
49+
if not self.netbox_secrets_installed:
50+
return self.username, self.password, self.auth_secondary
5751

58-
return self.username, self.password
52+
if secret := device.secrets.filter(role__name=self.user_role).first():
53+
username = value if (value := self.get_secret(secret)) else self.username
54+
else:
55+
username = self.username
56+
if secret := device.secrets.filter(role__name=self.password_role).first():
57+
password = value if (value := self.get_secret(secret)) else self.password
58+
else:
59+
password = self.password
60+
if secret := device.secrets.filter(role__name=self.auth_secondary_role).first():
61+
auth_secondary = value if (value := self.get_secret(secret)) else self.auth_secondary
62+
else:
63+
auth_secondary = self.auth_secondary
64+
65+
return username, password, auth_secondary
5966

6067
def check_netbox_secrets(self) -> None:
6168
if "netbox_secrets" in get_installed_plugins():
6269
self.get_master_key()
6370
self.user_role = get_plugin_config("netbox_config_diff", "USER_SECRET_ROLE")
6471
self.password_role = get_plugin_config("netbox_config_diff", "PASSWORD_SECRET_ROLE")
72+
self.auth_secondary_role = get_plugin_config("netbox_config_diff", "SECOND_AUTH_SECRET_ROLE")
6573
self.netbox_secrets_installed = True
66-
else:
67-
self.username = get_plugin_config("netbox_config_diff", "USERNAME")
68-
self.password = get_plugin_config("netbox_config_diff", "PASSWORD")
74+
75+
self.username = get_plugin_config("netbox_config_diff", "USERNAME")
76+
self.password = get_plugin_config("netbox_config_diff", "PASSWORD")
77+
self.auth_secondary = get_plugin_config("netbox_config_diff", "AUTH_SECONDARY")

0 commit comments

Comments
 (0)