Skip to content

Commit e3d1132

Browse files
authored
[Storage] az storage blob/container/share/file/queue/fs generate-sas: Add --user-delegation-tid to support cross tenant user delegated sas (#33187)
1 parent adb7895 commit e3d1132

25 files changed

Lines changed: 449 additions & 406 deletions

src/azure-cli/azure/cli/command_modules/storage/_params.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
get_api_version_type, blob_download_file_path_validator, blob_tier_validator, validate_subnet,
2525
validate_immutability_arguments, validate_blob_name_for_upload, validate_share_close_handle,
2626
blob_tier_validator_track2, services_type_v2, resource_type_type_v2, PermissionScopeAddAction,
27-
SshPublicKeyAddAction, user_delegation_oid_validator)
27+
SshPublicKeyAddAction, user_delegation_oid_validator, user_delegation_tid_validator)
2828

2929

3030
def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statements, too-many-lines, too-many-branches, line-too-long
@@ -979,6 +979,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
979979
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
980980
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
981981
'to the user specified in this value.')
982+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
983+
help='The delegated user tenant id in Azure AD. '
984+
'This parameter can only be specified when using OAuth.')
982985

983986
with self.argument_context('storage blob restore', resource_type=ResourceType.MGMT_STORAGE) as c:
984987
from ._validators import BlobRangeAddAction
@@ -1702,6 +1705,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
17021705
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
17031706
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
17041707
'to the user specified in this value.')
1708+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
1709+
help='The delegated user tenant id in Azure AD. '
1710+
'This parameter can only be specified when using OAuth.')
17051711

17061712
for cmd in ['acquire', 'renew', 'break', 'change', 'release']:
17071713
with self.argument_context(f'storage container lease {cmd}') as c:
@@ -1970,6 +1976,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
19701976
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
19711977
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
19721978
'to the user specified in this value.')
1979+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
1980+
help='The delegated user tenant id in Azure AD. '
1981+
'This parameter can only be specified when using OAuth.')
19731982

19741983
with self.argument_context('storage share update') as c:
19751984
c.extra('share_name', share_name_type, options_list=('--name', '-n'), required=True)
@@ -2185,6 +2194,8 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
21852194
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
21862195
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
21872196
'to the user specified in this value.')
2197+
c.extra('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
2198+
help='The delegated user tenant id in Azure AD. This parameter can only be specified when using OAuth.')
21882199

21892200
with self.argument_context('storage file list') as c:
21902201
c.extra('share_name', share_name_type, required=True)
@@ -2338,6 +2349,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
23382349
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
23392350
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
23402351
'to the user specified in this value.')
2352+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
2353+
help='The delegated user tenant id in Azure AD. '
2354+
'This parameter can only be specified when using OAuth.')
23412355

23422356
with self.argument_context('storage queue list') as c:
23432357
c.argument('include_metadata', help='Specify that queue metadata be returned in the response.')
@@ -2587,6 +2601,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
25872601
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
25882602
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
25892603
'to the user specified in this value.')
2604+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
2605+
help='The delegated user tenant id in Azure AD. '
2606+
'This parameter can only be specified when using OAuth.')
25902607

25912608
with self.argument_context('storage fs list') as c:
25922609
c.argument('include_metadata', arg_type=get_three_state_flag(),
@@ -2717,6 +2734,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
27172734
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
27182735
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
27192736
'to the user specified in this value.')
2737+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
2738+
help='The delegated user tenant id in Azure AD. '
2739+
'This parameter can only be specified when using OAuth.')
27202740

27212741
with self.argument_context('storage fs file generate-sas') as c:
27222742
t_file_system_permissions = self.get_sdk('_models#FileSystemSasPermissions',
@@ -2753,6 +2773,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
27532773
help='Specifies the Entra ID of the user that is authorized to use the resulting SAS URL. '
27542774
'The resulting SAS URL must be used in conjunction with an Entra ID token that has been issued '
27552775
'to the user specified in this value.')
2776+
c.argument('user_delegation_tid', validator=user_delegation_tid_validator, is_preview=True,
2777+
help='The delegated user tenant id in Azure AD. '
2778+
'This parameter can only be specified when using OAuth.')
27562779

27572780
with self.argument_context('storage fs file list') as c:
27582781
c.extra('file_system_name', options_list=['-f', '--file-system'],

src/azure-cli/azure/cli/command_modules/storage/_validators.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,8 +1562,13 @@ def as_user_validator(namespace):
15621562
def user_delegation_oid_validator(namespace):
15631563
if namespace.user_delegation_oid and not namespace.as_user:
15641564
raise argparse.ArgumentError(
1565-
None, "incorrect usage: need to specify '--as-user' when '--user-delegation-oid' is "
1566-
"provided")
1565+
None, "incorrect usage: need to specify '--as-user' when '--user-delegation-oid' is provided")
1566+
1567+
1568+
def user_delegation_tid_validator(namespace):
1569+
if namespace.user_delegation_tid and not namespace.user_delegation_oid:
1570+
raise argparse.ArgumentError(
1571+
None, "incorrect usage: need to specify '--user-delegation-oid' when '--user-delegation-tid' is provided")
15671572

