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

ca_certs zip file extraction permission issue with multiple users on Python 3.6 #5994

Closed
Peter200lx opened this issue Dec 1, 2021 · 2 comments

Comments

@Peter200lx
Copy link

Peter200lx commented Dec 1, 2021

When you have multiple users on a machine that each use requests from zipapps with certifi, one user running a request should not block other users from successfully performing requests. This issue only appears when using a zipapp on python3.6. For python3.7+ the certifi library handles the tempfile and requests.util.extract_zipped_paths never sees the zipapp. https://github.com/certifi/python-certifi/blob/2021.10.08/certifi/core.py#L43-L44

Expected Result

user1 # python3.6 zipapp.2.26.zip
get file
user2 # python3.6 zipapp.2.26.zip
get file

Actual Result

user1 # python3.6 zipapp.2.26.zip
get file
user2 # python3.6 zipapp.2.26.zip
Traceback (most recent call last):
  File "/tmp/zipapp.2.26.zip/urllib3/util/ssl_.py", line 402, in ssl_wrap_socket
PermissionError: [Errno 13] Permission denied

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/zipapp.2.26.zip/urllib3/connectionpool.py", line 706, in urlopen
  File "/tmp/zipapp.2.26.zip/urllib3/connectionpool.py", line 382, in _make_request
  File "/tmp/zipapp.2.26.zip/urllib3/connectionpool.py", line 1010, in _validate_conn
  File "/tmp/zipapp.2.26.zip/urllib3/connection.py", line 421, in connect
  File "/tmp/zipapp.2.26.zip/urllib3/util/ssl_.py", line 404, in ssl_wrap_socket
urllib3.exceptions.SSLError: [Errno 13] Permission denied

During the handling the above ....... <a bunch of MaxRetryError tracebacks>

Behaviors on versions:

The core issue is that the changes in #5707 result in different file permissions on disk. Prior to that change, the file would be extracted with 0o664 permissions, but afterwords it is generated with 0o600 permissions from mkstemp, which means that users other than the first runner couldn't access the certfille.

requests/requests/utils.py

Lines 275 to 276 in c193d97

with atomic_open(extracted_path) as file_handler:
file_handler.write(zip_file.read(member))

requests/requests/utils.py

Lines 283 to 288 in c193d97

replacer = os.rename if sys.version_info[0] == 2 else os.replace
tmp_descriptor, tmp_name = tempfile.mkstemp(dir=os.path.dirname(filename))
try:
with os.fdopen(tmp_descriptor, 'wb') as tmp_handler:
yield tmp_handler
replacer(tmp_name, filename)

Python3.6 w/ requests==2.25.1

$ PYTHONPATH=zipapp.2.25.zip python3.6
>>> import certifi, requests
>>> certifi.where()
'/tmp/zipapp.2.25.zip/certifi/cacert.pem'
>>> requests.utils.extract_zipped_paths(certifi.where())
'/tmp/certifi/cacert.pem'
$ ls -lah /tmp/certifi/cacert.pem
-rw-rw-r--. 1 user1 user1 278K May  7  2020 /tmp/certifi/cacert.pem

Python3.6 w/ requests==2.26.0

$ PYTHONPATH=zipapp.2.26.zip python3.6
>>> import certifi, requests
>>> certifi.where()
'/tmp/zipapp.2.26.zip/certifi/cacert.pem'
>>> requests.utils.extract_zipped_paths(certifi.where())
'/tmp/cacert.pem'
$ ls -lah /tmp/cacert.pem 
-rw-------. 1 user1 user1 254K Sep 23 23:34 /tmp/cacert.pem

Python3.7 w/ requests==2.26.0

$ PYTHONPATH=zipapp.2.26.zip python3.7
>>> import certifi, requests
>>> certifi.where()
'/tmp/tmpuwsvnshl'
>>> requests.utils.extract_zipped_paths(certifi.where())
'/tmp/tmpuwsvnshl'
$ ls -lah /tmp/tmpuwsvnshl 
-rw------- 1 user1 user1 260K Nov 30 15:46 /tmp/tmpuwsvnshl

System Information

$ PYTHONPATH=zipapp.2.26.zip python3.6 -m requests.help
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "2.0.8"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.3"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.8"
  },
  "platform": {
    "release": "3.10.0-862.3.2.el7.x86_64",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.26.0"
  },
  "system_ssl": {
    "version": "100020bf"
  },
  "urllib3": {
    "version": "1.26.7"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": false
}

Ideally I'd prefer the extract_zipped_paths writer use a temporary file like certifi which gets cleaned up at the end of the program, but as a fallback the writer could be updated to save with 0o664 permissions again so that it doesn't matter which user first runs.

@nateprewitt
Copy link
Member

Hi @Peter200lx, thanks for the detailed write up!

Adding read permissions (0o644) seems like a possibility, I'm not sure we want to return group write perms. Given 3.6 reaches end of life in ~10 days (2021-12-23), I'm not certain it's worth the effort though. It's likely we'll see support for Python 3.6 drop early next year which may be before we push out a release that has the code fix for this.

@nateprewitt
Copy link
Member

Given tomorrow's release will be the last to support Python 3.6 and we don't have any candidate solutions, I'm going to resolve this as won't fix. The support floor for the next non-hotfix release after 2.27.0 will have Python 3.7 as the floor for Python version support.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants