Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PROD-2134: Adds validation for taxonomy labels #4982

Merged
merged 7 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Comment on lines -9 to +10
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

running the static_checks command caused this change

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for including this cleanup here 👍


# 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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same happened here

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 @@
return system


async def validate_data_labels(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't sure what the best name for this was so suggestions are appreciated 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me, a docstring added to this function will add further clarification

Copy link
Contributor Author

@erosselli erosselli Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added the docstring in 61b7cea

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(

Check warning on line 72 in src/fides/api/db/system.py

View check run for this annotation

Codecov / codecov/patch

src/fides/api/db/system.py#L71-L72

Added lines #L71 - L72 were not covered by tests
status_code=HTTP_400_BAD_REQUEST,
detail=f"Invalid privacy declaration referencing unknown {sql_model.__name__} {label}",
)

if not resource.active:
raise HTTPException(

Check warning on line 78 in src/fides/api/db/system.py

View check run for this annotation

Codecov / codecov/patch

src/fides/api/db/system.py#L78

Added line #L78 was not covered by tests
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])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, putting this in a list so validate_data_labels can be reused 👍

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