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

Atomic avu handling (main) #65

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,17 @@ install(FILES ${CMAKE_SOURCE_DIR}/packaging/run_metadata_guard_test.py
DESTINATION ${IRODS_HOME_DIRECTORY}/scripts
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

install(FILES ${CMAKE_SOURCE_DIR}/packaging/irods_prc_tests/test_rule_engine_plugin_metadata_guard_atomic.py
DESTINATION ${IRODS_HOME_DIRECTORY}/scripts/irods_prc_tests
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
FifthPotato marked this conversation as resolved.
Show resolved Hide resolved

set(PLUGIN_PACKAGE_NAME irods-rule-engine-plugin-metadata-guard)

include(IrodsCPackCommon)

list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}${IRODS_HOME_DIRECTORY}")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}${IRODS_HOME_DIRECTORY}/scripts")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}${IRODS_HOME_DIRECTORY}/scripts/irods_prc_tests")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}${IRODS_HOME_DIRECTORY}/scripts/irods")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}${IRODS_HOME_DIRECTORY}/scripts/irods/test")

Expand Down
5 changes: 5 additions & 0 deletions irods_consortium_continuous_integration_test_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ def main():
)
)

irods_python_ci_utilities.subprocess_get_output(['python3', '-m', 'pip', 'install', 'python-irodsclient==1.1.9'], check_rc=True)

test = options.test or 'test_rule_engine_plugin_metadata_guard'

try:
test_output_file = 'log/test_output.log'
irods_python_ci_utilities.subprocess_get_output(['sudo', 'su', '-', 'irods', '-c',
f'python3 scripts/run_tests.py --xml_output --run_s {test} 2>&1 | tee {test_output_file}; exit $PIPESTATUS'],
check_rc=True)
irods_python_ci_utilities.subprocess_get_output(['sudo', 'su', '-', 'irods', '-c',
f'python3 scripts/irods_prc_tests/test_rule_engine_plugin_metadata_guard_atomic.py 2>&1 | tee {test_output_file}; exit $PIPESTATUS'],
check_rc=True)
finally:
output_root_directory = options.output_root_directory
if output_root_directory:
Expand Down
korydraughn marked this conversation as resolved.
Show resolved Hide resolved
FifthPotato marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from irods.access import iRODSAccess
from irods.session import iRODSSession
from irods.meta import iRODSMeta, AVUOperation

import irods.exception

import json
import os
import shutil
import tempfile
import unittest

class test_metadata_guard(unittest.TestCase):

IRODS_CONFIG_FILE_PATH = '/etc/irods/server_config.json'
TEST_DATA_OBJECT_PATH = '/tempZone/home/alice/test1'

@classmethod
def backup_irods_config(cls):
cls.temp_path = os.path.join(tempfile.mkdtemp(), 'irods_config_backup')
shutil.copy2(cls.IRODS_CONFIG_FILE_PATH, cls.temp_path)

@classmethod
def restore_irods_config(cls):
shutil.copy2(cls.temp_path,cls.IRODS_CONFIG_FILE_PATH)

@classmethod
def setUpClass(cls):
with iRODSSession(host='localhost', port=1247, user='rods', password='rods', zone='tempZone') as local_admin:
# create unprivileged user
local_admin.users.create_with_password('alice', 'test')

# unprivileged user creates test file
with iRODSSession(host='localhost', port=1247, user='alice', password='test', zone='tempZone') as unprivileged_user:
unprivileged_user.data_objects.create(cls.TEST_DATA_OBJECT_PATH)
unprivileged_user.acls.set( iRODSAccess('own', cls.TEST_DATA_OBJECT_PATH, 'rods', 'tempZone'))
FifthPotato marked this conversation as resolved.
Show resolved Hide resolved

coll = local_admin.collections.get("/tempZone")
# add metadata_guard config AVU to collection
METADATA_GUARD_CONFIG = {
'admin_only': True,
'prefixes': ['irods::']
}
if 'irods::metadata_guard' not in coll.metadata:
coll.metadata.add('irods::metadata_guard', json.dumps(METADATA_GUARD_CONFIG))

# create backup of irods config file
cls.backup_irods_config()
# insert metadata guard rule engine plugin to irods config file
with open(cls.IRODS_CONFIG_FILE_PATH, 'r+') as config_file:
METADATA_GUARD_PLUGIN_BLOCK = {
'instance_name': 'irods_rule_engine_plugin-metadata_guard-instance',
'plugin_name': 'irods_rule_engine_plugin-metadata_guard',
'plugin_specific_configuration': {}
}
config_json = json.load(config_file)
config_json['plugin_configuration']['rule_engines'].insert(0, METADATA_GUARD_PLUGIN_BLOCK)
with open(cls.IRODS_CONFIG_FILE_PATH, 'wt') as config_file:
json.dump(config_json, config_file)

@classmethod
def tearDownClass(cls):
cls.restore_irods_config()

def test_guard_atomic_bad_config__issue_38(self):
# set metadata_guard config AVU on collection to nonsense
with iRODSSession(host='localhost', port=1247, user='rods', password='rods', zone='tempZone') as local_admin:
coll = local_admin.collections.get("/tempZone")
coll.metadata['irods::metadata_guard'] = iRODSMeta('irods::metadata_guard', '{"broken": ["irods::"], ')

with iRODSSession(host='localhost', port=1247, user='alice', password='test', zone='tempZone') as unprivileged_user:
obj = unprivileged_user.data_objects.get(self.TEST_DATA_OBJECT_PATH)
obj.metadata.apply_atomic_operations( AVUOperation(operation='add', avu=iRODSMeta('irods::badconfig','badconfig')))

# bad config means operation should succeed
self.assertEqual(obj.metadata['irods::badconfig'], iRODSMeta('irods::badconfig', 'badconfig'))
obj.metadata.apply_atomic_operations( AVUOperation(operation='remove', avu=iRODSMeta('irods::badconfig','badconfig')))

def test_guard_atomic_operations_admin_only__issue_38(self):
# set metadata_guard config AVU on collection to admin_only and irods:: as protected prefix
with iRODSSession(host='localhost', port=1247, user='rods', password='rods', zone='tempZone') as local_admin:
coll = local_admin.collections.get("/tempZone")
METADATA_GUARD_CONFIG = {
'admin_only': True,
'prefixes': ['irods::']
}
coll.metadata['irods::metadata_guard'] = iRODSMeta('irods::metadata_guard', json.dumps(METADATA_GUARD_CONFIG))

obj = local_admin.data_objects.get(self.TEST_DATA_OBJECT_PATH)
obj.metadata.apply_atomic_operations( AVUOperation(operation='add', avu=iRODSMeta('irods::adminonly','adminonly')))

# admin should still be allowed to add metadata
self.assertEqual(obj.metadata['irods::adminonly'], iRODSMeta('irods::adminonly', 'adminonly'))

with iRODSSession(host='localhost', port=1247, user='alice', password='test', zone='tempZone') as unprivileged_user:
obj = unprivileged_user.data_objects.get(self.TEST_DATA_OBJECT_PATH)

# "unguarded::" not protected, so operation should succeed
obj.metadata.apply_atomic_operations( AVUOperation(operation='add', avu=iRODSMeta('unguarded::atr1','val1')))
self.assertEqual(obj.metadata['unguarded::atr1'], iRODSMeta('unguarded::atr1', 'val1'))

# "irods::" protected, so metadata add should fail
self.assertRaises(irods.exception.CAT_INSUFFICIENT_PRIVILEGE_LEVEL, lambda: obj.metadata.apply_atomic_operations( AVUOperation(operation='add', avu=iRODSMeta('irods::atr','val'))))
FifthPotato marked this conversation as resolved.
Show resolved Hide resolved

# "irods::" protected, so metadata delete should fail
self.assertRaises(irods.exception.CAT_INSUFFICIENT_PRIVILEGE_LEVEL, lambda: obj.metadata.apply_atomic_operations( AVUOperation(operation='remove', avu=iRODSMeta('irods::adminonly','adminonly'))))

def test_guard_atomic_operations_editor_list__issue_38(self):
# set metadata_guard config AVU on collection to admin_only: false and irods:: as protected prefix
# also, add alice user as editor
with iRODSSession(host='localhost', port=1247, user='rods', password='rods', zone='tempZone') as local_admin:
coll = local_admin.collections.get("/tempZone")
METADATA_GUARD_CONFIG = {
'admin_only': False,
'editors': [{'name': 'rods', 'type': 'user'}, {'name': 'alice', 'type': 'user'}],
'prefixes': ['irods::']
}
coll.metadata['irods::metadata_guard'] = iRODSMeta('irods::metadata_guard', json.dumps(METADATA_GUARD_CONFIG))

with iRODSSession(host='localhost', port=1247, user='alice', password='test', zone='tempZone') as unprivileged_user:
obj = unprivileged_user.data_objects.get(self.TEST_DATA_OBJECT_PATH)

# operation should succeed, as alice is set as an editor
obj.metadata.apply_atomic_operations( AVUOperation(operation='add', avu=iRODSMeta('irods::editorlist', 'editorlist')))
self.assertEqual(obj.metadata['irods::editorlist'], iRODSMeta('irods::editorlist', 'editorlist'))

# remove alice user from editor list
with iRODSSession(host='localhost', port=1247, user='rods', password='rods', zone='tempZone') as local_admin:
coll = local_admin.collections.get("/tempZone")
METADATA_GUARD_CONFIG = {
'admin_only': False,
'editors': [{'name': 'rods', 'type': 'user'}],
'prefixes': ['irods::']
}
coll.metadata['irods::metadata_guard'] = iRODSMeta('irods::metadata_guard', json.dumps(METADATA_GUARD_CONFIG))

with iRODSSession(host='localhost', port=1247, user='alice', password='test', zone='tempZone') as unprivileged_user:
obj = unprivileged_user.data_objects.get(self.TEST_DATA_OBJECT_PATH)

# this was set previously, make sure it is still the case
self.assertEqual(obj.metadata['irods::editorlist'], iRODSMeta('irods::editorlist', 'editorlist'))
# operation should fail, as test user is no longer in editor list
self.assertRaises(irods.exception.CAT_INSUFFICIENT_PRIVILEGE_LEVEL, lambda: obj.metadata.apply_atomic_operations( AVUOperation(operation='remove', avu=iRODSMeta('irods::editorlist', 'editorlist'))))
FifthPotato marked this conversation as resolved.
Show resolved Hide resolved


if __name__ == '__main__':
unittest.main()
2 changes: 2 additions & 0 deletions packaging/postinst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /etc/irods
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /usr/lib/irods/plugins/rule_engines/libirods_rule_engine_plugin-metadata_guard.so
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts/irods_prc_tests
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts/irods_prc_tests/test_rule_engine_plugin_metadata_guard_atomic.py
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts/irods
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts/irods/test
chown $IRODS_SERVICE_ACCOUNT_NAME:$IRODS_SERVICE_GROUP_NAME /var/lib/irods/scripts/irods/test/test_rule_engine_plugin_metadata_guard.py
Expand Down
Loading
Loading