Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions sdk/identity/azure-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Bugs Fixed

- Fixed the bug that `ClientAssertionCredential` constructor fails if kwargs are provided. ([#33673](https://github.com/Azure/azure-sdk-for-python/issues/33673))
- `ManagedIdentityCredential` is more lenient with the error message it matches when falling through to the next credential in the chain in the case that Docker Desktop returns a 403 response when attempting to access the IMDS endpoint. ([#33928](https://github.com/Azure/azure-sdk-for-python/pull/33928))

### Other Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ def _check_forbidden_response(ex: HttpResponseError) -> None:
"""Special case handling for Docker Desktop.

Docker Desktop proxies all HTTP traffic, and if the IMDS endpoint is unreachable, it
responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network".
responds with a 403 with a message that contains "unreachable".

:param ~azure.core.exceptions.HttpResponseError ex: The exception raised by the request
:raises ~azure.core.exceptions.CredentialUnavailableError: When the IMDS endpoint is unreachable
"""
if ex.status_code == 403:
if ex.message and "A socket operation was attempted to an unreachable network" in ex.message:
if ex.message and "unreachable" in ex.message:
error_message = f"ManagedIdentityCredential authentication unavailable. Error: {ex.message}"
raise CredentialUnavailableError(message=error_message) from ex

Expand Down
5 changes: 3 additions & 2 deletions sdk/identity/azure-identity/tests/test_imds_credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@ def send(request, **kwargs):
assert error_message in ex.value.message


def test_imds_request_failure_docker_desktop():
@pytest.mark.parametrize("error_ending", ("network", "host", "foo"))
def test_imds_request_failure_docker_desktop(error_ending):
"""The credential should raise CredentialUnavailableError when a 403 with a specific message is received"""

error_message = (
"connecting to 169.254.169.254:80: connecting to 169.254.169.254:80: dial tcp 169.254.169.254:80: "
"connectex: A socket operation was attempted to an unreachable network." # cspell:disable-line
f"connectex: A socket operation was attempted to an unreachable {error_ending}." # cspell:disable-line
)
probe = mock_response(status_code=403, json_payload={"error": error_message})
transport = mock.Mock(send=mock.Mock(return_value=probe))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,13 @@ async def send(request, **kwargs):
assert error_message in ex.value.message


async def test_imds_request_failure_docker_desktop():
@pytest.mark.parametrize("error_ending", ("network", "host", "foo"))
async def test_imds_request_failure_docker_desktop(error_ending):
"""The credential should raise CredentialUnavailableError when a 403 with a specific message is received"""

error_message = (
"connecting to 169.254.169.254:80: connecting to 169.254.169.254:80: dial tcp 169.254.169.254:80: "
"connectex: A socket operation was attempted to an unreachable network." # cspell:disable-line
f"connectex: A socket operation was attempted to an unreachable {error_ending}." # cspell:disable-line
)
probe = mock_response(status_code=403, json_payload={"error": error_message})
transport = mock.Mock(send=mock.Mock(return_value=get_completed_future(probe)))
Expand Down