Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def cf_synapse_spark_session(cli_ctx, workspace_name, sparkpool_name):
return synapse_spark_factory(cli_ctx, workspace_name, sparkpool_name).spark_session


def cf_synapse_client_accesscontrol_factory(cli_ctx, workspace_name):
def synapse_accesscontrol_factory(cli_ctx, workspace_name):
from azure.synapse.accesscontrol import AccessControlClient
from azure.cli.core._profile import Profile
from azure.cli.core.commands.client_factory import get_subscription_id
Expand All @@ -139,6 +139,14 @@ def cf_synapse_client_accesscontrol_factory(cli_ctx, workspace_name):
)


def cf_synapse_role_assignments(cli_ctx, workspace_name):
return synapse_accesscontrol_factory(cli_ctx, workspace_name).role_assignments


def cf_synapse_role_definitions(cli_ctx, workspace_name):
return synapse_accesscontrol_factory(cli_ctx, workspace_name).role_definitions


def cf_graph_client_factory(cli_ctx, **_):
from azure.cli.core._profile import Profile
from azure.cli.core.commands.client_factory import configure_common_settings
Expand Down
56 changes: 49 additions & 7 deletions src/azure-cli/azure/cli/command_modules/synapse/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,20 @@
short-summary: Manage Synapse's role assignments and definitions.
"""

helps['synapse role scope'] = """
type: group
short-summary: Manage Synapse's role scopes.
"""

helps['synapse role scope list'] = """
type: command
short-summary: List role scopes.
examples:
- name: List role scopes.
text: |-
az synapse role scope list --workspace-name testsynapseworkspace
"""

helps['synapse role assignment'] = """
type: group
short-summary: Manage Synapse's role assignments.
Expand All @@ -883,15 +897,23 @@
- name: List role assignments by role id/name.
text: |-
az synapse role assignment list --workspace-name testsynapseworkspace \\
--role "Sql Admin"
--role "Synapse Apache Spark Administrator"
- name: List role assignments by assignee.
text: |-
az synapse role assignment list --workspace-name testsynapseworkspace \\
--assignee sp_name
- name: List role assignments by objectId of the User, Group or Service Principal.
text: |-
az synapse role assignment list --workspace-name testsynapseworkspace \\
--assignee 00000000-0000-0000-0000-000000000000
--assignee-object-id 00000000-0000-0000-0000-000000000000
- name: List role assignments by scope.
text: |-
az synapse role assignment list --workspace-name testsynapseworkspace \\
--scope "workspaces/{workspaceName}"
- name: List role assignments by item type and item name.
text: |-
az synapse role assignment list --workspace-name testsynapseworkspace \\
--item-type "bigDataPools" --item "bigDataPoolName"
"""

helps['synapse role assignment create'] = """
Expand All @@ -901,15 +923,24 @@
- name: Create a role assignment using service principal name.
text: |-
az synapse role assignment create --workspace-name testsynapseworkspace \\
--role "Sql Admin" --assignee sp_name
Copy link
Contributor

Choose a reason for hiding this comment

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

does Sql Admin still work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, now Synapse is using new role name.
Synapse SQL Administrator
Synapse Apache Spark Administrator
...

https://docs.microsoft.com/en-us/azure/synapse-analytics/security/synapse-workspace-synapse-rbac-roles

Copy link
Contributor

Choose a reason for hiding this comment

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

In this way, it is breaking change to existing customers and we should try to avoid such breaking.
To not break customers, you should try to make previous definition work and add deprecation info to redirect to new definition.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we just allow this breaking change considering that the module is still in preview? Now Synapse moves to new names, we don't want to allow the old names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding breaking change description at History Notes

[Synapse] BREAKING CHANGE: az synapse role assignment create: Role names at old version are not allowed, Sql Admin, Apache Spark Admin, Workspace Admin

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. According to the telemetry, there is no much usage for this command as it is in preview. So we could accept the breaking change this time. Please note that we need to avoid breaking change as possible as we can in future design.

