#!/usr/bin/env python # coding=utf-8 __name__ = "trackme_rest_handler_licensing.py" __author__ = "TrackMe Limited" __copyright__ = "Copyright 2022-2026, TrackMe Limited, U.K." __credits__ = "TrackMe Limited, U.K." __license__ = "TrackMe Limited, all rights reserved" __version__ = "0.1.0" __maintainer__ = "TrackMe Limited, U.K." __email__ = "support@trackme-solutions.com" __status__ = "PRODUCTION" # Built-in libraries import json import os import re import sys from collections import OrderedDict # splunk home splunkhome = os.environ["SPLUNK_HOME"] # append current directory sys.path.append(os.path.dirname(os.path.abspath(__file__))) # import libs import import_declare_test # set logging from trackme_libs_logging import setup_logger logger = setup_logger( "trackme.rest.licensing_user", "trackme_rest_api_licensing_user.log" ) # Redirect global logging to use the same handler import logging logging.getLogger().handlers = logger.handlers logging.getLogger().setLevel(logger.level) # import rest handler import trackme_rest_handler # import trackme libs from trackme_libs import trackme_getloglevel, trackme_get_version # import trackme licensing libs from trackme_libs_licensing import ( trackme_return_license_status_offline, trackme_return_license_status_developer, ) # import trackme schema from trackme_libs_schema import trackme_schema_format_version # import Splunk libs import splunklib.client as client # import cryptolense from licensing.models import * from licensing.methods import Key, Helpers class TrackMeHandlerLicensingRead_v2(trackme_rest_handler.RESTHandler): def __init__(self, command_line, command_arg): super(TrackMeHandlerLicensingRead_v2, self).__init__( command_line, command_arg, logger ) def get_resource_group_desc_licensing(self, request_info, **kwargs): response = { "resource_group_name": "licensing", "resource_group_desc": "Endpoints for the purposes of license management (read only operations)", } return {"payload": response, "status": 200} # get the license status def get_license_status(self, request_info, **kwargs): describe = False # Retrieve from data try: resp_dict = json.loads(str(request_info.raw_args["payload"])) except Exception as e: resp_dict = None if resp_dict is not None: try: describe = resp_dict["describe"] if describe in ("true", "True"): describe = True except Exception as e: describe = False else: # body is not required in this endpoint, if not submitted do not describe the usage describe = False # if describe is requested, show the usage if describe: response = { "describe": "This endpoint verifies the status of the license, it requires a GET call with no options:", "resource_desc": "Get the license status", "resource_spl_example": '| trackme url="/services/trackme/v2/licensing/license_status" mode="get"', } return {"payload": response, "status": 200} # Get splunkd port splunkd_port = request_info.server_rest_port # Get service service = client.connect( owner="nobody", app="trackme", port=splunkd_port, token=request_info.system_authtoken, timeout=600, ) # set loglevel loglevel = trackme_getloglevel( request_info.system_authtoken, request_info.server_rest_port ) logger.setLevel(loglevel) # # get TrackMe version # # TrackMe version trackme_version = trackme_get_version(service) # get the schema_version_required schema_version_required = trackme_schema_format_version(trackme_version) # license limitations verifications: get the number of currently active tenants # Data collection collection_name = "kv_trackme_virtual_tenants" collection = service.kvstore[collection_name] # Get the current number of active tenants for licensing purposes query_string = { "tenant_status": "enabled", } try: vtenant_active_tenants = len( collection.data.query(query=json.dumps(query_string)) ) except Exception as e: vtenant_active_tenants = 0 # create a list of enabled tenants vtenant_active_tenants_list = [] for kvrecord in collection.data.query(query=json.dumps(query_string)): vtenant_active_tenants_list.append(kvrecord.get("tenant_id")) # Count the total number of active hybrid trackers hybrid_trackers = [] splk_components = [ "tenant_dsm_hybrid_objects", "tenant_dhm_hybrid_objects", "tenant_mhm_hybrid_objects", ] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: hybrid_record = kvrecord.get(splk_component) if hybrid_record: hybrid_record = json.loads(hybrid_record) hybrid_reports = hybrid_record.get("reports") if hybrid_reports: for report in hybrid_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): hybrid_trackers.append(report) # Count the number of active hybrid trackers for splk-dsm splk_dsm_hybrid_trackers = [] splk_components = ["tenant_dsm_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: hybrid_record = kvrecord.get(splk_component) if hybrid_record: hybrid_record = json.loads(hybrid_record) hybrid_reports = hybrid_record.get("reports") if hybrid_reports: for report in hybrid_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): splk_dsm_hybrid_trackers.append(report) # Count the number of active hybrid trackers for splk-dhm splk_dhm_hybrid_trackers = [] splk_components = ["tenant_dhm_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: hybrid_record = kvrecord.get(splk_component) if hybrid_record: hybrid_record = json.loads(hybrid_record) hybrid_reports = hybrid_record.get("reports") if hybrid_reports: for report in hybrid_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): splk_dhm_hybrid_trackers.append(report) # Count the number of active hybrid trackers for splk-mhm splk_mhm_hybrid_trackers = [] splk_components = ["tenant_mhm_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: hybrid_record = kvrecord.get(splk_component) if hybrid_record: hybrid_record = json.loads(hybrid_record) hybrid_reports = hybrid_record.get("reports") if hybrid_reports: for report in hybrid_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): splk_mhm_hybrid_trackers.append(report) # Count the number of active flex trackers flex_trackers = [] splk_components = ["tenant_flx_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: flex_tracker = kvrecord.get(splk_component) if flex_tracker: flex_tracker = json.loads(flex_tracker) flex_reports = flex_tracker.get("reports") if flex_reports: for report in flex_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): flex_trackers.append(report) # Count the number of active fqm trackers fqm_trackers = [] splk_components = ["tenant_fqm_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: fqm_tracker = kvrecord.get(splk_component) if fqm_tracker: fqm_tracker = json.loads(fqm_tracker) fqm_reports = fqm_tracker.get("reports") if fqm_reports: for report in fqm_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): fqm_trackers.append(report) # Count the number of active wlk trackers wlk_trackers = [] splk_components = ["tenant_wlk_hybrid_objects"] for kvrecord in collection.data.query(query=json.dumps(query_string)): for splk_component in splk_components: wlk_tracker = kvrecord.get(splk_component) if wlk_tracker: wlk_tracker = json.loads(wlk_tracker) wlk_reports = wlk_tracker.get("reports") if wlk_reports: for report in wlk_reports: if re.search(r"_tracker_", report) and not re.search( r"_abstract_|_wrapper_", report ): wlk_trackers.append(report) # # check license # try: collection_name = "kv_trackme_license_key" collection = service.kvstore[collection_name] # Get the current record # Notes: the record is returned as an array, as we search for a specific record, we expect one record only try: kvrecord = collection.data.query()[0] key = kvrecord.get("_key") license_string = kvrecord.get("license_string") license_type = kvrecord.get("license_type") except Exception as e: key = None if key: # if license is subscription based if license_type == "subscription": logger.debug("check license from signature") response = trackme_return_license_status_offline(license_string) # get license_subscription_class license_features = response.get("license_features") license_subscription_class = None try: enterprise = license_features[0].get("enterprise") if enterprise == "True": enterprise = True else: enterprise = False except Exception as e: enterprise = False try: unlimited = license_features[0].get("unlimited") if unlimited == "True": unlimited = True else: unlimited = False except Exception as e: unlimited = False try: free_extended = license_features[0].get("free_extended") if free_extended == "True": free_extended = True else: free_extended = False except Exception as e: free_extended = False if unlimited: license_subscription_class = "unlimited" elif enterprise: license_subscription_class = "enterprise" elif free_extended: license_subscription_class = "free_extended" # in case we failed, this could only happen for an already registered license before we # introduced the distinction between unlimited and enteprise else: license_subscription_class = "unlimited" # add to response response["license_subscription_class"] = license_subscription_class # add to response response["license_type"] = "subscription" # add to response response["license_active_tenants"] = vtenant_active_tenants # add to response response["license_active_tenants_list"] = ( vtenant_active_tenants_list ) # add to response response["license_active_hybrid_trackers"] = len(hybrid_trackers) # add to response response["license_active_hybrid_trackers_list"] = hybrid_trackers # dsm # add to response response["license_active_splk_dsm_hybrid_trackers"] = len( splk_dsm_hybrid_trackers ) # add to response response["license_active_splk_dsm_hybrid_trackers_list"] = ( splk_dsm_hybrid_trackers ) # dhm # add to response response["license_active_splk_dhm_hybrid_trackers"] = len( splk_dhm_hybrid_trackers ) # add to response response["license_active_splk_dhm_hybrid_trackers_list"] = ( splk_dhm_hybrid_trackers ) # mhm # add to response response["license_active_splk_mhm_hybrid_trackers"] = len( splk_mhm_hybrid_trackers ) # add to response response["license_active_splk_mhm_hybrid_trackers_list"] = ( splk_mhm_hybrid_trackers ) # flex # add to response response["license_active_flex_trackers"] = len(flex_trackers) # add to response response["license_active_flex_trackers_list"] = flex_trackers # fqm # add to response response["license_active_fqm_trackers"] = len(fqm_trackers) # add to response response["license_active_fqm_trackers_list"] = fqm_trackers # wlk # add to response response["license_active_wlk_trackers"] = len(wlk_trackers) # add to response response["license_active_wlk_trackers_list"] = wlk_trackers # add TrackMe version & schema_version_required response["trackme_version"] = trackme_version response["schema_version_required"] = schema_version_required elif license_type == "trial": logger.debug("check license from signature") response = trackme_return_license_status_offline(license_string) # add to response response["license_type"] = "trial" # add to response response["license_active_tenants"] = vtenant_active_tenants # add to response response["license_active_tenants_list"] = ( vtenant_active_tenants_list ) # add to response response["license_active_hybrid_trackers"] = len(hybrid_trackers) # add to response response["license_active_hybrid_trackers_list"] = hybrid_trackers # dsm # add to response response["license_active_splk_dsm_hybrid_trackers"] = len( splk_dsm_hybrid_trackers ) # add to response response["license_active_splk_dsm_hybrid_trackers_list"] = ( splk_dsm_hybrid_trackers ) # dhm # add to response response["license_active_splk_dhm_hybrid_trackers"] = len( splk_dhm_hybrid_trackers ) # add to response response["license_active_splk_dhm_hybrid_trackers_list"] = ( splk_dhm_hybrid_trackers ) # mhm # add to response response["license_active_splk_mhm_hybrid_trackers"] = len( splk_mhm_hybrid_trackers ) # add to response response["license_active_splk_mhm_hybrid_trackers_list"] = ( splk_mhm_hybrid_trackers ) # flex # add to response response["license_active_flex_trackers"] = len(flex_trackers) # add to response response["license_active_flex_trackers_list"] = flex_trackers # fqm # add to response response["license_active_fqm_trackers"] = len(fqm_trackers) # add to response response["license_active_fqm_trackers_list"] = fqm_trackers # wlk # add to response response["license_active_wlk_trackers"] = len(wlk_trackers) # add to response response["license_active_wlk_trackers_list"] = wlk_trackers # add TrackMe version & schema_version_required response["trackme_version"] = trackme_version response["schema_version_required"] = schema_version_required elif license_type == "developer": logger.debug("check license from signature") response = trackme_return_license_status_developer(license_string) # add to response response["license_type"] = "developer" # add to response response["license_active_tenants"] = vtenant_active_tenants # add to response response["license_active_tenants_list"] = ( vtenant_active_tenants_list ) # add to response response["license_active_hybrid_trackers"] = len(hybrid_trackers) # add to response response["license_active_hybrid_trackers_list"] = hybrid_trackers # dsm # add to response response["license_active_splk_dsm_hybrid_trackers"] = len( splk_dsm_hybrid_trackers ) # add to response response["license_active_splk_dsm_hybrid_trackers_list"] = ( splk_dsm_hybrid_trackers ) # dhm # add to response response["license_active_splk_dhm_hybrid_trackers"] = len( splk_dhm_hybrid_trackers ) # add to response response["license_active_splk_dhm_hybrid_trackers_list"] = ( splk_dhm_hybrid_trackers ) # mhm # add to response response["license_active_splk_mhm_hybrid_trackers"] = len( splk_mhm_hybrid_trackers ) # add to response response["license_active_splk_mhm_hybrid_trackers_list"] = ( splk_mhm_hybrid_trackers ) # flex # add to response response["license_active_flex_trackers"] = len(flex_trackers) # add to response response["license_active_flex_trackers_list"] = flex_trackers # fqm # add to response response["license_active_fqm_trackers"] = len(fqm_trackers) # add to response response["license_active_fqm_trackers_list"] = fqm_trackers # wlk # add to response response["license_active_wlk_trackers"] = len(wlk_trackers) # add to response response["license_active_wlk_trackers_list"] = wlk_trackers # add TrackMe version & schema_version_required response["trackme_version"] = trackme_version response["schema_version_required"] = schema_version_required return {"payload": response, "status": 200} else: response = { "action": "success", "license_is_valid": 0, "message": "This TrackMe deployment is currently unregistered, and running in free limited edition mode", } # add to response response["license_active_tenants"] = vtenant_active_tenants # add to response response["license_active_tenants_list"] = vtenant_active_tenants_list # add to response response["license_active_hybrid_trackers"] = len(hybrid_trackers) # add to response response["license_active_hybrid_trackers_list"] = hybrid_trackers # add to response response["license_active_splk_dsm_hybrid_trackers"] = len( splk_dsm_hybrid_trackers ) # add to response response["license_active_splk_dsm_hybrid_trackers_list"] = ( splk_dsm_hybrid_trackers ) # add to response response["license_active_splk_dhm_hybrid_trackers"] = len( splk_dhm_hybrid_trackers ) # add to response response["license_active_splk_dhm_hybrid_trackers_list"] = ( splk_dhm_hybrid_trackers ) # add to response response["license_active_splk_mhm_hybrid_trackers"] = len( splk_mhm_hybrid_trackers ) # add to response response["license_active_splk_mhm_hybrid_trackers_list"] = ( splk_mhm_hybrid_trackers ) # add TrackMe version & schema_version_required response["trackme_version"] = trackme_version response["schema_version_required"] = schema_version_required return {"payload": response, "status": 200} except Exception as e: response = { "action": "failure", "message": "An exception was encountered while checking the license status, license status could not be verified.", "exception": str(e), } return {"payload": response, "status": 500}