diff --git a/.changes/unreleased/optimization-20251225-091556.yaml b/.changes/unreleased/optimization-20251225-091556.yaml new file mode 100644 index 00000000..e4ee48ee --- /dev/null +++ b/.changes/unreleased/optimization-20251225-091556.yaml @@ -0,0 +1,3 @@ +kind: optimization +body: Reduced unnecessary Fabric administrator warnings for ACL commands +time: 2025-12-25T09:15:56.219714671Z diff --git a/docs/commands/acls/index.md b/docs/commands/acls/index.md index a4973111..c442e6b7 100644 --- a/docs/commands/acls/index.md +++ b/docs/commands/acls/index.md @@ -5,6 +5,8 @@ The access control list (`acl`) commands let you manage permissions and security **Supported Types:** - `.Workspace` (workspace-level ACLs) +- `.Connection` +- `.Gateway` - All workspace item types (item-level ACLs) - OneLake storage sections (RBAC) @@ -13,17 +15,17 @@ The access control list (`acl`) commands let you manage permissions and security | Command | Description | Usage | |-----------------|------------------------|----------------------------------------------------| | `acl ls` (dir) | List ACLs | `acl ls [-l]` | -| `acl set` | Set access controls | `acl set [-I ] [-R ] [-f]` | -| `acl rm` (del) | Remove an ACL | `acl rm [-I ] [-f]` | | `acl get` | Get ACL details | `acl get [-q ] [-o ]` | +| `acl set` | Set access controls | `acl set -I -R [-f]` | +| `acl rm` (del) | Remove an ACL | `acl rm -I [-f]` | --- ### ls (dir) -List access control entries for a workspace, item, or OneLake resource. +List access control entries for a workspace, item, gateway, connection or OneLake resource. -!!! info "Listing ACLs for a workspace or item requires tenant-level Fabric Administrator" +!!! info "Listing ACLs for an item requires tenant-level Fabric Administrator" **Usage:** @@ -40,85 +42,99 @@ fab acl ls [-l] [-q ] **Examples:** ``` -fab acl ls workspace1.workspace -fab acl ls lh1.lakehouse -l -fab acl ls /Files/data -l -fab acl ls workspace1.workspace -q [].[?role=='Admin'] +# List workspace acls +fab acl ls ws1.workspace + +# List workspace admins acls +fab acl ls ws1.workspace -q [].[?role=='Admin'] + +# List lakehouse item acls +fab acl ls ws1.workspace/lh1.lakehouse +fab acl ls ws1.workspace/lh1.lakehouse/Files/data ``` --- -### set +### get -Set access control permissions for a resource. +Get detailed ACL information with optional filtering for workspace, item, gateway, connection or OneLake resource. + + +!!! info "Retrieving ACLs for an item requires tenant-level Fabric Administrator" **Usage:** ``` -fab acl set [-I ] [-R ] [-f] +fab acl get [-q ] [-o ] ``` **Parameters:** - ``: Path to the resource. -- `-I, --identity`: Object ID of the Microsoft Entra identity to set or update. -- `-R, --role`: ACL role (admin, member, contributor, viewer). -- `-f, --force`: Skip confirmation prompt. Optional. +- `-q, --query`: JMESPath query to filter results. Optional. +- `-o, --output`: Output path for results. Optional. **Examples:** ``` -fab acl set ws1.Workspace/lh1.Lakehouse -I 11111111-2222-3333-4444-555555555555 -R viewer +# Get workspace acl +fab acl get ws1.Workspace + +# Get item acl +fab acl get ws1.Workspace/lh1.Lakehouse ``` --- -### rm (del) +### set -Remove access permissions for an identity. +Set access control permissions for a workspace, gateway or connection. **Usage:** ``` -fab acl rm [-I ] [-f] +fab acl set -I -R [-f] ``` **Parameters:** - ``: Path to the resource. -- `-I, --identity`: Object ID of the Microsoft Entra identity to remove. +- `-I, --identity`: Object ID of the Microsoft Entra identity to set or update. +- `-R, --role`: ACL role (admin, member, contributor, viewer). - `-f, --force`: Skip confirmation prompt. Optional. **Examples:** ``` -fab acl rm ws1.Workspace/lh1.Lakehouse -I 11111111-2222-3333-4444-555555555555 +fab acl set ws1.Workspace -I 11111111-2222-3333-4444-555555555555 -R viewer ``` --- -### get +### rm (del) -Get detailed ACL information with optional filtering. +Remove access permissions for an identity from a workspace, gateway or connection. **Usage:** ``` -fab acl get [-q ] [-o ] +fab acl rm -I [-f] ``` **Parameters:** - ``: Path to the resource. -- `-q, --query`: JMESPath query to filter results. Optional. -- `-o, --output`: Output path for results. Optional. +- `-I, --identity`: Object ID of the Microsoft Entra identity to remove. +- `-f, --force`: Skip confirmation prompt. Optional. **Examples:** ``` -fab acl get ws1.Workspace +fab acl rm ws1.Workspace -I 11111111-2222-3333-4444-555555555555 ``` + + --- For more examples and detailed scenarios, see [ACLs Examples](../../examples/acl_examples.md). diff --git a/docs/examples/workspace_examples.md b/docs/examples/workspace_examples.md index 9d648e3c..024e29e4 100644 --- a/docs/examples/workspace_examples.md +++ b/docs/examples/workspace_examples.md @@ -263,7 +263,7 @@ fab export ws1.Workspace -o /ws1.Workspace/lh1.Lakehouse/Files -a ### Copy Workspace Items #### Copy Items Between Workspaces -Copy items from one workspace to another. Supported for [exportable items](./item_examples.md#copy-items). +Copy items from one workspace to another. Supported for [exportable items](./item_examples.md#copy-item). ``` fab cp ws1.Workspace ws2.Workspace diff --git a/src/fabric_cli/commands/acls/fab_acls_get.py b/src/fabric_cli/commands/acls/fab_acls_get.py index f13a4b93..12debf55 100644 --- a/src/fabric_cli/commands/acls/fab_acls_get.py +++ b/src/fabric_cli/commands/acls/fab_acls_get.py @@ -32,13 +32,11 @@ def exec_command(args: Namespace, context: FabricElement) -> None: args.query = utils.process_nargs(args.query) if isinstance(context, Workspace): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _get_acls_workspace(context, args) elif isinstance(context, Item): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) _get_acls_item(context, args) elif isinstance(context, VirtualWorkspaceItem): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _get_acls_virtual_ws_item(context, args) elif ( # OneLake security only supporting Lakehouse items diff --git a/src/fabric_cli/commands/acls/fab_acls_ls.py b/src/fabric_cli/commands/acls/fab_acls_ls.py index 7f6347bc..0516c72f 100644 --- a/src/fabric_cli/commands/acls/fab_acls_ls.py +++ b/src/fabric_cli/commands/acls/fab_acls_ls.py @@ -26,13 +26,11 @@ def exec_command(args: Namespace, context: FabricElement) -> None: if isinstance(context, Workspace): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _ls_acls_workspace(context, args) elif isinstance(context, Item): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) _ls_acls_item(context, args) elif isinstance(context, VirtualWorkspaceItem): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _ls_acls_vwitem(context, args) elif ( # OneLake security only supporting Lakehouse items @@ -82,7 +80,7 @@ def _ls_acls_workspace(workspace: Workspace, args: Namespace) -> None: ) sorted_acls = sorted(sorted_acls, key=lambda acl: acl["acl"]) columns = ["acl", "identity", "type"] - + if show_all: columns.extend(["objectId", "name"]) @@ -131,7 +129,7 @@ def _ls_acls_gateway(gateway: VirtualWorkspaceItem, args: Namespace) -> None: ) sorted_acls = sorted(sorted_acls, key=lambda acl: acl["role"]) - + columns = ["role", "principalId", "principalType"] if show_all: columns.insert(0, "id") @@ -168,7 +166,7 @@ def _ls_acls_connection(connection: VirtualWorkspaceItem, args: Namespace) -> No ) sorted_acls = sorted(sorted_acls, key=lambda acl: acl["role"]) - + columns = ["role", "principalId", "principalType"] if show_all: columns.insert(0, "id") @@ -219,7 +217,7 @@ def _ls_acls_item(item: Item, args: Namespace) -> None: ) sorted_acls = sorted(sorted_acls, key=lambda acl: acl["acl"]) - + columns = ["acl", "identity", "type"] if show_all: columns = ["id", "name"] + columns diff --git a/src/fabric_cli/commands/acls/fab_acls_rm.py b/src/fabric_cli/commands/acls/fab_acls_rm.py index 6676c99f..fc47367d 100644 --- a/src/fabric_cli/commands/acls/fab_acls_rm.py +++ b/src/fabric_cli/commands/acls/fab_acls_rm.py @@ -22,10 +22,8 @@ def exec_command(args: Namespace, context: FabricElement) -> None: _rm_acls_workspace(context, args) elif isinstance(context, VirtualWorkspaceItem): if context.item_type == VirtualWorkspaceItemType.CONNECTION: - fab_logger.log_warning(constant.WARNING_FABRIC_ADMIN_ROLE) _rm_acls_connection(context, args) elif context.item_type == VirtualWorkspaceItemType.GATEWAY: - fab_logger.log_warning(constant.WARNING_FABRIC_ADMIN_ROLE) _rm_acls_gateway(context, args) else: raise FabricCLIError( diff --git a/src/fabric_cli/commands/acls/fab_acls_set.py b/src/fabric_cli/commands/acls/fab_acls_set.py index 4400d724..4d7adb55 100644 --- a/src/fabric_cli/commands/acls/fab_acls_set.py +++ b/src/fabric_cli/commands/acls/fab_acls_set.py @@ -34,11 +34,9 @@ def exec_command(args: Namespace, context: FabricElement) -> None: elif isinstance(context, VirtualWorkspaceItem): if context.item_type == VirtualWorkspaceItemType.CONNECTION: _validate_role_by_type(args.role, "Connection") - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _set_acls_connection(context, args) elif context.item_type == VirtualWorkspaceItemType.GATEWAY: _validate_role_by_type(args.role, "Gateway") - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) _set_acls_gateway(context, args) else: raise FabricCLIError( diff --git a/src/fabric_cli/commands/fs/assign/fab_fs_assign_domain.py b/src/fabric_cli/commands/fs/assign/fab_fs_assign_domain.py index 66ffdd66..da2213fa 100644 --- a/src/fabric_cli/commands/fs/assign/fab_fs_assign_domain.py +++ b/src/fabric_cli/commands/fs/assign/fab_fs_assign_domain.py @@ -20,7 +20,7 @@ def exec( args: Namespace, force_assign: bool, ) -> None: - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) if isinstance(ws, Workspace): payload = json.dumps( { diff --git a/src/fabric_cli/commands/fs/get/fab_fs_get_domain.py b/src/fabric_cli/commands/fs/get/fab_fs_get_domain.py index 145a04ba..c296e504 100644 --- a/src/fabric_cli/commands/fs/get/fab_fs_get_domain.py +++ b/src/fabric_cli/commands/fs/get/fab_fs_get_domain.py @@ -14,7 +14,7 @@ def exec( virtual_ws_item: VirtualWorkspaceItem, args: Namespace, verbose: bool = True ) -> dict: - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) args.name = virtual_ws_item.short_name args.id = virtual_ws_item.id diff --git a/src/fabric_cli/commands/fs/ls/fab_fs_ls_domain.py b/src/fabric_cli/commands/fs/ls/fab_fs_ls_domain.py index fc888159..54bc391e 100644 --- a/src/fabric_cli/commands/fs/ls/fab_fs_ls_domain.py +++ b/src/fabric_cli/commands/fs/ls/fab_fs_ls_domain.py @@ -11,7 +11,7 @@ def exec(vws: VirtualWorkspace, args, show_details): - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) domains = utils_mem_store.get_domains(vws.tenant) sorted_domains = utils_ls.sort_elements( [{"name": d.name, "id": d.id} for d in domains] @@ -45,8 +45,5 @@ def exec(vws: VirtualWorkspace, args, show_details): columns = base_cols + domains_detail_cols if show_details else base_cols utils_ls.format_and_print_output( - data=sorted_domains, - columns=columns, - args=args, - show_details=show_details + data=sorted_domains, columns=columns, args=args, show_details=show_details ) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py index 78babe62..cf6634cf 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py @@ -19,7 +19,7 @@ def exec(domain: VirtualWorkspaceItem, args: Namespace) -> None: ): return - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) utils_ui.print_grey(f"Creating a new Domain...") payload = {"displayName": f"{domain.short_name}"} @@ -50,7 +50,9 @@ def exec(domain: VirtualWorkspaceItem, args: Namespace) -> None: response = domain_api.create_domain(args, payload=json_payload) if response.status_code in (200, 201): data = json.loads(response.text) - utils_ui.print_output_format(args, message=f"'{domain.name}' created", data=data, show_headers=True) + utils_ui.print_output_format( + args, message=f"'{domain.name}' created", data=data, show_headers=True + ) domain._id = data["id"] diff --git a/src/fabric_cli/commands/fs/rm/fab_fs_rm_domain.py b/src/fabric_cli/commands/fs/rm/fab_fs_rm_domain.py index adbe8394..cd6f278a 100644 --- a/src/fabric_cli/commands/fs/rm/fab_fs_rm_domain.py +++ b/src/fabric_cli/commands/fs/rm/fab_fs_rm_domain.py @@ -12,7 +12,7 @@ def exec( virtual_ws_item: VirtualWorkspaceItem, args: Namespace, force_delete: bool ) -> None: - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) args.id = virtual_ws_item.id args.name = virtual_ws_item.name if domain_api.delete_domain(args, force_delete): diff --git a/src/fabric_cli/commands/fs/unassign/fab_fs_unassign_domain.py b/src/fabric_cli/commands/fs/unassign/fab_fs_unassign_domain.py index 3f4a68bd..ed69838a 100644 --- a/src/fabric_cli/commands/fs/unassign/fab_fs_unassign_domain.py +++ b/src/fabric_cli/commands/fs/unassign/fab_fs_unassign_domain.py @@ -20,7 +20,7 @@ def exec( args: Namespace, force_unassign: bool, ) -> None: - fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMIN_ROLE) + fab_logger.log_warning(fab_constant.WARNING_FABRIC_ADMINISTRATOR) if isinstance(ws, Workspace): args.id = virtual_ws_item.id diff --git a/src/fabric_cli/core/fab_constant.py b/src/fabric_cli/core/fab_constant.py index a25bf5e2..2e21356b 100644 --- a/src/fabric_cli/core/fab_constant.py +++ b/src/fabric_cli/core/fab_constant.py @@ -216,7 +216,7 @@ WARNING_INVALID_JSON_FORMAT = "Invalid JSON format" WARNING_MKDIR_INVALID_ONELAKE = "Invalid paths. Only supported within /Files" WARNING_OPERATION_NO_RESULT = "Long Running Operation returned no result" -WARNING_FABRIC_ADMIN_ROLE = "Requires Fabric admin role" +WARNING_FABRIC_ADMINISTRATOR = "Requires Fabric administrator" WARNING_ONELAKE_RBAC_ENABLED = "Requires data access roles enabled" WARNING_NON_FABRIC_CAPACITY = "Not a Fabric capacity" WARNING_ONLY_SUPPORTED_WITHIN_LAKEHOUSE = "Only supported within Lakehouse"