Skip to content

Commit

Permalink
Merge branch 'main' into CA-701-workshop-1-UX
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene committed Dec 12, 2024
2 parents 0159c68 + 12085fc commit 8eaa1ba
Show file tree
Hide file tree
Showing 30 changed files with 1,623 additions and 1,253 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
*.pyc
*.DS_Store
*~$*
**/*.mo
.git*
.pytest*
.idea*
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Check out the online documentation on <https://intuitem.gitbook.io/ciso-assistan
61. ECB Cyber resilience oversight expectations for financial market infrastructures 🇪🇺
62. Mindeststandard-des-BSI-zur-Nutzung-externer-Cloud-Dienste (Version 2.1) 🇩🇪
63. Formulaire d'évaluation de la maturité - niveau fondamental (DGA) 🇫🇷
64. Annex to the Implementing Regulation of NIS 2 on Technical and methodological requirements 🇪🇺
64. NIS2 technical and methodological requirements 2024/2690 🇪🇺

### Community contributions

Expand Down
1 change: 0 additions & 1 deletion backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
*.pyc
*.DS_Store
*~$*
**/*.mo
.git*
.pytest*
.idea*
Expand Down
4 changes: 2 additions & 2 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Based on https://docs.docker.com/samples/django/

FROM python:3.11-alpine
FROM python:3.12-alpine
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1

Expand All @@ -26,7 +26,7 @@ COPY poetry.lock /code/
COPY startup.sh /code/

RUN pip install --upgrade pip && \
pip install poetry==1.8.3
pip install poetry==1.8.5
RUN poetry install
RUN rm -rf $POETRY_CACHE_DIR

Expand Down
2 changes: 0 additions & 2 deletions backend/app_tests/api/test_api_requirement_assessments.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ def test_get_requirement_assessments(self, test):
"str": compliance_assessment.name,
},
"requirement": {
"str": str(RequirementNode.objects.all()[0]),
"id": str(RequirementNode.objects.all()[0].id),
"urn": RequirementNode.objects.all()[0].urn,
"annotation": RequirementNode.objects.all()[0].annotation,
Expand Down Expand Up @@ -252,7 +251,6 @@ def test_update_requirement_assessments(self, test):
"str": compliance_assessment.name,
},
"requirement": {
"str": str(RequirementNode.objects.all()[0]),
"id": str(RequirementNode.objects.all()[0].id),
"urn": RequirementNode.objects.all()[0].urn,
"annotation": RequirementNode.objects.all()[0].annotation,
Expand Down
26 changes: 26 additions & 0 deletions backend/core/migrations/0046_riskassessment_ebios_rm_study.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 5.1.4 on 2024-12-11 11:07

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("core", "0045_alter_appliedcontrol_category_and_more"),
("ebios_rm", "0003_remove_ebiosrmstudy_risk_assessments"),
]

operations = [
migrations.AddField(
model_name="riskassessment",
name="ebios_rm_study",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="risk_assessments",
to="ebios_rm.ebiosrmstudy",
verbose_name="EBIOS RM study",
),
),
]
26 changes: 25 additions & 1 deletion backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,12 +1581,28 @@ def get_security_objectives_display(self) -> list[dict[str, str]]:
]

def get_disaster_recovery_objectives_display(self) -> list[dict[str, str]]:
def format_seconds(seconds: int) -> str:
hours, remainder = divmod(seconds, 3600)
minutes, secs = divmod(remainder, 60)

parts = []
if hours > 0:
parts.append(f"{hours}h")
if minutes > 0:
parts.append(f"{minutes:02d}m")
if secs > 0 or (
not parts
): # Always show seconds if no other parts, or if > 0
parts.append(f"{secs:02d}s")

return "".join(parts)

