netbox-cisco-ise 0.1.4__tar.gz → 0.1.7__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.
Files changed (25) hide show
  1. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/PKG-INFO +7 -1
  2. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/README.md +6 -0
  3. netbox_cisco_ise-0.1.7/netbox_cisco_ise/__init__.py +137 -0
  4. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise/ise_client.py +3 -11
  5. netbox_cisco_ise-0.1.7/netbox_cisco_ise/templates/netbox_cisco_ise/device_tab.html +24 -0
  6. netbox_cisco_ise-0.1.7/netbox_cisco_ise/templates/netbox_cisco_ise/endpoint_tab_content.html +216 -0
  7. netbox_cisco_ise-0.1.7/netbox_cisco_ise/templates/netbox_cisco_ise/nad_tab_content.html +193 -0
  8. netbox_cisco_ise-0.1.7/netbox_cisco_ise/templates/netbox_cisco_ise/netbox_endpoint_tab.html +24 -0
  9. netbox_cisco_ise-0.1.7/netbox_cisco_ise/urls.py +21 -0
  10. netbox_cisco_ise-0.1.7/netbox_cisco_ise/views.py +410 -0
  11. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise.egg-info/PKG-INFO +7 -1
  12. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise.egg-info/SOURCES.txt +4 -0
  13. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/pyproject.toml +1 -1
  14. netbox_cisco_ise-0.1.4/netbox_cisco_ise/__init__.py +0 -60
  15. netbox_cisco_ise-0.1.4/netbox_cisco_ise/urls.py +0 -12
  16. netbox_cisco_ise-0.1.4/netbox_cisco_ise/views.py +0 -278
  17. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/LICENSE +0 -0
  18. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise/navigation.py +0 -0
  19. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise/templates/netbox_cisco_ise/endpoint_tab.html +0 -0
  20. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise/templates/netbox_cisco_ise/nad_tab.html +0 -0
  21. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise/templates/netbox_cisco_ise/settings.html +0 -0
  22. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise.egg-info/dependency_links.txt +0 -0
  23. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise.egg-info/requires.txt +0 -0
  24. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/netbox_cisco_ise.egg-info/top_level.txt +0 -0
  25. {netbox_cisco_ise-0.1.4 → netbox_cisco_ise-0.1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-cisco-ise
3
- Version: 0.1.4
3
+ Version: 0.1.7
4
4
  Summary: NetBox plugin for Cisco ISE integration - endpoint tracking, NAD management, and session visibility
5
5
  Author-email: sieteunoseis <jeremy.worden@gmail.com>
6
6
  License: Apache-2.0
@@ -273,6 +273,12 @@ Contributions are welcome! Please:
273
273
  2. Create a feature branch
274
274
  3. Submit a pull request
275
275
 
276
+ ## Support
277
+
278
+ If you find this plugin helpful, consider supporting development:
279
+
280
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat&logo=buy-me-a-coffee)](https://buymeacoffee.com/automatebldrs)
281
+
276
282
  ## Related Projects
277
283
 
278
284
  - [netbox-catalyst-center](https://github.com/sieteunoseis/netbox-catalyst-center) - Catalyst Center integration for NetBox
@@ -241,6 +241,12 @@ Contributions are welcome! Please:
241
241
  2. Create a feature branch
242
242
  3. Submit a pull request
243
243
 
244
+ ## Support
245
+
246
+ If you find this plugin helpful, consider supporting development:
247
+
248
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat&logo=buy-me-a-coffee)](https://buymeacoffee.com/automatebldrs)
249
+
244
250
  ## Related Projects
245
251
 
246
252
  - [netbox-catalyst-center](https://github.com/sieteunoseis/netbox-catalyst-center) - Catalyst Center integration for NetBox
@@ -0,0 +1,137 @@
1
+ """
2
+ NetBox Cisco ISE Plugin
3
+
4
+ Display Cisco Identity Services Engine (ISE) endpoint and NAD information in Device detail pages.
5
+ Shows endpoint identity, profiling data, active session status, and network access device details.
6
+ """
7
+
8
+ import logging
9
+
10
+ from netbox.plugins import PluginConfig
11
+
12
+ __version__ = "0.1.7"
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class CiscoISEConfig(PluginConfig):
18
+ """Plugin configuration for NetBox Cisco ISE integration."""
19
+
20
+ name = "netbox_cisco_ise"
21
+ verbose_name = "Cisco ISE"
22
+ description = "Display Cisco ISE endpoint and NAD information in device pages"
23
+ version = __version__
24
+ author = "sieteunoseis"
25
+ author_email = "jeremy.worden@gmail.com"
26
+ base_url = "cisco-ise"
27
+ min_version = "4.0.0"
28
+ max_version = "4.99"
29
+
30
+ # Required settings - plugin won't load without these
31
+ required_settings = []
32
+
33
+ # Default configuration values
34
+ default_settings = {
35
+ # ISE Connection Settings
36
+ "ise_url": "", # e.g., "https://ise.example.com"
37
+ "ise_username": "", # ERS Admin username
38
+ "ise_password": "", # ERS Admin password
39
+ "timeout": 30, # API timeout in seconds
40
+ "cache_timeout": 60, # Cache results for 60 seconds
41
+ "verify_ssl": False, # Skip SSL verification for self-signed certs
42
+ # Device mappings - determines which devices show ISE tab and lookup method
43
+ # Format: list of dicts with manufacturer (regex), device_type (regex, optional), lookup method
44
+ #
45
+ # lookup types:
46
+ # "endpoint" - MAC address lookup (for wireless clients, phones, badges)
47
+ # "nad" - Network Access Device lookup (for switches, routers, WLCs)
48
+ #
49
+ # Example:
50
+ # "device_mappings": [
51
+ # {"manufacturer": "cisco", "lookup": "nad"}, # Cisco network devices as NADs
52
+ # {"manufacturer": "vocera", "lookup": "endpoint"}, # Vocera badges by MAC
53
+ # {"manufacturer": "cisco", "device_type": ".*phone.*", "lookup": "endpoint"}, # Cisco phones by MAC
54
+ # ]
55
+ "device_mappings": [
56
+ {
57
+ "manufacturer": r"cisco",
58
+ "lookup": "nad",
59
+ }, # Default: Cisco devices as NADs
60
+ ],
61
+ # Endpoint mappings (requires netbox-endpoints plugin)
62
+ # Format: list of dicts with manufacturer (regex), endpoint_type (regex, optional)
63
+ # All endpoints use MAC lookup since they're endpoint devices
64
+ #
65
+ # Example:
66
+ # "endpoint_mappings": [
67
+ # {"manufacturer": "vocera"}, # All Vocera endpoints
68
+ # {"manufacturer": "cisco", "endpoint_type": ".*phone.*"}, # Cisco phones
69
+ # ]
70
+ # If empty, shows tab for ALL endpoints with a MAC address
71
+ "endpoint_mappings": [],
72
+ }
73
+
74
+ def ready(self):
75
+ """Register endpoint view if netbox_endpoints is available."""
76
+ super().ready()
77
+ self._register_endpoint_views()
78
+
79
+ def _register_endpoint_views(self):
80
+ """Register Cisco ISE tab for Endpoints if plugin is installed."""
81
+ import sys
82
+
83
+ # Quick check if netbox_endpoints is available
84
+ if "netbox_endpoints" not in sys.modules:
85
+ try:
86
+ import importlib.util
87
+
88
+ if importlib.util.find_spec("netbox_endpoints") is None:
89
+ logger.debug("netbox_endpoints not installed, skipping endpoint view registration")
90
+ return
91
+ except Exception:
92
+ logger.debug("netbox_endpoints not available, skipping endpoint view registration")
93
+ return
94
+
95
+ try:
96
+ from django.shortcuts import render
97
+ from netbox.views import generic
98
+ from netbox_endpoints.models import Endpoint
99
+ from utilities.views import ViewTab, register_model_view
100
+
101
+ from .views import should_show_ise_tab_endpoint
102
+
103
+ @register_model_view(Endpoint, name="cisco_ise", path="cisco-ise")
104
+ class EndpointISEView(generic.ObjectView):
105
+ """Display Cisco ISE endpoint details for a netbox Endpoint."""
106
+
107
+ queryset = Endpoint.objects.all()
108
+ template_name = "netbox_cisco_ise/netbox_endpoint_tab.html"
109
+
110
+ tab = ViewTab(
111
+ label="Cisco ISE",
112
+ weight=9001,
113
+ permission="netbox_endpoints.view_endpoint",
114
+ hide_if_empty=False,
115
+ visible=should_show_ise_tab_endpoint,
116
+ )
117
+
118
+ def get(self, request, pk):
119
+ endpoint = Endpoint.objects.get(pk=pk)
120
+ return render(
121
+ request,
122
+ self.template_name,
123
+ {
124
+ "object": endpoint,
125
+ "tab": self.tab,
126
+ "loading": True,
127
+ },
128
+ )
129
+
130
+ logger.info("Registered Cisco ISE tab for Endpoint model")
131
+ except ImportError:
132
+ logger.debug("netbox_endpoints not installed, skipping endpoint view registration")
133
+ except Exception as e:
134
+ logger.warning(f"Could not register endpoint views: {e}")
135
+
136
+
137
+ config = CiscoISEConfig
@@ -275,9 +275,7 @@ class ISEClient:
275
275
  cached["cached"] = True
276
276
  return cached
277
277
 
278
- result = self._make_ers_request(
279
- "/networkdevice", params={"filter": f"ipaddress.EQ.{ip_address}"}
280
- )
278
+ result = self._make_ers_request("/networkdevice", params={"filter": f"ipaddress.EQ.{ip_address}"})
281
279
 
282
280
  return self._process_nad_result(result, cache_key)
283
281
 
@@ -297,9 +295,7 @@ class ISEClient:
297
295
  cached["cached"] = True
298
296
  return cached
299
297
 
300
- result = self._make_ers_request(
301
- "/networkdevice", params={"filter": f"name.CONTAINS.{name}"}
302
- )
298
+ result = self._make_ers_request("/networkdevice", params={"filter": f"name.CONTAINS.{name}"})
303
299
 
304
300
  return self._process_nad_result(result, cache_key)
305
301
 
@@ -365,11 +361,7 @@ class ISEClient:
365
361
  "ro_community": bool(snmp_settings.get("roCommunity")),
366
362
  "polling_interval": snmp_settings.get("pollingInterval"),
367
363
  },
368
- "trustsec_enabled": bool(
369
- trustsec_settings.get("deviceAuthenticationSettings", {}).get(
370
- "sgaDeviceId"
371
- )
372
- ),
364
+ "trustsec_enabled": bool(trustsec_settings.get("deviceAuthenticationSettings", {}).get("sgaDeviceId")),
373
365
  "coA_port": nad.get("coaPort"),
374
366
  "cached": False,
375
367
  }
@@ -0,0 +1,24 @@
1
+ {% extends 'dcim/device/base.html' %}
2
+ {% load helpers %}
3
+
4
+ {% block content %}
5
+ {% if loading %}
6
+ <div id="ise-content"
7
+ hx-get="{% url 'plugins:netbox_cisco_ise:device_content' pk=object.pk %}"
8
+ hx-trigger="load"
9
+ hx-swap="innerHTML">
10
+ <div class="d-flex justify-content-center align-items-center py-5">
11
+ <div class="text-center">
12
+ <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
13
+ <span class="visually-hidden">Loading...</span>
14
+ </div>
15
+ <p class="text-muted mb-0">Loading Cisco ISE data...</p>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ {% elif error %}
20
+ <div class="alert alert-warning">
21
+ <i class="mdi mdi-alert"></i> {{ error }}
22
+ </div>
23
+ {% endif %}
24
+ {% endblock %}
@@ -0,0 +1,216 @@
1
+ {% load helpers %}
2
+
3
+ <div class="row">
4
+ <div class="col-12">
5
+ {% if error %}
6
+ <div class="alert alert-warning">
7
+ <i class="mdi mdi-alert"></i> {{ error }}
8
+ </div>
9
+ {% elif ise_data %}
10
+ <div class="row">
11
+ <!-- Session Status Card -->
12
+ <div class="col-md-4 mb-3">
13
+ <div class="card h-100">
14
+ <div class="card-header">
15
+ <h5 class="card-title mb-0">
16
+ <i class="mdi mdi-lan-connect"></i> Session Status
17
+ </h5>
18
+ </div>
19
+ <div class="card-body text-center">
20
+ {% if session_data.connected %}
21
+ <div class="p-3 mb-2 bg-success rounded">
22
+ <span class="text-white fs-3 fw-bold">
23
+ <i class="mdi mdi-check-circle"></i> Connected
24
+ </span>
25
+ </div>
26
+ {% if session_data.framed_ip_address %}
27
+ <div class="mt-2">
28
+ <span class="text-muted">IP Address:</span>
29
+ <code class="ms-2">{{ session_data.framed_ip_address }}</code>
30
+ </div>
31
+ {% endif %}
32
+ {% if session_data.authorization_profile %}
33
+ <div class="mt-1">
34
+ <span class="text-muted">Authorization:</span>
35
+ <span class="badge bg-info text-dark ms-2">{{ session_data.authorization_profile }}</span>
36
+ </div>
37
+ {% endif %}
38
+ {% if session_data.acct_session_time %}
39
+ <div class="mt-1 text-muted small">
40
+ Session time: {{ session_data.acct_session_time }} seconds
41
+ </div>
42
+ {% endif %}
43
+ {% else %}
44
+ <div class="p-3 mb-2 bg-secondary rounded">
45
+ <span class="text-white fs-3 fw-bold">
46
+ <i class="mdi mdi-lan-disconnect"></i> Disconnected
47
+ </span>
48
+ </div>
49
+ <div class="mt-2 text-muted">
50
+ No active session found
51
+ </div>
52
+ {% endif %}
53
+ </div>
54
+ </div>
55
+ </div>
56
+
57
+ <!-- Endpoint Identity Card -->
58
+ <div class="col-md-4 mb-3">
59
+ <div class="card h-100">
60
+ <div class="card-header">
61
+ <h5 class="card-title mb-0">
62
+ <i class="mdi mdi-account-badge"></i> Endpoint Identity
63
+ </h5>
64
+ </div>
65
+ <div class="card-body">
66
+ <table class="table table-sm table-borderless mb-0">
67
+ <tr>
68
+ <th class="text-muted" style="width: 40%">MAC Address:</th>
69
+ <td><code>{{ ise_data.mac_address }}</code></td>
70
+ </tr>
71
+ <tr>
72
+ <th class="text-muted">Profile:</th>
73
+ <td>{{ ise_data.profile_name|default:"N/A" }}</td>
74
+ </tr>
75
+ <tr>
76
+ <th class="text-muted">Identity Group:</th>
77
+ <td>{{ ise_data.group_name|default:"N/A" }}</td>
78
+ </tr>
79
+ <tr>
80
+ <th class="text-muted">Static Assignment:</th>
81
+ <td>
82
+ {% if ise_data.static_group_assignment %}
83
+ <span class="badge bg-success text-white">Yes</span>
84
+ {% else %}
85
+ <span class="badge bg-secondary text-white">No</span>
86
+ {% endif %}
87
+ </td>
88
+ </tr>
89
+ {% if ise_data.portal_user %}
90
+ <tr>
91
+ <th class="text-muted">Portal User:</th>
92
+ <td>{{ ise_data.portal_user }}</td>
93
+ </tr>
94
+ {% endif %}
95
+ </table>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <!-- Connection Details Card -->
101
+ <div class="col-md-4 mb-3">
102
+ <div class="card h-100">
103
+ <div class="card-header">
104
+ <h5 class="card-title mb-0">
105
+ <i class="mdi mdi-router-wireless"></i> Connection Details
106
+ </h5>
107
+ </div>
108
+ <div class="card-body">
109
+ {% if session_data.connected %}
110
+ <table class="table table-sm table-borderless mb-0">
111
+ {% if session_data.nas_ip_address %}
112
+ <tr>
113
+ <th class="text-muted" style="width: 40%">Connected To:</th>
114
+ <td><code>{{ session_data.nas_ip_address }}</code></td>
115
+ </tr>
116
+ {% endif %}
117
+ {% if session_data.nas_port_id %}
118
+ <tr>
119
+ <th class="text-muted">Port:</th>
120
+ <td>{{ session_data.nas_port_id }}</td>
121
+ </tr>
122
+ {% endif %}
123
+ {% if session_data.vlan %}
124
+ <tr>
125
+ <th class="text-muted">VLAN:</th>
126
+ <td>{{ session_data.vlan }}</td>
127
+ </tr>
128
+ {% endif %}
129
+ {% if session_data.ssid %}
130
+ <tr>
131
+ <th class="text-muted">SSID:</th>
132
+ <td>{{ session_data.ssid }}</td>
133
+ </tr>
134
+ {% endif %}
135
+ {% if session_data.auth_method %}
136
+ <tr>
137
+ <th class="text-muted">Auth Method:</th>
138
+ <td>{{ session_data.auth_method }}</td>
139
+ </tr>
140
+ {% endif %}
141
+ {% if session_data.security_group %}
142
+ <tr>
143
+ <th class="text-muted">Security Group:</th>
144
+ <td><span class="badge bg-primary text-white">{{ session_data.security_group }}</span></td>
145
+ </tr>
146
+ {% endif %}
147
+ </table>
148
+ {% else %}
149
+ <div class="text-center text-muted py-4">
150
+ <i class="mdi mdi-lan-disconnect mdi-48px"></i>
151
+ <p class="mt-2">No active connection</p>
152
+ </div>
153
+ {% endif %}
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ <!-- Custom Attributes -->
160
+ {% if ise_data.custom_attributes %}
161
+ <div class="row">
162
+ <div class="col-12 mb-3">
163
+ <div class="card">
164
+ <div class="card-header">
165
+ <h5 class="card-title mb-0">
166
+ <i class="mdi mdi-tag-multiple"></i> Custom Attributes
167
+ </h5>
168
+ </div>
169
+ <div class="card-body">
170
+ <table class="table table-sm table-hover">
171
+ <thead>
172
+ <tr>
173
+ <th>Attribute</th>
174
+ <th>Value</th>
175
+ </tr>
176
+ </thead>
177
+ <tbody>
178
+ {% for key, value in ise_data.custom_attributes.items %}
179
+ <tr>
180
+ <td>{{ key }}</td>
181
+ <td>{{ value }}</td>
182
+ </tr>
183
+ {% endfor %}
184
+ </tbody>
185
+ </table>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ {% endif %}
191
+
192
+ <!-- Cache indicator and external link -->
193
+ <div class="mt-3 d-flex justify-content-between align-items-center">
194
+ <div>
195
+ {% if ise_data.cached %}
196
+ <span class="text-muted small">
197
+ <i class="mdi mdi-cached"></i> Data from cache
198
+ </span>
199
+ {% endif %}
200
+ </div>
201
+ <div>
202
+ {% if ise_url %}
203
+ <a href="{{ ise_url }}" target="_blank" class="btn btn-outline-primary btn-sm">
204
+ <i class="mdi mdi-open-in-new"></i> Open Cisco ISE
205
+ </a>
206
+ {% endif %}
207
+ </div>
208
+ </div>
209
+
210
+ {% else %}
211
+ <div class="alert alert-info">
212
+ <i class="mdi mdi-information"></i> No endpoint data available from ISE.
213
+ </div>
214
+ {% endif %}
215
+ </div>
216
+ </div>
@@ -0,0 +1,193 @@
1
+ {% load helpers %}
2
+
3
+ <div class="row">
4
+ <div class="col-12">
5
+ {% if error %}
6
+ <div class="alert alert-warning">
7
+ <i class="mdi mdi-alert"></i> {{ error }}
8
+ </div>
9
+ {% elif ise_data %}
10
+ <div class="row">
11
+ <!-- NAD Registration Status Card -->
12
+ <div class="col-md-4 mb-3">
13
+ <div class="card h-100">
14
+ <div class="card-header">
15
+ <h5 class="card-title mb-0">
16
+ <i class="mdi mdi-check-decagram"></i> ISE Registration
17
+ </h5>
18
+ </div>
19
+ <div class="card-body text-center">
20
+ <div class="p-3 mb-2 bg-success rounded">
21
+ <span class="text-white fs-3 fw-bold">
22
+ <i class="mdi mdi-check-circle"></i> Registered
23
+ </span>
24
+ </div>
25
+ {% if ise_data.name %}
26
+ <div class="mt-2">
27
+ <span class="text-muted">NAD Name:</span>
28
+ <strong class="ms-2">{{ ise_data.name }}</strong>
29
+ </div>
30
+ {% endif %}
31
+ {% if ise_data.profile_name %}
32
+ <div class="mt-1">
33
+ <span class="text-muted">Profile:</span>
34
+ <span class="badge bg-info text-dark ms-2">{{ ise_data.profile_name }}</span>
35
+ </div>
36
+ {% endif %}
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <!-- Device Details Card -->
42
+ <div class="col-md-4 mb-3">
43
+ <div class="card h-100">
44
+ <div class="card-header">
45
+ <h5 class="card-title mb-0">
46
+ <i class="mdi mdi-router"></i> Device Details
47
+ </h5>
48
+ </div>
49
+ <div class="card-body">
50
+ <table class="table table-sm table-borderless mb-0">
51
+ {% if ise_data.ip_addresses %}
52
+ <tr>
53
+ <th class="text-muted" style="width: 40%">IP Address(es):</th>
54
+ <td>
55
+ {% for ip in ise_data.ip_addresses %}
56
+ <code>{{ ip }}</code>{% if not forloop.last %}, {% endif %}
57
+ {% endfor %}
58
+ </td>
59
+ </tr>
60
+ {% endif %}
61
+ {% if ise_data.model_name %}
62
+ <tr>
63
+ <th class="text-muted">Model:</th>
64
+ <td>{{ ise_data.model_name }}</td>
65
+ </tr>
66
+ {% endif %}
67
+ {% if ise_data.software_version %}
68
+ <tr>
69
+ <th class="text-muted">Software:</th>
70
+ <td>{{ ise_data.software_version }}</td>
71
+ </tr>
72
+ {% endif %}
73
+ {% if ise_data.description %}
74
+ <tr>
75
+ <th class="text-muted">Description:</th>
76
+ <td>{{ ise_data.description }}</td>
77
+ </tr>
78
+ {% endif %}
79
+ {% if ise_data.coA_port %}
80
+ <tr>
81
+ <th class="text-muted">CoA Port:</th>
82
+ <td>{{ ise_data.coA_port }}</td>
83
+ </tr>
84
+ {% endif %}
85
+ </table>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ <!-- Authentication Settings Card -->
91
+ <div class="col-md-4 mb-3">
92
+ <div class="card h-100">
93
+ <div class="card-header">
94
+ <h5 class="card-title mb-0">
95
+ <i class="mdi mdi-shield-key"></i> Authentication Settings
96
+ </h5>
97
+ </div>
98
+ <div class="card-body">
99
+ <table class="table table-sm table-borderless mb-0">
100
+ <tr>
101
+ <th class="text-muted" style="width: 50%">RADIUS:</th>
102
+ <td>
103
+ {% if ise_data.authentication_settings.radius_enabled %}
104
+ <span class="badge bg-success text-white">Enabled</span>
105
+ {% else %}
106
+ <span class="badge bg-warning text-dark">Disabled</span>
107
+ {% endif %}
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <th class="text-muted">TACACS+:</th>
112
+ <td>
113
+ {% if ise_data.tacacs_settings.enabled %}
114
+ <span class="badge bg-success text-white">Enabled</span>
115
+ {% else %}
116
+ <span class="badge bg-warning text-dark">Disabled</span>
117
+ {% endif %}
118
+ </td>
119
+ </tr>
120
+ <tr>
121
+ <th class="text-muted">TrustSec:</th>
122
+ <td>
123
+ {% if ise_data.trustsec_enabled %}
124
+ <span class="badge bg-success text-white">Enabled</span>
125
+ {% else %}
126
+ <span class="badge bg-warning text-dark">Disabled</span>
127
+ {% endif %}
128
+ </td>
129
+ </tr>
130
+ {% if ise_data.snmp_settings.version %}
131
+ <tr>
132
+ <th class="text-muted">SNMP:</th>
133
+ <td>{{ ise_data.snmp_settings.version }}</td>
134
+ </tr>
135
+ {% endif %}
136
+ </table>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+
142
+ <!-- Network Device Groups -->
143
+ {% if ise_data.groups %}
144
+ <div class="row">
145
+ <div class="col-12 mb-3">
146
+ <div class="card">
147
+ <div class="card-header">
148
+ <h5 class="card-title mb-0">
149
+ <i class="mdi mdi-folder-network"></i> Network Device Groups
150
+ </h5>
151
+ </div>
152
+ <div class="card-body">
153
+ <div class="row">
154
+ {% for category, value in ise_data.groups.items %}
155
+ <div class="col-md-3 col-sm-6 mb-2">
156
+ <div class="border rounded p-2">
157
+ <div class="text-muted small">{{ category }}</div>
158
+ <div class="fw-bold">{{ value }}</div>
159
+ </div>
160
+ </div>
161
+ {% endfor %}
162
+ </div>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ {% endif %}
168
+
169
+ <!-- Cache indicator and external link -->
170
+ <div class="mt-3 d-flex justify-content-between align-items-center">
171
+ <div>
172
+ {% if ise_data.cached %}
173
+ <span class="text-muted small">
174
+ <i class="mdi mdi-cached"></i> Data from cache
175
+ </span>
176
+ {% endif %}
177
+ </div>
178
+ <div>
179
+ {% if ise_url %}
180
+ <a href="{{ ise_url }}" target="_blank" class="btn btn-outline-primary btn-sm">
181
+ <i class="mdi mdi-open-in-new"></i> Open Cisco ISE
182
+ </a>
183
+ {% endif %}
184
+ </div>
185
+ </div>
186
+
187
+ {% else %}
188
+ <div class="alert alert-info">
189
+ <i class="mdi mdi-information"></i> This device is not registered as a Network Access Device in ISE.
190
+ </div>
191
+ {% endif %}
192
+ </div>
193
+ </div>
@@ -0,0 +1,24 @@
1
+ {% extends 'netbox_endpoints/endpoint.html' %}
2
+ {% load helpers %}
3
+
4
+ {% block content %}
5
+ {% if loading %}
6
+ <div id="ise-content"
7
+ hx-get="{% url 'plugins:netbox_cisco_ise:endpoint_content' pk=object.pk %}"
8
+ hx-trigger="load"
9
+ hx-swap="innerHTML">
10
+ <div class="d-flex justify-content-center align-items-center py-5">
11
+ <div class="text-center">
12
+ <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
13
+ <span class="visually-hidden">Loading...</span>
14
+ </div>
15
+ <p class="text-muted mb-0">Loading Cisco ISE data...</p>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ {% elif error %}
20
+ <div class="alert alert-warning">
21
+ <i class="mdi mdi-alert"></i> {{ error }}
22
+ </div>
23
+ {% endif %}
24
+ {% endblock %}