Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SB] combine conn str parser logic in base handler and _common #16464

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
except ImportError:
from urllib.parse import quote_plus

try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse # type: ignore
swathipil marked this conversation as resolved.
Show resolved Hide resolved

import uamqp
from uamqp import utils, compat
from uamqp.message import MessageProperties
Expand Down Expand Up @@ -83,17 +88,27 @@ def _parse_conn_str(conn_str):
): # Fallback since technically expiry is optional.
# An arbitrary, absurdly large number, since you can't renew.
shared_access_signature_expiry = int(time.time() * 2)
if not (
all((endpoint, shared_access_key_name, shared_access_key))
or all((endpoint, shared_access_signature))
) or all(
(shared_access_key_name, shared_access_signature)
): # this latter clause since we don't accept both

if not endpoint:
raise ValueError("Connection string is either blank or malformed.")
parsed = urlparse(endpoint.rstrip("/"))
if not parsed.netloc:
raise ValueError("Invalid Endpoint on the Connection String.")
swathipil marked this conversation as resolved.
Show resolved Hide resolved
if any([shared_access_key, shared_access_key_name]) and not all(
[shared_access_key, shared_access_key_name]
):
raise ValueError(
"Invalid connection string. Should be in the format: "
"Endpoint=sb://<FQDN>/;SharedAccessKeyName=<KeyName>;SharedAccessKey=<KeyValue>"
"\nWith alternate option of providing SharedAccessSignature instead of SharedAccessKeyName and Key"
"Connection string must have both SharedAccessKeyName and SharedAccessKey."
)
if shared_access_signature is not None and shared_access_key is not None:
raise ValueError(
"Only one of the SharedAccessKey or SharedAccessSignature must be present."
)
if shared_access_signature is None and shared_access_key is None:
raise ValueError(
"At least one of the SharedAccessKey or SharedAccessSignature must be present."
)
swathipil marked this conversation as resolved.
Show resolved Hide resolved

entity = cast(str, entity_path)
host = cast(str, strip_protocol_from_uri(cast(str, endpoint)))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse # type: ignore


from ..management._models import DictMixin
from .._base_handler import _parse_conn_str


class ServiceBusConnectionStringProperties(DictMixin):
Expand Down Expand Up @@ -71,39 +67,14 @@ def parse_connection_string(conn_str):
:type conn_str: str
:rtype: ~azure.servicebus.ServiceBusConnectionStringProperties
"""
conn_settings = [s.split("=", 1) for s in conn_str.split(";")]
if any(len(tup) != 2 for tup in conn_settings):
raise ValueError("Connection string is either blank or malformed.")
conn_settings = dict(conn_settings)
shared_access_signature = None
for key, value in conn_settings.items():
if key.lower() == "sharedaccesssignature":
shared_access_signature = value
shared_access_key = conn_settings.get("SharedAccessKey")
shared_access_key_name = conn_settings.get("SharedAccessKeyName")
swathipil marked this conversation as resolved.
Show resolved Hide resolved
if any([shared_access_key, shared_access_key_name]) and not all(
[shared_access_key, shared_access_key_name]
):
raise ValueError(
"Connection string must have both SharedAccessKeyName and SharedAccessKey."
)
if shared_access_signature is not None and shared_access_key is not None:
raise ValueError(
"Only one of the SharedAccessKey or SharedAccessSignature must be present."
)
endpoint = conn_settings.get("Endpoint")
if not endpoint:
raise ValueError("Connection string is either blank or malformed.")
parsed = urlparse(endpoint.rstrip("/"))
if not parsed.netloc:
raise ValueError("Invalid Endpoint on the Connection String.")
namespace = parsed.netloc.strip()
namespace, policy, key, entity, signature = _parse_conn_str(conn_str)[:-1]
endpoint = "sb://" + namespace + "/"
yunhaoling marked this conversation as resolved.
Show resolved Hide resolved
props = {
"fully_qualified_namespace": namespace,
"endpoint": endpoint,
swathipil marked this conversation as resolved.
Show resolved Hide resolved
"entity_path": conn_settings.get("EntityPath"),
swathipil marked this conversation as resolved.
Show resolved Hide resolved
"shared_access_signature": shared_access_signature,
"shared_access_key_name": shared_access_key_name,
"shared_access_key": shared_access_key,
"entity_path": entity,
"shared_access_signature": signature,
"shared_access_key_name": policy,
"shared_access_key": key,
}
return ServiceBusConnectionStringProperties(**props)
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,9 @@ def test_sb_parse_conn_str_no_key(self, **kwargs):
with pytest.raises(ValueError) as e:
parse_result = parse_connection_string(conn_str)
assert str(e.value) == 'Connection string must have both SharedAccessKeyName and SharedAccessKey.'

def test_sb_parse_conn_str_no_key_or_sas(self, **kwargs):
conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/'
with pytest.raises(ValueError) as e:
parse_result = parse_connection_string(conn_str)
assert str(e.value) == 'At least one of the SharedAccessKey or SharedAccessSignature must be present.'