-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Service Bus Connection String Parser #14772
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
ccd793a
initial
rakshith91 8fbee15
sol
rakshith91 7594a43
changes
rakshith91 4bb40c4
lint
rakshith91 e1e42e6
dict mixin
rakshith91 eaa986a
comments
rakshith91 2bf7bab
Update sdk/servicebus/azure-servicebus/CHANGELOG.md
69eb0a4
lint
rakshith91 cc21f02
change to method
rakshith91 de63a68
hide shared access key
rakshith91 dda76fb
fix
rakshith91 c8ae3dd
Apply suggestions from code review
3dbd773
coments
rakshith91 81f3760
few more changes
rakshith91 09f650f
tests
rakshith91 225e929
add back sky
rakshith91 0d64812
test
rakshith91 b188f5f
changelog
rakshith91 282abc6
Update sdk/servicebus/azure-servicebus/CHANGELOG.md
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
sdk/servicebus/azure-servicebus/azure/servicebus/_common/_connection_string_parser.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # -------------------------------------------------------------------------------------------- | ||
| # 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 azure.servicebus.management._models import DictMixin | ||
|
|
||
| class ServiceBusConnectionStringProperties(DictMixin): | ||
| """ | ||
| Properties of a connection string. | ||
| """ | ||
| def __init__(self, **kwargs): | ||
| self._fully_qualified_namespace = kwargs.pop('fully_qualified_namespace', None) | ||
| self._endpoint = kwargs.pop('endpoint', None) | ||
| self._entity_path = kwargs.pop('entity_path', None) | ||
| self._shared_access_signature = kwargs.pop('shared_access_signature', None) | ||
| self._shared_access_key_name = kwargs.pop('shared_access_key_name', None) | ||
| self._shared_access_key = kwargs.pop('shared_access_key', None) | ||
|
|
||
| @property | ||
| def fully_qualified_namespace(self): | ||
| """The fully qualified host name for the Service Bus namespace. | ||
| The namespace format is: `<yournamespace>.servicebus.windows.net`. | ||
| """ | ||
| return self._fully_qualified_namespace | ||
|
|
||
| @property | ||
| def endpoint(self): | ||
| """The endpoint for the Service Bus resource. In the format sb://<FQDN>/ | ||
| """ | ||
| return self._endpoint | ||
|
|
||
| @property | ||
| def entity_path(self): | ||
| """Optional. Represents the name of the queue/topic. | ||
| """ | ||
| return self._entity_path | ||
|
|
||
| @property | ||
| def shared_access_signature(self): | ||
| """ | ||
| This can be provided instead of the shared_access_key_name and the shared_access_key. | ||
| """ | ||
| return self._shared_access_signature | ||
|
|
||
| @property | ||
| def shared_access_key_name(self): | ||
| """ | ||
| The name of the shared_access_key. This must be used along with the shared_access_key. | ||
| """ | ||
| return self._shared_access_key_name | ||
|
|
||
| @property | ||
| def shared_access_key(self): | ||
| """ | ||
| The shared_access_key can be used along with the shared_access_key_name as a credential. | ||
| """ | ||
| return self._shared_access_key | ||
|
|
||
|
|
||
| def parse_connection_string(conn_str): | ||
| # type(str) -> ServiceBusConnectionStringProperties | ||
| """Parse the connection string into a properties bag containing its component parts. | ||
|
|
||
| :param conn_str: The connection string that has to be parsed. | ||
| :type conn_str: str | ||
rakshith91 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| :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') | ||
yunhaoling marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| shared_access_key_name = conn_settings.get('SharedAccessKeyName') | ||
| 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() | ||
| props = { | ||
| 'fully_qualified_namespace': namespace, | ||
| 'endpoint': endpoint, | ||
| 'entity_path': conn_settings.get('EntityPath'), | ||
| 'shared_access_signature': shared_access_signature, | ||
| 'shared_access_key_name': shared_access_key_name, | ||
| 'shared_access_key': shared_access_key | ||
| } | ||
| return ServiceBusConnectionStringProperties(**props) | ||
61 changes: 61 additions & 0 deletions
61
sdk/servicebus/azure-servicebus/tests/test_connection_string_parser.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #------------------------------------------------------------------------- | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for | ||
| # license information. | ||
| #-------------------------------------------------------------------------- | ||
|
|
||
| import os | ||
| import pytest | ||
| from azure.servicebus import ( | ||
| ServiceBusConnectionStringProperties, | ||
| parse_connection_string, | ||
| ) | ||
|
|
||
| from devtools_testutils import AzureMgmtTestCase | ||
|
|
||
| class ServiceBusConnectionStringParserTests(AzureMgmtTestCase): | ||
| def test_sb_conn_str_parse_cs(self, **kwargs): | ||
| conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/;SharedAccessKeyName=test;SharedAccessKey=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| parse_result = parse_connection_string(conn_str) | ||
| assert parse_result.endpoint == 'sb://resourcename.servicebus.windows.net/' | ||
| assert parse_result.fully_qualified_namespace == 'resourcename.servicebus.windows.net' | ||
| assert parse_result.shared_access_key_name == 'test' | ||
| assert parse_result.shared_access_key == 'THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
KieranBrantnerMagee marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def test_sb_conn_str_parse_sas_and_shared_key(self, **kwargs): | ||
| conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/;SharedAccessKeyName=test;SharedAccessKey=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=;SharedAccessSignature=THISISASASXXXXXXX=' | ||
| with pytest.raises(ValueError) as e: | ||
| parse_result = parse_connection_string(conn_str) | ||
| assert str(e.value) == 'Only one of the SharedAccessKey or SharedAccessSignature must be present.' | ||
|
|
||
| def test_sb_parse_malformed_conn_str_no_endpoint(self, **kwargs): | ||
| conn_str = 'SharedAccessKeyName=test;SharedAccessKey=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| with pytest.raises(ValueError) as e: | ||
| parse_result = parse_connection_string(conn_str) | ||
| assert str(e.value) == 'Connection string is either blank or malformed.' | ||
|
|
||
| def test_sb_parse_malformed_conn_str_no_netloc(self, **kwargs): | ||
| conn_str = 'Endpoint=MALFORMED;SharedAccessKeyName=test;SharedAccessKey=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| with pytest.raises(ValueError) as e: | ||
| parse_result = parse_connection_string(conn_str) | ||
| assert str(e.value) == 'Invalid Endpoint on the Connection String.' | ||
|
|
||
| def test_sb_parse_conn_str_sas(self, **kwargs): | ||
| conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/;SharedAccessSignature=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| parse_result = parse_connection_string(conn_str) | ||
| assert parse_result.endpoint == 'sb://resourcename.servicebus.windows.net/' | ||
| assert parse_result.fully_qualified_namespace == 'resourcename.servicebus.windows.net' | ||
| assert parse_result.shared_access_signature == 'THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| assert parse_result.shared_access_key_name == None | ||
|
|
||
| def test_sb_parse_conn_str_no_keyname(self, **kwargs): | ||
| conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/;SharedAccessKey=THISISATESTKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' | ||
| 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(self, **kwargs): | ||
| conn_str = 'Endpoint=sb://resourcename.servicebus.windows.net/;SharedAccessKeyName=Test' | ||
| 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.' | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.