--role "Synapse Administrator" --assignee sp_name
- name: Create a role assignment using user principal name.
text: |-
az synapse role assignment create --workspace-name testsynapseworkspace \\
--role "Sql Admin" --assignee [email protected]
--role "Synapse Administrator" --assignee [email protected]
- name: Create a role assignment using objectId of the User, Group or Service Principal.
text: |-
az synapse role assignment create --workspace-name testsynapseworkspace \\
--role "Sql Admin" --assignee 00000000-0000-0000-0000-000000000000
--role "Synapse Administrator" --assignee 00000000-0000-0000-0000-000000000000
- name: Create a role assignment at scope.
text: |-
az synapse role assignment create --workspace-name testsynapseworkspace \\
--scope "workspaces/{workspaceName}" --role "Synapse Administrator" --assignee [email protected]
- name: Create a role assignment at scope that combination of item type and item name.
text: |-
az synapse role assignment create --workspace-name testsynapseworkspace \\
--item-type "bigDataPools" --item "bigDataPoolName" --role "Synapse Administrator" \\
--assignee [email protected]
"""

helps['synapse role assignment delete'] = """
Expand All @@ -919,11 +950,11 @@
- name: Delete role assignments by role and assignee.
text: |-
az synapse role assignment delete --workspace-name testsynapseworkspace \\
--role "Sql Admin" --assignee sp_name
--role "Synapse Administrator" --assignee sp_name
- name: Delete role assignments by role id/name.
text: |-
az synapse role assignment delete --workspace-name testsynapseworkspace \\
--role "Sql Admin"
--role "Synapse Administrator"
- name: Delete role assignments by service principal name.
text: |-
az synapse role assignment delete --workspace-name testsynapseworkspace \\
Expand All @@ -940,6 +971,10 @@
text: |-
az synapse role assignment delete --workspace-name testsynapseworkspace \\
--ids 10000000-0000-0000-0000-10000000-10000000-0000-0000-0000-10000000
- name: Delete role assignments by scope.
text: |-
az synapse role assignment delete --workspace-name testsynapseworkspace \\
--scope "workspaces/testsynapseworkspace/linkedServices/testlinkedServices"
"""

helps['synapse role definition'] = """
Expand All @@ -954,6 +989,9 @@
- name: List role definitions.
text: |-
az synapse role definition list --workspace-name testsynapseworkspace
- name: List role definitions built-in by Synapse.
text: |-
az synapse role definition list --workspace-name testsynapseworkspace --is-built-in True
"""

helps['synapse role definition show'] = """
Expand All @@ -964,6 +1002,10 @@
text: |-
az synapse role definition show --workspace-name testsynapseworkspace \\
--role 00000000-0000-0000-0000-000000000000
- name: Get role definition by role name.
text: |-
az synapse role definition show --workspace-name testsynapseworkspace \\
--role "Synapse SQL Administrator"
"""

helps['synapse linked-service'] = """
Expand Down
41 changes: 38 additions & 3 deletions src/azure-cli/azure/cli/command_modules/synapse/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@
from azure.cli.core.util import get_json_object, shell_safe_json_parse
from ._validators import validate_storage_account, validate_statement_language
from ._completers import get_role_definition_name_completion_list
from .constant import SparkBatchLanguage, SparkStatementLanguage, SqlPoolConnectionClientType, \
SqlPoolConnectionClientAuthenticationType
from .constant import SparkBatchLanguage, SparkStatementLanguage, SqlPoolConnectionClientType, PrincipalType, \
SqlPoolConnectionClientAuthenticationType, ItemType
from .action import AddFilters, AddOrderBy

