netbox-dlm 0.1.0__py3-none-any.whl
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_dlm/__init__.py +24 -0
- netbox_dlm/admin.py +72 -0
- netbox_dlm/api/__init__.py +0 -0
- netbox_dlm/api/serializers.py +177 -0
- netbox_dlm/api/urls.py +19 -0
- netbox_dlm/api/views.py +71 -0
- netbox_dlm/choices.py +91 -0
- netbox_dlm/filtersets.py +169 -0
- netbox_dlm/forms.py +272 -0
- netbox_dlm/graphql/__init__.py +0 -0
- netbox_dlm/graphql/schema.py +39 -0
- netbox_dlm/graphql/types.py +66 -0
- netbox_dlm/migrations/__init__.py +0 -0
- netbox_dlm/models.py +392 -0
- netbox_dlm/navigation.py +123 -0
- netbox_dlm/scripts.py +126 -0
- netbox_dlm/tables.py +155 -0
- netbox_dlm/template_content.py +50 -0
- netbox_dlm/templates/netbox_dlm/contract.html +48 -0
- netbox_dlm/templates/netbox_dlm/cve.html +81 -0
- netbox_dlm/templates/netbox_dlm/device_lifecycle_panel.html +67 -0
- netbox_dlm/templates/netbox_dlm/devicesoftware.html +22 -0
- netbox_dlm/templates/netbox_dlm/devicetype_lifecycle_panel.html +35 -0
- netbox_dlm/templates/netbox_dlm/hardwarenotice.html +32 -0
- netbox_dlm/templates/netbox_dlm/provider.html +25 -0
- netbox_dlm/templates/netbox_dlm/softwareimagefile.html +26 -0
- netbox_dlm/templates/netbox_dlm/softwareversion.html +95 -0
- netbox_dlm/templates/netbox_dlm/validatedsoftware.html +54 -0
- netbox_dlm/templates/netbox_dlm/vulnerability.html +23 -0
- netbox_dlm/urls.py +133 -0
- netbox_dlm/views.py +293 -0
- netbox_dlm-0.1.0.dist-info/METADATA +183 -0
- netbox_dlm-0.1.0.dist-info/RECORD +36 -0
- netbox_dlm-0.1.0.dist-info/WHEEL +5 -0
- netbox_dlm-0.1.0.dist-info/licenses/LICENSE +190 -0
- netbox_dlm-0.1.0.dist-info/top_level.txt +1 -0
netbox_dlm/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from netbox.plugins import PluginConfig
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DeviceLifecycleConfig(PluginConfig):
|
|
5
|
+
name = "netbox_dlm"
|
|
6
|
+
verbose_name = "Device Lifecycle Management"
|
|
7
|
+
description = (
|
|
8
|
+
"Track hardware end-of-life/end-of-support notices, software versions and "
|
|
9
|
+
"validated-software compliance, CVE/vulnerability exposure, and maintenance "
|
|
10
|
+
"contracts — modeled after Nautobot's Device Lifecycle Management app."
|
|
11
|
+
)
|
|
12
|
+
version = "0.1.0"
|
|
13
|
+
base_url = "device-lifecycle"
|
|
14
|
+
min_version = "4.1.0"
|
|
15
|
+
default_settings = {
|
|
16
|
+
# Set to a NIST NVD API key to raise CVE-lookup rate limits (optional).
|
|
17
|
+
"nist_api_key": None,
|
|
18
|
+
# How many days out a hardware/software EoS date counts as "upcoming"
|
|
19
|
+
# for dashboard highlighting.
|
|
20
|
+
"eos_warning_days": 180,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
config = DeviceLifecycleConfig
|
netbox_dlm/admin.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
from .models import (
|
|
4
|
+
CVE,
|
|
5
|
+
Contract,
|
|
6
|
+
DeviceSoftware,
|
|
7
|
+
HardwareNotice,
|
|
8
|
+
Provider,
|
|
9
|
+
SoftwareImageFile,
|
|
10
|
+
SoftwareVersion,
|
|
11
|
+
ValidatedSoftware,
|
|
12
|
+
Vulnerability,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@admin.register(Provider)
|
|
17
|
+
class ProviderAdmin(admin.ModelAdmin):
|
|
18
|
+
list_display = ("name", "phone", "email", "portal_url")
|
|
19
|
+
search_fields = ("name", "email")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@admin.register(Contract)
|
|
23
|
+
class ContractAdmin(admin.ModelAdmin):
|
|
24
|
+
list_display = ("name", "provider", "support_level", "start_date", "end_date")
|
|
25
|
+
list_filter = ("provider", "support_level")
|
|
26
|
+
search_fields = ("name", "contract_number")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@admin.register(HardwareNotice)
|
|
30
|
+
class HardwareNoticeAdmin(admin.ModelAdmin):
|
|
31
|
+
list_display = ("__str__", "end_of_sale", "end_of_support", "end_of_security_patches")
|
|
32
|
+
list_filter = ("end_of_support",)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@admin.register(SoftwareVersion)
|
|
36
|
+
class SoftwareVersionAdmin(admin.ModelAdmin):
|
|
37
|
+
list_display = ("__str__", "platform", "version", "release_date", "end_of_support", "long_term_support")
|
|
38
|
+
list_filter = ("platform", "long_term_support")
|
|
39
|
+
search_fields = ("version", "alias")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@admin.register(SoftwareImageFile)
|
|
43
|
+
class SoftwareImageFileAdmin(admin.ModelAdmin):
|
|
44
|
+
list_display = ("file_name", "software_version", "hashing_algorithm", "default_image")
|
|
45
|
+
list_filter = ("hashing_algorithm", "default_image")
|
|
46
|
+
search_fields = ("file_name", "checksum")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@admin.register(DeviceSoftware)
|
|
50
|
+
class DeviceSoftwareAdmin(admin.ModelAdmin):
|
|
51
|
+
list_display = ("device", "software_version", "last_checked")
|
|
52
|
+
search_fields = ("device__name",)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@admin.register(ValidatedSoftware)
|
|
56
|
+
class ValidatedSoftwareAdmin(admin.ModelAdmin):
|
|
57
|
+
list_display = ("software_version", "start", "end", "preferred", "valid_now")
|
|
58
|
+
list_filter = ("preferred",)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@admin.register(CVE)
|
|
62
|
+
class CVEAdmin(admin.ModelAdmin):
|
|
63
|
+
list_display = ("cve_id", "name", "severity", "status", "cvss_score", "published_date")
|
|
64
|
+
list_filter = ("severity", "status")
|
|
65
|
+
search_fields = ("cve_id", "name", "description")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@admin.register(Vulnerability)
|
|
69
|
+
class VulnerabilityAdmin(admin.ModelAdmin):
|
|
70
|
+
list_display = ("cve", "software_version", "device", "status")
|
|
71
|
+
list_filter = ("status",)
|
|
72
|
+
search_fields = ("cve__cve_id", "device__name")
|
|
File without changes
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
from dcim.api.serializers import (
|
|
2
|
+
DeviceSerializer,
|
|
3
|
+
DeviceRoleSerializer,
|
|
4
|
+
DeviceTypeSerializer,
|
|
5
|
+
ModuleTypeSerializer,
|
|
6
|
+
PlatformSerializer,
|
|
7
|
+
)
|
|
8
|
+
from netbox.api.fields import ChoiceField
|
|
9
|
+
from netbox.api.serializers import NetBoxModelSerializer
|
|
10
|
+
from rest_framework import serializers
|
|
11
|
+
|
|
12
|
+
from ..choices import (
|
|
13
|
+
ContractSupportLevelChoices,
|
|
14
|
+
CVESeverityChoices,
|
|
15
|
+
CVEStatusChoices,
|
|
16
|
+
HashingAlgorithmChoices,
|
|
17
|
+
VulnerabilityStatusChoices,
|
|
18
|
+
)
|
|
19
|
+
from ..models import (
|
|
20
|
+
CVE,
|
|
21
|
+
Contract,
|
|
22
|
+
DeviceSoftware,
|
|
23
|
+
HardwareNotice,
|
|
24
|
+
Provider,
|
|
25
|
+
SoftwareImageFile,
|
|
26
|
+
SoftwareVersion,
|
|
27
|
+
ValidatedSoftware,
|
|
28
|
+
Vulnerability,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ProviderSerializer(NetBoxModelSerializer):
|
|
33
|
+
url = serializers.HyperlinkedIdentityField(
|
|
34
|
+
view_name="plugins-api:netbox_dlm-api:provider-detail"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
class Meta:
|
|
38
|
+
model = Provider
|
|
39
|
+
fields = (
|
|
40
|
+
"id", "url", "display", "name", "physical_address", "phone",
|
|
41
|
+
"email", "portal_url", "comments", "tags", "custom_fields",
|
|
42
|
+
"created", "last_updated",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ContractSerializer(NetBoxModelSerializer):
|
|
47
|
+
url = serializers.HyperlinkedIdentityField(
|
|
48
|
+
view_name="plugins-api:netbox_dlm-api:contract-detail"
|
|
49
|
+
)
|
|
50
|
+
provider = ProviderSerializer(nested=True)
|
|
51
|
+
support_level = ChoiceField(choices=ContractSupportLevelChoices, required=False)
|
|
52
|
+
devices = DeviceSerializer(nested=True, many=True, required=False)
|
|
53
|
+
|
|
54
|
+
class Meta:
|
|
55
|
+
model = Contract
|
|
56
|
+
fields = (
|
|
57
|
+
"id", "url", "display", "provider", "name", "contract_number",
|
|
58
|
+
"start_date", "end_date", "cost", "currency", "support_level",
|
|
59
|
+
"devices", "comments", "tags", "custom_fields", "created", "last_updated",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class HardwareNoticeSerializer(NetBoxModelSerializer):
|
|
64
|
+
url = serializers.HyperlinkedIdentityField(
|
|
65
|
+
view_name="plugins-api:netbox_dlm-api:hardwarenotice-detail"
|
|
66
|
+
)
|
|
67
|
+
device_type = DeviceTypeSerializer(nested=True, required=False, allow_null=True)
|
|
68
|
+
module_type = ModuleTypeSerializer(nested=True, required=False, allow_null=True)
|
|
69
|
+
|
|
70
|
+
class Meta:
|
|
71
|
+
model = HardwareNotice
|
|
72
|
+
fields = (
|
|
73
|
+
"id", "url", "display", "device_type", "module_type", "end_of_sale",
|
|
74
|
+
"end_of_support", "end_of_security_patches", "end_of_sw_releases",
|
|
75
|
+
"documentation_url", "comments", "tags", "custom_fields",
|
|
76
|
+
"created", "last_updated",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class SoftwareVersionSerializer(NetBoxModelSerializer):
|
|
81
|
+
url = serializers.HyperlinkedIdentityField(
|
|
82
|
+
view_name="plugins-api:netbox_dlm-api:softwareversion-detail"
|
|
83
|
+
)
|
|
84
|
+
platform = PlatformSerializer(nested=True)
|
|
85
|
+
|
|
86
|
+
class Meta:
|
|
87
|
+
model = SoftwareVersion
|
|
88
|
+
fields = (
|
|
89
|
+
"id", "url", "display", "platform", "version", "alias",
|
|
90
|
+
"release_date", "end_of_support", "long_term_support",
|
|
91
|
+
"documentation_url", "comments", "tags", "custom_fields",
|
|
92
|
+
"created", "last_updated",
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class SoftwareImageFileSerializer(NetBoxModelSerializer):
|
|
97
|
+
url = serializers.HyperlinkedIdentityField(
|
|
98
|
+
view_name="plugins-api:netbox_dlm-api:softwareimagefile-detail"
|
|
99
|
+
)
|
|
100
|
+
software_version = SoftwareVersionSerializer(nested=True)
|
|
101
|
+
hashing_algorithm = ChoiceField(choices=HashingAlgorithmChoices, required=False)
|
|
102
|
+
|
|
103
|
+
class Meta:
|
|
104
|
+
model = SoftwareImageFile
|
|
105
|
+
fields = (
|
|
106
|
+
"id", "url", "display", "software_version", "file_name", "checksum",
|
|
107
|
+
"hashing_algorithm", "file_size", "download_url", "default_image",
|
|
108
|
+
"comments", "tags", "custom_fields", "created", "last_updated",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class DeviceSoftwareSerializer(NetBoxModelSerializer):
|
|
113
|
+
url = serializers.HyperlinkedIdentityField(
|
|
114
|
+
view_name="plugins-api:netbox_dlm-api:devicesoftware-detail"
|
|
115
|
+
)
|
|
116
|
+
device = DeviceSerializer(nested=True)
|
|
117
|
+
software_version = SoftwareVersionSerializer(nested=True)
|
|
118
|
+
|
|
119
|
+
class Meta:
|
|
120
|
+
model = DeviceSoftware
|
|
121
|
+
fields = (
|
|
122
|
+
"id", "url", "display", "device", "software_version", "last_checked",
|
|
123
|
+
"comments", "tags", "custom_fields", "created", "last_updated",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class ValidatedSoftwareSerializer(NetBoxModelSerializer):
|
|
128
|
+
url = serializers.HyperlinkedIdentityField(
|
|
129
|
+
view_name="plugins-api:netbox_dlm-api:validatedsoftware-detail"
|
|
130
|
+
)
|
|
131
|
+
software_version = SoftwareVersionSerializer(nested=True)
|
|
132
|
+
device_types = DeviceTypeSerializer(nested=True, many=True, required=False)
|
|
133
|
+
device_roles = DeviceRoleSerializer(nested=True, many=True, required=False)
|
|
134
|
+
devices = DeviceSerializer(nested=True, many=True, required=False)
|
|
135
|
+
|
|
136
|
+
class Meta:
|
|
137
|
+
model = ValidatedSoftware
|
|
138
|
+
fields = (
|
|
139
|
+
"id", "url", "display", "software_version", "device_types",
|
|
140
|
+
"device_roles", "devices", "start", "end", "preferred",
|
|
141
|
+
"comments", "tags", "custom_fields", "created", "last_updated",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class CVESerializer(NetBoxModelSerializer):
|
|
146
|
+
url = serializers.HyperlinkedIdentityField(
|
|
147
|
+
view_name="plugins-api:netbox_dlm-api:cve-detail"
|
|
148
|
+
)
|
|
149
|
+
status = ChoiceField(choices=CVEStatusChoices, required=False)
|
|
150
|
+
severity = ChoiceField(choices=CVESeverityChoices, required=False)
|
|
151
|
+
affected_software = SoftwareVersionSerializer(nested=True, many=True, required=False)
|
|
152
|
+
|
|
153
|
+
class Meta:
|
|
154
|
+
model = CVE
|
|
155
|
+
fields = (
|
|
156
|
+
"id", "url", "display", "cve_id", "name", "description",
|
|
157
|
+
"published_date", "link", "status", "severity", "cvss_score",
|
|
158
|
+
"cvss_v2_score", "cvss_v3_score", "affected_software", "comments",
|
|
159
|
+
"tags", "custom_fields", "created", "last_updated",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class VulnerabilitySerializer(NetBoxModelSerializer):
|
|
164
|
+
url = serializers.HyperlinkedIdentityField(
|
|
165
|
+
view_name="plugins-api:netbox_dlm-api:vulnerability-detail"
|
|
166
|
+
)
|
|
167
|
+
cve = CVESerializer(nested=True)
|
|
168
|
+
software_version = SoftwareVersionSerializer(nested=True)
|
|
169
|
+
device = DeviceSerializer(nested=True, required=False, allow_null=True)
|
|
170
|
+
status = ChoiceField(choices=VulnerabilityStatusChoices, required=False)
|
|
171
|
+
|
|
172
|
+
class Meta:
|
|
173
|
+
model = Vulnerability
|
|
174
|
+
fields = (
|
|
175
|
+
"id", "url", "display", "cve", "software_version", "device",
|
|
176
|
+
"status", "comments", "tags", "custom_fields", "created", "last_updated",
|
|
177
|
+
)
|
netbox_dlm/api/urls.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from netbox.api.routers import NetBoxRouter
|
|
2
|
+
|
|
3
|
+
from . import views
|
|
4
|
+
|
|
5
|
+
app_name = "netbox_dlm-api"
|
|
6
|
+
|
|
7
|
+
router = NetBoxRouter()
|
|
8
|
+
|
|
9
|
+
router.register("providers", views.ProviderViewSet)
|
|
10
|
+
router.register("contracts", views.ContractViewSet)
|
|
11
|
+
router.register("hardware-notices", views.HardwareNoticeViewSet)
|
|
12
|
+
router.register("software-versions", views.SoftwareVersionViewSet)
|
|
13
|
+
router.register("software-images", views.SoftwareImageFileViewSet)
|
|
14
|
+
router.register("device-software", views.DeviceSoftwareViewSet)
|
|
15
|
+
router.register("validated-software", views.ValidatedSoftwareViewSet)
|
|
16
|
+
router.register("cves", views.CVEViewSet)
|
|
17
|
+
router.register("vulnerabilities", views.VulnerabilityViewSet)
|
|
18
|
+
|
|
19
|
+
urlpatterns = router.urls
|
netbox_dlm/api/views.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from netbox.api.viewsets import NetBoxModelViewSet
|
|
2
|
+
|
|
3
|
+
from .. import filtersets
|
|
4
|
+
from ..models import (
|
|
5
|
+
CVE,
|
|
6
|
+
Contract,
|
|
7
|
+
DeviceSoftware,
|
|
8
|
+
HardwareNotice,
|
|
9
|
+
Provider,
|
|
10
|
+
SoftwareImageFile,
|
|
11
|
+
SoftwareVersion,
|
|
12
|
+
ValidatedSoftware,
|
|
13
|
+
Vulnerability,
|
|
14
|
+
)
|
|
15
|
+
from . import serializers
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ProviderViewSet(NetBoxModelViewSet):
|
|
19
|
+
queryset = Provider.objects.all()
|
|
20
|
+
serializer_class = serializers.ProviderSerializer
|
|
21
|
+
filterset_class = filtersets.ProviderFilterSet
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ContractViewSet(NetBoxModelViewSet):
|
|
25
|
+
queryset = Contract.objects.prefetch_related("provider", "devices", "tags")
|
|
26
|
+
serializer_class = serializers.ContractSerializer
|
|
27
|
+
filterset_class = filtersets.ContractFilterSet
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class HardwareNoticeViewSet(NetBoxModelViewSet):
|
|
31
|
+
queryset = HardwareNotice.objects.prefetch_related("device_type", "module_type", "tags")
|
|
32
|
+
serializer_class = serializers.HardwareNoticeSerializer
|
|
33
|
+
filterset_class = filtersets.HardwareNoticeFilterSet
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SoftwareVersionViewSet(NetBoxModelViewSet):
|
|
37
|
+
queryset = SoftwareVersion.objects.prefetch_related("platform", "tags")
|
|
38
|
+
serializer_class = serializers.SoftwareVersionSerializer
|
|
39
|
+
filterset_class = filtersets.SoftwareVersionFilterSet
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SoftwareImageFileViewSet(NetBoxModelViewSet):
|
|
43
|
+
queryset = SoftwareImageFile.objects.prefetch_related("software_version", "tags")
|
|
44
|
+
serializer_class = serializers.SoftwareImageFileSerializer
|
|
45
|
+
filterset_class = filtersets.SoftwareImageFileFilterSet
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class DeviceSoftwareViewSet(NetBoxModelViewSet):
|
|
49
|
+
queryset = DeviceSoftware.objects.prefetch_related("device", "software_version", "tags")
|
|
50
|
+
serializer_class = serializers.DeviceSoftwareSerializer
|
|
51
|
+
filterset_class = filtersets.DeviceSoftwareFilterSet
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ValidatedSoftwareViewSet(NetBoxModelViewSet):
|
|
55
|
+
queryset = ValidatedSoftware.objects.prefetch_related(
|
|
56
|
+
"software_version", "device_types", "device_roles", "devices", "tags"
|
|
57
|
+
)
|
|
58
|
+
serializer_class = serializers.ValidatedSoftwareSerializer
|
|
59
|
+
filterset_class = filtersets.ValidatedSoftwareFilterSet
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CVEViewSet(NetBoxModelViewSet):
|
|
63
|
+
queryset = CVE.objects.prefetch_related("affected_software", "tags")
|
|
64
|
+
serializer_class = serializers.CVESerializer
|
|
65
|
+
filterset_class = filtersets.CVEFilterSet
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class VulnerabilityViewSet(NetBoxModelViewSet):
|
|
69
|
+
queryset = Vulnerability.objects.prefetch_related("cve", "software_version", "device", "tags")
|
|
70
|
+
serializer_class = serializers.VulnerabilitySerializer
|
|
71
|
+
filterset_class = filtersets.VulnerabilityFilterSet
|
netbox_dlm/choices.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from utilities.choices import ChoiceSet
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HashingAlgorithmChoices(ChoiceSet):
|
|
5
|
+
key = "SoftwareImageFile.hashing_algorithm"
|
|
6
|
+
|
|
7
|
+
MD5 = "md5"
|
|
8
|
+
SHA1 = "sha1"
|
|
9
|
+
SHA256 = "sha256"
|
|
10
|
+
SHA512 = "sha512"
|
|
11
|
+
|
|
12
|
+
CHOICES = [
|
|
13
|
+
(MD5, "MD5"),
|
|
14
|
+
(SHA1, "SHA1"),
|
|
15
|
+
(SHA256, "SHA256"),
|
|
16
|
+
(SHA512, "SHA512"),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ContractSupportLevelChoices(ChoiceSet):
|
|
21
|
+
key = "Contract.support_level"
|
|
22
|
+
|
|
23
|
+
BASIC = "basic"
|
|
24
|
+
STANDARD = "standard"
|
|
25
|
+
ENHANCED = "enhanced"
|
|
26
|
+
PREMIUM = "premium"
|
|
27
|
+
NEXT_BUSINESS_DAY = "next_business_day"
|
|
28
|
+
FOUR_HOUR = "four_hour_onsite"
|
|
29
|
+
NONE = "none"
|
|
30
|
+
|
|
31
|
+
CHOICES = [
|
|
32
|
+
(BASIC, "Basic"),
|
|
33
|
+
(STANDARD, "Standard"),
|
|
34
|
+
(ENHANCED, "Enhanced"),
|
|
35
|
+
(PREMIUM, "Premium"),
|
|
36
|
+
(NEXT_BUSINESS_DAY, "Next Business Day"),
|
|
37
|
+
(FOUR_HOUR, "4-Hour Onsite"),
|
|
38
|
+
(NONE, "None"),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CVESeverityChoices(ChoiceSet):
|
|
43
|
+
key = "CVE.severity"
|
|
44
|
+
|
|
45
|
+
NONE = "none"
|
|
46
|
+
LOW = "low"
|
|
47
|
+
MEDIUM = "medium"
|
|
48
|
+
HIGH = "high"
|
|
49
|
+
CRITICAL = "critical"
|
|
50
|
+
|
|
51
|
+
CHOICES = [
|
|
52
|
+
(NONE, "None", "gray"),
|
|
53
|
+
(LOW, "Low", "blue"),
|
|
54
|
+
(MEDIUM, "Medium", "yellow"),
|
|
55
|
+
(HIGH, "High", "orange"),
|
|
56
|
+
(CRITICAL, "Critical", "red"),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CVEStatusChoices(ChoiceSet):
|
|
61
|
+
key = "CVE.status"
|
|
62
|
+
|
|
63
|
+
AWAITING_REVIEW = "awaiting_review"
|
|
64
|
+
IN_REVIEW = "in_review"
|
|
65
|
+
RESOLVED = "resolved"
|
|
66
|
+
FALSE_POSITIVE = "false_positive"
|
|
67
|
+
|
|
68
|
+
CHOICES = [
|
|
69
|
+
(AWAITING_REVIEW, "Awaiting Review", "cyan"),
|
|
70
|
+
(IN_REVIEW, "In Review", "blue"),
|
|
71
|
+
(RESOLVED, "Resolved", "green"),
|
|
72
|
+
(FALSE_POSITIVE, "False Positive", "gray"),
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class VulnerabilityStatusChoices(ChoiceSet):
|
|
77
|
+
key = "Vulnerability.status"
|
|
78
|
+
|
|
79
|
+
OPEN = "open"
|
|
80
|
+
MITIGATED = "mitigated"
|
|
81
|
+
RESOLVED = "resolved"
|
|
82
|
+
ACCEPTED_RISK = "accepted_risk"
|
|
83
|
+
IGNORED = "ignored"
|
|
84
|
+
|
|
85
|
+
CHOICES = [
|
|
86
|
+
(OPEN, "Open", "red"),
|
|
87
|
+
(MITIGATED, "Mitigated", "yellow"),
|
|
88
|
+
(RESOLVED, "Resolved", "green"),
|
|
89
|
+
(ACCEPTED_RISK, "Accepted Risk", "purple"),
|
|
90
|
+
(IGNORED, "Ignored", "gray"),
|
|
91
|
+
]
|
netbox_dlm/filtersets.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import django_filters
|
|
2
|
+
from django.db.models import Q
|
|
3
|
+
|
|
4
|
+
from dcim.models import Device, DeviceRole, DeviceType, ModuleType, Platform
|
|
5
|
+
from netbox.filtersets import NetBoxModelFilterSet
|
|
6
|
+
|
|
7
|
+
from .choices import (
|
|
8
|
+
ContractSupportLevelChoices,
|
|
9
|
+
CVESeverityChoices,
|
|
10
|
+
CVEStatusChoices,
|
|
11
|
+
VulnerabilityStatusChoices,
|
|
12
|
+
)
|
|
13
|
+
from .models import (
|
|
14
|
+
CVE,
|
|
15
|
+
Contract,
|
|
16
|
+
DeviceSoftware,
|
|
17
|
+
HardwareNotice,
|
|
18
|
+
Provider,
|
|
19
|
+
SoftwareImageFile,
|
|
20
|
+
SoftwareVersion,
|
|
21
|
+
ValidatedSoftware,
|
|
22
|
+
Vulnerability,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ProviderFilterSet(NetBoxModelFilterSet):
|
|
27
|
+
class Meta:
|
|
28
|
+
model = Provider
|
|
29
|
+
fields = ("id", "name", "phone", "email")
|
|
30
|
+
|
|
31
|
+
def search(self, queryset, name, value):
|
|
32
|
+
if not value.strip():
|
|
33
|
+
return queryset
|
|
34
|
+
return queryset.filter(
|
|
35
|
+
Q(name__icontains=value) | Q(email__icontains=value) | Q(phone__icontains=value)
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ContractFilterSet(NetBoxModelFilterSet):
|
|
40
|
+
provider_id = django_filters.ModelMultipleChoiceFilter(queryset=Provider.objects.all())
|
|
41
|
+
support_level = django_filters.MultipleChoiceFilter(choices=ContractSupportLevelChoices)
|
|
42
|
+
device_id = django_filters.ModelMultipleChoiceFilter(
|
|
43
|
+
field_name="devices", queryset=Device.objects.all()
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
class Meta:
|
|
47
|
+
model = Contract
|
|
48
|
+
fields = ("id", "name", "contract_number", "provider_id", "support_level")
|
|
49
|
+
|
|
50
|
+
def search(self, queryset, name, value):
|
|
51
|
+
if not value.strip():
|
|
52
|
+
return queryset
|
|
53
|
+
return queryset.filter(Q(name__icontains=value) | Q(contract_number__icontains=value))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class HardwareNoticeFilterSet(NetBoxModelFilterSet):
|
|
57
|
+
device_type_id = django_filters.ModelMultipleChoiceFilter(queryset=DeviceType.objects.all())
|
|
58
|
+
module_type_id = django_filters.ModelMultipleChoiceFilter(queryset=ModuleType.objects.all())
|
|
59
|
+
|
|
60
|
+
class Meta:
|
|
61
|
+
model = HardwareNotice
|
|
62
|
+
fields = ("id", "device_type_id", "module_type_id")
|
|
63
|
+
|
|
64
|
+
def search(self, queryset, name, value):
|
|
65
|
+
if not value.strip():
|
|
66
|
+
return queryset
|
|
67
|
+
return queryset.filter(
|
|
68
|
+
Q(device_type__model__icontains=value) | Q(module_type__model__icontains=value)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SoftwareVersionFilterSet(NetBoxModelFilterSet):
|
|
73
|
+
platform_id = django_filters.ModelMultipleChoiceFilter(queryset=Platform.objects.all())
|
|
74
|
+
long_term_support = django_filters.BooleanFilter()
|
|
75
|
+
|
|
76
|
+
class Meta:
|
|
77
|
+
model = SoftwareVersion
|
|
78
|
+
fields = ("id", "platform_id", "version", "long_term_support")
|
|
79
|
+
|
|
80
|
+
def search(self, queryset, name, value):
|
|
81
|
+
if not value.strip():
|
|
82
|
+
return queryset
|
|
83
|
+
return queryset.filter(Q(version__icontains=value) | Q(alias__icontains=value))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class SoftwareImageFileFilterSet(NetBoxModelFilterSet):
|
|
87
|
+
software_version_id = django_filters.ModelMultipleChoiceFilter(
|
|
88
|
+
queryset=SoftwareVersion.objects.all()
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
class Meta:
|
|
92
|
+
model = SoftwareImageFile
|
|
93
|
+
fields = ("id", "software_version_id", "file_name", "default_image")
|
|
94
|
+
|
|
95
|
+
def search(self, queryset, name, value):
|
|
96
|
+
if not value.strip():
|
|
97
|
+
return queryset
|
|
98
|
+
return queryset.filter(Q(file_name__icontains=value) | Q(checksum__icontains=value))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class DeviceSoftwareFilterSet(NetBoxModelFilterSet):
|
|
102
|
+
device_id = django_filters.ModelMultipleChoiceFilter(queryset=Device.objects.all())
|
|
103
|
+
software_version_id = django_filters.ModelMultipleChoiceFilter(
|
|
104
|
+
queryset=SoftwareVersion.objects.all()
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
class Meta:
|
|
108
|
+
model = DeviceSoftware
|
|
109
|
+
fields = ("id", "device_id", "software_version_id")
|
|
110
|
+
|
|
111
|
+
def search(self, queryset, name, value):
|
|
112
|
+
if not value.strip():
|
|
113
|
+
return queryset
|
|
114
|
+
return queryset.filter(Q(device__name__icontains=value))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class ValidatedSoftwareFilterSet(NetBoxModelFilterSet):
|
|
118
|
+
software_version_id = django_filters.ModelMultipleChoiceFilter(
|
|
119
|
+
queryset=SoftwareVersion.objects.all()
|
|
120
|
+
)
|
|
121
|
+
device_type_id = django_filters.ModelMultipleChoiceFilter(
|
|
122
|
+
field_name="device_types", queryset=DeviceType.objects.all()
|
|
123
|
+
)
|
|
124
|
+
device_role_id = django_filters.ModelMultipleChoiceFilter(
|
|
125
|
+
field_name="device_roles", queryset=DeviceRole.objects.all()
|
|
126
|
+
)
|
|
127
|
+
preferred = django_filters.BooleanFilter()
|
|
128
|
+
|
|
129
|
+
class Meta:
|
|
130
|
+
model = ValidatedSoftware
|
|
131
|
+
fields = ("id", "software_version_id", "preferred")
|
|
132
|
+
|
|
133
|
+
def search(self, queryset, name, value):
|
|
134
|
+
return queryset
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class CVEFilterSet(NetBoxModelFilterSet):
|
|
138
|
+
severity = django_filters.MultipleChoiceFilter(choices=CVESeverityChoices)
|
|
139
|
+
status = django_filters.MultipleChoiceFilter(choices=CVEStatusChoices)
|
|
140
|
+
affected_software_id = django_filters.ModelMultipleChoiceFilter(
|
|
141
|
+
field_name="affected_software", queryset=SoftwareVersion.objects.all()
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
class Meta:
|
|
145
|
+
model = CVE
|
|
146
|
+
fields = ("id", "cve_id", "severity", "status")
|
|
147
|
+
|
|
148
|
+
def search(self, queryset, name, value):
|
|
149
|
+
if not value.strip():
|
|
150
|
+
return queryset
|
|
151
|
+
return queryset.filter(
|
|
152
|
+
Q(cve_id__icontains=value) | Q(name__icontains=value) | Q(description__icontains=value)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class VulnerabilityFilterSet(NetBoxModelFilterSet):
|
|
157
|
+
cve_id = django_filters.ModelMultipleChoiceFilter(queryset=CVE.objects.all())
|
|
158
|
+
device_id = django_filters.ModelMultipleChoiceFilter(queryset=Device.objects.all())
|
|
159
|
+
software_version_id = django_filters.ModelMultipleChoiceFilter(
|
|
160
|
+
queryset=SoftwareVersion.objects.all()
|
|
161
|
+
)
|
|
162
|
+
status = django_filters.MultipleChoiceFilter(choices=VulnerabilityStatusChoices)
|
|
163
|
+
|
|
164
|
+
class Meta:
|
|
165
|
+
model = Vulnerability
|
|
166
|
+
fields = ("id", "cve_id", "device_id", "software_version_id", "status")
|
|
167
|
+
|
|
168
|
+
def search(self, queryset, name, value):
|
|
169
|
+
return queryset
|