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.
SH-Deployer/apps/SA-ITOA/bin/itsi_content_packs_interfac...

251 lines
9.0 KiB

# Copyright (C) 2005-2025 Splunk Inc. All Rights Reserved.
try:
import http.client as httplib
except ImportError:
import httplib
import sys
from splunk.clilib.bundle_paths import make_splunkhome_path
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib']))
# Process .pth files
import site
site.addsitedir(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib', 'SA_ITOA_app_common']))
import itsi_path
import itsi_py3
from itsi.content_packs.constants import ContentPackInstallOptions
from itsi.content_packs.journal import TransactionJournal
from itsi.itsi_utils import ITOAInterfaceUtils
from itsi.rest_handler import rest_interface_splunkd
from itsi.rest_handler.rest_interface_splunkd import route
class ContentPacksInterface(rest_interface_splunkd.BaseRestInterfaceSplunkd):
"""Handles ITSI Content Pack REST operations."""
@route('/{content_pack_id}/{version}/install', methods=['POST'])
def install(self, request, content_pack_id, version):
"""
Installs a content pack based on the given content pack id and version.
:param request: the request
:type request: Request
:param content_pack_id: the content pack id
:type content_pack_id: str
:param version: the content pack version
:type version: str
:return: a tuple of response status code, and data
:rtype: tuple of (int, object)
"""
from itsi.content_packs.installer import install, LOGGER, update_saved_searches_status
from itsi.content_packs.retriever import retrieve_one
try:
session_key = request.session['authtoken']
action = request.data.get(ContentPackInstallOptions.SAVED_SEARCH_ACTION,
ContentPackInstallOptions.SAVED_SEARCH_RETAIN_STATUS).lower()
install_all = request.data.get(ContentPackInstallOptions.INSTALL_ALL, False)
content_pack_name = ''
transaction_id = ''
if len(request.data.get(ContentPackInstallOptions.CONTENT)) > 0 or install_all:
try:
content_pack_name = retrieve_one(content_pack_id, version, session_key)['title']
except Exception as ex:
LOGGER.info(f'Failed to retrieve content pack name due to {ex}')
journal, transaction_id = install(
content_pack_id,
version,
session_key=session_key,
options=request.data
)
search_page_url = f'app/itsi/search?q=search%20index%3D_internal%20tid%3D{transaction_id}%20source%3D*itsi_content_packs_install.log*' \
'&display.page.search.mode=smart&dispatch.sample_ratio=1&workload_pool=&earliest=-24h%40h&latest=now'
installation_complete_message = f'Installation of {content_pack_name} is complete. [[{search_page_url}|View logs.]]'
ITOAInterfaceUtils.create_message(
session_key,
installation_complete_message,
name=f'{transaction_id}-installed',
role='itoa_admin'
)
else:
journal = TransactionJournal()
journal.success([])
journal.failure([])
saved_searches = update_saved_searches_status(
content_pack_id=content_pack_id,
session_key=session_key,
action=action
)
journal['saved_searches'] = saved_searches
except Exception as ex:
LOGGER.error('Failed install of content_pack_id="%s" version="%s"', content_pack_id, version)
LOGGER.exception(ex)
search_page_error_url = 'app/itsi/search?q=search%20index%3D_internal%20source%3D*itsi_content_packs_install.log*%20ERROR' \
'&display.page.search.mode=smart&dispatch.sample_ratio=1&workload_pool=&earliest=-24h%40h&latest=now'
if content_pack_name:
installation_failed_message = f'Installation of {content_pack_name} failed. [[{search_page_error_url}|View logs.]]'
else:
installation_failed_message = f'Installation of content pack with id {content_pack_id} failed. [[{search_page_error_url}|View logs.]]'
content_pack_name = content_pack_id
ITOAInterfaceUtils.create_message(
session_key,
installation_failed_message,
name=f'{content_pack_name}-failed-install',
role='itoa_admin'
)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
LOGGER.info(f'tid={transaction_id} {journal}')
return httplib.OK, journal
@route('', methods=['GET'])
def retrieve_all(self, request):
"""
Returns all content packs for the given request parameters.
:param request: the request
:type request: Request
:return: the content packs data
:rtype: dict
"""
from itsi.content_packs.retriever import retrieve_all, LOGGER
try:
items = retrieve_all(
getargs=request.query,
session_key=request.session['authtoken']
)
except Exception as ex:
LOGGER.exception(ex)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
return httplib.OK, {
'items': items
}
@route('/{content_pack_id}/{version}', methods=['GET'])
def retrieve_one(self, request, content_pack_id, version):
"""
Returns the content data for the given content pack id and version.
:param request: the request
:type request: Request
:param content_pack_id: the content pack id
:type content_pack_id: str
:param version: the content pack version
:type version: str
:return: the content packs data
:rtype: dict
"""
from itsi.content_packs.retriever import retrieve_one, LOGGER
try:
item = retrieve_one(
content_pack_id=content_pack_id,
version=version,
session_key=request.session['authtoken']
)
except Exception as ex:
LOGGER.exception(ex)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
return httplib.OK, item
@route('/{content_pack_id}/{version}/preview', methods=['GET'])
def preview(self, request, content_pack_id, version):
"""
Preview content pack objects based on the given content pack id and version.
:param request: the request
:type request: Request
:param content_pack_id: the content pack id
:type content_pack_id: str
:param version: the content pack version
:type version: str
:return: a tuple of response status code, and data
:rtype: tuple of (int, object)
"""
from itsi.content_packs.preview import preview, LOGGER
try:
item = preview(
content_pack_id=content_pack_id,
version=version,
session_key=request.session['authtoken']
)
except Exception as ex:
LOGGER.exception(ex)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
return httplib.OK, item
@route('/status', methods=['GET'])
def status(self, request):
"""
Returns all content packs status for the given request parameters, used for telemtry.
:param request: the request
:type request: Request
:return: the content packs data
:rtype: dict
"""
from itsi.content_packs.retriever import LOGGER
from itsi.objects.itsi_content_pack_status import ItsiContentPackStatus
import json
try:
installed_content_pack = ItsiContentPackStatus(
request.session['authtoken'], 'nobody'
).get_bulk('nobody', fields=['installed_versions', '_key'])
items = json.dumps(installed_content_pack)
except Exception as ex:
LOGGER.exception(ex)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
return httplib.OK, items
@route('/refresh', methods=['POST'])
def refresh_content_library(self, request):
"""
:param request: the request
:type request: Request
:return: apps added and removed from itsi_content_packs.conf
:rtype: dict
"""
from itsi.content_packs.content_library_refresh import refresh_using_configparser
from itsi.content_packs.retriever import LOGGER
from ITOA.setup_logging import setup_logging
try:
logger = setup_logging(
logger_name='itsi_content_pack_authorship.refresh',
logfile_name='itsi_content_pack_authorship.log'
)
payload = refresh_using_configparser(request.session['authtoken'], logger)
except Exception as ex:
LOGGER.exception(ex)
return httplib.INTERNAL_SERVER_ERROR, str(ex)
return httplib.OK, payload