You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.9 KiB

# Copyright (C) 2005-2024 Splunk Inc. All Rights Reserved.
import sys
from splunk.clilib.bundle_paths import make_splunkhome_path
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-UserAccess', 'lib']))
from user_access_utils import UserAccess
from itsi.content_packs import constants
from itsi.content_packs.itoa import get_itoa_identifier_fields, get_itoa_object_class, get_itoa_object_title
from itsi.content_packs.journal import EntryType
USERACCESS_ACL = {
'read': ['*'],
'write': ['*'],
'delete': ['*']
}
ITSI_ACL = {
'can_change_perms': True,
'can_share_app': True,
'can_share_global': True,
'can_share_user': True,
'can_write': True,
'modifiable': True,
'owner': 'nobody',
'perms': {
'read': ['*'],
'write': ['*']
},
'sharing': 'app'
}
class AccessConfigurator(object):
"""
Configures ACLs for content objects.
"""
def __init__(self, logger, session_key):
"""
:param logger: a logger instance
:type logger: Logger
:param session_key: the session key
:type session_key: str
"""
self.logger = logger
self.session_key = session_key
def process_objects(self, content_objects, journal):
"""
Configures ACLs for supported content type objects.
:param content_objects: the content objects data
:type content_objects: dict
:param journal: a journal instance
:type journal: TransactionJournal
:return: the content objects data
:rtype: dict
"""
for content_type, objects in content_objects.items():
if content_type not in constants.CONTENT_TYPES_WITH_ACL:
continue
self.configure_access(content_type, objects, journal=journal)
return content_objects
def configure_access(self, content_type, objects, journal):
"""
Configures ACLs for the given content objects.
:param content_type: the content type
:type content_type: str
:param objects: the list of objects data
:type objects: list
:param journal:
:type journal: TransactionJournal
"""
object_type = constants.CONTENT_TYPE_TO_ITOA_TYPE.get(content_type)
if not object_type:
self.logger.warning(
'Unsupported content_type="%s" found while configuring ACLs', content_type
)
return
itoa_object_class = get_itoa_object_class(content_type)
if not itoa_object_class:
self.logger.warning(
'No object class available for content_type="%s"', content_type
)
return
object_storename = getattr(itoa_object_class, 'collection_name', None)
if not object_storename:
self.logger.warning(
'No collection name associated for content_type="%s"', content_type
)
return
object_ids = self.configure_itsi_acl(content_type, objects)
if not object_ids:
return
try:
UserAccess.bulk_update_perms(
object_ids=object_ids,
acl=USERACCESS_ACL,
object_app='itsi',
object_type=object_type,
object_storename=object_storename,
session_key=self.session_key,
logger=self.logger
)
except Exception as ex:
self.logger.error(
'Failed to bulk update permissions for content_type="%s" object_type="%s" '
'object_storename="%s" object_ids="%s"',
content_type,
object_type,
object_storename,
object_ids
)
self.logger.exception(ex)
journal.failure({
'error_message': str(ex),
'type': EntryType.ERROR_BULK_UPDATE_PERMS,
'content_type': content_type,
'object_type': object_type,
'object_storename': object_storename,
'ids': object_ids,
'titles': list({get_itoa_object_title(content_type, obj) for obj in objects})
})
def configure_itsi_acl(self, content_type, objects):
"""
Sets ACLs for valid objects and returns these object ids .
:param content_type: the content type
:type content_type: str
:param objects: the list of objects data
:type objects: list
:return: the list of object ids
:rtype: list
"""
object_ids = []
id_field = get_itoa_identifier_fields(content_type)[0]
for obj in objects:
object_id = obj.get(id_field)
if object_id:
obj['acl'] = ITSI_ACL
obj['_owner'] = 'nobody'
object_ids.append(object_id)
else:
self.logger.warning('No _key field found for object="%s"', obj)
return object_ids