Skip to content

[Bug] Init of ClientApplication fails on read only filesystems when msal-extensions is installed since 1.32.0 #800

@nluedema

Description

@nluedema

Describe the bug
After upgrading to 1.32.0, initializing ClientApplication fails with the following error when also msal-extensions is installed:

Traceback (most recent call last):
  File "//confidential_client_sample.py", line 42, in <module>
    global_app = msal.ConfidentialClientApplication(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/msal/application.py", line 664, in __init__
    _msal_extension_check()
  File "/usr/local/lib/python3.12/site-packages/msal/application.py", line 201, in _msal_extension_check
    from msal_extensions import __version__ as v
  File "/usr/local/lib/python3.12/site-packages/msal_extensions/__init__.py", line 11, in <module>
    from .cache_lock import CrossPlatLock
  File "/usr/local/lib/python3.12/site-packages/msal_extensions/cache_lock.py", line 8, in <module>
    import portalocker
  File "/usr/local/lib/python3.12/site-packages/portalocker/__init__.py", line 2, in <module>
    from .utils import (
  File "/usr/local/lib/python3.12/site-packages/portalocker/utils.py", line 418, in <module>
    class BoundedSemaphore(LockBase):
  File "/usr/local/lib/python3.12/site-packages/portalocker/utils.py", line 441, in BoundedSemaphore
    directory: str = tempfile.gettempdir(),
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 315, in gettempdir
    return _os.fsdecode(_gettempdir())
                        ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 308, in _gettempdir
    tempdir = _get_default_tempdir()
              ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 223, in _get_default_tempdir
    raise FileNotFoundError(_errno.ENOENT,
FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/']

We noticed this problem after our get_token calls started to fail for a azure.identity.ClientSecretCredential in fresh Docker builds for containers with a read-only filesystem. We traced the problem back to an update of msal from version 1.31.1 to 1.32.0. As you can see from the stack trace, the call to _msal_extension_check leads to portalocker being imported, which calls tempfile.gettempdir(). Calls to tempfile.gettempdir() fail on read-only filesystems.

To Reproduce
I was able to reproduce the error with Docker and your confidential_client_sample.py sample.
Here the Dockerfile:

FROM python:3.12.9-slim-bookworm

RUN pip install msal python-dotenv msal-extensions

COPY confidential_client_sample.py confidential_client_sample.py
COPY .env .env

CMD ["python","confidential_client_sample.py"]

Then run the following:

docker build . -t test
docker run --read-only test:latest

Which will result in the traceback shown above.

Expected behavior
Successfully acquiring a token.

What you see instead

Traceback (most recent call last):
  File "//confidential_client_sample.py", line 42, in <module>
    global_app = msal.ConfidentialClientApplication(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/msal/application.py", line 664, in __init__
    _msal_extension_check()
  File "/usr/local/lib/python3.12/site-packages/msal/application.py", line 201, in _msal_extension_check
    from msal_extensions import __version__ as v
  File "/usr/local/lib/python3.12/site-packages/msal_extensions/__init__.py", line 11, in <module>
    from .cache_lock import CrossPlatLock
  File "/usr/local/lib/python3.12/site-packages/msal_extensions/cache_lock.py", line 8, in <module>
    import portalocker
  File "/usr/local/lib/python3.12/site-packages/portalocker/__init__.py", line 2, in <module>
    from .utils import (
  File "/usr/local/lib/python3.12/site-packages/portalocker/utils.py", line 418, in <module>
    class BoundedSemaphore(LockBase):
  File "/usr/local/lib/python3.12/site-packages/portalocker/utils.py", line 441, in BoundedSemaphore
    directory: str = tempfile.gettempdir(),
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 315, in gettempdir
    return _os.fsdecode(_gettempdir())
                        ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 308, in _gettempdir
    tempdir = _get_default_tempdir()
              ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 223, in _get_default_tempdir
    raise FileNotFoundError(_errno.ENOENT,
FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/']

The MSAL Python version you are using
1.32.0

Additional context
I assume that this will also affect quite a few others, since running containers with a read-only filesystem is a security best practice.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions