From 67be2fd8ffd45956d30a2b658d6618e472ccba45 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 11 Sep 2025 09:19:33 +0300 Subject: [PATCH 1/2] warehouse audit APIs --- src/sempy_labs/__init__.py | 6 ++ src/sempy_labs/_warehouses.py | 174 +++++++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 2 deletions(-) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index ed67137f..2e0fb57e 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -101,6 +101,9 @@ get_warehouse_columns, get_warehouse_tables, get_warehouse_connection_string, + get_warehouse_sql_audit_settings, + update_warehouse_sql_audit_settings, + set_warehouse_audit_actions_and_group, ) from ._data_pipelines import ( list_data_pipelines, @@ -605,4 +608,7 @@ "set_workspace_network_communication_policy", "get_warehouse_connection_string", "list_data_access_roles", + "get_warehouse_sql_audit_settings", + "update_warehouse_sql_audit_settings", + "set_warehouse_audit_actions_and_group", ] diff --git a/src/sempy_labs/_warehouses.py b/src/sempy_labs/_warehouses.py index d1f7b02b..f5455255 100644 --- a/src/sempy_labs/_warehouses.py +++ b/src/sempy_labs/_warehouses.py @@ -1,4 +1,4 @@ -from ._helper_functions import ( +from sempy_labs._helper_functions import ( resolve_item_id, resolve_workspace_name_and_id, _base_api, @@ -6,9 +6,10 @@ _update_dataframe_datatypes, delete_item, resolve_workspace_id, + resolve_item_name_and_id, ) import pandas as pd -from typing import Optional +from typing import Optional, List import sempy_labs._icons as icons from uuid import UUID from sempy._utils._log import log @@ -287,3 +288,172 @@ def get_warehouse_connection_string( response = _base_api(request=url, client="fabric_sp") return response.json().get("connectionString") + + +@log +def get_warehouse_sql_audit_settings( + warehouse: str | UUID, workspace: Optional[str | UUID] = None +) -> pd.DataFrame: + """ + Shows the SQL audit settings of a Fabric warehouse. + + This is a wrapper function for the following API: `SQL Audit Settings - Get SQL Audit Settings `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + warehouse : str | uuid.UUID + Name or ID of the Fabric warehouse. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + + Returns + ------- + pandas.DataFrame + A pandas dataframe containing the SQL audit settings of the specified warehouse. + """ + workspace_id = resolve_workspace_id(workspace) + warehouse_id = resolve_item_id( + item=warehouse, type="Warehouse", workspace=workspace + ) + + columns = { + "State": "string", + "Retention Days": "int", + "Audit Actions And Group": "list", + } + + df = _create_dataframe(columns=columns) + + response = _base_api( + request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit", + client="fabric_sp", + ).json() + + rows = [] + rows.append( + { + "State": response.get("state"), + "Retention Days": response.get("retentionDays"), + "Audit Actions And Group": response.get("auditActionsAndGroups"), + } + ) + + if rows: + df = pd.DataFrame(rows, columns=list(columns.keys())) + _update_dataframe_datatypes(dataframe=df, column_map=columns) + + return df + + +@log +def update_warehouse_sql_audit_settings( + warehouse: str | UUID, + workspace: Optional[str | UUID] = None, + retention_days: Optional[int] = None, + state: Optional[str] = None, +): + """ + Update settings associated with the warehouse. + + This is a wrapper function for the following API: SQL Audit Settings - Update SQL Audit Settings `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + warehouse : str | uuid.UUID + Name or ID of the Fabric warehouse. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + (warehouse_name, warehouse_id) = resolve_item_name_and_id( + item=warehouse, type="Warehouse", workspace=workspace + ) + + payload = {} + if retention_days is not None: + if not isinstance(retention_days, int) or retention_days < 0: + raise ValueError( + f"{icons.red_dot} retention_days must be a non-negative integer." + ) + payload["retentionDays"] = retention_days + if state is not None: + state = state.capitalize() + if state not in ["Enabled", "Disabled"]: + raise ValueError( + f"{icons.red_dot} state must be either 'Enabled' or 'Disabled'." + ) + payload["state"] = state + + if not payload: + print( + f"{icons.info} No updates were made as neither retention_days nor state were provided." + ) + return + + _base_api( + request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit", + client="fabric_sp", + method="patch", + payload=payload, + ) + + print( + f"{icons.green_dot} The SQL audit settings for the '{warehouse_name}' warehouse within the '{workspace_name}' workspace have been updated accordingly." + ) + + +@log +def set_warehouse_audit_actions_and_group( + warehouse: str | UUID, + sql_audit_groups: List[str], + workspace: Optional[str | UUID] = None, +): + """ + Update the audit actions and groups for this warehouse. + + This is a wrapper function for the following API: SQL Audit Settings - Set Audit Actions And Groups `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + warehouse : str | uuid.UUID + Name or ID of the Fabric warehouse. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + (warehouse_name, warehouse_id) = resolve_item_name_and_id( + item=warehouse, type="Warehouse", workspace=workspace + ) + if ( + not sql_audit_groups + or not isinstance(sql_audit_groups, list) + or not all(isinstance(item, str) for item in sql_audit_groups) + ): + raise ValueError( + f"{icons.red_dot} sql_audit_groups must be a non-empty list of strings." + ) + + _base_api( + request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit/setAuditActionsAndGroups", + client="fabric_sp", + method="post", + payload=sql_audit_groups, + ) + + print( + f"{icons.green_dot} The SQL audit actions and groups for the '{warehouse_name}' warehouse within the '{workspace_name}' workspace have been updated accordingly." + ) From dee951b7cd3451777c2a3cc98e6cef8629750b5d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 14 Sep 2025 09:32:23 +0300 Subject: [PATCH 2/2] make generic --- src/sempy_labs/__init__.py | 14 +- src/sempy_labs/_sql_audit_settings.py | 208 ++++++++++++++++++++++++++ src/sempy_labs/_warehouses.py | 172 +-------------------- 3 files changed, 217 insertions(+), 177 deletions(-) create mode 100644 src/sempy_labs/_sql_audit_settings.py diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index 2e0fb57e..db0e8c54 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -101,9 +101,6 @@ get_warehouse_columns, get_warehouse_tables, get_warehouse_connection_string, - get_warehouse_sql_audit_settings, - update_warehouse_sql_audit_settings, - set_warehouse_audit_actions_and_group, ) from ._data_pipelines import ( list_data_pipelines, @@ -354,6 +351,11 @@ from ._data_access_security import ( list_data_access_roles, ) +from ._sql_audit_settings import ( + get_sql_audit_settings, + update_sql_audit_settings, + set_audit_actions_and_group, +) __all__ = [ "resolve_warehouse_id", @@ -608,7 +610,7 @@ "set_workspace_network_communication_policy", "get_warehouse_connection_string", "list_data_access_roles", - "get_warehouse_sql_audit_settings", - "update_warehouse_sql_audit_settings", - "set_warehouse_audit_actions_and_group", + "get_sql_audit_settings", + "update_sql_audit_settings", + "set_audit_actions_and_group", ] diff --git a/src/sempy_labs/_sql_audit_settings.py b/src/sempy_labs/_sql_audit_settings.py new file mode 100644 index 00000000..5f87efc9 --- /dev/null +++ b/src/sempy_labs/_sql_audit_settings.py @@ -0,0 +1,208 @@ +from sempy_labs._helper_functions import ( + resolve_item_id, + resolve_workspace_name_and_id, + _base_api, + _create_dataframe, + _update_dataframe_datatypes, + resolve_workspace_id, + resolve_item_name_and_id, +) +import pandas as pd +from typing import Optional, List, Literal +import sempy_labs._icons as icons +from uuid import UUID +from sempy._utils._log import log + + +def _get_base_url(item, type, workspace): + + workspace_id = resolve_workspace_id(workspace) + item_id = resolve_item_id(item=item, type=type, workspace=workspace) + + type_dict = { + "Warehouse": "warehouses", + "SQLEndpoint": "sqlEndpoints", + } + type_for_url = type_dict.get(type) + + if type in ["SQLEndpoint", "Warehouse"]: + url = f"/v1/workspaces/{workspace_id}/{type_for_url}/{item_id}" + else: + raise ValueError( + f"{icons.red_dot} The type must be 'Warehouse' or 'SQLEndpoint'." + ) + + return url + + +@log +def get_sql_audit_settings( + item: str | UUID, + type: Literal["Warehouse", "SQLEndpoint"], + workspace: Optional[str | UUID] = None, +) -> pd.DataFrame: + """ + Shows the SQL audit settings of a Fabric item. + + This is a wrapper function for the following API: `SQL Audit Settings - Get SQL Audit Settings `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + item : str | uuid.UUID + The name or ID of the item (Warehouse or SQLEndpoint). + type : Literal['Warehouse', 'SQLEndpoint'] + The type of the item. Must be 'Warehouse' or 'SQLEndpoint'. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + + Returns + ------- + pandas.DataFrame + A pandas dataframe containing the SQL audit settings of the specified warehouse. + """ + + columns = { + "State": "string", + "Retention Days": "int", + "Audit Actions And Group": "list", + } + + df = _create_dataframe(columns=columns) + + url = _get_base_url(item=item, type=type, workspace=workspace) + response = _base_api( + request=f"{url}/settings/sqlAudit", + client="fabric_sp", + ).json() + + rows = [] + rows.append( + { + "State": response.get("state"), + "Retention Days": response.get("retentionDays"), + "Audit Actions And Group": response.get("auditActionsAndGroups"), + } + ) + + if rows: + df = pd.DataFrame(rows, columns=list(columns.keys())) + _update_dataframe_datatypes(dataframe=df, column_map=columns) + + return df + + +@log +def update_sql_audit_settings( + item: str | UUID, + type: Literal["Warehouse", "SQLEndpoint"], + workspace: Optional[str | UUID] = None, + retention_days: Optional[int] = None, + state: Optional[str] = None, +): + """ + Update settings associated with the item. + + This is a wrapper function for the following API: SQL Audit Settings - Update SQL Audit Settings `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + item : str | uuid.UUID + The name or ID of the item (Warehouse or SQLEndpoint). + type : Literal['Warehouse', 'SQLEndpoint'] + The type of the item. Must be 'Warehouse' or 'SQLEndpoint'. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + + payload = {} + if retention_days is not None: + if not isinstance(retention_days, int) or retention_days < 0: + raise ValueError( + f"{icons.red_dot} retention_days must be a non-negative integer." + ) + payload["retentionDays"] = retention_days + if state is not None: + state = state.capitalize() + if state not in ["Enabled", "Disabled"]: + raise ValueError( + f"{icons.red_dot} state must be either 'Enabled' or 'Disabled'." + ) + payload["state"] = state + + if not payload: + print( + f"{icons.info} No updates were made as neither retention_days nor state were provided." + ) + return + + url = _get_base_url(item=item, type=type, workspace=workspace) + _base_api( + request=f"{url}/settings/sqlAudit", + client="fabric_sp", + method="patch", + payload=payload, + ) + + print( + f"{icons.green_dot} The SQL audit settings for the '{item}' {type.lower()} within the '{workspace_name}' workspace have been updated accordingly." + ) + + +@log +def set_audit_actions_and_group( + item: str | UUID, + type: Literal["Warehouse", "SQLEndpoint"], + sql_audit_groups: List[str], + workspace: Optional[str | UUID] = None, +): + """ + Update the audit actions and groups for this item. + + This is a wrapper function for the following API: SQL Audit Settings - Set Audit Actions And Groups `_. + + Service Principal Authentication is supported (see `here `_). + + Parameters + ---------- + item : str | uuid.UUID + The name or ID of the item (Warehouse or SQLEndpoint). + type : Literal['Warehouse', 'SQLEndpoint'] + The type of the item. Must be 'Warehouse' or 'SQLEndpoint'. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + + if ( + not sql_audit_groups + or not isinstance(sql_audit_groups, list) + or not all(isinstance(item, str) for item in sql_audit_groups) + ): + raise ValueError( + f"{icons.red_dot} sql_audit_groups must be a non-empty list of strings." + ) + + url = _get_base_url(item=item, type=type, workspace=workspace) + _base_api( + request=f"{url}/settings/sqlAudit/setAuditActionsAndGroups", + client="fabric_sp", + method="post", + payload=sql_audit_groups, + ) + + print( + f"{icons.green_dot} The SQL audit actions and groups for the '{item}' {type.lower()} within the '{workspace_name}' workspace have been updated accordingly." + ) diff --git a/src/sempy_labs/_warehouses.py b/src/sempy_labs/_warehouses.py index f5455255..df78c481 100644 --- a/src/sempy_labs/_warehouses.py +++ b/src/sempy_labs/_warehouses.py @@ -6,10 +6,9 @@ _update_dataframe_datatypes, delete_item, resolve_workspace_id, - resolve_item_name_and_id, ) import pandas as pd -from typing import Optional, List +from typing import Optional import sempy_labs._icons as icons from uuid import UUID from sempy._utils._log import log @@ -288,172 +287,3 @@ def get_warehouse_connection_string( response = _base_api(request=url, client="fabric_sp") return response.json().get("connectionString") - - -@log -def get_warehouse_sql_audit_settings( - warehouse: str | UUID, workspace: Optional[str | UUID] = None -) -> pd.DataFrame: - """ - Shows the SQL audit settings of a Fabric warehouse. - - This is a wrapper function for the following API: `SQL Audit Settings - Get SQL Audit Settings `_. - - Service Principal Authentication is supported (see `here `_). - - Parameters - ---------- - warehouse : str | uuid.UUID - Name or ID of the Fabric warehouse. - workspace : str | uuid.UUID, default=None - The Fabric workspace name or ID. - Defaults to None which resolves to the workspace of the attached lakehouse - or if no lakehouse attached, resolves to the workspace of the notebook. - - Returns - ------- - pandas.DataFrame - A pandas dataframe containing the SQL audit settings of the specified warehouse. - """ - workspace_id = resolve_workspace_id(workspace) - warehouse_id = resolve_item_id( - item=warehouse, type="Warehouse", workspace=workspace - ) - - columns = { - "State": "string", - "Retention Days": "int", - "Audit Actions And Group": "list", - } - - df = _create_dataframe(columns=columns) - - response = _base_api( - request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit", - client="fabric_sp", - ).json() - - rows = [] - rows.append( - { - "State": response.get("state"), - "Retention Days": response.get("retentionDays"), - "Audit Actions And Group": response.get("auditActionsAndGroups"), - } - ) - - if rows: - df = pd.DataFrame(rows, columns=list(columns.keys())) - _update_dataframe_datatypes(dataframe=df, column_map=columns) - - return df - - -@log -def update_warehouse_sql_audit_settings( - warehouse: str | UUID, - workspace: Optional[str | UUID] = None, - retention_days: Optional[int] = None, - state: Optional[str] = None, -): - """ - Update settings associated with the warehouse. - - This is a wrapper function for the following API: SQL Audit Settings - Update SQL Audit Settings `_. - - Service Principal Authentication is supported (see `here `_). - - Parameters - ---------- - warehouse : str | uuid.UUID - Name or ID of the Fabric warehouse. - workspace : str | uuid.UUID, default=None - The Fabric workspace name or ID. - Defaults to None which resolves to the workspace of the attached lakehouse - or if no lakehouse attached, resolves to the workspace of the notebook. - """ - - (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) - (warehouse_name, warehouse_id) = resolve_item_name_and_id( - item=warehouse, type="Warehouse", workspace=workspace - ) - - payload = {} - if retention_days is not None: - if not isinstance(retention_days, int) or retention_days < 0: - raise ValueError( - f"{icons.red_dot} retention_days must be a non-negative integer." - ) - payload["retentionDays"] = retention_days - if state is not None: - state = state.capitalize() - if state not in ["Enabled", "Disabled"]: - raise ValueError( - f"{icons.red_dot} state must be either 'Enabled' or 'Disabled'." - ) - payload["state"] = state - - if not payload: - print( - f"{icons.info} No updates were made as neither retention_days nor state were provided." - ) - return - - _base_api( - request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit", - client="fabric_sp", - method="patch", - payload=payload, - ) - - print( - f"{icons.green_dot} The SQL audit settings for the '{warehouse_name}' warehouse within the '{workspace_name}' workspace have been updated accordingly." - ) - - -@log -def set_warehouse_audit_actions_and_group( - warehouse: str | UUID, - sql_audit_groups: List[str], - workspace: Optional[str | UUID] = None, -): - """ - Update the audit actions and groups for this warehouse. - - This is a wrapper function for the following API: SQL Audit Settings - Set Audit Actions And Groups `_. - - Service Principal Authentication is supported (see `here `_). - - Parameters - ---------- - warehouse : str | uuid.UUID - Name or ID of the Fabric warehouse. - workspace : str | uuid.UUID, default=None - The Fabric workspace name or ID. - Defaults to None which resolves to the workspace of the attached lakehouse - or if no lakehouse attached, resolves to the workspace of the notebook. - """ - - (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) - (warehouse_name, warehouse_id) = resolve_item_name_and_id( - item=warehouse, type="Warehouse", workspace=workspace - ) - if ( - not sql_audit_groups - or not isinstance(sql_audit_groups, list) - or not all(isinstance(item, str) for item in sql_audit_groups) - ): - raise ValueError( - f"{icons.red_dot} sql_audit_groups must be a non-empty list of strings." - ) - - _base_api( - request=f"/v1/workspaces/{workspace_id}/warehouses/{warehouse_id}/settings/sqlAudit/setAuditActionsAndGroups", - client="fabric_sp", - method="post", - payload=sql_audit_groups, - ) - - print( - f"{icons.green_dot} The SQL audit actions and groups for the '{warehouse_name}' warehouse within the '{workspace_name}' workspace have been updated accordingly." - )