Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
58 changes: 51 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 Down Expand Up @@ -954,6 +985,15 @@
- name: List role definitions.
text: |-
az synapse role definition list --workspace-name testsynapseworkspace
- name: List role definitions by scope.
text: |-
az synapse role definition list --workspace-name testsynapseworkspace --scope "workspaces/{workspaceName}"
- name: List role definitions by item type.
text: |-
az synapse role definition list --workspace-name testsynapseworkspace --item-type "bigDataPools"
- 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 +1004,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
32 changes: 29 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,15 @@ 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='Select the part of the workspace to which want to grant access.')
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 +436,25 @@ 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='Scope at which the role assignment is created.')
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')
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 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.')
c.argument('scope', help='Scope at which the role assignment is created.')
c.argument('item_type', arg_type=get_enum_type(ItemType), help='Item type granted access in the workspace.')

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#RoleAssignmentsOperations.{}',
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
17 changes: 17 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,9 @@
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}',
'scopePools': '{scopePoolName}'}


class SynapseSqlCreateMode(str, Enum):
Expand Down Expand Up @@ -62,3 +65,17 @@ 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"
scopePools = "scopePools"
integrationRuntimes = "integrationRuntimes"
credentials = "credentials"
linkedServices = "linkedServices"
Copy link
Contributor

Choose a reason for hiding this comment

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

why not define in SDK?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Juliehzl I think this not belong to SDK's scope, we define these item type for CLI using friendly. User can pass item type and CLI code will use this parameter to generate scope which is defined in SDK and received by service.

PrincipalType and ItemType 's purpose is only to limit the user's input

@idear1203 Do we have a plan to move it to SDK?

Copy link
Contributor

Choose a reason for hiding this comment

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

Currently we don't have such definitions in SDK. This is a good suggestion.

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.

Loading