"""
Gets the disaster recovery objectives of a given asset as strings.
"""
disaster_recovery_objectives = self.get_disaster_recovery_objectives()
return [
{"str": f"{key}: {content.get('value', 0)}"}
{"str": f"{key}: {format_seconds(content.get('value', 0))}"}
for key, content in disaster_recovery_objectives.get(
"objectives", {}
).items()
Expand Down Expand Up @@ -1981,6 +1997,14 @@ class RiskAssessment(Assessment):
ref_id = models.CharField(
max_length=100, null=True, blank=True, verbose_name=_("reference id")
)
ebios_rm_study = models.ForeignKey(
"ebios_rm.EbiosRMStudy",
verbose_name=_("EBIOS RM study"),
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="risk_assessments",
)

class Meta:
verbose_name = _("Risk assessment")
Expand Down
47 changes: 32 additions & 15 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class RiskAssessmentReadSerializer(AssessmentReadSerializer):

class Meta:
model = RiskAssessment
fields = "__all__"
exclude = ["ebios_rm_study"]


class AssetWriteSerializer(BaseModelSerializer):
Expand All @@ -228,6 +228,20 @@ class Meta:
model = Asset
fields = "__all__"

def validate_parent_assets(self, parent_assets):
"""
Check that the assets graph will not contain cycles
"""
if not self.instance:
return parent_assets
if parent_assets:
for asset in parent_assets:
if self.instance in asset.ancestors_plus_self():
raise serializers.ValidationError(
"errorAssetGraphMustNotContainCycles"
)
return parent_assets


class AssetReadSerializer(AssetWriteSerializer):
folder = FieldsRelatedField()
Expand Down Expand Up @@ -629,26 +643,29 @@ class Meta:


class RequirementAssessmentReadSerializer(BaseModelSerializer):
class FilteredNodeSerializer(RequirementNodeReadSerializer):
class Meta:
model = RequirementNode
fields = [
"id",
"urn",
"annotation",
"name",
"description",
"typical_evidence",
"ref_id",
"associated_reference_controls",
"associated_threats",
"parent_requirement",
]

name = serializers.CharField(source="__str__")
description = serializers.CharField(source="get_requirement_description")
evidences = FieldsRelatedField(many=True)
compliance_assessment = FieldsRelatedField()
folder = FieldsRelatedField()
assessable = serializers.BooleanField(source="requirement.assessable")
requirement = FieldsRelatedField(
[
"id",
"urn",
"annotation",
"name",
"description",
"typical_evidence",
"ref_id",
"associated_reference_controls",
"associated_threats",
"parent_requirement",
]
)
requirement = FilteredNodeSerializer()

class Meta:
model = RequirementAssessment
Expand Down
1 change: 1 addition & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ class RiskAssessmentViewSet(BaseModelViewSet):
"authors",
"risk_matrix",
"status",
"ebios_rm_study",
]

@action(detail=False, name="Risk assessments per status")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 5.1.4 on 2024-12-11 11:07

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("ebios_rm", "0002_alter_roto_target_objective"),
]

operations = [
migrations.RemoveField(
model_name="ebiosrmstudy",
name="risk_assessments",
),
]
8 changes: 0 additions & 8 deletions backend/ebios_rm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
Asset,
ComplianceAssessment,
Qualification,
RiskAssessment,
RiskMatrix,
Threat,
)
Expand Down Expand Up @@ -49,13 +48,6 @@ class Status(models.TextChoices):
"Compliance assessments established as security baseline during workshop 1.4"
),
)
risk_assessments = models.ManyToManyField(
RiskAssessment,
blank=True,
verbose_name=_("Risk assessments"),
related_name="ebios_rm_studies",
help_text=_("Risk assessments generated at the end of workshop 4"),
)
reference_entity = models.ForeignKey(
Entity,
on_delete=models.PROTECT,
Expand Down
5 changes: 5 additions & 0 deletions backend/ebios_rm/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class EbiosRMStudyViewSet(BaseModelViewSet):
def status(self, request):
return Response(dict(EbiosRMStudy.Status.choices))

@action(detail=True, name="Get risk matrix", url_path="risk-matrix")
def risk_matrix(self, request, pk=None):
ebios_rm_study = self.get_object()
return Response(RiskMatrixReadSerializer(ebios_rm_study.risk_matrix).data)

@method_decorator(cache_page(60 * LONG_CACHE_TTL))
@action(detail=True, name="Get gravity choices")
def gravity(self, request, pk):
Expand Down
5 changes: 0 additions & 5 deletions backend/iam/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@

import structlog
from django.utils import translation
import os

logger = structlog.get_logger(__name__)

Expand Down Expand Up @@ -287,10 +286,6 @@ def _create_user(
)

logger.info("user created sucessfully", user=user)
FORCE_LANGUAGE = os.environ.get("FORCE_LANGUAGE")
if FORCE_LANGUAGE:
translation.activate(FORCE_LANGUAGE)
print("FORCE_LANGUAGE:", FORCE_LANGUAGE)

if mailing:
try:
Expand Down
Loading

0 comments on commit 8eaa1ba

Please sign in to comment.