workspace_name_arg_type = CLIArgumentType(help='The workspace name.',
completer=get_resource_name_completion_list('Microsoft.Synapse/workspaces'))
assignee_arg_type = CLIArgumentType(
help='Represent a user, group, or service principal. Supported format: object id, user sign-in name, or service principal name.')
help='Represent a user or service principal. Supported format: object id, user sign-in name, or service principal name.')

assignee_object_id_arg_type = CLIArgumentType(
help="Use this parameter instead of '--assignee' to bypass Graph API invocation in case of insufficient privileges. "
"This parameter only works with object ids for users, groups, service principals, and "
"managed identities. For managed identities use the principal id. For service principals, "
"use the object id and not the app id.")

role_arg_type = CLIArgumentType(help='The role name/id that is assigned to the principal.',
completer=get_role_definition_name_completion_list)
definition_file_arg_type = CLIArgumentType(options_list=['--file'], completer=FilesCompleter(),
Expand Down Expand Up @@ -410,6 +417,18 @@ def load_arguments(self, _):
c.argument('workspace_name', arg_type=workspace_name_arg_type)
c.argument('role', arg_type=role_arg_type)
c.argument('assignee', arg_type=assignee_arg_type)
c.argument('assignee_object_id', arg_type=assignee_object_id_arg_type)
c.argument('scope', help='A scope defines the resources or artifacts that the access applies to. Synapse supports hierarchical scopes. '
'Permissions granted at a higher-level scope are inherited by objects at a lower level. '
'In Synapse RBAC, the top-level scope is a workspace. '
'Assigning a role with workspace scope grants permissions to all applicable objects in the workspace.')
c.argument('item', help='Item granted access in the workspace. Using with --item-type to combine the scope of assignment')
c.argument('item_type', arg_type=get_enum_type(ItemType), help='Item type granted access in the workspace. Using with --item to combine the scope of assignment.')

with self.argument_context('synapse role assignment create') as c:
c.argument('assignee_principal_type', options_list=['--assignee-principal-type', '--assignee-type'], arg_type=get_enum_type(PrincipalType),
help='use with --assignee-object-id to avoid errors caused by propagation latency in AAD Graph')
c.argument('assignment_id', help='Custom role assignment id in guid format, if not specified, assignment id will be randomly generated.')

with self.argument_context('synapse role assignment show') as c:
c.argument('workspace_name', arg_type=workspace_name_arg_type)
Expand All @@ -420,15 +439,31 @@ def load_arguments(self, _):
c.argument('workspace_name', arg_type=workspace_name_arg_type)
c.argument('role', arg_type=role_arg_type)
c.argument('assignee', arg_type=assignee_arg_type)
c.argument('assignee_object_id', arg_type=assignee_object_id_arg_type)
c.argument('scope', help='A scope defines the resources or artifacts that the access applies to. Synapse supports hierarchical scopes. '
'Permissions granted at a higher-level scope are inherited by objects at a lower level. '
'In Synapse RBAC, the top-level scope is a workspace. '
'Using az role assignment with filter condition before executing delete operation '
'to be clearly aware of which assignments will be deleted.')
c.argument('ids', nargs='+',
help='space-separated role assignment ids. You should not provide --role or --assignee when --ids is provided.')
c.argument('item', help='Item granted access in the workspace. Using with --item-type to combine the scope of assignment.'
'Using az role assignment with filter condition before executing delete operation '
'to be clearly aware of which assignments will be deleted.')
c.argument('item_type', arg_type=get_enum_type(ItemType), help='Item type granted access in the workspace. Using with --item to combine the scope of assignment.'
'Using az role assignment with filter condition before executing delete operation '
'to be clearly aware of which assignments will be deleted.')

with self.argument_context('synapse role definition show') as c:
c.argument('workspace_name', arg_type=workspace_name_arg_type)
c.argument('role', arg_type=role_arg_type)

with self.argument_context('synapse role definition list') as c:
c.argument('workspace_name', arg_type=workspace_name_arg_type)
c.argument('is_built_in', arg_type=get_three_state_flag(), help='Is a Synapse Built-In Role or not.')

with self.argument_context('synapse role scope list') as c:
c.argument('workspace_name', arg_type=workspace_name_arg_type)

# synapse artifacts linked-service
for scope in ['create', 'set']:
Expand Down
16 changes: 12 additions & 4 deletions src/azure-cli/azure/cli/command_modules/synapse/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,12 @@ def get_custom_sdk(custom_module, client_factory):
operations_tmpl='azure.synapse.spark.operations#SparkBatchOperations.{}',
client_factory=None)

