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.
192 lines
7.5 KiB
192 lines
7.5 KiB
# Copyright (C) 2005-2025 Splunk Inc. All Rights Reserved.
|
|
|
|
"""
|
|
A script that registers ITSI's capabilities with SA-UserAccess and
|
|
then disables its own subsequent runs after a successful run.
|
|
"""
|
|
|
|
import copy
|
|
import sys
|
|
|
|
from splunk.clilib.bundle_paths import make_splunkhome_path
|
|
|
|
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib']))
|
|
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib', 'SA_ITOA_app_common']))
|
|
import itsi_path
|
|
import itsi_py3
|
|
from itsi.itsi_utils import CAPABILITY_MATRIX
|
|
from ITOA.event_management.notable_event_utils import CAPABILITY_MATRIX as CAPABILITY_MATRIX_NOTABLE_EVENTS
|
|
from maintenance_services.constants import CAPABILITY_MATRIX as CAPABILITY_MATRIX_MAINTENANCE_SERVICES
|
|
from ITOA.setup_logging import getLogger4ModInput, logger
|
|
from ITOA.mod_input_utils import skip_run_during_migration
|
|
from ITOA.itoa_common import modular_input_should_run, get_current_utc_epoch
|
|
from ITOA.storage.itoa_storage import ITOAStorage
|
|
|
|
from SA_ITOA_app_common.solnlib.modular_input import ModularInput
|
|
|
|
from user_access_utils import UserAccess
|
|
from user_access_errors import BadRequest
|
|
|
|
|
|
class ITSIUserAccessInit(ModularInput):
|
|
'''
|
|
Modular input responsible for registering the capabilities matrix with SA-UserAccess
|
|
It shuts itself off after doing this once
|
|
'''
|
|
title = "IT Service Intelligence Access Control Registration"
|
|
description = "Registers ITSI's capabilities with SA-UserAccess."
|
|
handlers = None
|
|
app = 'SA-ITOA'
|
|
name = 'itsi_user_access_init'
|
|
use_single_instance = True
|
|
use_kvstore_checkpointer = False
|
|
use_hec_event_writer = False
|
|
|
|
def extra_arguments(self):
|
|
return [{
|
|
'name': "log_level",
|
|
'title': "Logging Level",
|
|
'description': "This is the level at which the modular input will log data."
|
|
}, {
|
|
'name': "registered_capabilities",
|
|
'title': "Configuration Flag",
|
|
'description': ("This flag indicates whether or not the application has previously "
|
|
"registered its capabilities.")
|
|
}, {
|
|
'name': "app_name",
|
|
'title': "Application name",
|
|
'description': "String indicating the name of the app that wants to register its capabilities."
|
|
}]
|
|
|
|
def register_app_capabilities(self, app_name):
|
|
'''
|
|
A custom method to register app capabilities. The logic always
|
|
re-writes the capability matrix as it is desirable for upgrade scenario.
|
|
This piece of code will eventually change when we get rid of SA-UserAccess
|
|
and starting app-common'ing.
|
|
|
|
@type app_name: string
|
|
@param app_name: represents app name
|
|
Ex: itsi/es etc...
|
|
|
|
@type capability_matrix: dict
|
|
@param capability_matrix: capabilities viz-a-viz app objects
|
|
Ex:
|
|
{
|
|
'glass_table': {
|
|
'read': 'read_itsi_glass_table',
|
|
'write': 'write_itsi_glass_table',
|
|
'delete': 'delete_itsi_glass_table'
|
|
},
|
|
'deep_dive': {
|
|
'read': 'read_itsi_deep_dive',
|
|
'write': 'write_itsi_deep_dive',
|
|
'delete': 'delete_itsi_deep_dive'
|
|
},
|
|
...
|
|
}
|
|
|
|
@type session_key: string
|
|
@param session_key : splunkd session key
|
|
|
|
@return True on successful registration, False if otherwise
|
|
'''
|
|
LOG_PREFIX = "[ITSIUserAccessInit] [register_app_capabilities] "
|
|
STORE_NAME = UserAccess.get_app_capability_store_name()
|
|
if not isinstance(app_name, itsi_py3.string_type) or not isinstance(CAPABILITY_MATRIX, dict):
|
|
message = 'Expecting a non-None string for app_name and a non-None dict for capability_matrix'
|
|
logger.error('%s %s', LOG_PREFIX, message)
|
|
return False
|
|
|
|
# Work on the copy of the matrix
|
|
capability_matrix = copy.deepcopy(CAPABILITY_MATRIX)
|
|
|
|
if not isinstance(CAPABILITY_MATRIX_NOTABLE_EVENTS, dict):
|
|
message = 'Expecting a non-None dict for capability_matrix_notable_events'
|
|
logger.error('%s %s', LOG_PREFIX, message)
|
|
return False
|
|
capability_matrix.update(CAPABILITY_MATRIX_NOTABLE_EVENTS)
|
|
|
|
if not isinstance(CAPABILITY_MATRIX_MAINTENANCE_SERVICES, dict):
|
|
message = 'Expecting a non-None dict for capability_matrix_maintenance_services'
|
|
logger.error('%s %s', LOG_PREFIX, message)
|
|
return False
|
|
capability_matrix.update(CAPABILITY_MATRIX_MAINTENANCE_SERVICES)
|
|
|
|
# Adding mod time
|
|
capability_matrix["mod_time"] = get_current_utc_epoch()
|
|
|
|
try:
|
|
UserAccess.get_app_capabilities(app_name, self.session_key, logger)
|
|
success, data = UserAccess.store.single_update(
|
|
store_name=STORE_NAME,
|
|
record=capability_matrix,
|
|
session_key=self.session_key,
|
|
logger=logger, record_id=app_name)
|
|
|
|
# Unable to find app
|
|
except BadRequest:
|
|
logger.info("%s has not registered its capabilities. Trying to register them now.", app_name)
|
|
success, data = UserAccess.store.create(
|
|
store_name=STORE_NAME,
|
|
record=capability_matrix,
|
|
session_key=self.session_key,
|
|
logger=logger, record_id=app_name)
|
|
|
|
if success is True:
|
|
logger.debug("Successfully registered capabilities for app %s. Response: %s", app_name, data)
|
|
else:
|
|
logger.error("Unable to register capabilities for app %s.", app_name)
|
|
return success
|
|
|
|
@skip_run_during_migration
|
|
def do_run(self, input_config):
|
|
"""
|
|
Entry point for the modular input
|
|
@type input_config: dict
|
|
@param input_config: input configuration for this modular input
|
|
input_config is a dictionary key'ed by the name of the modular input
|
|
the configuration for this input is contained in the corresponding
|
|
value
|
|
"""
|
|
logger = getLogger4ModInput(input_config)
|
|
|
|
if not modular_input_should_run(self.session_key):
|
|
logger.info("Will not run modular input on this node.")
|
|
return
|
|
|
|
LOG_PREFIX = "[ITSIUserAccessInit] [run] "
|
|
logger.info("%s Starting: Input config=%s", LOG_PREFIX, input_config)
|
|
|
|
# input_config is a dictionary key'ed by the name of the modular input
|
|
# the configuration for this input is contained in the corresponding value
|
|
for stanza_name, stanza_data in input_config.items():
|
|
self.process_itsi_user_access(stanza_data)
|
|
|
|
logger.debug("%s Finished: Input config=%s", LOG_PREFIX, input_config)
|
|
|
|
def process_itsi_user_access(self, config):
|
|
|
|
LOG_PREFIX = "[ITSIUserAccessInit] [process_itsi_user_access] " # noqa E128
|
|
app_name = config.get('app_name', 'itsi')
|
|
|
|
kvstore = ITOAStorage()
|
|
if kvstore.wait_for_storage_init(self.session_key):
|
|
try:
|
|
registered = self.register_app_capabilities(app_name)
|
|
|
|
except Exception:
|
|
logger.exception("Registration of capabilities failed.")
|
|
raise
|
|
|
|
if not registered:
|
|
logger.error('Unable to register capabilities "%s" for app %s. Try again.',
|
|
CAPABILITY_MATRIX, app_name)
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
worker = ITSIUserAccessInit()
|
|
worker.execute()
|
|
sys.exit(0)
|