Skip to content

Commit

Permalink
Merge pull request #2168 from MaibornWolff/dev
Browse files Browse the repository at this point in the history
chore: merge to main for release 1.22.0
  • Loading branch information
StefanFl authored Nov 7, 2024
2 parents 1cad389 + c79440b commit 76dbfdf
Show file tree
Hide file tree
Showing 85 changed files with 4,447 additions and 968 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/scan_sca_current.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: 'v1.21.0'
ref: 'v1.22.0'
-
name: Run SCA vulnerability scanners
uses: MaibornWolff/secobserve_actions_templates/actions/vulnerability_scanner@6eefe400d9efeaae2b7abe05710785fa4a53dbf6 # main
Expand Down
2 changes: 1 addition & 1 deletion backend/application/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.21.0"
__version__ = "1.22.0"

import pymysql

Expand Down
6 changes: 6 additions & 0 deletions backend/application/access_control/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class UserPasswortRulesSerializer(Serializer):
class AuthorizationGroupSerializer(ModelSerializer):
has_product_group_members = SerializerMethodField()
has_product_members = SerializerMethodField()
has_users = SerializerMethodField()
is_manager = SerializerMethodField()

class Meta:
Expand All @@ -203,6 +204,11 @@ def get_has_product_members(self, obj: Authorization_Group) -> bool:
authorization_group=obj, product__is_product_group=False
).exists()

def get_has_users(self, obj: Authorization_Group) -> bool:
return Authorization_Group_Member.objects.filter(
authorization_group=obj
).exists()

def get_is_manager(self, obj: Authorization_Group) -> bool:
user = get_current_user()
return Authorization_Group_Member.objects.filter(
Expand Down
5 changes: 5 additions & 0 deletions backend/application/core/services/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ def normalize_description(observation):
while observation.description.endswith("\n"):
observation.description = observation.description[:-1]

# \u0000 can lead to SQL exceptions
observation.description = observation.description.replace(
"\u0000", "REDACTED_NULL"
)


def normalize_origin_component(observation): # pylint: disable=too-many-branches
if not observation.origin_component_name_version:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,26 @@ def _get_component(self, component_data: dict[str, Any]) -> Optional[Component]:
if not component_data.get("bom-ref"):
return None

unknown_license = ""
unknown_licenses = []
licenses = component_data.get("licenses", [])
if licenses and licenses[0].get("expression"):
unknown_license = licenses[0].get("expression")
unknown_licenses.append(licenses[0].get("expression"))
else:
unknown_license_ids = []
unknown_license_names = []
for my_license in licenses:
component_license = my_license.get("license", {}).get("id")
if component_license:
unknown_license += (
f", {component_license}"
if unknown_license
else component_license
)
unknown_license_ids.append(component_license)

component_license = my_license.get("license", {}).get("name")
if component_license:
unknown_license_names.append(component_license)

if unknown_license_ids:
unknown_licenses = unknown_license_ids
else:
unknown_licenses = unknown_license_names

return Component(
bom_ref=component_data.get("bom-ref", ""),
Expand All @@ -145,7 +152,7 @@ def _get_component(self, component_data: dict[str, Any]) -> Optional[Component]:
purl=component_data.get("purl", ""),
cpe=component_data.get("cpe", ""),
json=component_data,
unknown_license=unknown_license,
unknown_license=", ".join(unknown_licenses),
)

def _create_observations( # pylint: disable=too-many-locals
Expand Down
20 changes: 19 additions & 1 deletion backend/application/import_observations/parsers/ocsf/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
StatusID,
)
from py_ocsf_models.events.findings.finding import ActivityID
from rest_framework.exceptions import ValidationError
from semver import Version

from application.core.models import Observation
from application.core.types import Severity
Expand Down Expand Up @@ -56,6 +58,22 @@ def check_format(self, file: File) -> tuple[bool, list[str], dict | list]:
{},
)

tool_name = (
first_element.get("metadata", {}).get("product", {}).get("name", "")
)
tool_version = (
first_element.get("metadata", {}).get("product", {}).get("version", "")
)
if tool_name == "Prowler":
if not tool_version or Version.parse(tool_version) < Version.parse(
"4.5.0"
):
return (
False,
["Prowler is only supported with version 4.5.0 and above"],
{},
)

return True, [], data

def get_observations(self, data: list) -> list[Observation]:
Expand Down Expand Up @@ -108,7 +126,7 @@ def get_observations(self, data: list) -> list[Observation]:

observation.unsaved_references = get_references(finding)
except Exception as e:
logger.warning("Error parsing OCSF finding: %s", str(e))
raise ValidationError(f"Error parsing OCSF finding: {str(e)}") from e

return observations

Expand Down
44 changes: 42 additions & 2 deletions backend/application/licenses/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
License,
License_Component,
License_Group,
License_Group_Authorization_Group_Member,
License_Group_Member,
License_Policy,
License_Policy_Authorization_Group_Member,
License_Policy_Item,
License_Policy_Member,
)
Expand Down Expand Up @@ -133,12 +135,31 @@ class LicenseGroupMemberFilter(FilterSet):
("user__full_name", "user_data.full_name"),
("license_group", "license_group"),
("user", "user"),
("is_manager", "is_manager"),
),
)

class Meta:
model = License_Group_Member
fields = ["license_group", "user", "username", "full_name"]
fields = ["license_group", "user", "username", "full_name", "is_manager"]


class LicenseGroupAuthorizationGroupFilter(FilterSet):
name = CharFilter(field_name="authorization_group__name", lookup_expr="icontains")

ordering = OrderingFilter(
# tuple-mapping retains order
fields=(
("authorization_group__name", "authorization_group_data.name"),
("license_group", "license_group"),
("authorization_group", "authorization_group"),
("is_manager", "is_manager"),
),
)

class Meta:
model = License_Group_Authorization_Group_Member
fields = ["license_group", "authorization_group", "name", "is_manager"]


class LicensePolicyFilter(FilterSet):
Expand Down Expand Up @@ -233,9 +254,28 @@ class LicensePolicyMemberFilter(FilterSet):
("user__full_name", "user_data.full_name"),
("license_policy", "license_policy"),
("user", "user"),
("is_manager", "is_manager"),
),
)

class Meta:
model = License_Policy_Member
fields = ["license_policy", "user", "username", "full_name"]
fields = ["license_policy", "user", "username", "full_name", "is_manager"]


class LicensePolicyAuthorizationGroupFilter(FilterSet):
name = CharFilter(field_name="authorization_group__name", lookup_expr="icontains")

ordering = OrderingFilter(
# tuple-mapping retains order
fields=(
("authorization_group__name", "authorization_group_data.name"),
("license_policy", "license_policy"),
("authorization_group", "authorization_group"),
("is_manager", "is_manager"),
),
)

class Meta:
model = License_Policy_Authorization_Group_Member
fields = ["license_policy", "authorization_group", "name", "is_manager"]
90 changes: 76 additions & 14 deletions backend/application/licenses/api/permissions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from django.shortcuts import get_object_or_404
from rest_framework.exceptions import NotFound
from rest_framework.permissions import BasePermission

from application.access_control.queries.authorization_group import (
get_authorization_groups,
)
from application.licenses.models import (
License_Group,
License_Group_Authorization_Group_Member,
License_Group_Member,
License_Policy,
License_Policy_Authorization_Group_Member,
License_Policy_Member,
)

Expand Down Expand Up @@ -40,6 +46,30 @@ def has_object_permission(self, request, view, obj: License_Group_Member):
return True


class UserHasLicenseGroupAuthenticationGroupMemberPermission(BasePermission):
def has_permission(self, request, view):
if request.method == "POST":
license_group = get_object_or_404(
License_Group, pk=request.data.get("license_group")
)

authorization_groups = get_authorization_groups().values_list(
"id", flat=True
)
if request.data.get("authorization_group") not in authorization_groups:
raise NotFound("Authorization_Group not found.")

return _has_license_group_manage_permission(request, license_group)

return True

def has_object_permission(self, request, view, obj: License_Group_Member):
if request.method != "GET":
return _has_license_group_manage_permission(request, obj.license_group)

return True


class UserHasLicensePolicyPermission(BasePermission):
def has_permission(self, request, view):
if request.method == "POST":
Expand Down Expand Up @@ -71,18 +101,46 @@ def has_object_permission(self, request, view, obj: License_Policy_Member):
return True


class UserHasLicensePolicyAuthorizationGroupMemberPermission(BasePermission):
def has_permission(self, request, view):
if request.method == "POST":
license_policy = get_object_or_404(
License_Policy, pk=request.data.get("license_policy")
)

authorization_groups = get_authorization_groups().values_list(
"id", flat=True
)
if request.data.get("authorization_group") not in authorization_groups:
raise NotFound("Authorization_Group not found.")

return _has_license_policy_manage_permission(request, license_policy)

return True

def has_object_permission(self, request, view, obj: License_Policy_Member):
if request.method != "GET":
return _has_license_policy_manage_permission(request, obj.license_policy)

return True


def _has_license_group_manage_permission(request, license_group: License_Group) -> bool:
user = request.user
if user and user.is_superuser:
return True

try:
license_group_member = License_Group_Member.objects.get(
license_group=license_group, user=user
)
return license_group_member.is_manager
except License_Group_Member.DoesNotExist:
return False
if License_Group_Member.objects.filter(
license_group=license_group, user=user, is_manager=True
).exists():
return True

if License_Group_Authorization_Group_Member.objects.filter(
license_group=license_group, authorization_group__users=user, is_manager=True
).exists():
return True

return False


def _has_license_policy_manage_permission(
Expand All @@ -92,10 +150,14 @@ def _has_license_policy_manage_permission(
if user and user.is_superuser:
return True

try:
license_policy_member = License_Policy_Member.objects.get(
license_policy=license_policy, user=user
)
return license_policy_member.is_manager
except License_Policy_Member.DoesNotExist:
return False
if License_Policy_Member.objects.filter(
license_policy=license_policy, user=user, is_manager=True
).exists():
return True

if License_Policy_Authorization_Group_Member.objects.filter(
license_policy=license_policy, authorization_group__users=user, is_manager=True
).exists():
return True

return False
Loading

0 comments on commit 76dbfdf

Please sign in to comment.