Maintenance will be performed on git.ligo.org, chat.ligo.org, containers.ligo.org, and docs.ligo.org on Tuesday 26 May 2020 starting at approximately 10am CDT. It is expected to take around 30 minutes and will involve a short period of downtime, around 5 minutes, towards the end of the maintenance period. Please address any questions, comments, or concerns to uwm-help@cgca.uwm.edu.

Commit 5b53da72 authored by Leo Pound Singer's avatar Leo Pound Singer Committed by Leo Pound Singer

Update safe_netrc from https://git.ligo.org/emfollow/safe-netrc

This brings support for the NETRC environment variable, which
makes it easier to isolate the unit tests from the users's
own netrc file.
parent dbf85fec
Pipeline #102284 failed with stages
in 6 minutes and 59 seconds
"""Bundled copies of third-party dependencies.
The following bundled sources are included:
* safe_netrc: copied from https://git.ligo.org/emfollow/safe-netrc
"""
from netrc import netrc as _netrc
from netrc import NetrcParseError
import os
import stat
__all__ = ('netrc', 'NetrcParseError')
class netrc(_netrc): # noqa: N801
"""Subclass of the Python standard library :class:`~netrc.netrc` class to
add some custom behaviors.
1. If the ``NETRC`` environment variable is defined, then use it as
the default netrc file path.
2. Backport permissions checks that were added in Python 3.1
(see https://bugs.python.org/issue14984).
3. Apply permissions checks whether or or not we are reading from the
default netrc file, and whether or not the file contains passwords.
"""
def __init__(self, file=None):
if file is None:
file = os.environ.get('NETRC')
_netrc.__init__(self, file)
def _parse(self, file, fp, *args, **kwargs):
# Adapted from Python 3.7
if os.name == 'posix':
prop = os.fstat(fp.fileno())
if prop.st_uid != os.getuid():
import pwd
try:
fowner = pwd.getpwuid(prop.st_uid)[0]
except KeyError:
fowner = 'uid %s' % prop.st_uid
try:
user = pwd.getpwuid(os.getuid())[0]
except KeyError:
user = 'uid %s' % os.getuid()
raise NetrcParseError(
("~/.netrc file owner (%s) does not match"
" current user (%s)") % (fowner, user),
file)
if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)):
raise NetrcParseError(
"~/.netrc access too permissive: access"
" permissions must restrict access to only"
" the owner", file)
_netrc._parse(self, file, fp, *args, **kwargs)
import os
import stat
import pytest
from .. import netrc, NetrcParseError
try:
FileNotFoundError
except NameError:
FileNotFoundError = IOError
def check(filename):
# Check that an exception is raised when the netrc file does not exist.
with pytest.raises(FileNotFoundError) as excinfo:
netrc()
assert excinfo.value.filename == filename
with open(filename, 'w') as f:
fd = f.fileno()
# Check that an exception is raised when the permissions too relaxed.
os.fchmod(fd, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
with pytest.raises(NetrcParseError) as excinfo:
netrc()
assert excinfo.value.filename == filename
# Check that no exceptions are raised if the permissions are correct.
os.fchmod(fd, stat.S_IRWXU)
netrc()
def test_netrc_in_environ(monkeypatch, tmpdir):
"""Check file specified by NETRC environment variable"""
filename = str(tmpdir / 'netrc')
monkeypatch.setenv('NETRC', filename)
check(filename)
def test_netrc_in_homedir(monkeypatch, tmpdir):
"""Check file specified by home directory"""
filename = str(tmpdir / '.netrc')
monkeypatch.setenv('HOME', str(tmpdir))
check(filename)
......@@ -31,8 +31,9 @@ import ssl
import sys
from .exceptions import HTTPError
from .extern.safe_netrc import netrc as safe_netrc
from .version import __version__
from .utils import event_or_superevent, safe_netrc
from .utils import event_or_superevent
DEFAULT_SERVICE_URL = "https://gracedb.ligo.org/api/"
......
import os
import re
import six
import stat
from functools import wraps
from netrc import netrc, NetrcParseError
if os.name == 'posix':
import pwd
EVENT_PREFIXES = ['G', 'E', 'H', 'M', 'T']
event_prefix_regex = re.compile(r'^({prefixes})\d+'.format(
......@@ -36,37 +31,3 @@ def handle_str_or_list_arg(arg, arg_name):
raise TypeError("{0} arg is {1}, should be str or list"
.format(arg_name, type(arg)))
return arg
# Parse a datetime object out of the openssl output.
# Note that this returns a naive datetime object.
class safe_netrc(netrc):
"""The netrc.netrc class from the Python standard library applies access
safety checks (requiring that the netrc file is readable only by the
current user, and not by group members or other users) only if using the
netrc file in the default location (~/.netrc). This subclass applies the
same access safety checks regardless of the path to the netrc file."""
def _parse(self, file, fp, *args, **kwargs):
# Copied and adapted from netrc.py from Python 2.7
if os.name == 'posix':
prop = os.fstat(fp.fileno())
if prop.st_uid != os.getuid():
try:
fowner = pwd.getpwuid(prop.st_uid)[0]
except KeyError:
fowner = 'uid %s' % prop.st_uid
try:
user = pwd.getpwuid(os.getuid())[0]
except KeyError:
user = 'uid %s' % os.getuid()
raise NetrcParseError(
("~/.netrc file owner (%s) does not match"
" current user (%s)") % (fowner, user),
file)
if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)):
raise NetrcParseError(
"~/.netrc access too permissive: access"
" permissions must restrict access to only"
" the owner", file)
return netrc._parse(self, file, fp, *args, **kwargs)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment