From 86b93cdadbc80dc09328fec01fbc5998eb09d904 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 12:39:11 -0700 Subject: [PATCH 01/11] Expose account name on clients --- .../azure/storage/blob/_shared/base_client.py | 3 +++ .../azure-storage-blob/tests/test_blob_client.py | 14 ++++++++++++++ .../tests/test_blob_client_async.py | 14 ++++++++++++++ .../azure/storage/file/_shared/base_client.py | 8 ++++++-- .../azure-storage-file/tests/test_file_client.py | 6 ++++++ .../tests/test_file_client_async.py | 6 ++++++ .../azure/storage/queue/_shared/base_client.py | 8 ++++++-- .../azure-storage-queue/tests/test_queue_client.py | 10 ++++++++++ .../tests/test_queue_client_async.py | 10 ++++++++++ 9 files changed, 75 insertions(+), 4 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py index 91205c8f3fdb..f463d668cb90 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py @@ -75,11 +75,14 @@ def __init__( if service not in ["blob", "queue", "file"]: raise ValueError("Invalid service: {}".format(service)) account = parsed_url.netloc.split(".{}.core.".format(service)) + self.account_name = account[0] secondary_hostname = None + self.credential = format_shared_key_credential(account, credential) if self.scheme.lower() != "https" and hasattr(self.credential, "get_token"): raise ValueError("Token credential is only supported with HTTPS.") if hasattr(self.credential, "account_name"): + self.account_name = self.credential.account_name secondary_hostname = "{}-secondary.{}.{}".format(self.credential.account_name, service, SERVICE_HOST_BASE) if not self._hosts: diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_client.py b/sdk/storage/azure-storage-blob/tests/test_blob_client.py index a3805ac02c9d..779de264d5b8 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_client.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_client.py @@ -44,6 +44,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, url_type): self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue('{}.{}.core.windows.net'.format(self.account_name, url_type) in service.url) @@ -71,6 +72,7 @@ def test_create_blob_client_with_complete_blob_url(self): self.assertEqual(service.scheme, 'https') self.assertEqual(service.container_name, 'foo') self.assertEqual(service.blob_name, 'bar') + self.assertEqual(service.account_name, self.account_name) def test_create_service_with_connection_string(self): @@ -93,6 +95,7 @@ def test_create_service_with_sas(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -109,6 +112,7 @@ def test_create_service_with_token(self): self.assertEqual(service.credential, self.token_credential) self.assertFalse(hasattr(service.credential, 'account_key')) self.assertTrue(hasattr(service.credential, 'get_token')) + self.assertEqual(service.account_name, self.account_name) def test_create_service_with_token_and_http(self): for service_type in SERVICES: @@ -128,6 +132,7 @@ def test_create_service_china(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith( @@ -158,6 +163,7 @@ def test_create_blob_service_anonymous(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertIsNone(service.credential) @@ -175,6 +181,7 @@ def test_create_blob_service_custom_domain(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -226,6 +233,7 @@ def test_create_service_with_connection_string_sas(self): self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) def test_create_service_with_connection_string_endpoint_protocol(self): # Arrange @@ -238,6 +246,7 @@ def test_create_service_with_connection_string_endpoint_protocol(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue( @@ -267,6 +276,7 @@ def test_create_service_with_connection_string_anonymous(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, "www.mydomain.com") self.assertIsNone(service.credential) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) with self.assertRaises(ValueError): @@ -283,6 +293,7 @@ def test_create_service_with_connection_string_custom_domain(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -299,6 +310,7 @@ def test_create_service_with_connection_string_custom_domain_trailing_slash(self # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -317,6 +329,7 @@ def test_create_service_with_connection_string_custom_domain_secondary_override( # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -350,6 +363,7 @@ def test_create_service_with_connection_string_succeeds_if_secondary_with_primar # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_client_async.py b/sdk/storage/azure-storage-blob/tests/test_blob_client_async.py index 95cda6b9f56c..6a05020a6397 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_client_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_client_async.py @@ -60,6 +60,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, url_type): self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue('{}.{}.core.windows.net'.format(self.account_name, url_type) in service.url) @@ -99,6 +100,7 @@ def test_create_service_with_sas_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -115,6 +117,7 @@ def test_create_service_with_token_async(self): self.assertEqual(service.credential, self.token_credential) self.assertFalse(hasattr(service.credential, 'account_key')) self.assertTrue(hasattr(service.credential, 'get_token')) + self.assertEqual(service.account_name, self.account_name) def test_create_service_with_token_and_http_async(self): for service_type in SERVICES: @@ -134,6 +137,7 @@ def test_create_service_china_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith( @@ -166,6 +170,7 @@ def test_create_blob_service_anonymous_async(self): self.assertIsNotNone(service) self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) def test_create_blob_service_custom_domain_async(self): # Arrange @@ -181,6 +186,7 @@ def test_create_blob_service_custom_domain_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -232,6 +238,7 @@ def test_create_service_with_connection_string_sas_async(self): self.assertTrue(service.url.startswith('https://' + self.account_name + '.blob.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) def test_create_blob_client_with_complete_blob_url_async(self): # Arrange @@ -242,6 +249,7 @@ def test_create_blob_client_with_complete_blob_url_async(self): self.assertEqual(service.scheme, 'https') self.assertEqual(service.container_name, 'foo') self.assertEqual(service.blob_name, 'bar') + self.assertEqual(service.account_name, self.account_name) def test_create_service_with_connection_string_endpoint_protocol_async(self): # Arrange @@ -254,6 +262,7 @@ def test_create_service_with_connection_string_endpoint_protocol_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue( @@ -283,6 +292,7 @@ def test_create_service_with_connection_string_anonymous_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, "www.mydomain.com") self.assertIsNone(service.credential) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) with self.assertRaises(ValueError): @@ -299,6 +309,7 @@ def test_create_service_with_connection_string_custom_domain_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -315,6 +326,7 @@ def test_create_service_with_connection_string_custom_domain_trailing_slash_asyn # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -332,6 +344,7 @@ def test_create_service_with_connection_string_custom_domain_secondary_override_ # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -364,6 +377,7 @@ def test_create_service_with_connection_string_succeeds_if_secondary_with_primar # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py index f784ac130cf9..f463d668cb90 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py @@ -75,11 +75,14 @@ def __init__( if service not in ["blob", "queue", "file"]: raise ValueError("Invalid service: {}".format(service)) account = parsed_url.netloc.split(".{}.core.".format(service)) + self.account_name = account[0] secondary_hostname = None + self.credential = format_shared_key_credential(account, credential) if self.scheme.lower() != "https" and hasattr(self.credential, "get_token"): raise ValueError("Token credential is only supported with HTTPS.") if hasattr(self.credential, "account_name"): + self.account_name = self.credential.account_name secondary_hostname = "{}-secondary.{}.{}".format(self.credential.account_name, service, SERVICE_HOST_BASE) if not self._hosts: @@ -184,7 +187,8 @@ def _create_pipeline(self, credential, **kwargs): return config, Pipeline(config.transport, policies=policies) def _batch_send( - self, *reqs # type: HttpRequest + self, *reqs, # type: HttpRequest + **kwargs ): """Given a series of request, do a Storage batch call. """ @@ -204,7 +208,7 @@ def _batch_send( ) pipeline_response = self._pipeline.run( - request, + request, **kwargs ) response = pipeline_response.http_response diff --git a/sdk/storage/azure-storage-file/tests/test_file_client.py b/sdk/storage/azure-storage-file/tests/test_file_client.py index b6bf44543fe5..86427c230667 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_client.py +++ b/sdk/storage/azure-storage-file/tests/test_file_client.py @@ -44,6 +44,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, service_type, protocol='https'): self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('{}://{}.{}.core.windows.net/'.format( @@ -77,6 +78,7 @@ def test_create_service_with_sas(self): # Assert self.assertIsNotNone(service) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.endswith(self.sas_token)) def test_create_service_with_token(self): @@ -98,6 +100,7 @@ def test_create_service_china(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, '{}.{}.core.chinacloudapi.cn'.format( @@ -175,6 +178,7 @@ def test_create_service_with_connection_string_sas(self): # Assert self.assertIsNotNone(service) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.endswith(self.sas_token)) def test_create_service_with_connection_string_endpoint_protocol(self): @@ -189,6 +193,7 @@ def test_create_service_with_connection_string_endpoint_protocol(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, '{}.{}.core.chinacloudapi.cn'.format(self.account_name, service_type[1])) @@ -233,6 +238,7 @@ def test_create_service_with_connection_string_succeeds_if_secondary_with_primar # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, 'www.mydomain.com') diff --git a/sdk/storage/azure-storage-file/tests/test_file_client_async.py b/sdk/storage/azure-storage-file/tests/test_file_client_async.py index a3bd440f570f..4b23104371e6 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_client_async.py +++ b/sdk/storage/azure-storage-file/tests/test_file_client_async.py @@ -57,6 +57,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, service_type, protocol='https'): self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertTrue(service.primary_endpoint.startswith('{}://{}.{}.core.windows.net/'.format( @@ -92,6 +93,7 @@ def test_create_service_with_sas_async(self): # Assert self.assertIsNotNone(service) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.endswith(self.sas_token)) @record @@ -115,6 +117,7 @@ def test_create_service_china_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, '{}.{}.core.chinacloudapi.cn'.format( @@ -195,6 +198,7 @@ def test_create_service_with_connection_string_sas_async(self): # Assert self.assertIsNotNone(service) self.assertIsNone(service.credential) + self.assertEqual(service.account_name, self.account_name) self.assertTrue(service.url.endswith(self.sas_token)) @record @@ -210,6 +214,7 @@ def test_create_service_with_connection_string_endpoint_protocol_async(self): # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, '{}.{}.core.chinacloudapi.cn'.format(self.account_name, service_type[1])) @@ -257,6 +262,7 @@ def test_create_service_with_connection_string_succeeds_if_secondary_with_primar # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, self.account_name) self.assertEqual(service.credential.account_name, self.account_name) self.assertEqual(service.credential.account_key, self.account_key) self.assertEqual(service.primary_hostname, 'www.mydomain.com') diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py index f784ac130cf9..f463d668cb90 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py @@ -75,11 +75,14 @@ def __init__( if service not in ["blob", "queue", "file"]: raise ValueError("Invalid service: {}".format(service)) account = parsed_url.netloc.split(".{}.core.".format(service)) + self.account_name = account[0] secondary_hostname = None + self.credential = format_shared_key_credential(account, credential) if self.scheme.lower() != "https" and hasattr(self.credential, "get_token"): raise ValueError("Token credential is only supported with HTTPS.") if hasattr(self.credential, "account_name"): + self.account_name = self.credential.account_name secondary_hostname = "{}-secondary.{}.{}".format(self.credential.account_name, service, SERVICE_HOST_BASE) if not self._hosts: @@ -184,7 +187,8 @@ def _create_pipeline(self, credential, **kwargs): return config, Pipeline(config.transport, policies=policies) def _batch_send( - self, *reqs # type: HttpRequest + self, *reqs, # type: HttpRequest + **kwargs ): """Given a series of request, do a Storage batch call. """ @@ -204,7 +208,7 @@ def _batch_send( ) pipeline_response = self._pipeline.run( - request, + request, **kwargs ) response = pipeline_response.http_response diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_client.py b/sdk/storage/azure-storage-queue/tests/test_queue_client.py index 24f8cd082874..8d1d87e09f70 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_client.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_client.py @@ -35,6 +35,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, url_type, account_name, account_key): self.assertIsNotNone(service) + self.assertEqual(service.account_name, account_name) self.assertEqual(service.credential.account_name, account_name) self.assertEqual(service.credential.account_key, account_key) self.assertTrue('{}.{}.core.windows.net'.format(account_name, url_type) in service.url) @@ -80,6 +81,7 @@ def test_create_service_with_sas(self, resource_group, location, storage_account # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -94,6 +96,7 @@ def test_create_service_with_token(self, resource_group, location, storage_accou # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertEqual(service.credential, self.token_credential) self.assertFalse(hasattr(service.credential, 'account_key')) @@ -121,6 +124,7 @@ def test_create_service_china(self, resource_group, location, storage_account, s # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith( @@ -202,6 +206,7 @@ def test_create_service_with_connection_string_sas(self, resource_group, locatio # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -219,6 +224,7 @@ def test_create_service_with_connection_string_endpoint_protocol(self, resource_ # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue( @@ -253,6 +259,7 @@ def test_create_service_with_connection_string_custom_domain(self, resource_grou # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -271,6 +278,7 @@ def test_create_service_with_conn_str_custom_domain_trailing_slash(self, resourc # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -290,6 +298,7 @@ def test_create_service_with_conn_str_custom_domain_sec_override(self, resource_ # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -326,6 +335,7 @@ def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self, resourc # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_client_async.py b/sdk/storage/azure-storage-queue/tests/test_queue_client_async.py index efbe15f3c359..8fd9ae2c9a78 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_client_async.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_client_async.py @@ -49,6 +49,7 @@ def setUp(self): # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, url_type, storage_account, storage_account_key): self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue('{}.{}.core.windows.net'.format(storage_account.name, url_type) in service.url) @@ -94,6 +95,7 @@ def test_create_service_with_sas(self, resource_group, location, storage_account # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -108,6 +110,7 @@ def test_create_service_with_token(self, resource_group, location, storage_accou # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertEqual(service.credential, self.token_credential) self.assertFalse(hasattr(service.credential, 'account_key')) @@ -135,6 +138,7 @@ def test_create_service_china(self, resource_group, location, storage_account, s # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith( @@ -216,6 +220,7 @@ def test_create_service_with_connection_string_sas(self, resource_group, locatio # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertTrue(service.url.startswith('https://' + storage_account.name + '.queue.core.windows.net')) self.assertTrue(service.url.endswith(self.sas_token)) self.assertIsNone(service.credential) @@ -233,6 +238,7 @@ def test_create_service_with_conn_str_endpoint_protocol(self, resource_group, lo # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue( @@ -267,6 +273,7 @@ def test_create_service_with_connection_string_custom_domain(self, resource_grou # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -285,6 +292,7 @@ def test_create_serv_with_cs_custom_dmn_trlng_slash(self, resource_group, locati # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -305,6 +313,7 @@ def test_create_service_with_cs_custom_dmn_sec_override(self, resource_group, lo # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) @@ -341,6 +350,7 @@ def test_create_service_with_cs_succeeds_if_sec_with_prim(self, resource_group, # Assert self.assertIsNotNone(service) + self.assertEqual(service.account_name, storage_account.name) self.assertEqual(service.credential.account_name, storage_account.name) self.assertEqual(service.credential.account_key, storage_account_key) self.assertTrue(service.primary_endpoint.startswith('https://www.mydomain.com/')) From d3c7bde8a97f85ed4349c7a6e1dec66d21af3820 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 14:29:36 -0700 Subject: [PATCH 02/11] Updated blob sas gen --- .../azure/storage/blob/__init__.py | 6 +- .../azure/storage/blob/_shared/models.py | 4 +- .../storage/blob/_shared_access_signature.py | 276 ++++++++++++++++++ .../azure/storage/blob/blob_client.py | 111 ------- .../azure/storage/blob/blob_service_client.py | 77 +---- .../azure/storage/blob/container_client.py | 117 +------- .../azure/storage/blob/models.py | 8 +- .../tests/test_append_blob.py | 85 +++++- .../tests/test_append_blob_async.py | 86 +++++- .../tests/test_blob_samples_authentication.py | 6 +- .../test_blob_samples_authentication_async.py | 6 +- .../tests/test_blob_samples_containers.py | 7 +- .../test_blob_samples_containers_async.py | 7 +- .../tests/test_block_blob_sync_copy.py | 10 +- .../tests/test_block_blob_sync_copy_async.py | 16 +- .../tests/test_common_blob.py | 97 +++++- .../tests/test_common_blob_async.py | 83 +++++- .../tests/test_container.py | 13 +- .../tests/test_container_async.py | 8 +- .../azure-storage-blob/tests/test_cpk.py | 22 +- .../tests/test_cpk_async.py | 23 +- .../azure-storage-blob/tests/test_logging.py | 16 +- .../tests/test_logging_async.py | 14 +- .../tests/test_page_blob.py | 101 ++++++- .../tests/test_page_blob_async.py | 101 ++++++- 25 files changed, 881 insertions(+), 419 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py b/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py index 5bab6a093b5d..27e1ab0cbfc7 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py @@ -13,6 +13,7 @@ from .blob_service_client import BlobServiceClient from .lease import LeaseClient from .download import StorageStreamDownloader +from ._shared_access_signature import generate_account_sas, generate_container_sas, generate_blob_sas from ._shared.policies import ExponentialRetry, LinearRetry from ._shared.models import( LocationMode, @@ -89,7 +90,10 @@ 'AccountSasPermissions', 'StorageStreamDownloader', 'CustomerProvidedEncryptionKey', - 'RehydratePriority' + 'RehydratePriority', + 'generate_account_sas', + 'generate_container_sas', + 'generate_blob_sas' ] diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py index 80c4d22a6b2f..2c491acdf8e3 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py @@ -261,8 +261,8 @@ def from_string(cls, string): class AccountSasPermissions(object): """ - :class:`~ResourceTypes` class to be used with generate_shared_access_signature - method and for the AccessPolicies used with set_*_acl. There are two types of + :class:`~ResourceTypes` class to be used with generate_account_sas + function and for the AccessPolicies used with set_*_acl. There are two types of SAS which may be used to grant resource access. One is to grant access to a specific resource (resource-specific). Another is to grant access to the entire service for a specific account and allow certain operations based on diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py index 4c05f380ad78..3782b65dd939 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py @@ -6,6 +6,7 @@ from azure.storage.blob._shared import sign_string, url_quote from azure.storage.blob._shared.constants import X_MS_VERSION +from azure.storage.blob._shared.models import Services from azure.storage.blob._shared.shared_access_signature import SharedAccessSignature, _SharedAccessHelper, \ QueryStringConstants @@ -260,3 +261,278 @@ def get_token(self): exclude = [BlobQueryStringConstants.SIGNED_TIMESTAMP] return '&'.join(['{0}={1}'.format(n, url_quote(v)) for n, v in self.query_dict.items() if v is not None and n not in exclude]) + + +def generate_account_sas( + account_name, # type: str + account_key, # type: str + resource_types, # type: Union[ResourceTypes, str] + permission, # type: Union[AccountSasPermissions, str] + expiry, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): # type: (...) -> str + """Generates a shared access signature for the blob service. + + Use the returned signature with the credential parameter of any BlobServiceClient, + ContainerClient or BlobClient. + + :param resource_types: + Specifies the resource types that are accessible with the account SAS. + :type resource_types: str or ~azure.storage.blob.ResourceTypes + :param permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :type permission: str or ~azure.storage.blob.AccountSasPermissions + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: ~datetime.datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: ~datetime.datetime or str + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + + .. admonition:: Example: + + .. literalinclude:: ../tests/test_blob_samples_authentication.py + :start-after: [START create_sas_token] + :end-before: [END create_sas_token] + :language: python + :dedent: 8 + :caption: Generating a shared access signature. + """ + sas = SharedAccessSignature(account_name, account_key) + return sas.generate_account( + services=Services(blob=True), + resource_types=resource_types, + permission=permission, + expiry=expiry, + start=start, + ip=ip, + **kwargs + ) # type: ignore + + +def generate_container_sas( + account_name, # type: str + container_name, # type: str + account_key=None, # type: Optional[str] + user_delegation_key=None, # type: Optional[UserDelegationKey] + permission=None, # type: Optional[Union[ContainerSasPermissions, str]] + expiry=None, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + policy_id=None, # type: Optional[str] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> Any + """Generates a shared access signature for the container. + Use the returned signature with the credential parameter of any BlobServiceClient, + ContainerClient or BlobClient. + + :param permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Permissions must be ordered read, write, delete, list. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :type permission: str or ~azure.storage.blob.ContainerSasPermissions + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: datetime or str + :param str policy_id: + A unique value up to 64 characters in length that correlates to a + stored access policy. To create a stored access policy, use :func:`~set_container_access_policy`. + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :param ~azure.storage.blob.UserDelegationKey user_delegation_key: + Instead of an account key, the user could pass in a user delegation key. + A user delegation key can be obtained from the service by authenticating with an AAD identity; + this can be accomplished by calling get_user_delegation_key. + When present, the SAS is signed with the user delegation key instead. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :keyword str account_name: + Specifies the account_name when using oauth token as credential. If you use oauth token as credential. + :keyword str cache_control: + Response header value for Cache-Control when resource is accessed + using this shared access signature. + :keyword str content_disposition: + Response header value for Content-Disposition when resource is accessed + using this shared access signature. + :keyword str content_encoding: + Response header value for Content-Encoding when resource is accessed + using this shared access signature. + :keyword str content_language: + Response header value for Content-Language when resource is accessed + using this shared access signature. + :keyword str content_type: + Response header value for Content-Type when resource is accessed + using this shared access signature. + :return: A Shared Access Signature (sas) token. + :rtype: str + + .. admonition:: Example: + + .. literalinclude:: ../tests/test_blob_samples_containers.py + :start-after: [START generate_sas_token] + :end-before: [END generate_sas_token] + :language: python + :dedent: 12 + :caption: Generating a sas token. + """ + if not user_delegation_key and not account_key: + raise ValueError("Either user_delegation_key or account_key must be provided.") + + if user_delegation_key: + sas = BlobSharedAccessSignature(account_name, user_delegation_key=user_delegation_key) + else: + sas = BlobSharedAccessSignature(account_name, account_key=account_key) + return sas.generate_container( + container_name, + permission=permission, + expiry=expiry, + start=start, + policy_id=policy_id, + ip=ip, + **kwargs + ) + + +def generate_blob_sas( + account_name, # type: str + container_name, # type: str + blob_name, # type: str + snapshot=None, # type: Optional[str] + account_key=None, # type: Optional[str] + user_delegation_key=None, # type: Optional[UserDelegationKey] + permission=None, # type: Optional[Union[BlobSasPermissions, str]] + expiry=None, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + policy_id=None, # type: Optional[str] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> Any + """ + Generates a shared access signature for a blob. + Use the returned signature with the credential parameter of any BlobServiceClient, + ContainerClient or BlobClient. + + :param permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Permissions must be ordered read, write, delete, list. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :type permission: str or ~azure.storage.blob.BlobSasPermissions + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: ~datetime.datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: ~datetime.datetime or str + :param str policy_id: + A unique value up to 64 characters in length that correlates to a + stored access policy. To create a stored access policy, use + :func:`~ContainerClient.set_container_access_policy()`. + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :param ~azure.storage.blob.UserDelegationKey user_delegation_key: + Instead of a shared key, the user could pass in a user delegation key. + A user delegation key can be obtained from the service by authenticating with an AAD identity; + this can be accomplished by calling get_user_delegation_key. + When present, the SAS is signed with the user delegation key instead. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :keyword str account_name: + Specifies the account_name when using oauth token as credential. If you use oauth token as credential. + :keyword str cache_control: + Response header value for Cache-Control when resource is accessed + using this shared access signature. + :keyword str content_disposition: + Response header value for Content-Disposition when resource is accessed + using this shared access signature. + :keyword str content_encoding: + Response header value for Content-Encoding when resource is accessed + using this shared access signature. + :keyword str content_language: + Response header value for Content-Language when resource is accessed + using this shared access signature. + :keyword str content_type: + Response header value for Content-Type when resource is accessed + using this shared access signature. + :return: A Shared Access Signature (sas) token. + :rtype: str + """ + if not user_delegation_key and not account_key: + raise ValueError("Either user_delegation_key or account_key must be provided.") + + if user_delegation_key: + sas = BlobSharedAccessSignature(account_name, user_delegation_key=user_delegation_key) + else: + sas = BlobSharedAccessSignature(account_name, account_key=account_key) + return sas.generate_blob( + container_name, + blob_name, + snapshot=snapshot, + permission=permission, + expiry=expiry, + start=start, + policy_id=policy_id, + ip=ip, + **kwargs + ) \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py index 958eeb28bdec..d093a6db587c 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py @@ -49,7 +49,6 @@ from .models import BlobType, BlobBlock from .download import StorageStreamDownloader from .lease import LeaseClient, get_access_conditions -from ._shared_access_signature import BlobSharedAccessSignature if TYPE_CHECKING: from datetime import datetime @@ -261,116 +260,6 @@ def from_connection_string( return cls( account_url, container_name=container_name, blob_name=blob_name, snapshot=snapshot, credential=credential, **kwargs - ) - - def generate_shared_access_signature( - self, permission=None, # type: Optional[Union[BlobSasPermissions, str]] - expiry=None, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - policy_id=None, # type: Optional[str] - ip=None, # type: Optional[str] - user_delegation_key=None, # type: Optional[UserDelegationKey] - **kwargs # type: Any - ): - # type: (...) -> Any - """ - Generates a shared access signature for the blob. - Use the returned signature with the credential parameter of any BlobServiceClient, - ContainerClient or BlobClient. - - :param permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Permissions must be ordered read, write, delete, list. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :type permission: str or ~azure.storage.blob.BlobSasPermissions - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: ~datetime.datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: ~datetime.datetime or str - :param str policy_id: - A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use - :func:`~ContainerClient.set_container_access_policy()`. - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :param ~azure.storage.blob.UserDelegationKey user_delegation_key: - Instead of an account key, the user could pass in a user delegation key. - A user delegation key can be obtained from the service by authenticating with an AAD identity; - this can be accomplished by calling get_user_delegation_key. - When present, the SAS is signed with the user delegation key instead. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :keyword str account_name: - Specifies the account_name when using oauth token as credential. If you use oauth token as credential. - :keyword str cache_control: - Response header value for Cache-Control when resource is accessed - using this shared access signature. - :keyword str content_disposition: - Response header value for Content-Disposition when resource is accessed - using this shared access signature. - :keyword str content_encoding: - Response header value for Content-Encoding when resource is accessed - using this shared access signature. - :keyword str content_language: - Response header value for Content-Language when resource is accessed - using this shared access signature. - :keyword str content_type: - Response header value for Content-Type when resource is accessed - using this shared access signature. - :return: A Shared Access Signature (sas) token. - :rtype: str - """ - protocol = kwargs.pop('protocol', None) - account_name = kwargs.pop('account_name', None) - cache_control = kwargs.pop('cache_control', None) - content_disposition = kwargs.pop('content_disposition', None) - content_encoding = kwargs.pop('content_encoding', None) - content_language = kwargs.pop('content_language', None) - content_type = kwargs.pop('content_type', None) - - if user_delegation_key is not None: - if not hasattr(self.credential, 'account_name') and not account_name: - raise ValueError("No account_name available. Please provide account_name parameter.") - - account_name = self.credential.account_name if hasattr(self.credential, 'account_name') else account_name - sas = BlobSharedAccessSignature(account_name, user_delegation_key=user_delegation_key) - else: - if not hasattr(self.credential, 'account_key') or not self.credential.account_key: - raise ValueError("No account SAS key available.") - sas = BlobSharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_blob( - self.container_name, - self.blob_name, - snapshot=self.snapshot, - permission=permission, - expiry=expiry, - start=start, - policy_id=policy_id, - ip=ip, - protocol=protocol, - cache_control=cache_control, - content_disposition=content_disposition, - content_encoding=content_encoding, - content_language=content_language, - content_type=content_type, ) @distributed_trace diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py index 2a9d87b22598..36ef87155b71 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py @@ -18,8 +18,7 @@ from azure.core.paging import ItemPaged from azure.core.tracing.decorator import distributed_trace -from ._shared.shared_access_signature import SharedAccessSignature -from ._shared.models import LocationMode, Services, UserDelegationKey +from ._shared.models import LocationMode, UserDelegationKey from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query from ._shared.parser import _to_utc_datetime from ._shared.response_handlers import return_response_headers, process_storage_error, \ @@ -34,7 +33,6 @@ from datetime import datetime from azure.core.pipeline.transport import HttpTransport from azure.core.pipeline.policies import HTTPPolicy - from ._shared.models import AccountSasPermissions, ResourceTypes from .lease import LeaseClient from .models import ( BlobProperties, @@ -157,79 +155,6 @@ def from_connection_string( kwargs['secondary_hostname'] = secondary return cls(account_url, credential=credential, **kwargs) - def generate_shared_access_signature( - self, resource_types, # type: Union[ResourceTypes, str] - permission, # type: Union[AccountSasPermissions, str] - expiry, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): # type: (...) -> str - """Generates a shared access signature for the blob service. - - Use the returned signature with the credential parameter of any BlobServiceClient, - ContainerClient or BlobClient. - - :param resource_types: - Specifies the resource types that are accessible with the account SAS. - :type resource_types: str or ~azure.storage.blob.ResourceTypes - :param permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :type permission: str or ~azure.storage.blob.AccountSasPermissions - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: ~datetime.datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: ~datetime.datetime or str - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - - .. admonition:: Example: - - .. literalinclude:: ../tests/test_blob_samples_authentication.py - :start-after: [START create_sas_token] - :end-before: [END create_sas_token] - :language: python - :dedent: 8 - :caption: Generating a shared access signature. - """ - protocol = kwargs.pop('protocol', None) - if not hasattr(self.credential, 'account_key') and not self.credential.account_key: - raise ValueError("No account SAS key available.") - - sas = SharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_account( - services=Services(blob=True), - resource_types=resource_types, - permission=permission, - expiry=expiry, - start=start, - ip=ip, - protocol=protocol - ) # type: ignore - @distributed_trace def get_user_delegation_key(self, key_start_time, # type: datetime key_expiry_time, # type: datetime diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py index 15e9012f9b7c..6df9e9b03b11 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py @@ -43,14 +43,13 @@ BlobPrefix) from .lease import LeaseClient, get_access_conditions from .blob_client import BlobClient -from ._shared_access_signature import BlobSharedAccessSignature if TYPE_CHECKING: from azure.core.pipeline.transport import HttpTransport, HttpResponse # pylint: disable=ungrouped-imports from azure.core.pipeline.policies import HTTPPolicy # pylint: disable=ungrouped-imports - from .models import ContainerSasPermissions, PublicAccess from datetime import datetime from .models import ( # pylint: disable=unused-import + PublicAccess, AccessPolicy, ContentSettings, PremiumPageBlobTier) @@ -212,120 +211,6 @@ def from_connection_string( return cls( account_url, container_name=container_name, credential=credential, **kwargs) - def generate_shared_access_signature( - self, permission=None, # type: Optional[Union[ContainerSasPermissions, str]] - expiry=None, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - policy_id=None, # type: Optional[str] - ip=None, # type: Optional[str] - user_delegation_key=None, # type: Optional[Any] - **kwargs # type: Any - ): - # type: (...) -> Any - """Generates a shared access signature for the container. - Use the returned signature with the credential parameter of any BlobServiceClient, - ContainerClient or BlobClient. - - :param permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Permissions must be ordered read, write, delete, list. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :type permission: str or ~azure.storage.blob.ContainerSasPermissions - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: datetime or str - :param str policy_id: - A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_container_access_policy`. - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :param ~azure.storage.blob.UserDelegationKey user_delegation_key: - Instead of an account key, the user could pass in a user delegation key. - A user delegation key can be obtained from the service by authenticating with an AAD identity; - this can be accomplished by calling get_user_delegation_key. - When present, the SAS is signed with the user delegation key instead. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :keyword str account_name: - Specifies the account_name when using oauth token as credential. If you use oauth token as credential. - :keyword str cache_control: - Response header value for Cache-Control when resource is accessed - using this shared access signature. - :keyword str content_disposition: - Response header value for Content-Disposition when resource is accessed - using this shared access signature. - :keyword str content_encoding: - Response header value for Content-Encoding when resource is accessed - using this shared access signature. - :keyword str content_language: - Response header value for Content-Language when resource is accessed - using this shared access signature. - :keyword str content_type: - Response header value for Content-Type when resource is accessed - using this shared access signature. - :return: A Shared Access Signature (sas) token. - :rtype: str - - .. admonition:: Example: - - .. literalinclude:: ../tests/test_blob_samples_containers.py - :start-after: [START generate_sas_token] - :end-before: [END generate_sas_token] - :language: python - :dedent: 12 - :caption: Generating a sas token. - """ - protocol = kwargs.pop('protocol', None) - account_name = kwargs.pop('account_name', None) - cache_control = kwargs.pop('cache_control', None) - content_disposition = kwargs.pop('content_disposition', None) - content_encoding = kwargs.pop('content_encoding', None) - content_language = kwargs.pop('content_language', None) - content_type = kwargs.pop('content_type', None) - if user_delegation_key is not None: - if not hasattr(self.credential, 'account_name') and not account_name: - raise ValueError("No account_name available. Please provide account_name parameter.") - - account_name = self.credential.account_name if hasattr(self.credential, 'account_name') else account_name - sas = BlobSharedAccessSignature(account_name, user_delegation_key=user_delegation_key) - else: - if not hasattr(self.credential, 'account_key') and not self.credential.account_key: - raise ValueError("No account SAS key available.") - sas = BlobSharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_container( - self.container_name, - permission=permission, - expiry=expiry, - start=start, - policy_id=policy_id, - ip=ip, - protocol=protocol, - cache_control=cache_control, - content_disposition=content_disposition, - content_encoding=content_encoding, - content_language=content_language, - content_type=content_type, - ) - @distributed_trace def create_container(self, metadata=None, public_access=None, **kwargs): # type: (Optional[Dict[str, str]], Optional[Union[PublicAccess, str]], **Any) -> None diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/models.py b/sdk/storage/azure-storage-blob/azure/storage/blob/models.py index 30e2d7a7f454..08f9aad9b14c 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/models.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/models.py @@ -848,8 +848,8 @@ def __init__(self, permission=None, expiry=None, start=None): class ContainerSasPermissions(object): - """ContainerSasPermissions class to be used with - :func:`~azure.storage.blob.ContainerClient.generate_shared_access_signature` API and + """ContainerSasPermissions class to be used with the + :func:`~azure.storage.blob.generate_container_sas` function and for the AccessPolicies used with :func:`~azure.storage.blob.ContainerClient.set_container_access_policy`. @@ -894,8 +894,8 @@ def from_string(cls, permission): class BlobSasPermissions(object): - """BlobSasPermissions class to be used with - :func:`~azure.storage.blob.blob_client.BlobClient.generate_shared_access_signature` API. + """BlobSasPermissions class to be used with the + :func:`~azure.storage.blob.generate_blob_sas` function. :param bool read: Read the content, properties, metadata and block list. Use the blob as diff --git a/sdk/storage/azure-storage-blob/tests/test_append_blob.py b/sdk/storage/azure-storage-blob/tests/test_append_blob.py index c965f80f7e63..7fc9e7e6dbb2 100644 --- a/sdk/storage/azure-storage-blob/tests/test_append_blob.py +++ b/sdk/storage/azure-storage-blob/tests/test_append_blob.py @@ -13,6 +13,7 @@ from azure.core.exceptions import ResourceNotFoundError, ResourceModifiedError, HttpResponseError from azure.storage.blob import ( + generate_blob_sas, BlobServiceClient, ContainerClient, BlobClient, @@ -197,7 +198,12 @@ def test_append_block_from_url(self): # Arrange source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -239,7 +245,12 @@ def test_append_block_from_url_and_validate_content_md5(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) src_md5 = StorageContentValidation.get_content_md5(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -272,7 +283,12 @@ def test_append_block_from_url_with_source_if_modified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_blob_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -310,7 +326,12 @@ def test_append_block_from_url_with_source_if_unmodified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_blob_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -348,7 +369,12 @@ def test_append_block_from_url_with_source_if_match(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_blob_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -384,7 +410,12 @@ def test_append_block_from_url_with_source_if_none_match(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_blob_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -419,7 +450,12 @@ def test_append_block_from_url_with_if_match(self): # Arrange source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -458,7 +494,12 @@ def test_append_block_from_url_with_if_none_match(self): # Arrange source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -493,7 +534,12 @@ def test_append_block_from_url_with_maxsize_condition(self): # Arrange source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -528,7 +574,12 @@ def test_append_block_from_url_with_appendpos_condition(self): # Arrange source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -564,7 +615,12 @@ def test_append_block_from_url_with_if_modified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -601,7 +657,12 @@ def test_append_block_from_url_with_if_unmodified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data) source_properties = source_blob_client.append_block(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_append_blob_async.py b/sdk/storage/azure-storage-blob/tests/test_append_blob_async.py index 0cfd5b560ad4..71430563e6d7 100644 --- a/sdk/storage/azure-storage-blob/tests/test_append_blob_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_append_blob_async.py @@ -18,7 +18,7 @@ from azure.core.pipeline.transport import AioHttpTransport from multidict import CIMultiDict, CIMultiDictProxy -from azure.storage.blob import BlobSasPermissions +from azure.storage.blob import BlobSasPermissions, generate_blob_sas from azure.storage.blob._shared.policies import StorageContentValidation from azure.storage.blob import BlobType from azure.storage.blob.aio import ( @@ -254,7 +254,12 @@ async def _test_append_block_from_url(self): await self._setup() source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -301,7 +306,12 @@ async def _test_append_block_from_url_and_validate_content_md5(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) src_md5 = StorageContentValidation.get_content_md5(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -339,7 +349,12 @@ async def _test_append_block_from_url_with_source_if_modified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_blob_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -382,7 +397,12 @@ async def _test_append_block_from_url_with_source_if_unmodified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_blob_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -426,7 +446,12 @@ async def _test_append_block_from_url_with_source_if_match(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -467,7 +492,12 @@ async def _test_append_block_from_url_with_source_if_none_match(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -507,7 +537,12 @@ async def _test_append_block_from_url_with_if_match(self): await self._setup() source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -551,7 +586,12 @@ async def _test_append_block_from_url_with_if_none_match(self): await self._setup() source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -592,7 +632,12 @@ async def _test_append_block_from_url_with_maxsize_condition(self): await self._setup() source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -633,7 +678,12 @@ async def _test_append_block_from_url_with_appendpos_condition(self): await self._setup() source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -675,7 +725,12 @@ async def _test_append_block_from_url_with_if_modified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -718,7 +773,12 @@ async def _test_append_block_from_url_with_if_unmodified(self): source_blob_data = self.get_random_bytes(LARGE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication.py b/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication.py index 780c7660823b..20686ed04d9a 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication.py @@ -115,9 +115,11 @@ def test_auth_shared_access_signature(self): # [START create_sas_token] # Create a SAS token to use to authenticate a new client from datetime import datetime, timedelta - from azure.storage.blob import ResourceTypes, AccountSasPermissions + from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas - sas_token = blob_service_client.generate_shared_access_signature( + sas_token = generate_account_sas( + blob_service_client.account_name, + account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication_async.py b/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication_async.py index 817a75882e76..2a11e5578d28 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_samples_authentication_async.py @@ -140,9 +140,11 @@ async def _test_auth_shared_access_signature_async(self): # [START create_sas_token] # Create a SAS token to use to authenticate a new client from datetime import datetime, timedelta - from azure.storage.blob import ResourceTypes, AccountSasPermissions + from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas - sas_token = blob_service_client.generate_shared_access_signature( + sas_token = generate_account_sas( + blob_service_client.account_name, + account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers.py b/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers.py index bd7d3cd6cc22..4f2d960e7b87 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers.py @@ -166,7 +166,12 @@ def test_container_access_policy(self): # [START generate_sas_token] # Use access policy to generate a sas token - sas_token = container_client.generate_shared_access_signature( + from azure.storage.blob import generate_container_sas + + sas_token = generate_container_sas( + container_client.account_name, + container_client.container_name, + account_key=container_client.credential.account_key, policy_id='my-access-policy-id' ) # [END generate_sas_token] diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers_async.py b/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers_async.py index b4feac762ef1..0eccb1041aec 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_samples_containers_async.py @@ -183,7 +183,12 @@ async def _test_container_access_policy_async(self): # [START generate_sas_token] # Use access policy to generate a sas token - sas_token = container_client.generate_shared_access_signature( + from azure.storage.blob import generate_container_sas + + sas_token = generate_container_sas( + container_client.account_name, + container_client.container_name, + account_key=container_client.credential.account_key, policy_id='my-access-policy-id' ) # [END generate_sas_token] diff --git a/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy.py b/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy.py index 8b2604838ec1..5a298d783e19 100644 --- a/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy.py +++ b/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy.py @@ -12,7 +12,8 @@ ContainerClient, BlobClient, StorageErrorCode, - BlobSasPermissions + BlobSasPermissions, + generate_blob_sas ) from azure.storage.blob._shared.policies import StorageContentValidation from testcase import ( @@ -54,7 +55,12 @@ def setUp(self): blob.upload_blob(self.source_blob_data) # generate a SAS so that it is accessible with a URL - sas_token = blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy_async.py b/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy_async.py index e4017cb39b41..845f6b303b8b 100644 --- a/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_block_blob_sync_copy_async.py @@ -11,7 +11,7 @@ from azure.core.pipeline.transport import AioHttpTransport from multidict import CIMultiDict, CIMultiDictProxy -from azure.storage.blob import StorageErrorCode, BlobSasPermissions +from azure.storage.blob import StorageErrorCode, BlobSasPermissions, generate_blob_sas from azure.storage.blob.aio import ( BlobServiceClient, @@ -68,7 +68,12 @@ def setUp(self): blob = self.bsc.get_blob_client(self.container_name, self.source_blob_name) # generate a SAS so that it is accessible with a URL - sas_token = blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -94,7 +99,12 @@ async def _setup(self): await blob.upload_blob(self.source_blob_data, overwrite=True) # generate a SAS so that it is accessible with a URL - sas_token = blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_common_blob.py b/sdk/storage/azure-storage-blob/tests/test_common_blob.py index 92f66abad986..302f2fb55e01 100644 --- a/sdk/storage/azure-storage-blob/tests/test_common_blob.py +++ b/sdk/storage/azure-storage-blob/tests/test_common_blob.py @@ -20,6 +20,9 @@ from azure.storage.blob import ( upload_blob_to_url, download_blob_from_url, + generate_account_sas, + generate_blob_sas, + generate_container_sas, BlobServiceClient, ContainerClient, BlobClient, @@ -944,7 +947,12 @@ def test_copy_blob_async_private_blob_with_sas(self): data = b'12345678' * 1024 * 1024 self._create_remote_container() source_blob = self._create_remote_block_blob(blob_data=data) - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1207,7 +1215,12 @@ def test_sas_access_blob(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1231,7 +1244,12 @@ def test_sas_access_blob_snapshot(self): blob_snapshot = blob_client.create_snapshot() blob_snapshot_client = self.bsc.get_blob_client(self.container_name, blob_name, snapshot=blob_snapshot) - token = blob_snapshot_client.generate_shared_access_signature( + token = generate_blob_sas( + blob_snapshot_client.account_name, + blob_snapshot_client.container_name, + blob_snapshot_client.blob_name, + snapshot=blob_snapshot_client.snapshot, + account_key=blob_snapshot_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1270,7 +1288,13 @@ def test_sas_signed_identifier(self): resp = container.set_container_access_policy(identifiers) - token = blob.generate_shared_access_signature(policy_id='testid') + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, + policy_id='testid') # Act service = BlobClient.from_blob_url(blob.url, credential=token) @@ -1289,7 +1313,9 @@ def test_account_sas(self): # Arrange blob_name = self._create_block_blob() - token = self.bsc.generate_shared_access_signature( + token = generate_account_sas( + self.bsc.account_name, + self.bsc.credential.account_key, ResourceTypes(container=True, object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -1356,7 +1382,12 @@ def test_user_delegation_sas_for_blob(self): blob_client = container_client.get_blob_client(self.get_resource_name('oauthblob')) blob_client.upload_blob(self.byte_data, length=len(self.byte_data)) - token = blob_client.generate_shared_access_signature( + token = generate_blob_sas( + blob_client.account_name, + blob_client.container_name, + blob_client.blob_name, + snapshot=blob_client.snapshot, + account_key=blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), user_delegation_key=user_delegation_key, @@ -1402,7 +1433,12 @@ def test_shared_read_access_blob(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1426,7 +1462,12 @@ def test_shared_read_access_blob_with_content_query_params(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), cache_control='no-cache', @@ -1460,7 +1501,12 @@ def test_shared_write_access_blob(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1486,7 +1532,12 @@ def test_shared_delete_access_blob(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1540,7 +1591,10 @@ def test_get_account_information_with_container_sas(self): # Arrange container = self.bsc.get_container_client(self.container_name) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, permission=ContainerSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1563,7 +1617,12 @@ def test_get_account_information_with_blob_sas(self): blob_name = self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1584,7 +1643,12 @@ def test_download_to_file_with_sas(self): data = b'12345678' * 1024 * 1024 self._create_remote_container() source_blob = self._create_remote_block_blob(blob_data=data) - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1698,7 +1762,12 @@ def test_upload_to_url_bytes_with_sas(self): blob_name = self._get_blob_reference() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_common_blob_async.py b/sdk/storage/azure-storage-blob/tests/test_common_blob_async.py index dd732030b4de..936fa74af6ae 100644 --- a/sdk/storage/azure-storage-blob/tests/test_common_blob_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_common_blob_async.py @@ -32,6 +32,9 @@ from azure.storage.blob import ( upload_blob_to_url, download_blob_from_url, + generate_blob_sas, + generate_account_sas, + generate_container_sas, BlobType, StorageErrorCode, BlobSasPermissions, @@ -1250,7 +1253,12 @@ async def _test_copy_blob_async_private_blob_with_sas(self): data = b'12345678' * 1024 * 1024 await self._create_remote_container() source_blob = await self._create_remote_block_blob(blob_data=data) - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1601,7 +1609,12 @@ async def _test_sas_access_blob(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1638,7 +1651,13 @@ async def _test_sas_signed_identifier(self): resp = await container.set_container_access_policy(identifiers) - token = blob.generate_shared_access_signature(policy_id='testid') + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, + policy_id='testid') # Act service = BlobClient.from_blob_url(blob.url, credential=token) @@ -1662,7 +1681,9 @@ async def _test_account_sas(self): await self._setup() blob_name = await self._create_block_blob() - token = self.bsc.generate_shared_access_signature( + token = generate_account_sas( + self.bsc.account_name, + self.bsc.credential.account_key, ResourceTypes(container=True, object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -1765,7 +1786,12 @@ async def _test_shared_read_access_blob(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1794,7 +1820,12 @@ async def _test_shared_read_access_blob_with_content_query_params(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), cache_control='no-cache', @@ -1833,7 +1864,12 @@ async def _test_shared_write_access_blob(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1864,7 +1900,12 @@ async def _test_shared_delete_access_blob(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1938,7 +1979,10 @@ async def _test_get_account_information_with_container_sas(self): # Arrange await self._setup() container = self.bsc.get_container_client(self.container_name) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, permission=ContainerSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1966,7 +2010,12 @@ async def _test_get_account_information_with_blob_sas(self): blob_name = await self._create_block_blob() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1992,7 +2041,12 @@ async def _test_download_to_file_with_sas(self): data = b'12345678' * 1024 * 1024 await self._create_remote_container() source_blob = await self._create_remote_block_blob(blob_data=data) - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -2130,7 +2184,12 @@ async def _test_upload_to_url_bytes_with_sas(self): blob_name = self._get_blob_reference() blob = self.bsc.get_blob_client(self.container_name, blob_name) - token = blob.generate_shared_access_signature( + token = generate_blob_sas( + blob.account_name, + blob.container_name, + blob.blob_name, + snapshot=blob.snapshot, + account_key=blob.credential.account_key, permission=BlobSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_container.py b/sdk/storage/azure-storage-blob/tests/test_container.py index 3bd206d347a6..79f4feebd49f 100644 --- a/sdk/storage/azure-storage-blob/tests/test_container.py +++ b/sdk/storage/azure-storage-blob/tests/test_container.py @@ -25,7 +25,8 @@ ContainerSasPermissions, AccessPolicy, StandardBlobTier, - PremiumPageBlobTier + PremiumPageBlobTier, + generate_container_sas, ) from azure.identity import ClientSecretCredential @@ -1210,7 +1211,10 @@ def test_shared_access_container(self): blob = container.get_blob_client(blob_name) blob.upload_blob(data) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, expiry=datetime.utcnow() + timedelta(hours=1), permission=ContainerSasPermissions(read=True), ) @@ -1268,7 +1272,10 @@ def test_user_delegation_sas_for_container(self): datetime.utcnow() + timedelta(hours=1)) container_client = service_client.create_container(self.get_resource_name('oauthcontainer')) - token = container_client.generate_shared_access_signature( + token = generate_container_sas( + container_client.account_name, + container_client.container_name, + account_key=container_client.credential.account_key, expiry=datetime.utcnow() + timedelta(hours=1), permission=ContainerSasPermissions(read=True), user_delegation_key=user_delegation_key, diff --git a/sdk/storage/azure-storage-blob/tests/test_container_async.py b/sdk/storage/azure-storage-blob/tests/test_container_async.py index 29487d7141e7..70ca725b5495 100644 --- a/sdk/storage/azure-storage-blob/tests/test_container_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_container_async.py @@ -27,7 +27,8 @@ BlobProperties, ContainerSasPermissions, StandardBlobTier, - PremiumPageBlobTier + PremiumPageBlobTier, + generate_container_sas ) from azure.storage.blob.aio import ( @@ -1477,7 +1478,10 @@ async def _test_shared_access_container(self): blob = container.get_blob_client(blob_name) await blob.upload_blob(data) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, expiry=datetime.utcnow() + timedelta(hours=1), permission=ContainerSasPermissions(read=True), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_cpk.py b/sdk/storage/azure-storage-blob/tests/test_cpk.py index 4ddbb845d7f6..c46bfad64397 100644 --- a/sdk/storage/azure-storage-blob/tests/test_cpk.py +++ b/sdk/storage/azure-storage-blob/tests/test_cpk.py @@ -13,6 +13,7 @@ BlobServiceClient, BlobType, BlobBlock, + generate_blob_sas ) from azure.storage.blob.models import CustomerProvidedEncryptionKey, BlobSasPermissions from testcase import ( @@ -218,7 +219,12 @@ def test_put_block_from_url_and_commit_with_cpk(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # Make sure using chunk upload, then we can record the request source_blob_client, _ = self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) @@ -297,7 +303,12 @@ def test_append_block_from_url(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # chunk upload source_blob_client, _ = self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) @@ -392,7 +403,12 @@ def test_update_page_from_url(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # Make sure using chunk upload, then we can record the request source_blob_client, _ = self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) diff --git a/sdk/storage/azure-storage-blob/tests/test_cpk_async.py b/sdk/storage/azure-storage-blob/tests/test_cpk_async.py index d91f12f2348a..a2249c708729 100644 --- a/sdk/storage/azure-storage-blob/tests/test_cpk_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_cpk_async.py @@ -12,7 +12,7 @@ from azure.core.exceptions import HttpResponseError from azure.core.pipeline.transport import AioHttpTransport from multidict import CIMultiDict, CIMultiDictProxy -from azure.storage.blob import BlobType, BlobBlock +from azure.storage.blob import BlobType, BlobBlock, generate_blob_sas from azure.storage.blob.aio import BlobServiceClient from azure.storage.blob.models import CustomerProvidedEncryptionKey, BlobSasPermissions from testcase import ( @@ -250,7 +250,12 @@ async def _test_put_block_from_url_and_commit(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # Make sure using chunk upload, then we can record the request source_blob_client, _ = await self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) @@ -339,7 +344,12 @@ async def _test_append_block_from_url(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # chunk upload source_blob_client, _ = await self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) @@ -446,7 +456,12 @@ async def _test_update_page_from_url(self): source_blob_name = self.get_resource_name("sourceblob") self.config.use_byte_buffer = True # Make sure using chunk upload, then we can record the request source_blob_client, _ = await self._create_block_blob(blob_name=source_blob_name, data=self.byte_data) - source_blob_sas = source_blob_client.generate_shared_access_signature( + source_blob_sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) diff --git a/sdk/storage/azure-storage-blob/tests/test_logging.py b/sdk/storage/azure-storage-blob/tests/test_logging.py index dcd41ef319fb..8607e2478c5f 100644 --- a/sdk/storage/azure-storage-blob/tests/test_logging.py +++ b/sdk/storage/azure-storage-blob/tests/test_logging.py @@ -15,7 +15,9 @@ ContainerClient, BlobClient, ContainerSasPermissions, - BlobSasPermissions + BlobSasPermissions, + generate_blob_sas, + generate_container_sas ) from azure.storage.blob._shared.shared_access_signature import QueryStringConstants @@ -55,7 +57,12 @@ def setUp(self): source_blob.upload_blob(self.source_blob_data) # generate a SAS so that it is accessible with a URL - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -90,7 +97,10 @@ def test_sas_signature_is_scrubbed_off(self): # Arrange container = self.bsc.get_container_client(self.container_name) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, permission=ContainerSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_logging_async.py b/sdk/storage/azure-storage-blob/tests/test_logging_async.py index 3436b7480a55..b8614f864fb5 100644 --- a/sdk/storage/azure-storage-blob/tests/test_logging_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_logging_async.py @@ -23,6 +23,8 @@ from azure.storage.blob import ( ContainerSasPermissions, BlobSasPermissions, + generate_container_sas, + generate_blob_sas ) from azure.storage.blob._shared.shared_access_signature import QueryStringConstants @@ -87,7 +89,12 @@ async def _setup(self): await source_blob.upload_blob(self.source_blob_data) # generate a SAS so that it is accessible with a URL - sas_token = source_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + source_blob.account_name, + source_blob.container_name, + source_blob.blob_name, + snapshot=source_blob.snapshot, + account_key=source_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -123,7 +130,10 @@ async def _test_sas_signature_is_scrubbed_off(self): await self._setup() # Arrange container = self.bsc.get_container_client(self.container_name) - token = container.generate_shared_access_signature( + token = generate_container_sas( + container.account_name, + container.container_name, + account_key=container.credential.account_key, permission=ContainerSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_page_blob.py b/sdk/storage/azure-storage-blob/tests/test_page_blob.py index 6cb20eb2671a..a674618102a0 100644 --- a/sdk/storage/azure-storage-blob/tests/test_page_blob.py +++ b/sdk/storage/azure-storage-blob/tests/test_page_blob.py @@ -22,7 +22,8 @@ BlobType, PremiumPageBlobTier, SequenceNumberAction, - StorageErrorCode) + StorageErrorCode, + generate_blob_sas) from azure.storage.blob._shared.policies import StorageContentValidation from testcase import ( @@ -377,7 +378,12 @@ def test_upload_pages_from_url(self): # Arrange source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -408,7 +414,12 @@ def test_upload_pages_from_url_and_validate_content_md5(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) src_md5 = StorageContentValidation.get_content_md5(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -444,7 +455,12 @@ def test_upload_pages_from_url_with_source_if_modified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -482,7 +498,12 @@ def test_upload_pages_from_url_with_source_if_unmodified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -519,7 +540,12 @@ def test_upload_pages_from_url_with_source_if_match(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -555,7 +581,12 @@ def test_upload_pages_from_url_with_source_if_none_match(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -591,7 +622,12 @@ def test_upload_pages_from_url_with_if_modified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -628,7 +664,12 @@ def test_upload_pages_from_url_with_if_unmodified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -665,7 +706,12 @@ def test_upload_pages_from_url_with_if_match(self): # Arrange source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -701,7 +747,12 @@ def test_upload_pages_from_url_with_if_none_match(self): # Arrange source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -738,7 +789,12 @@ def test_upload_pages_from_url_with_sequence_number_lt(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -774,7 +830,12 @@ def test_upload_pages_from_url_with_sequence_number_lte(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -810,7 +871,12 @@ def test_upload_pages_from_url_with_sequence_number_eq(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -1354,7 +1420,12 @@ def test_incremental_copy_blob(self): snapshot_blob = BlobClient.from_blob_url( source_blob.url, credential=source_blob.credential, snapshot=source_snapshot_blob) - sas_token = snapshot_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + snapshot_blob.account_name, + snapshot_blob.container_name, + snapshot_blob.blob_name, + snapshot=snapshot_blob.snapshot, + account_key=snapshot_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-blob/tests/test_page_blob_async.py b/sdk/storage/azure-storage-blob/tests/test_page_blob_async.py index 9f123782f9f8..c72f075bb9c0 100644 --- a/sdk/storage/azure-storage-blob/tests/test_page_blob_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_page_blob_async.py @@ -24,7 +24,8 @@ BlobType, PremiumPageBlobTier, SequenceNumberAction, - StorageErrorCode + StorageErrorCode, + generate_blob_sas ) from azure.storage.blob.aio import ( @@ -484,7 +485,12 @@ async def _test_upload_pages_from_url(self): await self._setup() source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -518,7 +524,12 @@ async def _test_upload_pages_from_url_and_validate_content_md5(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) src_md5 = StorageContentValidation.get_content_md5(source_blob_data) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -558,7 +569,12 @@ async def _test_upload_pages_from_url_with_source_if_modified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -600,7 +616,12 @@ async def _test_upload_pages_from_url_with_source_if_unmodified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -642,7 +663,12 @@ async def _test_upload_pages_from_url_with_source_if_match(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -681,7 +707,12 @@ async def _test_upload_pages_from_url_with_source_if_none_match(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -720,7 +751,12 @@ async def _test_upload_pages_from_url_with_if_modified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -762,7 +798,12 @@ async def _test_upload_pages_from_url_with_if_unmodified(self): source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) source_properties = await source_blob_client.get_blob_properties() - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -803,7 +844,12 @@ async def _test_upload_pages_from_url_with_if_match(self): await self._setup() source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -842,7 +888,12 @@ async def _test_upload_pages_from_url_with_if_none_match(self): await self._setup() source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -881,7 +932,12 @@ async def _test_upload_pages_from_url_with_sequence_number_lt(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -920,7 +976,12 @@ async def _test_upload_pages_from_url_with_sequence_number_lte(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -959,7 +1020,12 @@ async def _test_upload_pages_from_url_with_sequence_number_eq(self): start_sequence = 10 source_blob_data = self.get_random_bytes(SOURCE_BLOB_SIZE) source_blob_client = await self._create_source_blob(source_blob_data, 0, SOURCE_BLOB_SIZE) - sas = source_blob_client.generate_shared_access_signature( + sas = generate_blob_sas( + source_blob_client.account_name, + source_blob_client.container_name, + source_blob_client.blob_name, + snapshot=source_blob_client.snapshot, + account_key=source_blob_client.credential.account_key, permission=BlobSasPermissions(read=True, delete=True), expiry=datetime.utcnow() + timedelta(hours=1)) @@ -1627,7 +1693,12 @@ async def _test_incremental_copy_blob(self): snapshot_blob = BlobClient.from_blob_url( source_blob.url, credential=source_blob.credential, snapshot=source_snapshot_blob) - sas_token = snapshot_blob.generate_shared_access_signature( + sas_token = generate_blob_sas( + snapshot_blob.account_name, + snapshot_blob.container_name, + snapshot_blob.blob_name, + snapshot=snapshot_blob.snapshot, + account_key=snapshot_blob.credential.account_key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) From 47e575c283a9d9c4f5ad9743796df8ac46e7ca66 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 15:23:58 -0700 Subject: [PATCH 03/11] Updated file sas gen --- .../azure/storage/file/__init__.py | 8 +- .../azure/storage/file/_shared/models.py | 4 +- .../storage/file/_shared_access_signature.py | 243 ++++++++++++++++++ .../azure/storage/file/file_client.py | 99 +------ .../azure/storage/file/file_service_client.py | 74 ------ .../azure/storage/file/share_client.py | 94 +------ .../azure-storage-file/tests/test_file.py | 87 +++++-- .../tests/test_file_async.py | 86 +++++-- .../tests/test_file_samples_authentication.py | 6 +- .../test_file_samples_authentication_async.py | 6 +- .../tests/test_file_samples_service_async.py | 2 +- .../azure-storage-file/tests/test_share.py | 19 +- .../tests/test_share_async.py | 6 +- 13 files changed, 415 insertions(+), 319 deletions(-) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/__init__.py b/sdk/storage/azure-storage-file/azure/storage/file/__init__.py index 83382a9e6486..9099ce806096 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/__init__.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/__init__.py @@ -9,8 +9,9 @@ from .directory_client import DirectoryClient from .share_client import ShareClient from .file_service_client import FileServiceClient +from ._shared_access_signature import generate_account_sas, generate_share_sas, generate_file_sas from ._shared.policies import ExponentialRetry, LinearRetry -from ._shared.models import( +from ._shared.models import ( LocationMode, ResourceTypes, AccountSasPermissions, @@ -58,5 +59,8 @@ 'ContentSettings', 'Handle', 'NTFSAttributes', - 'HandleItem' + 'HandleItem', + 'generate_account_sas', + 'generate_share_sas', + 'generate_file_sas' ] diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/models.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/models.py index 943842ced4c2..c14d8cad8b8e 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/models.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/models.py @@ -261,8 +261,8 @@ def from_string(cls, string): class AccountSasPermissions(object): """ - :class:`~ResourceTypes` class to be used with generate_shared_access_signature - method and for the AccessPolicies used with set_*_acl. There are two types of + :class:`~ResourceTypes` class to be used with generate_account_sas + function and for the AccessPolicies used with set_*_acl. There are two types of SAS which may be used to grant resource access. One is to grant access to a specific resource (resource-specific). Another is to grant access to the entire service for a specific account and allow certain operations based on diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py index 1bfac4a176f0..b4fde0c4fa76 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py @@ -6,6 +6,7 @@ from ._shared import sign_string from ._shared.constants import X_MS_VERSION +from ._shared.models import Services from ._shared.shared_access_signature import SharedAccessSignature, _SharedAccessHelper, QueryStringConstants from ._shared.parser import _str @@ -219,3 +220,245 @@ def get_value_to_append(query): self._add_query(QueryStringConstants.SIGNED_SIGNATURE, sign_string(account_key, string_to_sign)) + + +def generate_account_sas( + account_name, # type: str + account_key, # type: str + resource_types, # type: Union[ResourceTypes, str] + permission, # type: Union[AccountSasPermissions, str] + expiry, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> str + """Generates a shared access signature for the file service. + + Use the returned signature with the credential parameter of any FileServiceClient, + ShareClient, DirectoryClient, or FileClient. + + :param ~azure.storage.file.ResourceTypes resource_types: + Specifies the resource types that are accessible with the account SAS. + :param ~azure.storage.file.AccountSasPermissions permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: datetime or str + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + + .. admonition:: Example: + + .. literalinclude:: ../tests/test_file_samples_authentication.py + :start-after: [START generate_sas_token] + :end-before: [END generate_sas_token] + :language: python + :dedent: 8 + :caption: Generate a sas token. + """ + sas = SharedAccessSignature(account_name, account_key) + return sas.generate_account( + services=Services(file=True), + resource_types=resource_types, + permission=permission, + expiry=expiry, + start=start, + ip=ip, + **kwargs + ) # type: ignore + + +def generate_share_sas( + account_name, # type: str + share_name, # type: str + account_key, # type: str + permission=None, # type: Optional[Union[ShareSasPermissions, str]] + expiry=None, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + policy_id=None, # type: Optional[str] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): # type: (...) -> str + """Generates a shared access signature for the share. + Use the returned signature with the credential parameter of any FileServiceClient, + ShareClient, DirectoryClient, or FileClient. + + :param ~azure.storage.file.ShareSasPermissions permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Permissions must be ordered read, create, write, delete, list. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: ~datetime.datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: ~datetime.datetime or str + :param str policy_id: + A unique value up to 64 characters in length that correlates to a + stored access policy. To create a stored access policy, use :func:`~set_share_access_policy`. + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. Possible values are + both HTTPS and HTTP (https,http) or HTTPS only (https). The default value + is https,http. Note that HTTP only is not a permitted value. + :keyword str cache_control: + Response header value for Cache-Control when resource is accessed + using this shared access signature. + :keyword str content_disposition: + Response header value for Content-Disposition when resource is accessed + using this shared access signature. + :keyword str content_encoding: + Response header value for Content-Encoding when resource is accessed + using this shared access signature. + :keyword str content_language: + Response header value for Content-Language when resource is accessed + using this shared access signature. + :keyword str content_type: + Response header value for Content-Type when resource is accessed + using this shared access signature. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + """ + sas = FileSharedAccessSignature(account_name, account_key) + return sas.generate_share( + share_name=share_name, + permission=permission, + expiry=expiry, + start=start, + policy_id=policy_id, + ip=ip, + **kwargs + ) + + +def generate_file_sas( + account_name, # type: str + share_name, # type: str + file_path, # type: List[str] + account_key, # type: str + permission=None, # type: Optional[Union[FileSasPermissions, str]] + expiry=None, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + policy_id=None, # type: Optional[str] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> str + """Generates a shared access signature for the file. + + Use the returned signature with the credential parameter of any FileServiceClient, + ShareClient, DirectoryClient, or FileClient. + + :param ~azure.storage.file.FileSasPermissions permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Permissions must be ordered read, write, delete, list. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: ~datetime.datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: ~datetime.datetime or str + :param str policy_id: + A unique value up to 64 characters in length that correlates to a + stored access policy. + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :keyword str cache_control: + Response header value for Cache-Control when resource is accessed + using this shared access signature. + :keyword str content_disposition: + Response header value for Content-Disposition when resource is accessed + using this shared access signature. + :keyword str content_encoding: + Response header value for Content-Encoding when resource is accessed + using this shared access signature. + :keyword str content_language: + Response header value for Content-Language when resource is accessed + using this shared access signature. + :keyword str content_type: + Response header value for Content-Type when resource is accessed + using this shared access signature. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + """ + sas = FileSharedAccessSignature(account_name, account_key) + if len(file_path) > 1: + dir_path = '/'.join(file_path[:-1]) + else: + dir_path = None # type: ignore + return sas.generate_file( # type: ignore + share_name=share_name, + directory_name=dir_path, + file_name=file_path[-1], + permission=permission, + expiry=expiry, + start=start, + policy_id=policy_id, + ip=ip, + **kwargs + ) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/file_client.py b/sdk/storage/azure-storage-file/azure/storage/file/file_client.py index 9af4d7a859e5..5f5aa36c0fd8 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/file_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/file_client.py @@ -208,7 +208,7 @@ def from_file_url( path_snapshot, _ = parse_query(parsed_url.query) snapshot = snapshot or path_snapshot share_name = unquote(path_share) - file_path = [unquote(p) for p in path_file.split('/')] + file_path = '/'.join([unquote(p) for p in path_file.split('/')]) return cls(account_url, share_name, file_path, snapshot, credential, **kwargs) def _format_url(self, hostname): @@ -266,103 +266,6 @@ def from_connection_string( return cls( account_url, share_name=share_name, file_path=file_path, snapshot=snapshot, credential=credential, **kwargs) - def generate_shared_access_signature( - self, permission=None, # type: Optional[Union[FileSasPermissions, str]] - expiry=None, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - policy_id=None, # type: Optional[str] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): - # type: (...) -> str - """Generates a shared access signature for the file. - - Use the returned signature with the credential parameter of any FileServiceClient, - ShareClient, DirectoryClient, or FileClient. - - :param ~azure.storage.file.FileSasPermissions permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Permissions must be ordered read, write, delete, list. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: ~datetime.datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: ~datetime.datetime or str - :param str policy_id: - A unique value up to 64 characters in length that correlates to a - stored access policy. - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :keyword str cache_control: - Response header value for Cache-Control when resource is accessed - using this shared access signature. - :keyword str content_disposition: - Response header value for Content-Disposition when resource is accessed - using this shared access signature. - :keyword str content_encoding: - Response header value for Content-Encoding when resource is accessed - using this shared access signature. - :keyword str content_language: - Response header value for Content-Language when resource is accessed - using this shared access signature. - :keyword str content_type: - Response header value for Content-Type when resource is accessed - using this shared access signature. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - """ - protocol = kwargs.pop('protocol', None) - cache_control = kwargs.pop('cache_control', None) - content_disposition = kwargs.pop('content_disposition', None) - content_encoding = kwargs.pop('content_encoding', None) - content_language = kwargs.pop('content_language', None) - content_type = kwargs.pop('content_type', None) - - if not hasattr(self.credential, 'account_key') or not self.credential.account_key: - raise ValueError("No account SAS key available.") - sas = FileSharedAccessSignature(self.credential.account_name, self.credential.account_key) - if len(self.file_path) > 1: - file_path = '/'.join(self.file_path[:-1]) - else: - file_path = None # type: ignore - return sas.generate_file( # type: ignore - share_name=self.share_name, - directory_name=file_path, - file_name=self.file_name, - permission=permission, - expiry=expiry, - start=start, - policy_id=policy_id, - ip=ip, - protocol=protocol, - cache_control=cache_control, - content_disposition=content_disposition, - content_encoding=content_encoding, - content_language=content_language, - content_type=content_type) - @distributed_trace def create_file( # type: ignore self, size, # type: int diff --git a/sdk/storage/azure-storage-file/azure/storage/file/file_service_client.py b/sdk/storage/azure-storage-file/azure/storage/file/file_service_client.py index e349527fa0f4..591bfefb2fdd 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/file_service_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/file_service_client.py @@ -17,8 +17,6 @@ from azure.core.paging import ItemPaged from azure.core.tracing.decorator import distributed_trace -from ._shared.shared_access_signature import SharedAccessSignature -from ._shared.models import Services from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query from ._shared.response_handlers import process_storage_error from ._generated import AzureFileStorage @@ -29,7 +27,6 @@ if TYPE_CHECKING: from datetime import datetime - from ._shared.models import ResourceTypes, AccountSasPermissions from .models import Metrics, CorsRule, ShareProperties @@ -137,77 +134,6 @@ def from_connection_string( kwargs['secondary_hostname'] = secondary return cls(account_url, credential=credential, **kwargs) - def generate_shared_access_signature( - self, resource_types, # type: Union[ResourceTypes, str] - permission, # type: Union[AccountSasPermissions, str] - expiry, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): # type: (...) -> str - """Generates a shared access signature for the file service. - - Use the returned signature with the credential parameter of any FileServiceClient, - ShareClient, DirectoryClient, or FileClient. - - :param ~azure.storage.file.ResourceTypes resource_types: - Specifies the resource types that are accessible with the account SAS. - :param ~azure.storage.file.AccountSasPermissions permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: datetime or str - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - - .. admonition:: Example: - - .. literalinclude:: ../tests/test_file_samples_authentication.py - :start-after: [START generate_sas_token] - :end-before: [END generate_sas_token] - :language: python - :dedent: 8 - :caption: Generate a sas token. - """ - protocol = kwargs.pop('protocol', None) - if not hasattr(self.credential, 'account_key') and not self.credential.account_key: - raise ValueError("No account SAS key available.") - - sas = SharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_account( - services=Services(file=True), - resource_types=resource_types, - permission=permission, - expiry=expiry, - start=start, - ip=ip, - protocol=protocol - ) # type: ignore - @distributed_trace def get_service_properties(self, **kwargs): # type: (Any) -> Dict[str, Any] diff --git a/sdk/storage/azure-storage-file/azure/storage/file/share_client.py b/sdk/storage/azure-storage-file/azure/storage/file/share_client.py index 29618ef0cf7a..e41cd1468d4f 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/share_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/share_client.py @@ -31,10 +31,9 @@ from ._deserialize import deserialize_share_properties, deserialize_permission_key, deserialize_permission from .directory_client import DirectoryClient from .file_client import FileClient -from ._shared_access_signature import FileSharedAccessSignature if TYPE_CHECKING: - from .models import ShareProperties, AccessPolicy, ShareSasPermissions + from .models import ShareProperties, AccessPolicy class ShareClient(StorageAccountHostsMixin): @@ -196,97 +195,6 @@ def from_connection_string( return cls( account_url, share_name=share_name, snapshot=snapshot, credential=credential, **kwargs) - def generate_shared_access_signature( - self, permission=None, # type: Optional[Union[ShareSasPermissions, str]] - expiry=None, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - policy_id=None, # type: Optional[str] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): # type: (...) -> str - """Generates a shared access signature for the share. - Use the returned signature with the credential parameter of any FileServiceClient, - ShareClient, DirectoryClient, or FileClient. - - :param ~azure.storage.file.ShareSasPermissions permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Permissions must be ordered read, create, write, delete, list. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: ~datetime.datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: ~datetime.datetime or str - :param str policy_id: - A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_share_access_policy`. - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. Possible values are - both HTTPS and HTTP (https,http) or HTTPS only (https). The default value - is https,http. Note that HTTP only is not a permitted value. - :keyword str cache_control: - Response header value for Cache-Control when resource is accessed - using this shared access signature. - :keyword str content_disposition: - Response header value for Content-Disposition when resource is accessed - using this shared access signature. - :keyword str content_encoding: - Response header value for Content-Encoding when resource is accessed - using this shared access signature. - :keyword str content_language: - Response header value for Content-Language when resource is accessed - using this shared access signature. - :keyword str content_type: - Response header value for Content-Type when resource is accessed - using this shared access signature. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - """ - protocol = kwargs.pop('protocol', None) - cache_control = kwargs.pop('cache_control', None) - content_disposition = kwargs.pop('content_disposition', None) - content_encoding = kwargs.pop('content_encoding', None) - content_language = kwargs.pop('content_language', None) - content_type = kwargs.pop('content_type', None) - if not hasattr(self.credential, 'account_key') or not self.credential.account_key: - raise ValueError("No account SAS key available.") - sas = FileSharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_share( - share_name=self.share_name, - permission=permission, - expiry=expiry, - start=start, - policy_id=policy_id, - ip=ip, - protocol=protocol, - cache_control=cache_control, - content_disposition=content_disposition, - content_encoding=content_encoding, - content_language=content_language, - content_type=content_type, - ) - def get_directory_client(self, directory_path=None): # type: (Optional[str]) -> DirectoryClient """Get a client to interact with the specified directory. diff --git a/sdk/storage/azure-storage-file/tests/test_file.py b/sdk/storage/azure-storage-file/tests/test_file.py index 2f54e618c567..3f3e9a5a7ace 100644 --- a/sdk/storage/azure-storage-file/tests/test_file.py +++ b/sdk/storage/azure-storage-file/tests/test_file.py @@ -16,6 +16,8 @@ from azure.core.exceptions import HttpResponseError, ResourceNotFoundError, ResourceExistsError from azure.storage.file import ( + generate_account_sas, + generate_file_sas, FileClient, FileServiceClient, ContentSettings, @@ -596,8 +598,12 @@ def test_update_range_from_file_url_when_source_file_does_not_have_enough_bytes( destination_file_client = self._create_file(destination_file_name) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature() + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key, + ) source_file_url = source_file_client.url + '?' + sas_token_for_source_file @@ -618,10 +624,13 @@ def test_update_range_from_file_url(self): destination_file_client = self._create_empty_file(file_name=destination_file_name) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature( - FileSasPermissions(read=True), - expiry=datetime.utcnow() + timedelta(hours=1)) + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key, + FileSasPermissions(read=True), + expiry=datetime.utcnow() + timedelta(hours=1)) source_file_url = source_file_client.url + '?' + sas_token_for_source_file # Act @@ -650,10 +659,13 @@ def test_update_big_range_from_file_url(self): destination_file_client = self._create_empty_file(file_name=destination_file_name, file_size=1024 * 1024) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature( - FileSasPermissions(read=True), - expiry=datetime.utcnow() + timedelta(hours=1)) + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key, + FileSasPermissions(read=True), + expiry=datetime.utcnow() + timedelta(hours=1)) source_file_url = source_file_client.url + '?' + sas_token_for_source_file @@ -857,7 +869,11 @@ def test_copy_file_async_private_file_with_sas(self): data = b'12345678' * 1024 * 1024 self._create_remote_share() source_file = self._create_remote_file(file_data=data) - sas_token = source_file.generate_shared_access_signature( + sas_token = generate_file_sas( + source_file.account_name, + source_file.share_name, + source_file.file_path, + source_file.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -885,7 +901,11 @@ def test_abort_copy_file(self): data = b'12345678' * 1024 * 1024 self._create_remote_share() source_file = self._create_remote_file(file_data=data) - sas_token = source_file.generate_shared_access_signature( + sas_token = generate_file_sas( + source_file.account_name, + source_file.share_name, + source_file.file_path, + source_file.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1402,7 +1422,11 @@ def test_sas_access_file(self): # Arrange file_client = self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1435,10 +1459,15 @@ def test_sas_signed_identifier(self): identifiers = {'testid': access_policy} share_client.set_share_access_policy(identifiers) - token = file_client.generate_shared_access_signature(policy_id='testid') + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, + policy_id='testid') # Act - sas_file = FileClient( + sas_file = FileClient.from_file_url( file_client.url, credential=token) @@ -1455,7 +1484,9 @@ def test_account_sas(self): # Arrange file_client = self._create_file() - token = self.fsc.generate_shared_access_signature( + token = generate_account_sas( + self.fsc.account_name, + self.fsc.credential.account_key, ResourceTypes(object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -1482,7 +1513,11 @@ def test_shared_read_access_file(self): # Arrange file_client = self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1507,7 +1542,11 @@ def test_shared_read_access_file_with_content_query_params(self): # Arrange file_client = self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), cache_control='no-cache', @@ -1542,7 +1581,11 @@ def test_shared_write_access_file(self): # Arrange updated_data = b'updated file data' file_client_admin = self._create_file() - token = file_client_admin.generate_shared_access_signature( + token = generate_file_sas( + file_client_admin.account_name, + file_client_admin.share_name, + file_client_admin.file_path, + file_client_admin.credential.account_key, permission=FileSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1569,7 +1612,11 @@ def test_shared_delete_access_file(self): # Arrange file_client_admin = self._create_file() - token = file_client_admin.generate_shared_access_signature( + token = generate_file_sas( + file_client_admin.account_name, + file_client_admin.share_name, + file_client_admin.file_path, + file_client_admin.credential.account_key, permission=FileSasPermissions(delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-file/tests/test_file_async.py b/sdk/storage/azure-storage-file/tests/test_file_async.py index 547dd59f077c..3164adf92895 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_async.py +++ b/sdk/storage/azure-storage-file/tests/test_file_async.py @@ -17,6 +17,8 @@ from azure.core.exceptions import HttpResponseError, ResourceNotFoundError, ResourceExistsError from azure.storage.file import ( + generate_account_sas, + generate_file_sas, NTFSAttributes, ContentSettings, FileSasPermissions, @@ -741,8 +743,11 @@ async def _test_update_range_from_file_url_when_source_file_does_not_have_enough destination_file_client = await self._create_file(destination_file_name) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature() + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key) source_file_url = source_file_client.url + '?' + sas_token_for_source_file @@ -767,10 +772,13 @@ async def _test_update_range_from_file_url(self): destination_file_client = await self._create_empty_file(file_name=destination_file_name) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature( - FileSasPermissions(read=True), - expiry=datetime.utcnow() + timedelta(hours=1)) + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key, + FileSasPermissions(read=True), + expiry=datetime.utcnow() + timedelta(hours=1)) source_file_url = source_file_client.url + '?' + sas_token_for_source_file # Act @@ -804,10 +812,13 @@ async def _test_update_big_range_from_file_url(self): destination_file_client = await self._create_empty_file(file_name=destination_file_name, file_size=1024 * 1024) # generate SAS for the source file - sas_token_for_source_file = \ - source_file_client.generate_shared_access_signature( - FileSasPermissions(read=True), - expiry=datetime.utcnow() + timedelta(hours=1)) + sas_token_for_source_file = generate_file_sas( + source_file_client.account_name, + source_file_client.share_name, + source_file_client.file_path, + source_file_client.credential.account_key, + FileSasPermissions(read=True), + expiry=datetime.utcnow() + timedelta(hours=1)) source_file_url = source_file_client.url + '?' + sas_token_for_source_file @@ -1062,7 +1073,11 @@ async def _test_copy_file_async_private_file_with_sas_async(self): data = b'12345678' * 1024 * 1024 await self._create_remote_share() source_file = await self._create_remote_file(file_data=data) - sas_token = source_file.generate_shared_access_signature( + sas_token = generate_file_sas( + source_file.account_name, + source_file.share_name, + source_file.file_path, + source_file.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1097,7 +1112,11 @@ async def _test_abort_copy_file_async(self): data = b'12345678' * 1024 * 1024 await self._create_remote_share() source_file = await self._create_remote_file(file_data=data) - sas_token = source_file.generate_shared_access_signature( + sas_token = generate_file_sas( + source_file.account_name, + source_file.share_name, + source_file.file_path, + source_file.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1734,7 +1753,11 @@ async def _test_sas_access_file_async(self): # Arrange file_client = await self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1772,10 +1795,15 @@ async def _test_sas_signed_identifier_async(self): identifiers = {'testid': access_policy} await share_client.set_share_access_policy(identifiers) - token = file_client.generate_shared_access_signature(policy_id='testid') + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, + policy_id='testid') # Act - sas_file = FileClient( + sas_file = FileClient.from_file_url( file_client.url, credential=token) @@ -1797,7 +1825,9 @@ async def _test_account_sas_async(self): # Arrange file_client = await self._create_file() - token = self.fsc.generate_shared_access_signature( + token = generate_account_sas( + self.fsc.account_name, + self.fsc.credential.account_key, ResourceTypes(object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -1828,7 +1858,11 @@ async def _test_shared_read_access_file_async(self): # Arrange file_client = await self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1857,7 +1891,11 @@ async def _test_shared_read_access_file_with_content_query_params_async(self): # Arrange file_client = await self._create_file() - token = file_client.generate_shared_access_signature( + token = generate_file_sas( + file_client.account_name, + file_client.share_name, + file_client.file_path, + file_client.credential.account_key, permission=FileSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1), cache_control='no-cache', @@ -1896,7 +1934,11 @@ async def _test_shared_write_access_file_async(self): # Arrange updated_data = b'updated file data' file_client_admin = await self._create_file() - token = file_client_admin.generate_shared_access_signature( + token = generate_file_sas( + file_client_admin.account_name, + file_client_admin.share_name, + file_client_admin.file_path, + file_client_admin.credential.account_key, permission=FileSasPermissions(write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) @@ -1928,7 +1970,11 @@ async def _test_shared_delete_access_file_async(self): # Arrange file_client_admin = await self._create_file() - token = file_client_admin.generate_shared_access_signature( + token = generate_file_sas( + file_client_admin.account_name, + file_client_admin.share_name, + file_client_admin.file_path, + file_client_admin.credential.account_key, permission=FileSasPermissions(delete=True), expiry=datetime.utcnow() + timedelta(hours=1), ) diff --git a/sdk/storage/azure-storage-file/tests/test_file_samples_authentication.py b/sdk/storage/azure-storage-file/tests/test_file_samples_authentication.py index 746a9b758189..6ef8d950a47c 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_samples_authentication.py +++ b/sdk/storage/azure-storage-file/tests/test_file_samples_authentication.py @@ -64,7 +64,11 @@ def test_auth_shared_access_signature(self): # Create a SAS token to use to authenticate a new client # [START generate_sas_token] - sas_token = file_service_client.generate_shared_access_signature( + from azure.storage.file import generate_account_sas + + sas_token = generate_account_sas( + file_service_client.account_name, + file_service_client.credential.account_key, resource_types="object", permission="read", expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-file/tests/test_file_samples_authentication_async.py b/sdk/storage/azure-storage-file/tests/test_file_samples_authentication_async.py index ab78f5fad071..93b327fd17b4 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_samples_authentication_async.py +++ b/sdk/storage/azure-storage-file/tests/test_file_samples_authentication_async.py @@ -75,7 +75,11 @@ async def _test_auth_shared_access_signature(self): # Create a SAS token to use to authenticate a new client # [START generate_sas_token] - sas_token = file_service_client.generate_shared_access_signature( + from azure.storage.file import generate_account_sas + + sas_token = generate_account_sas( + file_service_client.account_name, + file_service_client.credential.account_key, resource_types="object", permission="read", expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-file/tests/test_file_samples_service_async.py b/sdk/storage/azure-storage-file/tests/test_file_samples_service_async.py index 5df46ee76608..86c45dc81f55 100644 --- a/sdk/storage/azure-storage-file/tests/test_file_samples_service_async.py +++ b/sdk/storage/azure-storage-file/tests/test_file_samples_service_async.py @@ -104,7 +104,7 @@ async def _test_get_share_client(self): file_service = FileServiceClient.from_connection_string(self.connection_string) # Get a share client to interact with a specific share - share = await file_service.get_share_client("fileshare") + share = file_service.get_share_client("fileshare") # [END get_share_client] def test_get_share_client(self): diff --git a/sdk/storage/azure-storage-file/tests/test_share.py b/sdk/storage/azure-storage-file/tests/test_share.py index 53f6063e2e13..3824ff9f608b 100644 --- a/sdk/storage/azure-storage-file/tests/test_share.py +++ b/sdk/storage/azure-storage-file/tests/test_share.py @@ -15,11 +15,15 @@ ResourceNotFoundError, ResourceExistsError) -from azure.storage.file.models import AccessPolicy, ShareSasPermissions -from azure.storage.file.file_service_client import FileServiceClient -from azure.storage.file.directory_client import DirectoryClient -from azure.storage.file.file_client import FileClient -from azure.storage.file.share_client import ShareClient +from azure.storage.file import ( + AccessPolicy, + ShareSasPermissions, + FileServiceClient, + DirectoryClient, + FileClient, + ShareClient, + generate_share_sas) + from azure.storage.file._generated.models import DeleteSnapshotsOptionType, ListSharesIncludeType from filetestcase import ( FileTestCase, @@ -725,7 +729,10 @@ def test_shared_access_share(self): dir1 = share.create_directory(dir_name) dir1.upload_file(file_name, data) - token = share.generate_shared_access_signature( + token = generate_share_sas( + share.account_name, + share.share_name, + share.credential.account_key, expiry=datetime.utcnow() + timedelta(hours=1), permission=ShareSasPermissions(read=True), ) diff --git a/sdk/storage/azure-storage-file/tests/test_share_async.py b/sdk/storage/azure-storage-file/tests/test_share_async.py index fe4d3687d017..08e2136e0fef 100644 --- a/sdk/storage/azure-storage-file/tests/test_share_async.py +++ b/sdk/storage/azure-storage-file/tests/test_share_async.py @@ -20,6 +20,7 @@ from azure.storage.file import ( AccessPolicy, ShareSasPermissions, + generate_share_sas, ) from azure.storage.file.aio import ( FileServiceClient, @@ -874,7 +875,10 @@ async def _test_shared_access_share_async(self): dir1 = await share.create_directory(dir_name) await dir1.upload_file(file_name, data) - token = share.generate_shared_access_signature( + token = generate_share_sas( + share.account_name, + share.share_name, + share.credential.account_key, expiry=datetime.utcnow() + timedelta(hours=1), permission=ShareSasPermissions(read=True), ) From ed02d48a53cdd5313213ce05e63c7f2bd435bb59 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 16:06:09 -0700 Subject: [PATCH 04/11] Update queue sas gen --- .../azure/storage/queue/__init__.py | 3 + .../azure/storage/queue/_shared/models.py | 4 +- .../storage/queue/_shared_access_signature.py | 129 ++++++++++++++++++ .../azure/storage/queue/models.py | 7 +- .../azure/storage/queue/queue_client.py | 74 +--------- .../storage/queue/queue_service_client.py | 60 -------- .../azure-storage-queue/tests/test_queue.py | 31 ++++- .../tests/test_queue_async.py | 31 ++++- .../test_queue_samples_authentication.py | 6 +- ...test_queue_samples_authentication_async.py | 6 +- .../tests/test_queue_samples_message.py | 7 +- .../tests/test_queue_samples_message_async.py | 7 +- 12 files changed, 210 insertions(+), 155 deletions(-) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/__init__.py b/sdk/storage/azure-storage-queue/azure/storage/queue/__init__.py index 127e8f946ba2..2643a4d24c03 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/__init__.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/__init__.py @@ -7,6 +7,7 @@ from .version import VERSION from .queue_client import QueueClient from .queue_service_client import QueueServiceClient +from ._shared_access_signature import generate_account_sas, generate_queue_sas from ._shared.policies import ExponentialRetry, LinearRetry from ._shared.models import( LocationMode, @@ -62,4 +63,6 @@ 'Metrics', 'CorsRule', 'RetentionPolicy', + 'generate_account_sas', + 'generate_queue_sas' ] diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py index b8078927e0de..6ddfaee28734 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py @@ -261,8 +261,8 @@ def from_string(cls, string): class AccountSasPermissions(object): """ - :class:`~ResourceTypes` class to be used with generate_shared_access_signature - method and for the AccessPolicies used with set_*_acl. There are two types of + :class:`~ResourceTypes` class to be used with generate_account_sas + function and for the AccessPolicies used with set_*_acl. There are two types of SAS which may be used to grant resource access. One is to grant access to a specific resource (resource-specific). Another is to grant access to the entire service for a specific account and allow certain operations based on diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py index 827d00c77084..b903e165a847 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py @@ -6,6 +6,7 @@ from azure.storage.queue._shared import sign_string from azure.storage.queue._shared.constants import X_MS_VERSION +from azure.storage.queue._shared.models import Services from azure.storage.queue._shared.shared_access_signature import SharedAccessSignature, _SharedAccessHelper, \ QueryStringConstants @@ -108,3 +109,131 @@ def get_value_to_append(query): self._add_query(QueryStringConstants.SIGNED_SIGNATURE, sign_string(account_key, string_to_sign)) + + +def generate_account_sas( + account_name, # type: str + account_key, # type: str + resource_types, # type: Union[ResourceTypes, str] + permission, # type: Union[AccountSasPermissions, str] + expiry, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): # type: (...) -> str + """Generates a shared access signature for the queue service. + + Use the returned signature with the credential parameter of any Queue Service. + + :param ~azure.storage.queue.ResourceTypes resource_types: + Specifies the resource types that are accessible with the account SAS. + :param ~azure.storage.queue.AccountSasPermissions permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless an id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: ~datetime.datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: ~datetime.datetime or str + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + """ + sas = SharedAccessSignature(account_name, account_key) + return sas.generate_account( + services=Services(queue=True), + resource_types=resource_types, + permission=permission, + expiry=expiry, + start=start, + ip=ip, + **kwargs + ) # type: ignore + + +def generate_queue_sas( + account_name, # type: str + queue_name, # type: str + account_key, # type: str + permission=None, # type: Optional[Union[QueueSasPermissions, str]] + expiry=None, # type: Optional[Union[datetime, str]] + start=None, # type: Optional[Union[datetime, str]] + policy_id=None, # type: Optional[str] + ip=None, # type: Optional[str] + **kwargs # type: Any + ): # type: (...) -> str + """Generates a shared access signature for the queue. + + Use the returned signature with the credential parameter of any Queue Service. + + :param ~azure.storage.queue.QueueSasPermissions permission: + The permissions associated with the shared access signature. The + user is restricted to operations allowed by the permissions. + Required unless a policy_id is given referencing a stored access policy + which contains this field. This field must be omitted if it has been + specified in an associated stored access policy. + :param expiry: + The time at which the shared access signature becomes invalid. + Required unless a policy_id is given referencing a stored access policy + which contains this field. This field must be omitted if it has + been specified in an associated stored access policy. Azure will always + convert values to UTC. If a date is passed in without timezone info, it + is assumed to be UTC. + :type expiry: datetime or str + :param start: + The time at which the shared access signature becomes valid. If + omitted, start time for this call is assumed to be the time when the + storage service receives the request. Azure will always convert values + to UTC. If a date is passed in without timezone info, it is assumed to + be UTC. + :type start: datetime or str + :param str policy_id: + A unique value up to 64 characters in length that correlates to a + stored access policy. To create a stored access policy, use :func:`~set_queue_access_policy`. + :param str ip: + Specifies an IP address or a range of IP addresses from which to accept requests. + If the IP address from which the request originates does not match the IP address + or address range specified on the SAS token, the request is not authenticated. + For example, specifying sip='168.1.5.65' or sip='168.1.5.60-168.1.5.70' on the SAS + restricts the request to those IP addresses. + :keyword str protocol: + Specifies the protocol permitted for a request made. The default value is https. + :return: A Shared Access Signature (sas) token. + :rtype: str + + .. admonition:: Example: + + .. literalinclude:: ../tests/test_queue_samples_message.py + :start-after: [START queue_client_sas_token] + :end-before: [END queue_client_sas_token] + :language: python + :dedent: 12 + :caption: Generate a sas token. + """ + sas = QueueSharedAccessSignature(account_name, account_key) + return sas.generate_queue( + queue_name, + permission=permission, + expiry=expiry, + start=start, + policy_id=policy_id, + ip=ip, + **kwargs + ) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/models.py b/sdk/storage/azure-storage-queue/azure/storage/queue/models.py index 87a3992de8c8..549e0874a458 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/models.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/models.py @@ -332,10 +332,9 @@ def _extract_data_cb(self, get_next_return): class QueueSasPermissions(object): - """QueueSasPermissions class to be used with - :func:`~azure.storage.queue.queue_client.QueueClient.generate_shared_access_signature` - method and for the AccessPolicies used with - :func:`~azure.storage.queue.queue_client.QueueClient.set_queue_access_policy`. + """QueueSasPermissions class to be used with the + :func:`~azure.storage.queue.generate_queue_sas` function and for the AccessPolicies used with + :func:`~azure.storage.queue.QueueClient.set_queue_access_policy`. :param bool read: Read metadata and properties, including message count. Peek at messages. diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py index ea8411414352..0447caccbf91 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py @@ -30,13 +30,12 @@ from ._generated.models import StorageErrorException, SignedIdentifier from ._generated.models import QueueMessage as GenQueueMessage -from ._shared_access_signature import QueueSharedAccessSignature from .models import QueueMessage, AccessPolicy, MessagesPaged if TYPE_CHECKING: from datetime import datetime from azure.core.pipeline.policies import HTTPPolicy - from .models import QueueSasPermissions, QueueProperties + from .models import QueueProperties class QueueClient(StorageAccountHostsMixin): @@ -186,77 +185,6 @@ def from_connection_string( kwargs['secondary_hostname'] = secondary return cls(account_url, queue_name=queue_name, credential=credential, **kwargs) # type: ignore - def generate_shared_access_signature( - self, permission=None, # type: Optional[Union[QueueSasPermissions, str]] - expiry=None, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - policy_id=None, # type: Optional[str] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): # type: (...) -> str - """Generates a shared access signature for the queue. - - Use the returned signature with the credential parameter of any Queue Service. - - :param ~azure.storage.queue.QueueSasPermissions permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - Required unless a policy_id is given referencing a stored access policy - which contains this field. This field must be omitted if it has been - specified in an associated stored access policy. - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless a policy_id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: datetime or str - :param str policy_id: - A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_queue_access_policy`. - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying sip='168.1.5.65' or sip='168.1.5.60-168.1.5.70' on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - - .. admonition:: Example: - - .. literalinclude:: ../tests/test_queue_samples_message.py - :start-after: [START queue_client_sas_token] - :end-before: [END queue_client_sas_token] - :language: python - :dedent: 12 - :caption: Generate a sas token. - """ - protocol = kwargs.pop('protocol', None) - if not hasattr(self.credential, 'account_key') and not self.credential.account_key: - raise ValueError("No account SAS key available.") - sas = QueueSharedAccessSignature( - self.credential.account_name, self.credential.account_key) - return sas.generate_queue( - self.queue_name, - permission=permission, - expiry=expiry, - start=start, - policy_id=policy_id, - ip=ip, - protocol=protocol, - ) - @distributed_trace def create_queue(self, **kwargs): # type: (Optional[Any]) -> None diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py index 86f6ea6c6d67..f6cd19cd7a9a 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py @@ -15,7 +15,6 @@ from azure.core.paging import ItemPaged from azure.core.tracing.decorator import distributed_trace -from ._shared.shared_access_signature import SharedAccessSignature from ._shared.models import LocationMode, Services from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query from ._shared.response_handlers import process_storage_error @@ -29,7 +28,6 @@ from datetime import datetime from azure.core import Configuration from azure.core.pipeline.policies import HTTPPolicy - from ._shared.models import AccountSasPermissions, ResourceTypes from .models import ( QueueProperties, Logging, @@ -149,64 +147,6 @@ def from_connection_string( kwargs['secondary_hostname'] = secondary return cls(account_url, credential=credential, **kwargs) - def generate_shared_access_signature( - self, resource_types, # type: Union[ResourceTypes, str] - permission, # type: Union[AccountSasPermissions, str] - expiry, # type: Optional[Union[datetime, str]] - start=None, # type: Optional[Union[datetime, str]] - ip=None, # type: Optional[str] - **kwargs # type: Any - ): # type: (...) -> str - """Generates a shared access signature for the queue service. - - Use the returned signature with the credential parameter of any Queue Service. - - :param ~azure.storage.queue.ResourceTypes resource_types: - Specifies the resource types that are accessible with the account SAS. - :param ~azure.storage.queue.AccountSasPermissions permission: - The permissions associated with the shared access signature. The - user is restricted to operations allowed by the permissions. - :param expiry: - The time at which the shared access signature becomes invalid. - Required unless an id is given referencing a stored access policy - which contains this field. This field must be omitted if it has - been specified in an associated stored access policy. Azure will always - convert values to UTC. If a date is passed in without timezone info, it - is assumed to be UTC. - :type expiry: ~datetime.datetime or str - :param start: - The time at which the shared access signature becomes valid. If - omitted, start time for this call is assumed to be the time when the - storage service receives the request. Azure will always convert values - to UTC. If a date is passed in without timezone info, it is assumed to - be UTC. - :type start: ~datetime.datetime or str - :param str ip: - Specifies an IP address or a range of IP addresses from which to accept requests. - If the IP address from which the request originates does not match the IP address - or address range specified on the SAS token, the request is not authenticated. - For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS - restricts the request to those IP addresses. - :keyword str protocol: - Specifies the protocol permitted for a request made. The default value is https. - :return: A Shared Access Signature (sas) token. - :rtype: str - """ - protocol = kwargs.pop('protocol', None) - if not hasattr(self.credential, 'account_key') and not self.credential.account_key: - raise ValueError("No account SAS key available.") - - sas = SharedAccessSignature(self.credential.account_name, self.credential.account_key) - return sas.generate_account( - services=Services(queue=True), - resource_types=resource_types, - permission=permission, - expiry=expiry, - start=start, - ip=ip, - protocol=protocol - ) # type: ignore - @distributed_trace def get_service_stats(self, **kwargs): # type: ignore # type: (Optional[Any]) -> Dict[str, Any] diff --git a/sdk/storage/azure-storage-queue/tests/test_queue.py b/sdk/storage/azure-storage-queue/tests/test_queue.py index f7a03392df77..e7e40252bd02 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue.py @@ -31,6 +31,8 @@ AccessPolicy, ResourceTypes, AccountSasPermissions, + generate_account_sas, + generate_queue_sas ) from queuetestcase import ( @@ -541,7 +543,9 @@ def test_account_sas(self, resource_group, location, storage_account, storage_ac queue_client = self._get_queue_reference(qsc) queue_client.create_queue() queue_client.enqueue_message(u'message1') - token = qsc.generate_shared_access_signature( + token = generate_account_sas( + qsc.account_name, + qsc.credential.account_key, ResourceTypes(object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -599,7 +603,10 @@ def test_sas_read(self, resource_group, location, storage_account, storage_accou queue_client = self._get_queue_reference(qsc) queue_client.create_queue() queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), datetime.utcnow() - timedelta(minutes=5) @@ -631,7 +638,10 @@ def test_sas_add(self, resource_group, location, storage_account, storage_accoun qsc = QueueServiceClient(self._account_url(storage_account.name), storage_account_key) queue_client = self._get_queue_reference(qsc) queue_client.create_queue() - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(add=True), datetime.utcnow() + timedelta(hours=1), ) @@ -659,7 +669,10 @@ def test_sas_update(self, resource_group, location, storage_account, storage_acc queue_client = self._get_queue_reference(qsc) queue_client.create_queue() queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(update=True), datetime.utcnow() + timedelta(hours=1), ) @@ -694,7 +707,10 @@ def test_sas_process(self, resource_group, location, storage_account, storage_ac queue_client = self._get_queue_reference(qsc) queue_client.create_queue() queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(process=True), datetime.utcnow() + timedelta(hours=1), ) @@ -733,7 +749,10 @@ def test_sas_signed_identifier(self, resource_group, location, storage_account, queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, policy_id='testid' ) diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_async.py b/sdk/storage/azure-storage-queue/tests/test_queue_async.py index 69d36debbdd9..70b8fb9d4e97 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_async.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_async.py @@ -28,6 +28,8 @@ AccessPolicy, ResourceTypes, AccountSasPermissions, + generate_account_sas, + generate_queue_sas ) from azure.storage.queue.aio import QueueServiceClient, QueueClient @@ -583,7 +585,9 @@ async def test_account_sas(self, resource_group, location, storage_account, stor # Arrange queue_client = await self._create_queue(qsc) await queue_client.enqueue_message(u'message1') - token = qsc.generate_shared_access_signature( + token = generate_account_sas( + qsc.account_name, + qsc.credential.account_key, ResourceTypes(object=True), AccountSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), @@ -646,7 +650,10 @@ async def test_sas_read(self, resource_group, location, storage_account, storage # Arrange queue_client = await self._create_queue(qsc) await queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(read=True), datetime.utcnow() + timedelta(hours=1), datetime.utcnow() - timedelta(minutes=5) @@ -678,7 +685,10 @@ async def test_sas_add(self, resource_group, location, storage_account, storage_ # Arrange queue_client = await self._create_queue(qsc) - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(add=True), datetime.utcnow() + timedelta(hours=1), ) @@ -709,7 +719,10 @@ async def test_sas_update(self, resource_group, location, storage_account, stora # Arrange queue_client = await self._create_queue(qsc) await queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(update=True), datetime.utcnow() + timedelta(hours=1), ) @@ -749,7 +762,10 @@ async def test_sas_process(self, resource_group, location, storage_account, stor # Arrange queue_client = await self._create_queue(qsc) await queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, QueueSasPermissions(process=True), datetime.utcnow() + timedelta(hours=1), ) @@ -791,7 +807,10 @@ async def test_sas_signed_identifier(self, resource_group, location, storage_acc await queue_client.enqueue_message(u'message1') - token = queue_client.generate_shared_access_signature( + token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, policy_id='testid' ) diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication.py b/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication.py index a24332962c37..92999b0f9dc6 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication.py @@ -91,7 +91,11 @@ def test_auth_shared_access_signature(self, resource_group, location, storage_ac queue_service = QueueServiceClient.from_connection_string(connection_string) # Create a SAS token to use for authentication of a client - sas_token = queue_service.generate_shared_access_signature( + from azure.storage.queue import generate_account_sas + + sas_token = generate_account_sas( + queue_service.account_name, + queue_service.credential.account_key, resource_types="object", permission="read", expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication_async.py b/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication_async.py index ee58bf06fb6e..3ba2722dbcae 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication_async.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_samples_authentication_async.py @@ -87,7 +87,11 @@ async def test_auth_shared_access_signature(self, resource_group, location, stor queue_service = QueueServiceClient(self._account_url(storage_account.name), storage_account_key) # Create a SAS token to use for authentication of a client - sas_token = queue_service.generate_shared_access_signature( + from azure.storage.queue import generate_account_sas + + sas_token = generate_account_sas( + queue_service.account_name, + queue_service.credential.account_key, resource_types="object", permission="read", expiry=datetime.utcnow() + timedelta(hours=1) diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_samples_message.py b/sdk/storage/azure-storage-queue/tests/test_queue_samples_message.py index 00f67b4ed71c..9b2dfce28d14 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_samples_message.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_samples_message.py @@ -52,7 +52,12 @@ def test_set_access_policy(self, resource_group, location, storage_account, stor # Use the access policy to generate a SAS token # [START queue_client_sas_token] - sas_token = queue_client.generate_shared_access_signature( + from azure.storage.queue import generate_queue_sas + + sas_token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, policy_id='my-access-policy-id' ) # [END queue_client_sas_token] diff --git a/sdk/storage/azure-storage-queue/tests/test_queue_samples_message_async.py b/sdk/storage/azure-storage-queue/tests/test_queue_samples_message_async.py index 334638a9d7eb..540d7c387649 100644 --- a/sdk/storage/azure-storage-queue/tests/test_queue_samples_message_async.py +++ b/sdk/storage/azure-storage-queue/tests/test_queue_samples_message_async.py @@ -51,7 +51,12 @@ async def test_set_access_policy(self, resource_group, location, storage_account # [END async_set_access_policy] # Use the access policy to generate a SAS token - sas_token = queue_client.generate_shared_access_signature( + from azure.storage.queue import generate_queue_sas + + sas_token = generate_queue_sas( + queue_client.account_name, + queue_client.queue_name, + queue_client.credential.account_key, policy_id='my-access-policy-id' ) # [END async_set_access_policy] From b7fcb4fc7e20443f6e7cc51daacb69f092c61a61 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 16:35:12 -0700 Subject: [PATCH 05/11] Updated docstrings --- .../storage/blob/_shared_access_signature.py | 54 +++++++++++++------ .../storage/file/_shared_access_signature.py | 27 ++++++++-- .../storage/queue/_shared_access_signature.py | 15 +++++- 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py index 3782b65dd939..9607b0b6fdcb 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py @@ -278,6 +278,10 @@ def generate_account_sas( Use the returned signature with the credential parameter of any BlobServiceClient, ContainerClient or BlobClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str account_key: + The access key to generate the shared access signature. :param resource_types: Specifies the resource types that are accessible with the account SAS. :type resource_types: str or ~azure.storage.blob.ResourceTypes @@ -348,10 +352,23 @@ def generate_container_sas( **kwargs # type: Any ): # type: (...) -> Any - """Generates a shared access signature for the container. + """Generates a shared access signature for a container. + Use the returned signature with the credential parameter of any BlobServiceClient, ContainerClient or BlobClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str container_name: + The name of the container. + :param str account_key: + The access key to generate the shared access signature. Either `account_key` or + `user_delegation_key` must be specified. + :param ~azure.storage.blob.UserDelegationKey user_delegation_key: + Instead of an account key, the user could pass in a user delegation key. + A user delegation key can be obtained from the service by authenticating with an AAD identity; + this can be accomplished by calling :func:`~azure.storage.blob.BlobServiceClient.get_user_delegation_key`. + When present, the SAS is signed with the user delegation key instead. :param permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. @@ -377,18 +394,14 @@ def generate_container_sas( :type start: datetime or str :param str policy_id: A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_container_access_policy`. + stored access policy. To create a stored access policy, use + :func:`~azure.storage.blob.ContainerClient.set_container_access_policy`. :param str ip: Specifies an IP address or a range of IP addresses from which to accept requests. If the IP address from which the request originates does not match the IP address or address range specified on the SAS token, the request is not authenticated. For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS restricts the request to those IP addresses. - :param ~azure.storage.blob.UserDelegationKey user_delegation_key: - Instead of an account key, the user could pass in a user delegation key. - A user delegation key can be obtained from the service by authenticating with an AAD identity; - this can be accomplished by calling get_user_delegation_key. - When present, the SAS is signed with the user delegation key instead. :keyword str protocol: Specifies the protocol permitted for a request made. The default value is https. :keyword str account_name: @@ -453,11 +466,27 @@ def generate_blob_sas( **kwargs # type: Any ): # type: (...) -> Any - """ - Generates a shared access signature for a blob. + """Generates a shared access signature for a blob. + Use the returned signature with the credential parameter of any BlobServiceClient, ContainerClient or BlobClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str container_name: + The name of the container. + :param str blob_name: + The name of the blob. + :param str snapshot: + An optional blob snapshot ID. + :param str account_key: + The access key to generate the shared access signature. Either `account_key` or + `user_delegation_key` must be specified. + :param ~azure.storage.blob.UserDelegationKey user_delegation_key: + Instead of an account key, the user could pass in a user delegation key. + A user delegation key can be obtained from the service by authenticating with an AAD identity; + this can be accomplished by calling :func:`~azure.storage.blob.BlobServiceClient.get_user_delegation_key`. + When present, the SAS is signed with the user delegation key instead. :param permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. @@ -484,18 +513,13 @@ def generate_blob_sas( :param str policy_id: A unique value up to 64 characters in length that correlates to a stored access policy. To create a stored access policy, use - :func:`~ContainerClient.set_container_access_policy()`. + :func:`~azure.storage.blob.ContainerClient.set_container_access_policy()`. :param str ip: Specifies an IP address or a range of IP addresses from which to accept requests. If the IP address from which the request originates does not match the IP address or address range specified on the SAS token, the request is not authenticated. For example, specifying ip=168.1.5.65 or ip=168.1.5.60-168.1.5.70 on the SAS restricts the request to those IP addresses. - :param ~azure.storage.blob.UserDelegationKey user_delegation_key: - Instead of a shared key, the user could pass in a user delegation key. - A user delegation key can be obtained from the service by authenticating with an AAD identity; - this can be accomplished by calling get_user_delegation_key. - When present, the SAS is signed with the user delegation key instead. :keyword str protocol: Specifies the protocol permitted for a request made. The default value is https. :keyword str account_name: diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py index b4fde0c4fa76..93d8fd7d2bbd 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared_access_signature.py @@ -238,6 +238,10 @@ def generate_account_sas( Use the returned signature with the credential parameter of any FileServiceClient, ShareClient, DirectoryClient, or FileClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str account_key: + The access key to generate the shared access signature. :param ~azure.storage.file.ResourceTypes resource_types: Specifies the resource types that are accessible with the account SAS. :param ~azure.storage.file.AccountSasPermissions permission: @@ -304,10 +308,17 @@ def generate_share_sas( ip=None, # type: Optional[str] **kwargs # type: Any ): # type: (...) -> str - """Generates a shared access signature for the share. + """Generates a shared access signature for a share. + Use the returned signature with the credential parameter of any FileServiceClient, ShareClient, DirectoryClient, or FileClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str share_name: + The name of the share. + :param str account_key: + The access key to generate the shared access signature. :param ~azure.storage.file.ShareSasPermissions permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. @@ -332,7 +343,8 @@ def generate_share_sas( :type start: ~datetime.datetime or str :param str policy_id: A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_share_access_policy`. + stored access policy. To create a stored access policy, use + :func:`~azure.storage.file.ShareClient.set_share_access_policy`. :param str ip: Specifies an IP address or a range of IP addresses from which to accept requests. If the IP address from which the request originates does not match the IP address @@ -388,11 +400,20 @@ def generate_file_sas( **kwargs # type: Any ): # type: (...) -> str - """Generates a shared access signature for the file. + """Generates a shared access signature for a file. Use the returned signature with the credential parameter of any FileServiceClient, ShareClient, DirectoryClient, or FileClient. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str share_name: + The name of the share. + :param file_path: + The file path represented as a list of path segments, including the file name. + :type file_path: List[str] + :param str account_key: + The access key to generate the shared access signature. :param ~azure.storage.file.FileSasPermissions permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py index b903e165a847..29b0e8f2b9c7 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared_access_signature.py @@ -125,6 +125,10 @@ def generate_account_sas( Use the returned signature with the credential parameter of any Queue Service. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str account_key: + The access key to generate the shared access signature. :param ~azure.storage.queue.ResourceTypes resource_types: Specifies the resource types that are accessible with the account SAS. :param ~azure.storage.queue.AccountSasPermissions permission: @@ -179,10 +183,16 @@ def generate_queue_sas( ip=None, # type: Optional[str] **kwargs # type: Any ): # type: (...) -> str - """Generates a shared access signature for the queue. + """Generates a shared access signature for a queue. Use the returned signature with the credential parameter of any Queue Service. + :param str account_name: + The storage account name used to generate the shared access signature. + :param str queue_name: + The name of the queue. + :param str account_key: + The access key to generate the shared access signature. :param ~azure.storage.queue.QueueSasPermissions permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. @@ -206,7 +216,8 @@ def generate_queue_sas( :type start: datetime or str :param str policy_id: A unique value up to 64 characters in length that correlates to a - stored access policy. To create a stored access policy, use :func:`~set_queue_access_policy`. + stored access policy. To create a stored access policy, use + :func:`~azure.storage.queue.QueueClient.set_queue_access_policy`. :param str ip: Specifies an IP address or a range of IP addresses from which to accept requests. If the IP address from which the request originates does not match the IP address From 2f17c06afbfe657988bd6325ef961ee24b4d70f6 Mon Sep 17 00:00:00 2001 From: antisch Date: Wed, 16 Oct 2019 17:07:07 -0700 Subject: [PATCH 06/11] Some pylint fixes --- .../azure/storage/blob/_shared/authentication.py | 2 +- .../azure/storage/blob/_shared/base_client.py | 2 +- .../azure/storage/blob/_shared/request_handlers.py | 3 --- .../azure/storage/blob/_shared/uploads.py | 2 +- .../azure/storage/blob/blob_service_client.py | 6 ++++-- .../azure/storage/file/_shared/authentication.py | 2 +- .../azure/storage/file/_shared/base_client.py | 2 +- .../azure/storage/file/_shared/request_handlers.py | 3 --- .../azure/storage/file/_shared/uploads.py | 2 +- .../azure/storage/queue/_shared/authentication.py | 2 +- .../azure/storage/queue/_shared/base_client.py | 2 +- .../azure/storage/queue/_shared/request_handlers.py | 3 --- .../azure/storage/queue/_shared/uploads.py | 2 +- .../azure/storage/queue/queue_service_client.py | 2 +- 14 files changed, 14 insertions(+), 21 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py index 6806bf922584..d0838b8e2e82 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = [(name, value) for name, value in request.http_request.query.items()] + sorted_queries = list(request.http_request.query.items()) sorted_queries.sort() string_to_sign = '' diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py index f463d668cb90..11212a9f5c49 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py @@ -59,7 +59,7 @@ } -class StorageAccountHostsMixin(object): +class StorageAccountHostsMixin(object): # pylint: disable=too-many-instance-attributes def __init__( self, parsed_url, # type: Any diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/request_handlers.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/request_handlers.py index cd5e4848633d..0a9693389fec 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/request_handlers.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/request_handlers.py @@ -14,10 +14,7 @@ from io import (SEEK_END, SEEK_SET, UnsupportedOperation) import isodate - -from azure.core import Configuration from azure.core.exceptions import raise_with_traceback -from azure.core.pipeline import Pipeline _LOGGER = logging.getLogger(__name__) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/uploads.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/uploads.py index 6ed1f9084df5..032915c06e2d 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/uploads.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/uploads.py @@ -395,7 +395,7 @@ def flush(self): pass def read(self, size=None): - if self.closed: + if self.closed: # pylint: disable=using-constant-test raise ValueError("Stream is closed.") if size is None: diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py index be57339b73f5..57b74da0abc8 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py @@ -18,7 +18,7 @@ from azure.core.paging import ItemPaged from azure.core.tracing.decorator import distributed_trace -from ._shared.models import LocationMode, UserDelegationKey +from ._shared.models import LocationMode from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query from ._shared.parser import _to_utc_datetime from ._shared.response_handlers import return_response_headers, process_storage_error, \ @@ -27,15 +27,17 @@ from ._generated.models import StorageErrorException, StorageServiceProperties, KeyInfo from .container_client import ContainerClient from .blob_client import BlobClient -from .models import ContainerProperties, ContainerPropertiesPaged +from .models import ContainerPropertiesPaged if TYPE_CHECKING: from datetime import datetime from azure.core.pipeline.transport import HttpTransport from azure.core.pipeline.policies import HTTPPolicy + from ._shared.models import UserDelegationKey from .lease import LeaseClient from .models import ( BlobProperties, + ContainerProperties, BlobAnalyticsLogging, Metrics, RetentionPolicy, diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py index 6806bf922584..d0838b8e2e82 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = [(name, value) for name, value in request.http_request.query.items()] + sorted_queries = list(request.http_request.query.items()) sorted_queries.sort() string_to_sign = '' diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py index f463d668cb90..11212a9f5c49 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py @@ -59,7 +59,7 @@ } -class StorageAccountHostsMixin(object): +class StorageAccountHostsMixin(object): # pylint: disable=too-many-instance-attributes def __init__( self, parsed_url, # type: Any diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/request_handlers.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/request_handlers.py index cd5e4848633d..0a9693389fec 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/request_handlers.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/request_handlers.py @@ -14,10 +14,7 @@ from io import (SEEK_END, SEEK_SET, UnsupportedOperation) import isodate - -from azure.core import Configuration from azure.core.exceptions import raise_with_traceback -from azure.core.pipeline import Pipeline _LOGGER = logging.getLogger(__name__) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/uploads.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/uploads.py index 6ed1f9084df5..032915c06e2d 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/uploads.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/uploads.py @@ -395,7 +395,7 @@ def flush(self): pass def read(self, size=None): - if self.closed: + if self.closed: # pylint: disable=using-constant-test raise ValueError("Stream is closed.") if size is None: diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py index 6806bf922584..d0838b8e2e82 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = [(name, value) for name, value in request.http_request.query.items()] + sorted_queries = list(request.http_request.query.items()) sorted_queries.sort() string_to_sign = '' diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py index f463d668cb90..11212a9f5c49 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py @@ -59,7 +59,7 @@ } -class StorageAccountHostsMixin(object): +class StorageAccountHostsMixin(object): # pylint: disable=too-many-instance-attributes def __init__( self, parsed_url, # type: Any diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/request_handlers.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/request_handlers.py index cd5e4848633d..0a9693389fec 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/request_handlers.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/request_handlers.py @@ -14,10 +14,7 @@ from io import (SEEK_END, SEEK_SET, UnsupportedOperation) import isodate - -from azure.core import Configuration from azure.core.exceptions import raise_with_traceback -from azure.core.pipeline import Pipeline _LOGGER = logging.getLogger(__name__) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/uploads.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/uploads.py index 6ed1f9084df5..032915c06e2d 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/uploads.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/uploads.py @@ -395,7 +395,7 @@ def flush(self): pass def read(self, size=None): - if self.closed: + if self.closed: # pylint: disable=using-constant-test raise ValueError("Stream is closed.") if size is None: diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py index 1f7dd6f4616a..cf0793990fa1 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py @@ -15,7 +15,7 @@ from azure.core.paging import ItemPaged from azure.core.tracing.decorator import distributed_trace -from ._shared.models import LocationMode, Services +from ._shared.models import LocationMode from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query from ._shared.response_handlers import process_storage_error from ._generated import AzureQueueStorage From 63ac961bafa3cd5df7b35e89493180dbaa08c915 Mon Sep 17 00:00:00 2001 From: antisch Date: Thu, 17 Oct 2019 07:32:11 -0700 Subject: [PATCH 07/11] More pylint --- .../azure/storage/blob/_shared_access_signature.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py index 9607b0b6fdcb..0d3ad19d2eb2 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py @@ -559,4 +559,4 @@ def generate_blob_sas( policy_id=policy_id, ip=ip, **kwargs - ) \ No newline at end of file + ) From e8e906a08db5941f0f98fef4002173475d4d5ab3 Mon Sep 17 00:00:00 2001 From: antisch Date: Thu, 17 Oct 2019 08:38:40 -0700 Subject: [PATCH 08/11] More pylint --- .../azure-storage-file/azure/storage/file/file_client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/file_client.py b/sdk/storage/azure-storage-file/azure/storage/file/file_client.py index 5f5aa36c0fd8..f34ae32a7182 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/file_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/file_client.py @@ -34,12 +34,11 @@ from ._deserialize import deserialize_file_properties, deserialize_file_stream from ._polling import CloseHandles from .models import HandlesPaged, NTFSAttributes # pylint: disable=unused-import -from ._shared_access_signature import FileSharedAccessSignature from .download import StorageStreamDownloader if TYPE_CHECKING: from datetime import datetime - from .models import ShareProperties, FileSasPermissions, ContentSettings, FileProperties + from .models import ShareProperties, ContentSettings, FileProperties from ._generated.models import HandleItem From 5e31c3dcc2c44a707ded825fdbc0991f4d8f3ec1 Mon Sep 17 00:00:00 2001 From: antisch Date: Fri, 18 Oct 2019 08:51:40 -0700 Subject: [PATCH 09/11] Reverted auth change --- .../azure/storage/blob/_shared/authentication.py | 2 +- .../azure/storage/file/_shared/authentication.py | 2 +- .../azure/storage/queue/_shared/authentication.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py index d0838b8e2e82..6806bf922584 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = list(request.http_request.query.items()) + sorted_queries = [(name, value) for name, value in request.http_request.query.items()] sorted_queries.sort() string_to_sign = '' diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py index d0838b8e2e82..6806bf922584 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = list(request.http_request.query.items()) + sorted_queries = [(name, value) for name, value in request.http_request.query.items()] sorted_queries.sort() string_to_sign = '' diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py index d0838b8e2e82..6806bf922584 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/authentication.py @@ -96,7 +96,7 @@ def _get_canonicalized_headers(self, request): return string_to_sign def _get_canonicalized_resource_query(self, request): - sorted_queries = list(request.http_request.query.items()) + sorted_queries = [(name, value) for name, value in request.http_request.query.items()] sorted_queries.sort() string_to_sign = '' From 1f083b4eaf45d4bd435c68252b6f31a8d3853d3c Mon Sep 17 00:00:00 2001 From: antisch Date: Fri, 18 Oct 2019 08:57:01 -0700 Subject: [PATCH 10/11] Added release notes --- sdk/storage/azure-storage-blob/HISTORY.md | 2 ++ sdk/storage/azure-storage-file/HISTORY.md | 1 + sdk/storage/azure-storage-queue/HISTORY.md | 2 ++ 3 files changed, 5 insertions(+) diff --git a/sdk/storage/azure-storage-blob/HISTORY.md b/sdk/storage/azure-storage-blob/HISTORY.md index fa5e07d3928d..4a5031c7fedd 100644 --- a/sdk/storage/azure-storage-blob/HISTORY.md +++ b/sdk/storage/azure-storage-blob/HISTORY.md @@ -9,6 +9,8 @@ - Removed types that were accidentally exposed from two modules. Only `BlobServiceClient`, `ContainerClient`, `BlobClient` and `LeaseClient` should be imported from azure.storage.blob.aio - `Logging` has been renamed to `BlobAnalyticsLogging`. +- The `generate_shared_access_signature` methods on each of `BlobServiceClient`, `ContainerClient` and `BlobClient` have been replaced by module level functions `generate_account_sas`, `generate_container_sas` and `generate_blob_sas`. + **New features** diff --git a/sdk/storage/azure-storage-file/HISTORY.md b/sdk/storage/azure-storage-file/HISTORY.md index 4887eb95b418..709e8d64ddb3 100644 --- a/sdk/storage/azure-storage-file/HISTORY.md +++ b/sdk/storage/azure-storage-file/HISTORY.md @@ -21,6 +21,7 @@ To use a directory_url, the method `from_directory_url` must be used. - `max_concurrency` - `validate_content` - `timeout` etc. +- The `generate_shared_access_signature` methods on each of `FileServiceClient`, `ShareClient` and `FileClient` have been replaced by module level functions `generate_account_sas`, `generate_share_sas` and `generate_file_sas`. **New features** diff --git a/sdk/storage/azure-storage-queue/HISTORY.md b/sdk/storage/azure-storage-queue/HISTORY.md index bdbd883e6ad0..5ff6703625bb 100644 --- a/sdk/storage/azure-storage-queue/HISTORY.md +++ b/sdk/storage/azure-storage-queue/HISTORY.md @@ -20,6 +20,8 @@ should be imported from azure.storage.queue.aio to `inserted_on`, `next_visible_on`, `expires_on`, respectively. - `Logging` has been renamed to `QueueAnalyticsLogging`. - `enqueue_message` is now called `send_message`. +- The `generate_shared_access_signature` methods on both `QueueServiceClient` and `QueueClient` have been replaced by module level functions `generate_account_sas` and `generate_queue_sas`. + **New features** From 94b543fc92dfac2ca9dca384fc00fbd84f305374 Mon Sep 17 00:00:00 2001 From: antisch Date: Fri, 18 Oct 2019 16:04:22 -0700 Subject: [PATCH 11/11] Fixed kwarg docstring --- .../azure/storage/blob/_shared_access_signature.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py index 0d3ad19d2eb2..8ab9411bf67d 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py @@ -404,8 +404,6 @@ def generate_container_sas( restricts the request to those IP addresses. :keyword str protocol: Specifies the protocol permitted for a request made. The default value is https. - :keyword str account_name: - Specifies the account_name when using oauth token as credential. If you use oauth token as credential. :keyword str cache_control: Response header value for Cache-Control when resource is accessed using this shared access signature. @@ -522,8 +520,6 @@ def generate_blob_sas( restricts the request to those IP addresses. :keyword str protocol: Specifies the protocol permitted for a request made. The default value is https. - :keyword str account_name: - Specifies the account_name when using oauth token as credential. If you use oauth token as credential. :keyword str cache_control: Response header value for Cache-Control when resource is accessed using this shared access signature.