synapse_accesscontrol_sdk = CliCommandType(
operations_tmpl='azure.synapse.accesscontrol.operations#AccessControlClientOperationsMixin.{}',
synapse_role_assignment_sdk = CliCommandType(
operations_tmpl='azure.synapse.accesscontrol.operations#RoleAssignmentsOperations.{}',
client_factory=None)

synapse_role_definitions_sdk = CliCommandType(
operations_tmpl='azure.synapse.accesscontrol.operations#RoleDefinitionsOperations.{}',
client_factory=None)

synapse_linked_service_sdk = CliCommandType(
Expand Down Expand Up @@ -375,18 +379,22 @@ def get_custom_sdk(custom_module, client_factory):
g.custom_command('cancel', 'cancel_spark_session_statement', confirmation=True)

# Data Plane Commands --Access control operations
with self.command_group('synapse role assignment', synapse_accesscontrol_sdk,
with self.command_group('synapse role assignment', synapse_role_assignment_sdk,
custom_command_type=get_custom_sdk('accesscontrol', None)) as g:
g.custom_command('create', 'create_role_assignment')
g.custom_command('list', 'list_role_assignments')
g.custom_show_command('show', 'get_role_assignment_by_id')
g.custom_command('delete', 'delete_role_assignment', confirmation=True)

with self.command_group('synapse role definition', synapse_accesscontrol_sdk,
with self.command_group('synapse role definition', synapse_role_definitions_sdk,
custom_command_type=get_custom_sdk('accesscontrol', None)) as g:
g.custom_command('list', 'list_role_definitions')
g.custom_show_command('show', 'get_role_definition')

with self.command_group('synapse role scope', synapse_role_definitions_sdk,
custom_command_type=get_custom_sdk('accesscontrol', None)) as g:
Copy link
Contributor

Choose a reason for hiding this comment

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

You could declare your client factory here and don't need to define in every fuction.

g.custom_command('list', 'list_scopes')

# Data Plane Commands --Artifacts Linked service operations
with self.command_group('synapse linked-service', synapse_linked_service_sdk,
custom_command_type=get_custom_sdk('artifacts', None)) as g:
Expand Down
15 changes: 15 additions & 0 deletions src/azure-cli/azure/cli/command_modules/synapse/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
SPARK_DOTNET_UDFS_FOLDER_NAME = 'udfs'
SPARK_SERVICE_ENDPOINT_API_VERSION = '2019-11-01-priview'
AdministratorType = "activeDirectory"
ITEM_NAME_MAPPING = {'bigDataPools': '{bigDataPoolName}', 'integrationRuntimes': '{integrationRuntimeName}',
'linkedServices': '{linkedServiceName}', 'credentials': '{credentialName}'}


class SynapseSqlCreateMode(str, Enum):
Expand Down Expand Up @@ -62,3 +64,16 @@ class SqlPoolConnectionClientAuthenticationType(str, Enum):
SqlPassword = 'SqlPassword'
ActiveDirectoryPassword = 'ADPassword'
ActiveDirectoryIntegrated = 'ADIntegrated'


class PrincipalType(str, Enum):
user = "User"
group = "Group"
service_principal = "ServicePrincipal"


class ItemType(str, Enum):
bigDataPools = "bigDataPools"
integrationRuntimes = "integrationRuntimes"
credentials = "credentials"
linkedServices = "linkedServices"
Loading