forked from Georg/pyacl
Implement native ACL parsing
Instead of parsing a string representation, parse the native ACL entries to construct the ACL mapping. This should yield better reliability. Keep the existing logic in a renamed function, as it might still be useful to parse existing string representations. Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
This commit is contained in:
parent
4a2fb83885
commit
722fec83b3
71
pyacl/acl.py
71
pyacl/acl.py
@ -8,7 +8,7 @@ An English copy of the Licence is shipped in a file called LICENSE along with th
|
||||
You may obtain copies of the Licence in any of the official languages at https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12.
|
||||
"""
|
||||
|
||||
from pwd import getpwnam
|
||||
from pwd import getpwnam, getpwuid
|
||||
|
||||
from posix1e import (
|
||||
ACL,
|
||||
@ -58,7 +58,7 @@ def reduce_entries(acl):
|
||||
return entries
|
||||
|
||||
|
||||
def parse_permission(strpermission):
|
||||
def parsestrpermission(strpermission):
|
||||
if len(strpermission) != MAX_PERMBITS:
|
||||
return ValueError('Invalid permission')
|
||||
|
||||
@ -92,7 +92,7 @@ def parse_permission(strpermission):
|
||||
return outmap
|
||||
|
||||
|
||||
def parse_entry(strentry):
|
||||
def parsestrentry(strentry):
|
||||
if not strentry:
|
||||
raise ValueError('Got empty string')
|
||||
|
||||
@ -111,18 +111,73 @@ def parse_entry(strentry):
|
||||
|
||||
return {
|
||||
entrytype: {
|
||||
entryvalue: parse_permission(permissions),
|
||||
entryvalue: parsestrpermission(permissions),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def parsefromacl(acl): # noqa PLR0912, FIXME: uncomplexify this
|
||||
permap = {
|
||||
permission: False for permission in DEFAULT_PERMISSIONS.keys()
|
||||
}
|
||||
outmap = {
|
||||
group: {
|
||||
None: permap.copy(),
|
||||
} for group in DEFAULT_ENTRYTYPES
|
||||
}
|
||||
|
||||
for entry in acl:
|
||||
name = None
|
||||
permset = entry.permset
|
||||
tag_type = entry.tag_type
|
||||
try:
|
||||
qualifier = entry.qualifier
|
||||
except TypeError:
|
||||
qualifier = None
|
||||
|
||||
if tag_type == 0:
|
||||
return ValueError('Got ACL with undefined tag')
|
||||
|
||||
if isinstance(qualifier, int):
|
||||
try:
|
||||
name = getpwuid(qualifier).pw_name
|
||||
except KeyError:
|
||||
name = qualifier
|
||||
elif qualifier is not None:
|
||||
return ValueError('Got ACL with unhandled qualifier')
|
||||
|
||||
if tag_type in [ACL_USER, ACL_GROUP, ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_MASK, ACL_OTHER]:
|
||||
for tag_high, tag_low in LIBACL_TAGS.items():
|
||||
if tag_low == tag_type:
|
||||
lowmap = permap.copy()
|
||||
for permission in lowmap.keys():
|
||||
lowmap[permission] = getattr(permset, permission)
|
||||
outtag = tag_high
|
||||
if tag_type == ACL_USER_OBJ:
|
||||
outname = None
|
||||
outtag = 'user'
|
||||
elif tag_type == ACL_GROUP_OBJ:
|
||||
outname = None
|
||||
outtag = 'group'
|
||||
else:
|
||||
outname = name
|
||||
if outtag not in outmap:
|
||||
outmap[outtag] = {}
|
||||
if len(outmap[outtag]) == 1 and list(outmap[outtag].keys())[0] is None:
|
||||
del outmap[outtag][None]
|
||||
outmap[outtag][outname] = lowmap
|
||||
break
|
||||
|
||||
return outmap
|
||||
|
||||
|
||||
def parse_entries(acl):
|
||||
outmap = {
|
||||
group: DEFAULT_PERMISSIONS for group in DEFAULT_ENTRYTYPES
|
||||
}
|
||||
|
||||
for entry in acl:
|
||||
outmap.update(parse_entry(entry))
|
||||
outmap.update(parsestrentry(entry))
|
||||
|
||||
return outmap
|
||||
|
||||
@ -168,5 +223,9 @@ def entriesfromfile(path):
|
||||
return reduce_entries(aclfromfile(path))
|
||||
|
||||
|
||||
def parsefromfile(path):
|
||||
def parsefromfile_throughstring(path):
|
||||
return parse_entries(reduce_entries(aclfromfile(path)))
|
||||
|
||||
|
||||
def parsefromfile(path):
|
||||
return parsefromacl(aclfromfile(path))
|
||||
|
@ -24,7 +24,13 @@ def load_yaml(file):
|
||||
|
||||
|
||||
@mark.parametrize('aclin, aclout', load_yaml('matrix.yaml'))
|
||||
def test_parse_acl(sample_file_with_acl, aclin, aclout):
|
||||
def test_parse_acl_through_string(sample_file_with_acl, aclin, aclout):
|
||||
have = acl.parsefromfile_throughstring(sample_file_with_acl)
|
||||
assert aclout == have
|
||||
|
||||
|
||||
@mark.parametrize('aclin, aclout', load_yaml('matrix.yaml'))
|
||||
def test_parse_acl_native(sample_file_with_acl, aclin, aclout):
|
||||
have = acl.parsefromfile(sample_file_with_acl)
|
||||
assert aclout == have
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user