Skip to content

Commit b681610

Browse files
Maffoochclaude
andauthored
remove: Credential Manager (2.57 deprecation, 2.59 EOL) (#14836)
* remove: Credential Manager (announced 2.57, EOL in 2.59) Per the 2.59 release notes, retires the Credential Manager feature in its entirety: UI, API, models, DB tables, and the system-settings toggle that gated it. Endpoints removed (now `404`): - /api/v2/credentials/ - /api/v2/credential_mappings/ UI removed: - All `/cred/*`, `/product/<id>/cred/*`, `/engagement/<id>/cred/*`, `/test/<id>/cred/*`, `/finding/<id>/cred/*` routes - "Credential Manager" sidebar entry and per-product Add/View Credentials shortcuts in the navbar - Credential sections from view_test, view_eng, and view_finding Code deleted: - The entire `dojo/cred/` module (views, urls, signals, queries) - All `*cred*.html` templates - `CredMappingForm`, `CredMappingFormProd`, `CredUserForm` in forms.py - `ApiCredentialsFilter` in filters.py - `CredentialsViewSet`, `CredentialsMappingViewSet`, `CredentialSerializer`, `CredentialMappingSerializer`, `UserHasCredentialPermission` - Selenium tests `tests/credential_test.py` and `tests/product_credential_test.py` - The four `Credential_*` permissions and `Permissions.get_credential_permissions()`, plus their entries in every role's permission set - The `Cred_Mapping` reverse-lookup blocks in test/finding/engagement views (and the `cred_form` plumbing in the import-scan flow) - `Cred_User` from audit-log and pghistory tracking lists, including the `Cred_UserEvent` history table Schema dropped via 0265_remove_credential_manager: - `system_settings.enable_credentials` (no longer gates anything) - `Cred_Mapping`, `Cred_User`, `Cred_UserEvent` models, with their pghistory triggers cleared first The 2.59 upgrade doc already documents the removal; nothing to update in `docs/`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: ruff E302 + drop cred refs from fixtures - dojo/authorization/roles_permissions.py: add the second blank line before get_roles_with_permissions() that ruff's E302 demands. - Remove the now-orphan dojo.cred_user / dojo.cred_mapping entries from the three test fixtures, drop watson.searchentry rows pointing at those content types, and strip the gone enable_credentials field from System_Settings entries (the loaddata test was failing on it). The fixture normalization picks up small indentation diffs in unrelated sections (Python's json.dump uses one consistent indent) but the data is unchanged otherwise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: drop credential_manager refs from sample_data_locations fixture + matrix - dojo/fixtures/defect_dojo_sample_data_locations.json: missed in the previous fixture sweep — strip enable_credentials, cred_user / cred_mapping rows, and the matching watson.searchentry rows so loaddata stops failing. - .github/workflows/integration-tests.yml: drop the credential_test.py and product_credential_test.py entries from the UI test matrix; both files were deleted in this PR and CI was failing trying to run them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: drop cred_user from configuration permissions list dojo/user/utils.py left a Permission_Helper(name="cred user", ...) in the configuration-permissions form that drives /user/<id>/edit_permissions and /group/<id>/edit_permissions. With Cred_User gone, the underlying view_cred_user / add_cred_user / change_cred_user / delete_cred_user django auth permissions no longer exist and the form 500s on save — which is what was breaking the group_test and user_test UI integration tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: drop malformed watson.searchentry rows left by bad merge The merge of dev into this branch (2f8f682) collided on the watson search-entry rows: dev removed stub_finding entries while this branch removed cred_user entries, and the three-way merge dropped only the model name from each conflicting row, leaving six entries per fixture with content_type set to ['dojo'] (a one-element natural key). loaddata then failed with: ContentTypeManager.get_by_natural_key() missing 1 required positional argument: 'model' ... (watson.searchentry:pk=4) field_value was '['dojo']' These rows pointed at the now-removed cred_user content type and were already supposed to be deleted (see 12d749f). Remove them from both fixture files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f50bb18 commit b681610

49 files changed

Lines changed: 59 additions & 3163 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/integration-tests.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jobs:
2222
"tests/check_various_pages.py",
2323
"tests/close_old_findings_dedupe_test.py",
2424
"tests/close_old_findings_test.py",
25-
"tests/credential_test.py",
2625
"tests/dashboard_test.py",
2726
"tests/dedupe_test.py",
2827
"tests/endpoint_extended_test.py",
@@ -46,7 +45,6 @@ jobs:
4645
"tests/notification_webhook_test.py",
4746
"tests/notifications_test.py",
4847
"tests/object_test.py",
49-
"tests/product_credential_test.py",
5048
"tests/product_group_test.py",
5149
"tests/product_member_test.py",
5250
"tests/product_metadata_test.py",

dojo/api_v2/permissions.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from dojo.importers.auto_create_context import AutoCreateContextManager
2121
from dojo.location.models import Location
2222
from dojo.models import (
23-
Cred_Mapping,
2423
Development_Environment,
2524
Dojo_Group,
2625
Endpoint,
@@ -146,38 +145,6 @@ def has_object_permission(self, request, view, obj):
146145
)
147146

148147

149-
class UserHasCredentialPermission(permissions.BasePermission):
150-
def has_permission(self, request, view):
151-
if request.data.get("product") is not None:
152-
return check_post_permission(
153-
request, Cred_Mapping, "product", Permissions.Credential_Add,
154-
)
155-
if request.data.get("engagement") is not None:
156-
return check_post_permission(
157-
request, Cred_Mapping, "engagement", Permissions.Credential_Add,
158-
)
159-
if request.data.get("test") is not None:
160-
return check_post_permission(
161-
request, Cred_Mapping, "test", Permissions.Credential_Add,
162-
)
163-
if request.data.get("finding") is not None:
164-
return check_post_permission(
165-
request, Cred_Mapping, "finding", Permissions.Credential_Add,
166-
)
167-
return check_post_permission(
168-
request, Cred_Mapping, "product", Permissions.Credential_Add,
169-
)
170-
171-
def has_object_permission(self, request, view, obj):
172-
return check_object_permission(
173-
request,
174-
obj.product,
175-
Permissions.Credential_View,
176-
Permissions.Credential_Edit,
177-
Permissions.Credential_Delete,
178-
)
179-
180-
181148
class UserHasDojoGroupPermission(permissions.BasePermission):
182149
def has_permission(self, request, view):
183150
if request.method == "GET":

dojo/api_v2/serializers.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@
5151
App_Analysis,
5252
BurpRawRequestResponse,
5353
Check_List,
54-
Cred_Mapping,
55-
Cred_User,
5654
Development_Environment,
5755
Dojo_Group,
5856
Dojo_Group_Member,
@@ -2144,18 +2142,6 @@ def update(self, instance, validated_data):
21442142
return super().update(instance, validated_data)
21452143

21462144

2147-
class CredentialSerializer(serializers.ModelSerializer):
2148-
class Meta:
2149-
model = Cred_User
2150-
exclude = ("password",)
2151-
2152-
2153-
class CredentialMappingSerializer(serializers.ModelSerializer):
2154-
class Meta:
2155-
model = Cred_Mapping
2156-
fields = "__all__"
2157-
2158-
21592145
class ProductSerializer(serializers.ModelSerializer):
21602146
findings_count = serializers.SerializerMethodField()
21612147
findings_list = serializers.SerializerMethodField()

dojo/api_v2/views.py

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
from dojo.authorization.authorization import user_has_permission_or_403
5050
from dojo.authorization.roles_permissions import Permissions
5151
from dojo.celery_dispatch import dojo_dispatch_task
52-
from dojo.cred.queries import get_authorized_cred_mappings
5352
from dojo.endpoint.queries import (
5453
get_authorized_endpoint_status,
5554
get_authorized_endpoints,
@@ -59,7 +58,6 @@
5958
from dojo.engagement.services import close_engagement, reopen_engagement
6059
from dojo.filters import (
6160
ApiAppAnalysisFilter,
62-
ApiCredentialsFilter,
6361
ApiDojoMetaFilter,
6462
ApiEndpointFilter,
6563
ApiEngagementFilter,
@@ -93,8 +91,6 @@
9391
App_Analysis,
9492
BurpRawRequestResponse,
9593
Check_List,
96-
Cred_Mapping,
97-
Cred_User,
9894
Development_Environment,
9995
Dojo_Group,
10096
Dojo_Group_Member,
@@ -872,130 +868,6 @@ def get_queryset(self):
872868
return get_authorized_app_analysis(Permissions.Product_View)
873869

874870

875-
# Authorization: object-based
876-
@extend_schema_view(**schema_with_prefetch())
877-
class CredentialsViewSet(
878-
PrefetchDojoModelViewSet,
879-
DeprecationNoticeMixin,
880-
):
881-
deprecated = True
882-
end_of_life_date = datetime(2026, 6, 1)
883-
serializer_class = serializers.CredentialSerializer
884-
queryset = Cred_User.objects.all()
885-
filter_backends = (DjangoFilterBackend,)
886-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
887-
888-
def get_queryset(self):
889-
return Cred_User.objects.all().order_by("id")
890-
891-
@extend_schema(
892-
deprecated=True,
893-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
894-
)
895-
def list(self, request, *args, **kwargs):
896-
return super().list(request, *args, **kwargs)
897-
898-
@extend_schema(
899-
deprecated=True,
900-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
901-
)
902-
def retrieve(self, request, *args, **kwargs):
903-
return super().retrieve(request, *args, **kwargs)
904-
905-
@extend_schema(
906-
deprecated=True,
907-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
908-
)
909-
def create(self, request, *args, **kwargs):
910-
return super().create(request, *args, **kwargs)
911-
912-
@extend_schema(
913-
deprecated=True,
914-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
915-
)
916-
def update(self, request, *args, **kwargs):
917-
return super().update(request, *args, **kwargs)
918-
919-
@extend_schema(
920-
deprecated=True,
921-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
922-
)
923-
def partial_update(self, request, *args, **kwargs):
924-
return super().partial_update(request, *args, **kwargs)
925-
926-
@extend_schema(
927-
deprecated=True,
928-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
929-
)
930-
def destroy(self, request, *args, **kwargs):
931-
return super().destroy(request, *args, **kwargs)
932-
933-
934-
# Authorization: configuration
935-
# @extend_schema_view(**schema_with_prefetch())
936-
# Nested models with prefetch make the response schema too long for Swagger UI
937-
class CredentialsMappingViewSet(
938-
PrefetchDojoModelViewSet,
939-
DeprecationNoticeMixin,
940-
):
941-
deprecated = True
942-
end_of_life_date = datetime(2026, 6, 1)
943-
serializer_class = serializers.CredentialMappingSerializer
944-
queryset = Cred_Mapping.objects.none()
945-
filter_backends = (DjangoFilterBackend,)
946-
filterset_class = ApiCredentialsFilter
947-
948-
permission_classes = (
949-
IsAuthenticated,
950-
permissions.UserHasCredentialPermission,
951-
)
952-
953-
def get_queryset(self):
954-
return get_authorized_cred_mappings(Permissions.Credential_View)
955-
956-
@extend_schema(
957-
deprecated=True,
958-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
959-
)
960-
def list(self, request, *args, **kwargs):
961-
return super().list(request, *args, **kwargs)
962-
963-
@extend_schema(
964-
deprecated=True,
965-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
966-
)
967-
def retrieve(self, request, *args, **kwargs):
968-
return super().retrieve(request, *args, **kwargs)
969-
970-
@extend_schema(
971-
deprecated=True,
972-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
973-
)
974-
def create(self, request, *args, **kwargs):
975-
return super().create(request, *args, **kwargs)
976-
977-
@extend_schema(
978-
deprecated=True,
979-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
980-
)
981-
def update(self, request, *args, **kwargs):
982-
return super().update(request, *args, **kwargs)
983-
984-
@extend_schema(
985-
deprecated=True,
986-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
987-
)
988-
def partial_update(self, request, *args, **kwargs):
989-
return super().partial_update(request, *args, **kwargs)
990-
991-
@extend_schema(
992-
deprecated=True,
993-
description="This endpoint is deprecated and will be removed on 2026-06-01.",
994-
)
995-
def destroy(self, request, *args, **kwargs):
996-
return super().destroy(request, *args, **kwargs)
997-
998-
999871
# Authorization: configuration
1000872
class FindingTemplatesViewSet(
1001873
DojoModelViewSet,

dojo/apps.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def ready(self):
7676
# Importing the signals file is good enough if using the receiver decorator
7777
import dojo.announcement.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
7878
import dojo.benchmark.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
79-
import dojo.cred.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8079

8180
# TODO: Delete this after the move to Locations
8281
import dojo.endpoint.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady

dojo/auditlog/backfill.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ def get_excluded_fields(model_name):
2020
excluded_fields_map = {
2121
"Dojo_User": ["password"],
2222
"Product": ["updated"],
23-
"Cred_User": ["password"],
2423
"Notification_Webhooks": ["header_name", "header_value"],
2524
}
2625
return excluded_fields_map.get(model_name, [])
@@ -43,9 +42,6 @@ def get_table_names(model_name):
4342
elif model_name == "Finding_Template":
4443
table_name = "dojo_finding_template"
4544
event_table_name = "dojo_finding_templateevent"
46-
elif model_name == "Cred_User":
47-
table_name = "dojo_cred_user"
48-
event_table_name = "dojo_cred_userevent"
4945
elif model_name == "Notification_Webhooks":
5046
table_name = "dojo_notification_webhooks"
5147
event_table_name = "dojo_notification_webhooksevent"
@@ -366,7 +362,7 @@ def get_tracked_models():
366362
return [
367363
"Dojo_User", "Endpoint", "Engagement", "Finding", "Finding_Group",
368364
"Product_Type", "Product", "Test", "Risk_Acceptance",
369-
"Finding_Template", "Cred_User", "Notification_Webhooks",
365+
"Finding_Template", "Notification_Webhooks",
370366
"FindingReviewers", # M2M through table for Finding.reviewers
371367
"Location", "URL",
372368
# Tag through tables (tagulous auto-generated)

dojo/auditlog/services.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ def register_django_pghistory_models():
151151
from dojo.location.models import Location # noqa: PLC0415
152152
from dojo.models import ( # noqa: PLC0415
153153
App_Analysis,
154-
Cred_User,
155154
Dojo_User,
156155
# TODO: Delete this after the move to Locations
157156
Endpoint,
@@ -312,21 +311,6 @@ def register_django_pghistory_models():
312311
},
313312
)(Finding_Template)
314313

315-
pghistory.track(
316-
pghistory.InsertEvent(),
317-
pghistory.UpdateEvent(condition=pghistory.AnyChange(exclude_auto=True)),
318-
pghistory.DeleteEvent(),
319-
pghistory.ManualEvent(label="initial_backfill"),
320-
exclude=["password"],
321-
meta={
322-
"indexes": [
323-
models.Index(fields=["pgh_created_at"]),
324-
models.Index(fields=["pgh_label"]),
325-
models.Index(fields=["pgh_context_id"]),
326-
],
327-
},
328-
)(Cred_User)
329-
330314
pghistory.track(
331315
pghistory.InsertEvent(),
332316
pghistory.UpdateEvent(condition=pghistory.AnyChange(exclude_auto=True)),

dojo/authorization/authorization.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from dojo.location.models import AbstractLocation, Location
1111
from dojo.models import (
1212
App_Analysis,
13-
Cred_Mapping,
1413
Dojo_Group,
1514
Dojo_Group_Member,
1615
Dojo_User,
@@ -219,25 +218,6 @@ def user_has_permission(user: Dojo_User, obj: Model, permission: int) -> bool:
219218
user, obj.group, permission,
220219
)
221220
return user_has_permission(user, obj.group, permission)
222-
if (
223-
isinstance(obj, Cred_Mapping)
224-
and permission in Permissions.get_credential_permissions()
225-
):
226-
if obj.product:
227-
return user_has_permission(user, obj.product, permission)
228-
if obj.engagement:
229-
return user_has_permission(
230-
user, obj.engagement.product, permission,
231-
)
232-
if obj.test:
233-
return user_has_permission(
234-
user, obj.test.engagement.product, permission,
235-
)
236-
if obj.finding:
237-
return user_has_permission(
238-
user, obj.finding.test.engagement.product, permission,
239-
)
240-
return None
241221
msg = f"No authorization implemented for class {type(obj).__name__} and permission {permission}"
242222
raise NoAuthorizationImplementedError(msg)
243223

0 commit comments

Comments
 (0)