15681573

15691574
def validator_change_feed_retention_days(namespace):

src/azure-cli/azure/cli/command_modules/storage/operations/blob.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ def generate_sas_blob_uri(cmd, client, permission=None, expiry=None, start=None,
839839
protocol=None, cache_control=None, content_disposition=None,
840840
content_encoding=None, content_language=None,
841841
content_type=None, full_uri=False, as_user=False, snapshot=None, user_delegation_oid=None,
842-
**kwargs):
842+
user_delegation_tid=None, **kwargs):
843843
from ..url_quote_util import encode_url_path
844844
from urllib.parse import quote
845845
t_generate_blob_sas = get_sdk(cmd.cli_ctx, ResourceType.DATA_STORAGE_BLOB,
@@ -850,7 +850,8 @@ def generate_sas_blob_uri(cmd, client, permission=None, expiry=None, start=None,
850850
account_key = None
851851
if as_user:
852852
user_delegation_key = client.get_user_delegation_key(
853-
get_datetime_from_string(start) if start else datetime.utcnow(), get_datetime_from_string(expiry))
853+
get_datetime_from_string(start) if start else datetime.utcnow(), get_datetime_from_string(expiry),
854+
delegated_user_tid=user_delegation_tid)
854855
else:
855856
account_key = client.credential.account_key
856857

@@ -889,7 +890,8 @@ def generate_sas_blob_uri(cmd, client, permission=None, expiry=None, start=None,
889890
def generate_container_shared_access_signature(cmd, client, container_name, permission=None, expiry=None,
890891
start=None, id=None, ip=None, protocol=None, cache_control=None,
891892
content_disposition=None, content_encoding=None, content_language=None,
892-
content_type=None, user_delegation_oid=None, as_user=False, **kwargs):
893+
content_type=None, user_delegation_oid=None, user_delegation_tid=None,
894+
as_user=False, **kwargs):
893895
t_generate_container_sas = get_sdk(cmd.cli_ctx, ResourceType.DATA_STORAGE_BLOB,
894896
'_shared_access_signature#generate_container_sas')
895897

@@ -898,7 +900,8 @@ def generate_container_shared_access_signature(cmd, client, container_name, perm
898900
account_key = None
899901
if as_user:
900902
user_delegation_key = client.get_user_delegation_key(
901-
get_datetime_from_string(start) if start else datetime.utcnow(), get_datetime_from_string(expiry))
903+
get_datetime_from_string(start) if start else datetime.utcnow(), get_datetime_from_string(expiry),
904+
delegated_user_tid=user_delegation_tid)
902905
else:
903906
account_key = client.credential.account_key
904907

src/azure-cli/azure/cli/command_modules/storage/operations/file.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,8 @@ def _file_share_exists(client, resource_group_name, account_name, share_name):
538538

539539
# pylint: disable=redefined-builtin
540540
def generate_sas_file(cmd, client, share_name=None, directory_name=None, file_name=None, permission=None, expiry=None,
541-
start=None, id=None, ip=None, protocol=None, as_user=False, user_delegation_oid=None, **kwargs):
541+
start=None, id=None, ip=None, protocol=None, as_user=False, user_delegation_oid=None,
542+
user_delegation_tid=None, **kwargs):
542543
t_generate_file_sas = get_sdk(cmd.cli_ctx, ResourceType.DATA_STORAGE_FILESHARE,
543544
'_shared_access_signature#generate_file_sas')
544545
file_path = file_name
@@ -552,7 +553,8 @@ def generate_sas_file(cmd, client, share_name=None, directory_name=None, file_na
552553
from datetime import datetime
553554
user_delegation_key = client.get_user_delegation_key(
554555
start=get_datetime_from_string(start) if start else datetime.utcnow(),
555-
expiry=get_datetime_from_string(expiry))
556+
expiry=get_datetime_from_string(expiry),
557+
delegated_user_tid=user_delegation_tid)
556558
else:
557559
account_key = client.credential.account_key
558560

src/azure-cli/azure/cli/command_modules/storage/operations/fileshare.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ def share_exists(cmd, client, **kwargs):
5757

5858
def generate_share_sas(cmd, client, share_name=None, permission=None, expiry=None, start=None, policy_id=None, ip=None,
5959
protocol=None, cache_control=None, content_disposition=None, content_encoding=None,
60-
content_language=None, content_type=None, as_user=False, user_delegation_oid=None):
60+
content_language=None, content_type=None, as_user=False, user_delegation_oid=None,
61+
user_delegation_tid=None):
6162
generate_share_sas_fn = cmd.get_models('_shared_access_signature#generate_share_sas')
6263

