Skip to content

Commit 64c9a3c

Browse files
[STG78] Copy Source OAuth Token Support (#18998)
* OAuth Copy Source Support * added tokens to blob client * added support in file client * Added tests * regenerated * Added sync tests and renamed param * added some async tests * removed import and fixed desc and validation * added more tests * remove import * fixed ci
1 parent 6a3b0fd commit 64c9a3c

34 files changed

+5457
-25
lines changed

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ def _upload_blob_from_url_options(self, source_url, **kwargs):
426426
tier = kwargs.pop('standard_blob_tier', None)
427427
overwrite = kwargs.pop('overwrite', False)
428428
content_settings = kwargs.pop('content_settings', None)
429+
source_authorization = kwargs.pop('source_authorization', None)
429430
if content_settings:
430431
kwargs['blob_http_headers'] = BlobHTTPHeaders(
431432
blob_cache_control=content_settings.cache_control,
@@ -444,6 +445,7 @@ def _upload_blob_from_url_options(self, source_url, **kwargs):
444445
encryption_algorithm=cpk.algorithm)
445446

446447
options = {
448+
'copy_source_authorization': source_authorization,
447449
'content_length': 0,
448450
'copy_source_blob_properties': kwargs.pop('include_source_blob_properties', True),
449451
'source_content_md5': kwargs.pop('source_content_md5', None),
@@ -552,6 +554,9 @@ def upload_blob_from_url(self, source_url, **kwargs):
552554
:keyword ~azure.storage.blob.StandardBlobTier standard_blob_tier:
553555
A standard blob tier value to set the blob to. For this version of the library,
554556
this is only applicable to block blobs on standard storage accounts.
557+
:keyword str source_authorization:
558+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
559+
the prefix of the source_authorization string.
555560
"""
556561
options = self._upload_blob_from_url_options(
557562
source_url=self._encode_source_url(source_url),
@@ -1756,10 +1761,17 @@ def _start_copy_from_url_options(self, source_url, metadata=None, incremental_co
17561761
headers['x-ms-source-lease-id'] = source_lease
17571762

17581763
tier = kwargs.pop('premium_page_blob_tier', None) or kwargs.pop('standard_blob_tier', None)
1759-
1760-
if kwargs.get('requires_sync'):
1761-
headers['x-ms-requires-sync'] = str(kwargs.pop('requires_sync'))
1762-
1764+
requires_sync = kwargs.pop('requires_sync', None)
1765+
source_authorization = kwargs.pop('source_authorization', None)
1766+
if source_authorization and incremental_copy:
1767+
raise ValueError("Source authorization tokens are not applicable for incremental copying.")
1768+
if requires_sync is True:
1769+
headers['x-ms-requires-sync'] = str(requires_sync)
1770+
if source_authorization:
1771+
headers['x-ms-copy-source-authorization'] = source_authorization
1772+
else:
1773+
if source_authorization:
1774+
raise ValueError("Source authorization tokens are only applicable for synchronous copy operations.")
17631775
timeout = kwargs.pop('timeout', None)
17641776
dest_mod_conditions = get_modify_conditions(kwargs)
17651777
blob_tags_string = serialize_blob_tags_header(kwargs.pop('tags', None))
@@ -1916,6 +1928,10 @@ def start_copy_from_url(self, source_url, metadata=None, incremental_copy=False,
19161928
19171929
:keyword bool requires_sync:
19181930
Enforces that the service will not return a response until the copy is complete.
1931+
:keyword str source_authorization:
1932+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
1933+
the prefix of the source_authorization string. This option is only available when `incremental_copy` is
1934+
set to False and `requires_sync` is set to True.
19191935
:returns: A dictionary of copy properties (etag, last_modified, copy_id, copy_status).
19201936
:rtype: dict[str, str or ~datetime.datetime]
19211937
@@ -2210,6 +2226,7 @@ def _stage_block_from_url_options(
22102226
**kwargs
22112227
):
22122228
# type: (...) -> Dict[str, Any]
2229+
source_authorization = kwargs.pop('source_authorization', None)
22132230
if source_length is not None and source_offset is None:
22142231
raise ValueError("Source offset value must not be None if length is set.")
22152232
if source_length is not None:
@@ -2229,6 +2246,7 @@ def _stage_block_from_url_options(
22292246
cpk_info = CpkInfo(encryption_key=cpk.key_value, encryption_key_sha256=cpk.key_hash,
22302247
encryption_algorithm=cpk.algorithm)
22312248
options = {
2249+
'copy_source_authorization': source_authorization,
22322250
'block_id': block_id,
22332251
'content_length': 0,
22342252
'source_url': source_url,
@@ -2245,7 +2263,7 @@ def _stage_block_from_url_options(
22452263

22462264
@distributed_trace
22472265
def stage_block_from_url(
2248-
self, block_id, # type: str
2266+
self, block_id, # type: Union[str, int]
22492267
source_url, # type: str
22502268
source_offset=None, # type: Optional[int]
22512269
source_length=None, # type: Optional[int]
@@ -2286,6 +2304,9 @@ def stage_block_from_url(
22862304
22872305
:keyword int timeout:
22882306
The timeout parameter is expressed in seconds.
2307+
:keyword str source_authorization:
2308+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
2309+
the prefix of the source_authorization string.
22892310
:returns: Blob property dict.
22902311
:rtype: dict[str, Any]
22912312
"""
@@ -3151,6 +3172,7 @@ def _upload_pages_from_url_options( # type: ignore
31513172
if_sequence_number_less_than=kwargs.pop('if_sequence_number_lt', None),
31523173
if_sequence_number_equal_to=kwargs.pop('if_sequence_number_eq', None)
31533174
)
3175+
source_authorization = kwargs.pop('source_authorization', None)
31543176
access_conditions = get_access_conditions(kwargs.pop('lease', None))
31553177
mod_conditions = get_modify_conditions(kwargs)
31563178
source_mod_conditions = get_source_conditions(kwargs)
@@ -3165,6 +3187,7 @@ def _upload_pages_from_url_options( # type: ignore
31653187
encryption_algorithm=cpk.algorithm)
31663188

31673189
options = {
3190+
'copy_source_authorization': source_authorization,
31683191
'source_url': source_url,
31693192
'content_length': 0,
31703193
'source_range': source_range,
@@ -3279,6 +3302,9 @@ def upload_pages_from_url(self, source_url, # type: str
32793302
32803303
:keyword int timeout:
32813304
The timeout parameter is expressed in seconds.
3305+
:keyword str source_authorization:
3306+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
3307+
the prefix of the source_authorization string.
32823308
"""
32833309
options = self._upload_pages_from_url_options(
32843310
source_url=self._encode_source_url(source_url),
@@ -3571,6 +3597,7 @@ def _append_block_from_url_options( # type: ignore
35713597
max_size=maxsize_condition,
35723598
append_position=appendpos_condition
35733599
)
3600+
source_authorization = kwargs.pop('source_authorization', None)
35743601
access_conditions = get_access_conditions(kwargs.pop('lease', None))
35753602
mod_conditions = get_modify_conditions(kwargs)
35763603
source_mod_conditions = get_source_conditions(kwargs)
@@ -3584,6 +3611,7 @@ def _append_block_from_url_options( # type: ignore
35843611
encryption_algorithm=cpk.algorithm)
35853612

35863613
options = {
3614+
'copy_source_authorization': source_authorization,
35873615
'source_url': copy_source_url,
35883616
'content_length': 0,
35893617
'source_range': source_range,
@@ -3690,6 +3718,9 @@ def append_block_from_url(self, copy_source_url, # type: str
36903718
36913719
:keyword int timeout:
36923720
The timeout parameter is expressed in seconds.
3721+
:keyword str source_authorization:
3722+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
3723+
the prefix of the source_authorization string.
36933724
"""
36943725
options = self._append_block_from_url_options(
36953726
copy_source_url=self._encode_source_url(copy_source_url),

sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ async def upload_blob_from_url(self, source_url, **kwargs):
229229
:keyword ~azure.storage.blob.StandardBlobTier standard_blob_tier:
230230
A standard blob tier value to set the blob to. For this version of the library,
231231
this is only applicable to block blobs on standard storage accounts.
232+
:keyword str source_authorization:
233+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
234+
the prefix of the source_authorization string.
232235
"""
233236
options = self._upload_blob_from_url_options(
234237
source_url=self._encode_source_url(source_url),
@@ -1161,6 +1164,10 @@ async def start_copy_from_url(self, source_url, metadata=None, incremental_copy=
11611164
11621165
:keyword bool requires_sync:
11631166
Enforces that the service will not return a response until the copy is complete.
1167+
:keyword str source_authorization:
1168+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
1169+
the prefix of the source_authorization string. This option is only available when `incremental_copy` is
1170+
set to False and `requires_sync` is set to True.
11641171
:returns: A dictionary of copy properties (etag, last_modified, copy_id, copy_status).
11651172
:rtype: dict[str, str or ~datetime.datetime]
11661173
@@ -1377,7 +1384,7 @@ async def stage_block(
13771384

13781385
@distributed_trace_async
13791386
async def stage_block_from_url(
1380-
self, block_id, # type: str
1387+
self, block_id, # type: Union[str, int]
13811388
source_url, # type: str
13821389
source_offset=None, # type: Optional[int]
13831390
source_length=None, # type: Optional[int]
@@ -1418,6 +1425,9 @@ async def stage_block_from_url(
14181425
14191426
:keyword int timeout:
14201427
The timeout parameter is expressed in seconds.
1428+
:keyword str source_authorization:
1429+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
1430+
the prefix of the source_authorization string.
14211431
:rtype: None
14221432
"""
14231433
options = self._stage_block_from_url_options(
@@ -2131,6 +2141,9 @@ async def upload_pages_from_url(self, source_url, # type: str
21312141
21322142
:keyword int timeout:
21332143
The timeout parameter is expressed in seconds.
2144+
:keyword str source_authorization:
2145+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
2146+
the prefix of the source_authorization string.
21342147
"""
21352148

21362149
options = self._upload_pages_from_url_options(
@@ -2391,6 +2404,9 @@ async def append_block_from_url(self, copy_source_url, # type: str
23912404
23922405
:keyword int timeout:
23932406
The timeout parameter is expressed in seconds.
2407+
:keyword str source_authorization:
2408+
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
2409+
the prefix of the source_authorization string.
23942410
"""
23952411
options = self._append_block_from_url_options(
23962412
copy_source_url=self._encode_source_url(copy_source_url),

sdk/storage/azure-storage-blob/tests/recordings/test_append_blob.test_append_block_from_url_with_oauth.yaml

Lines changed: 360 additions & 0 deletions
Large diffs are not rendered by default.

sdk/storage/azure-storage-blob/tests/recordings/test_append_blob_async.test_append_block_from_url_with_oauth.yaml

Lines changed: 237 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)