Detect non-base64 encoded storage account keys

- Resolves #62
This commit is contained in:
Fred Park 2018-04-05 12:55:29 -07:00
Родитель 04d3774be2
Коммит ec8086ee5a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3C4D545F457737EB
6 изменённых файлов: 24 добавлений и 12 удалений

Просмотреть файл

@ -30,6 +30,7 @@ from builtins import ( # noqa
bytes, dict, int, list, object, range, ascii, chr, hex, input, bytes, dict, int, list, object, range, ascii, chr, hex, input,
next, oct, open, pow, round, super, filter, map, zip) next, oct, open, pow, round, super, filter, map, zip)
# stdlib imports # stdlib imports
import re
# non-stdlib imports # non-stdlib imports
import requests import requests
# local imports # local imports
@ -86,6 +87,10 @@ class StorageCredentials(object):
class StorageAccount(object): class StorageAccount(object):
"""Azure Storage Account""" """Azure Storage Account"""
_VALID_BASE64_RE = re.compile(
'^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|'
'[A-Za-z0-9+/]{2}==)$')
def __init__(self, name, key, endpoint, transfer_threads, timeout, proxy): def __init__(self, name, key, endpoint, transfer_threads, timeout, proxy):
# type: (StorageAccount, str, str, str, int, # type: (StorageAccount, str, str, str, int,
# blobxfer.models.options.Timeout, # blobxfer.models.options.Timeout,
@ -112,9 +117,16 @@ class StorageAccount(object):
self.endpoint = endpoint self.endpoint = endpoint
self.is_sas = StorageAccount._key_is_sas(self.key) self.is_sas = StorageAccount._key_is_sas(self.key)
self.create_containers = self._container_creation_allowed() self.create_containers = self._container_creation_allowed()
# normalize sas keys if self.is_sas:
if self.is_sas and self.key.startswith('?'): # normalize sas keys
self.key = self.key[1:] if self.key.startswith('?'):
self.key = self.key[1:]
else:
# check if sa shared key is base64
if StorageAccount._VALID_BASE64_RE.match(self.key) is None:
raise ValueError(
('specified storage account key is invalid for storage '
'account: {}').format(self.name))
# create requests session for connection pooling # create requests session for connection pooling
self.session = requests.Session() self.session = requests.Session()
self.session.mount( self.session.mount(

Просмотреть файл

@ -71,12 +71,12 @@ def test_key_is_sas():
to.max_retries = None to.max_retries = None
a = azops.StorageAccount( a = azops.StorageAccount(
'name', 'abcdef', 'core.windows.net', 10, to, mock.MagicMock()) 'name', 'AAAAAA==', 'core.windows.net', 10, to, mock.MagicMock())
assert not a.is_sas assert not a.is_sas
a = azops.StorageAccount( with pytest.raises(ValueError):
'name', 'abcdef&blah', 'core.windows.net', 10, to, None) a = azops.StorageAccount(
assert not a.is_sas 'name', 'abcdef&blah', 'core.windows.net', 10, to, None)
a = azops.StorageAccount( a = azops.StorageAccount(
'name', '?abcdef', 'core.windows.net', 10, to, None) 'name', '?abcdef', 'core.windows.net', 10, to, None)
@ -100,7 +100,7 @@ def test_container_creation_allowed():
to.max_retries = None to.max_retries = None
a = azops.StorageAccount( a = azops.StorageAccount(
'name', 'abcdef', 'core.windows.net', 10, to, None) 'name', 'AAAAAA==', 'core.windows.net', 10, to, None)
assert a._container_creation_allowed() assert a._container_creation_allowed()
a = azops.StorageAccount( a = azops.StorageAccount(

Просмотреть файл

@ -20,7 +20,7 @@ def test_create_client():
to.max_retries = None to.max_retries = None
sa = azops.StorageAccount( sa = azops.StorageAccount(
'name', 'key', 'core.windows.net', 10, to, mock.MagicMock()) 'name', 'AAAAAA==', 'core.windows.net', 10, to, mock.MagicMock())
client = ops.create_client(sa, to, mock.MagicMock()) client = ops.create_client(sa, to, mock.MagicMock())
assert client is not None assert client is not None
assert isinstance(client, azure.storage.blob.AppendBlobService) assert isinstance(client, azure.storage.blob.AppendBlobService)

Просмотреть файл

@ -20,7 +20,7 @@ def test_create_client():
to.max_retries = None to.max_retries = None
sa = azops.StorageAccount( sa = azops.StorageAccount(
'name', 'key', 'core.windows.net', 10, to, mock.MagicMock()) 'name', 'AAAAAA==', 'core.windows.net', 10, to, mock.MagicMock())
client = ops.create_client(sa, to, mock.MagicMock()) client = ops.create_client(sa, to, mock.MagicMock())
assert client is not None assert client is not None
assert isinstance(client, azure.storage.blob.BlockBlobService) assert isinstance(client, azure.storage.blob.BlockBlobService)

Просмотреть файл

@ -20,7 +20,7 @@ def test_create_client():
to.max_retries = None to.max_retries = None
sa = azops.StorageAccount( sa = azops.StorageAccount(
'name', 'key', 'core.windows.net', 10, to, mock.MagicMock()) 'name', 'AAAAAA==', 'core.windows.net', 10, to, mock.MagicMock())
client = ops.create_client(sa, to, mock.MagicMock()) client = ops.create_client(sa, to, mock.MagicMock())
assert client is not None assert client is not None
assert isinstance(client, azure.storage.blob.PageBlobService) assert isinstance(client, azure.storage.blob.PageBlobService)

Просмотреть файл

@ -27,7 +27,7 @@ def test_create_client():
to.max_retries = None to.max_retries = None
sa = azops.StorageAccount( sa = azops.StorageAccount(
'name', 'key', 'core.windows.net', 10, to, mock.MagicMock()) 'name', 'AAAAAA==', 'core.windows.net', 10, to, mock.MagicMock())
client = ops.create_client(sa, to, mock.MagicMock()) client = ops.create_client(sa, to, mock.MagicMock())
assert client is not None assert client is not None
assert isinstance(client, azure.storage.file.FileService) assert isinstance(client, azure.storage.file.FileService)