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

NAS-123903 / 24.04 / Add initial test support for NFSv41 acl_flag #12451

Merged
merged 3 commits into from
Dec 4, 2023
Merged
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
Original file line number Diff line number Diff line change
@@ -248,6 +248,7 @@ class ACLBase(ServicePartBase):
'nfs41_flags',
Bool('autoinherit', default=False),
Bool('protected', default=False),
Bool('defaulted', default=False),
),
Str('acltype', enum=[x.name for x in ACLType], null=True),
Dict(
Original file line number Diff line number Diff line change
@@ -312,6 +312,7 @@ def getacl_nfs4(self, path, simplified, resolve_ids):
na41flags = output.pop('nfs41_flags')
output['nfs41_flags'] = {
"protected": na41flags['PROTECTED'],
"defaulted": na41flags['DEFAULTED'],
"autoinherit": na41flags['AUTOINHERIT']
}
output['acltype'] = 'NFS4'
125 changes: 76 additions & 49 deletions tests/api2/test_300_nfs.py
Original file line number Diff line number Diff line change
@@ -1088,12 +1088,14 @@ def test_42_check_nfs_client_status(request):
def test_43_check_nfsv4_acl_support(request):
"""
This test validates reading and setting NFSv4 ACLs through an NFSv4
mount in the following manner:
mount in the following manner for NFSv4.2, NFSv4.1 & NFSv4.0:
1) Create and locally mount an NFSv4 share on the TrueNAS server
2) Iterate through all possible permissions options and set them
via an NFS client, read back through NFS client, and read resulting
ACL through the filesystem API.
3) Repeate same process for each of the supported flags.
3) Repeat same process for each of the supported ACE flags.
4) For NFSv4.1 or NFSv4.2, repeat same process for each of the
supported acl_flags.
"""
acl_nfs_path = f'/mnt/{pool_name}/test_nfs4_acl'
test_perms = {
@@ -1119,57 +1121,82 @@ def test_43_check_nfsv4_acl_support(request):
"NO_PROPAGATE_INHERIT": False,
"INHERITED": False
}
theacl = [
{"tag": "owner@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "group@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "everyone@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "USER", "id": 65534, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "GROUP", "id": 666, "perms": test_perms.copy(), "flags": test_flags.copy(), "type": "ALLOW"},
]
with nfs_dataset("test_nfs4_acl", {"acltype": "NFSV4", "aclmode": "PASSTHROUGH"}, theacl):
with nfs_share(acl_nfs_path):
with SSH_NFS(ip, acl_nfs_path, vers=4, user=user, password=password, ip=ip) as n:
nfsacl = n.getacl(".")
for idx, ace in enumerate(nfsacl):
assert ace == theacl[idx], str(ace)

for perm in test_perms.keys():
if perm == 'SYNCHRONIZE':
# break in SYNCHRONIZE because Linux tool limitation
break

theacl[4]['perms'][perm] = False
n.setacl(".", theacl)
for (version, test_acl_flag) in [(4, True), (4.1, True), (4.0, False)]:
theacl = [
{"tag": "owner@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "group@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "everyone@", "id": -1, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "USER", "id": 65534, "perms": test_perms, "flags": test_flags, "type": "ALLOW"},
{"tag": "GROUP", "id": 666, "perms": test_perms.copy(), "flags": test_flags.copy(), "type": "ALLOW"},
]
with nfs_dataset("test_nfs4_acl", {"acltype": "NFSV4", "aclmode": "PASSTHROUGH"}, theacl):
with nfs_share(acl_nfs_path):
with SSH_NFS(ip, acl_nfs_path, vers=version, user=user, password=password, ip=ip) as n:
nfsacl = n.getacl(".")
for idx, ace in enumerate(nfsacl):
assert ace == theacl[idx], str(ace)

payload = {
'path': acl_nfs_path,
'simplified': False
}
result = POST('/filesystem/getacl/', payload)
assert result.status_code == 200, result.text

for idx, ace in enumerate(result.json()['acl']):
assert ace == nfsacl[idx], str(ace)

for flag in ("INHERIT_ONLY", "NO_PROPAGATE_INHERIT"):
theacl[4]['flags'][flag] = True
n.setacl(".", theacl)
nfsacl = n.getacl(".")
for idx, ace in enumerate(nfsacl):
assert ace == theacl[idx], str(ace)

payload = {
'path': acl_nfs_path,
'simplified': False
}
result = POST('/filesystem/getacl/', payload)
assert result.status_code == 200, result.text

for idx, ace in enumerate(result.json()['acl']):
assert ace == nfsacl[idx], str(ace)
for perm in test_perms.keys():
if perm == 'SYNCHRONIZE':
# break in SYNCHRONIZE because Linux tool limitation
break

theacl[4]['perms'][perm] = False
n.setacl(".", theacl)
nfsacl = n.getacl(".")
for idx, ace in enumerate(nfsacl):
assert ace == theacl[idx], str(ace)

payload = {
'path': acl_nfs_path,
'simplified': False
}
result = POST('/filesystem/getacl/', payload)
assert result.status_code == 200, result.text

for idx, ace in enumerate(result.json()['acl']):
assert ace == nfsacl[idx], str(ace)

for flag in ("INHERIT_ONLY", "NO_PROPAGATE_INHERIT"):
theacl[4]['flags'][flag] = True
n.setacl(".", theacl)
nfsacl = n.getacl(".")
for idx, ace in enumerate(nfsacl):
assert ace == theacl[idx], str(ace)

payload = {
'path': acl_nfs_path,
'simplified': False
}
result = POST('/filesystem/getacl/', payload)
assert result.status_code == 200, result.text

for idx, ace in enumerate(result.json()['acl']):
assert ace == nfsacl[idx], str(ace)
if test_acl_flag:
assert 'none' == n.getaclflag(".")
for acl_flag in ['auto-inherit', 'protected', 'defaulted']:
n.setaclflag(".", acl_flag)
assert acl_flag == n.getaclflag(".")
payload = {
'path': acl_nfs_path,
'simplified': False
}
result = POST('/filesystem/getacl/', payload)
assert result.status_code == 200, result.text
# Normalize the flag_is_set name for comparision to plugin equivalent
# (just remove the '-' from auto-inherit)
if acl_flag == 'auto-inherit':
flag_is_set = 'autoinherit'
else:
flag_is_set = acl_flag
# Now ensure that only the expected flag is set
nfs41_flags = result.json()['nfs41_flags']
for flag in ['autoinherit', 'protected', 'defaulted']:
if flag == flag_is_set:
assert nfs41_flags[flag], nfs41_flags
else:
assert not nfs41_flags[flag], nfs41_flags


def test_44_check_nfs_xattr_support(request):
24 changes: 24 additions & 0 deletions tests/protocols/nfs_proto.py
Original file line number Diff line number Diff line change
@@ -290,6 +290,30 @@ def setacl(self, path, acl):
if setfacl['result'] is False:
raise RuntimeError(setfacl['stderr'])

def getaclflag(self, path):
self.validate(path)
# nfs4_getfacl has no knowledge of acl_flags, use nfs4xfr_getfacl instead
getfacl = SSH_TEST(
f"nfs4xdr_getfacl {self._localpath}/{path}",
self._user, self._password, self._ip
)
if getfacl['result'] is False:
raise RuntimeError(getfacl['stderr'])
for line in getfacl['stdout'].split('\n'):
if line.startswith('# ACL flags:'):
return line.split(':')[1].strip()
raise RuntimeError('Could not find acl_flag')

def setaclflag(self, path, value):
self.validate(path)
# nfs4_setfacl has no knowledge of acl_flags, use nfs4xfr_setfacl instead
getfacl = SSH_TEST(
f"nfs4xdr_setfacl -p {value} {self._localpath}/{path}",
self._user, self._password, self._ip
)
if getfacl['result'] is False:
raise RuntimeError(getfacl['stderr'])

def getxattr(self, path, xattr_name):
self.validate(path)