Skip to content

Commit

Permalink
PROD-2134: Adds validation for taxonomy labels (#4982)
Browse files Browse the repository at this point in the history
Adds validation for privacy declaration taxonomy labels when creating / updating a system. Taxonomy labels should exist and have their active attribute set to True.
  • Loading branch information
erosselli authored Jun 14, 2024
1 parent c9124dd commit 3b92387
Show file tree
Hide file tree
Showing 6 changed files with 461 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The types of changes are:
- Fixed "add" icons on some buttons being wrong size [#4975](https://github.com/ethyca/fides/pull/4975)
- Masked "Keyfile credentials" input on integration config form [#4971](https://github.com/ethyca/fides/pull/4971)
- Fixed ability to update consent preferences after they've previously been set [#4984](https://github.com/ethyca/fides/pull/4984)
- Fixed validations for privacy declaration taxonomy labels when creating/updating a System [#4982](https://github.com/ethyca/fides/pull/4982)

## [2.38.0](https://github.com/ethyca/fides/compare/2.37.0...2.38.0)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
"""

from alembic import op
import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision = "a3c173391603"
Expand Down
6 changes: 2 additions & 4 deletions src/fides/api/api/v1/endpoints/consent_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
)
from fides.api.models.property import Property
from fides.api.oauth.utils import verify_oauth_client
from fides.api.schemas.messaging.messaging import MessagingMethod, MessagingActionType
from fides.api.schemas.messaging.messaging import MessagingActionType, MessagingMethod
from fides.api.schemas.privacy_request import BulkPostPrivacyRequests
from fides.api.schemas.privacy_request import Consent as ConsentSchema
from fides.api.schemas.privacy_request import (
Expand All @@ -56,9 +56,7 @@
)
from fides.api.schemas.redis_cache import Identity
from fides.api.service._verification import send_verification_code_to_user
from fides.api.service.messaging.message_dispatch_service import (
message_send_enabled,
)
from fides.api.service.messaging.message_dispatch_service import message_send_enabled
from fides.api.util.api_router import APIRouter
from fides.api.util.consent_util import (
get_or_create_fides_user_device_id_provided_identity,
Expand Down
54 changes: 42 additions & 12 deletions src/fides/api/db/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

import copy
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Dict, List, Optional, Tuple, Type, Union

from deepdiff import DeepDiff
from fastapi import HTTPException
from fideslang.models import Cookies as CookieSchema
from fideslang.models import System as SystemSchema
from fideslang.validation import FidesKey
from loguru import logger as log
from sqlalchemy import and_, delete, insert, select, update
from sqlalchemy.ext.asyncio import AsyncSession
Expand All @@ -20,6 +21,8 @@
from fides.api.db.crud import create_resource, get_resource, update_resource
from fides.api.models.sql_models import ( # type: ignore[attr-defined]
Cookies,
DataCategory,
DataSubject,
DataUse,
PrivacyDeclaration,
System,
Expand Down Expand Up @@ -48,27 +51,54 @@ def get_system(db: Session, fides_key: str) -> System:
return system


async def validate_data_labels(
db: AsyncSession,
sql_model: Union[Type[DataUse], Type[DataSubject], Type[DataCategory]],
labels: List[FidesKey],
) -> None:
"""
Given a model and a list of FidesKeys, check that for each Fides Key
there is a model instance with that key and the active attribute set to True.
If any of the keys don't exist or exist but are not active, raise a 400 error
"""
for label in labels:
try:
resource = await get_resource(
sql_model=sql_model,
fides_key=label,
async_session=db,
)
except NotFoundError:
raise HTTPException(
status_code=HTTP_400_BAD_REQUEST,
detail=f"Invalid privacy declaration referencing unknown {sql_model.__name__} {label}",
)

if not resource.active:
raise HTTPException(
status_code=HTTP_400_BAD_REQUEST,
detail=f"Invalid privacy declaration referencing inactive {sql_model.__name__} {label}",
)


async def validate_privacy_declarations(db: AsyncSession, system: SystemSchema) -> None:
"""
Ensure that the `PrivacyDeclaration`s on the provided `System` resource are valid:
- that they reference valid `DataUse` records
- that they reference valid `DataCategory` records
- that they reference valid `DataSubject` records
- that there are not "duplicate" `PrivacyDeclaration`s as defined by their "logical ID"
If not, a `400` is raised
"""
logical_ids = set()
for privacy_declaration in system.privacy_declarations:
try:
await get_resource(
sql_model=DataUse,
fides_key=privacy_declaration.data_use,
async_session=db,
)
except NotFoundError:
raise HTTPException(
status_code=HTTP_400_BAD_REQUEST,
detail=f"Invalid privacy declaration referencing unknown DataUse {privacy_declaration.data_use}",
)
await validate_data_labels(db, DataUse, [privacy_declaration.data_use])
await validate_data_labels(
db, DataCategory, privacy_declaration.data_categories
)
await validate_data_labels(db, DataSubject, privacy_declaration.data_subjects)

logical_id = privacy_declaration_logical_id(privacy_declaration)
if logical_id in logical_ids:
raise HTTPException(
Expand Down
5 changes: 3 additions & 2 deletions src/fides/api/schemas/connection_configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@
SaaSSchemaFactory as SaaSSchemaFactory,
)
from fides.api.schemas.connection_configuration.connection_secrets_scylla import (
ScyllaSchema, ScyllaDocsSchema,
ScyllaDocsSchema,
ScyllaSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_snowflake import (
SnowflakeDocsSchema as SnowflakeDocsSchema,
Expand Down Expand Up @@ -175,5 +176,5 @@ def get_connection_secrets_schema(
FidesDocsSchema,
SovrnDocsSchema,
DynamoDBDocsSchema,
ScyllaDocsSchema
ScyllaDocsSchema,
]
Loading

0 comments on commit 3b92387

Please sign in to comment.