6364
sas_kwargs = {'protocol': protocol}
@@ -67,7 +68,8 @@ def generate_share_sas(cmd, client, share_name=None, permission=None, expiry=Non
6768
if as_user:
6869
user_delegation_key = client.get_user_delegation_key(
6970
start=get_datetime_from_string(start) if start else datetime.utcnow(),
70-
expiry=get_datetime_from_string(expiry))
71+
expiry=get_datetime_from_string(expiry),
72+
delegated_user_tid=user_delegation_tid)
7173
else:
7274
account_key = client.credential.account_key
7375

src/azure-cli/azure/cli/command_modules/storage/operations/filesystem.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ def generate_sas_fs_uri(client, cmd, file_system, permission=None,
3939
protocol=None, cache_control=None, content_disposition=None,
4040
content_encoding=None, content_language=None,
4141
content_type=None, full_uri=False, as_user=False, encryption_scope=None,
42-
user_delegation_oid=None):
42+
user_delegation_oid=None, user_delegation_tid=None):
4343
generate_file_system_sas = cmd.get_models('_shared_access_signature#generate_file_system_sas')
4444

4545
sas_kwargs = {}
4646
if as_user:
4747
user_delegation_key = client.get_user_delegation_key(
4848
get_datetime_from_string(start) if start else datetime.utcnow(),
49-
get_datetime_from_string(expiry))
49+
get_datetime_from_string(expiry),
50+
delegated_user_tid=user_delegation_tid)
5051

5152
sas_token = generate_file_system_sas(account_name=client.account_name, file_system_name=file_system,
5253
credential=user_delegation_key if as_user else client.credential.account_key,

src/azure-cli/azure/cli/command_modules/storage/operations/fs_directory.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,16 @@ def generate_sas_directory_uri(client, cmd, file_system_name, directory_name, pe
9999
protocol=None, cache_control=None, content_disposition=None,
100100
content_encoding=None, content_language=None,
101101
content_type=None, full_uri=False, as_user=False, encryption_scope=None,
102-
user_delegation_oid=None):
102+
user_delegation_oid=None, user_delegation_tid=None):
103103
from urllib.parse import quote
104104
generate_directory_sas = cmd.get_models('_shared_access_signature#generate_directory_sas')
105105

106106
sas_kwargs = {}
107107
if as_user:
108108
user_delegation_key = client.get_user_delegation_key(
109109
get_datetime_from_string(start) if start else datetime.utcnow(),
110-
get_datetime_from_string(expiry))
110+
get_datetime_from_string(expiry),
111+
delegated_user_tid=user_delegation_tid)
111112

112113
sas_token = generate_directory_sas(account_name=client.account_name, file_system_name=file_system_name,
113114
directory_name=directory_name,

src/azure-cli/azure/cli/command_modules/storage/operations/fs_file.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,16 @@ def generate_sas_file_uri(client, cmd, file_system_name, path, permission=None,
154154
protocol=None, cache_control=None, content_disposition=None,
155155
content_encoding=None, content_language=None,
156156
content_type=None, full_uri=False, as_user=False, encryption_scope=None,
157-
user_delegation_oid=None):
157+
user_delegation_oid=None, user_delegation_tid=None):
158158
from urllib.parse import quote
159159
generate_file_sas = cmd.get_models('_shared_access_signature#generate_file_sas')
160160

161161
sas_kwargs = {}
162162
if as_user:
163163
user_delegation_key = client.get_user_delegation_key(
164164
get_datetime_from_string(start) if start else datetime.utcnow(),
165-
get_datetime_from_string(expiry))
165+
get_datetime_from_string(expiry),
166+
delegated_user_tid=user_delegation_tid)
166167

167168
directory_name, file_name = os.path.split(path)
168169

src/azure-cli/azure/cli/command_modules/storage/operations/queue.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def queue_exists(cmd, client, **kwargs):
4343

4444

4545
def generate_queue_sas(cmd, client, queue_name=None, permission=None, expiry=None, start=None,
46-
policy_id=None, ip=None, protocol=None, as_user=False, user_delegation_oid=None):
46+
policy_id=None, ip=None, protocol=None, as_user=False, user_delegation_oid=None,
47+
user_delegation_tid=None):
4748
generate_queue_sas_fn = cmd.get_models('_shared_access_signature#generate_queue_sas')
4849

4950
sas_kwargs = {'protocol': protocol}
@@ -54,7 +55,8 @@ def generate_queue_sas(cmd, client, queue_name=None, permission=None, expiry=Non
5455
from datetime import datetime
5556
user_delegation_key = client.get_user_delegation_key(
5657
start=get_datetime_from_string(start) if start else datetime.utcnow(),
57-
expiry=get_datetime_from_string(expiry))
58+
expiry=get_datetime_from_string(expiry),
59+
delegated_user_tid=user_delegation_tid)
5860
else:
5961
account_key = client.credential.account_key
6062

0 commit comments

Comments
 (0)