Compare commits
6 Commits
34fe2694eb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2999b4b0ce | |||
| e2594bc66d | |||
| 38e208642a | |||
| 8ff792cffc | |||
| 50d9c060dd | |||
| 9c21be41c0 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,3 @@
|
|||||||
.venv
|
.venv
|
||||||
detelete_old_clients_ds/output/
|
delete_old_clients_ds/output/
|
||||||
detelete_old_clients_ds/detelete_old_clients_ds-*.tar.gz
|
delete_old_clients_ds/delete_old_clients_ds-*.tar.gz
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Splunk Add-on to delete old clients from Deployment Server
|
|
||||||
|
|
||||||
Interesting Commands:
|
|
||||||
- Build Add-on: ucc-gen build --ta-version="Tag version"
|
|
||||||
- Package Add-on:ucc-gen package -o . --path "path to output/app.manifest"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# detelete_old_clients_ds
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
{
|
|
||||||
"pages": {
|
|
||||||
"configuration": {
|
|
||||||
"tabs": [
|
|
||||||
{
|
|
||||||
"name": "account",
|
|
||||||
"table": {
|
|
||||||
"actions": [
|
|
||||||
"edit",
|
|
||||||
"delete",
|
|
||||||
"clone"
|
|
||||||
],
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"label": "Name",
|
|
||||||
"field": "name"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"entity": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"label": "Name",
|
|
||||||
"validators": [
|
|
||||||
{
|
|
||||||
"type": "regex",
|
|
||||||
"errorMsg": "Account Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.",
|
|
||||||
"pattern": "^[a-zA-Z]\\w*$"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"errorMsg": "Length of input name should be between 1 and 100",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 100
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"field": "name",
|
|
||||||
"help": "A unique name for the account.",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"label": "Username",
|
|
||||||
"field": "username",
|
|
||||||
"help": "Deployment server username",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"label": "Password",
|
|
||||||
"field": "password",
|
|
||||||
"help": "Password",
|
|
||||||
"required": true,
|
|
||||||
"encrypted": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "Accounts"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "loggingTab"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "Configuration",
|
|
||||||
"description": "Set up your add-on"
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"title": "Inputs",
|
|
||||||
"description": "Manage your data inputs",
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"name": "example_input_one",
|
|
||||||
"title": "Example Input",
|
|
||||||
"entity": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"label": "Deployment Server URL",
|
|
||||||
"field": "url",
|
|
||||||
"help": "URL of the DS instance",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "interval",
|
|
||||||
"field": "interval",
|
|
||||||
"label": "Interval",
|
|
||||||
"help": "Time interval of the data input, in seconds .",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"table": {
|
|
||||||
"actions": [
|
|
||||||
"edit",
|
|
||||||
"enable",
|
|
||||||
"delete",
|
|
||||||
"search",
|
|
||||||
"clone"
|
|
||||||
],
|
|
||||||
"header": [],
|
|
||||||
"moreInfo": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dashboard": {
|
|
||||||
"panels": [
|
|
||||||
{
|
|
||||||
"name": "default"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"name": "delete_old_clients_ds",
|
|
||||||
"restRoot": "delete_old_clients_ds",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"displayName": "DS Add-on Delete old clients",
|
|
||||||
"schemaVersion": "0.0.7",
|
|
||||||
"_uccVersion": "5.46.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": "2.0.0",
|
|
||||||
"info": {
|
|
||||||
"title": "DS Add-on Delete old clients",
|
|
||||||
"id": {
|
|
||||||
"group": null,
|
|
||||||
"name": "delete_old_clients_ds",
|
|
||||||
"version": "0.0.1"
|
|
||||||
},
|
|
||||||
"author": [
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"email": null,
|
|
||||||
"company": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"releaseDate": null,
|
|
||||||
"description": "DS Add-on Delete old clients",
|
|
||||||
"classification": {
|
|
||||||
"intendedAudience": "IT Professionals",
|
|
||||||
"categories": [
|
|
||||||
"Security, Fraud & Compliance"
|
|
||||||
],
|
|
||||||
"developmentStatus": "Production/Stable"
|
|
||||||
},
|
|
||||||
"commonInformationModels": null,
|
|
||||||
"license": {
|
|
||||||
"name": null,
|
|
||||||
"text": "LICENSE.txt",
|
|
||||||
"uri": null
|
|
||||||
},
|
|
||||||
"privacyPolicy": {
|
|
||||||
"name": null,
|
|
||||||
"text": null,
|
|
||||||
"uri": null
|
|
||||||
},
|
|
||||||
"releaseNotes": {
|
|
||||||
"name": "README",
|
|
||||||
"text": "README.txt",
|
|
||||||
"uri": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": null,
|
|
||||||
"tasks": null,
|
|
||||||
"inputGroups": null,
|
|
||||||
"incompatibleApps": null,
|
|
||||||
"platformRequirements": null,
|
|
||||||
"supportedDeployments": [
|
|
||||||
"_standalone",
|
|
||||||
"_distributed",
|
|
||||||
"_search_head_clustering"
|
|
||||||
],
|
|
||||||
"targetWorkloads": [
|
|
||||||
"_search_heads",
|
|
||||||
"_indexers"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import import_declare_test
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from splunklib import modularinput as smi
|
|
||||||
from delete_old_clients_ds_helper import stream_events, validate_input
|
|
||||||
|
|
||||||
|
|
||||||
class DELETE_OLD_CLIENTS_DS(smi.Script):
|
|
||||||
def __init__(self):
|
|
||||||
super(DELETE_OLD_CLIENTS_DS, self).__init__()
|
|
||||||
|
|
||||||
def get_scheme(self):
|
|
||||||
scheme = smi.Scheme('delete_old_clients_ds')
|
|
||||||
scheme.description = 'demo_input input'
|
|
||||||
scheme.use_external_validation = True
|
|
||||||
scheme.streaming_mode_xml = True
|
|
||||||
scheme.use_single_instance = False
|
|
||||||
|
|
||||||
scheme.add_argument(
|
|
||||||
smi.Argument(
|
|
||||||
'name',
|
|
||||||
title='Name',
|
|
||||||
description='Name',
|
|
||||||
required_on_create=True
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return scheme
|
|
||||||
|
|
||||||
def validate_input(self, definition: smi.ValidationDefinition):
|
|
||||||
return validate_input(definition)
|
|
||||||
|
|
||||||
def stream_events(self, inputs: smi.InputDefinition, ew: smi.EventWriter):
|
|
||||||
return stream_events(inputs, ew)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
exit_code = DELETE_OLD_CLIENTS_DS().run(sys.argv)
|
|
||||||
sys.exit(exit_code)
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import json
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import import_declare_test
|
|
||||||
from solnlib import conf_manager, log
|
|
||||||
from splunklib import modularinput as smi
|
|
||||||
|
|
||||||
|
|
||||||
ADDON_NAME = "detelete_old_clients_ds"
|
|
||||||
|
|
||||||
|
|
||||||
def logger_for_input(input_name: str) -> logging.Logger:
|
|
||||||
return log.Logs().get_logger(f"{ADDON_NAME.lower()}_{input_name}")
|
|
||||||
|
|
||||||
|
|
||||||
def get_account_api_key(session_key: str, account_name: str):
|
|
||||||
cfm = conf_manager.ConfManager(
|
|
||||||
session_key,
|
|
||||||
ADDON_NAME,
|
|
||||||
realm=f"__REST_CREDENTIAL__#{ADDON_NAME}#configs/conf-detelete_old_clients_ds_account",
|
|
||||||
)
|
|
||||||
account_conf_file = cfm.get_conf("detelete_old_clients_ds_account")
|
|
||||||
return account_conf_file.get(account_name).get("api_key")
|
|
||||||
|
|
||||||
|
|
||||||
def get_data_from_api(logger: logging.Logger, api_key: str):
|
|
||||||
logger.info("Getting data from an external API")
|
|
||||||
dummy_data = [
|
|
||||||
{
|
|
||||||
"line1": "hello",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"line2": "world",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
return dummy_data
|
|
||||||
|
|
||||||
|
|
||||||
def validate_input(definition: smi.ValidationDefinition):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def stream_events(inputs: smi.InputDefinition, event_writer: smi.EventWriter):
|
|
||||||
# inputs.inputs is a Python dictionary object like:
|
|
||||||
# {
|
|
||||||
# "delete_old_clients_ds://<input_name>": {
|
|
||||||
# "account": "<account_name>",
|
|
||||||
# "disabled": "0",
|
|
||||||
# "host": "$decideOnStartup",
|
|
||||||
# "index": "<index_name>",
|
|
||||||
# "interval": "<interval_value>",
|
|
||||||
# "python.version": "python3",
|
|
||||||
# },
|
|
||||||
# }
|
|
||||||
for input_name, input_item in inputs.inputs.items():
|
|
||||||
normalized_input_name = input_name.split("/")[-1]
|
|
||||||
logger = logger_for_input(normalized_input_name)
|
|
||||||
try:
|
|
||||||
session_key = inputs.metadata["session_key"]
|
|
||||||
log_level = conf_manager.get_log_level(
|
|
||||||
logger=logger,
|
|
||||||
session_key=session_key,
|
|
||||||
app_name=ADDON_NAME,
|
|
||||||
conf_name=f"{ADDON_NAME}_settings",
|
|
||||||
)
|
|
||||||
logger.setLevel(log_level)
|
|
||||||
log.modular_input_start(logger, normalized_input_name)
|
|
||||||
api_key = get_account_api_key(session_key, input_item.get("account"))
|
|
||||||
data = get_data_from_api(logger, api_key)
|
|
||||||
sourcetype = "dummy-data"
|
|
||||||
for line in data:
|
|
||||||
event_writer.write_event(
|
|
||||||
smi.Event(
|
|
||||||
data=json.dumps(line, ensure_ascii=False, default=str),
|
|
||||||
index=input_item.get("index"),
|
|
||||||
sourcetype=sourcetype,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
log.events_ingested(
|
|
||||||
logger,
|
|
||||||
normalized_input_name,
|
|
||||||
sourcetype,
|
|
||||||
len(data),
|
|
||||||
input_item.get("index"),
|
|
||||||
account=input_item.get("account"),
|
|
||||||
)
|
|
||||||
log.modular_input_end(logger, normalized_input_name)
|
|
||||||
except Exception as e:
|
|
||||||
log.log_exception(logger, e, "my custom error type", msg_before="Exception raised while ingesting data for demo_input: ")
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
class deleteClientDS():
|
|
||||||
def __init__(self):
|
|
||||||
deployment_server = os.getenv('SPLUNK_DS')
|
|
||||||
splunk_username = os.getenv('SPLUNK_DS_USER')
|
|
||||||
splunk_password = os.getenv('SPLUNK_DS_PASS')
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
splunktaucclib
|
|
||||||
splunk-sdk
|
|
||||||
solnlib
|
|
||||||
61
removeOldClientsDS.py
Normal file
61
removeOldClientsDS.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import time
|
||||||
|
import splunklib.client as client
|
||||||
|
from splunklib.results import JSONResultsReader
|
||||||
|
from splunklib.binding import HTTPError
|
||||||
|
|
||||||
|
def connectSplunk():
|
||||||
|
HOST = "10.218.7.194"
|
||||||
|
PORT = 8089
|
||||||
|
USERNAME = "" # Configurar como variable de entorno
|
||||||
|
PASSWORD = "" # Configurar como variable de entorno
|
||||||
|
|
||||||
|
try:
|
||||||
|
service = client.connect(host=HOST, port=PORT, username=USERNAME, password=PASSWORD)
|
||||||
|
print(service.token)
|
||||||
|
return service
|
||||||
|
except Exception as e:
|
||||||
|
print(f'An error occurred while connecting to Splunk: {e}')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def searchOldClient(service):
|
||||||
|
search = ('| rest splunk_server=local /services/deployment/server/clients '
|
||||||
|
'| eval last_seen = now() - lastPhoneHomeTime '
|
||||||
|
'| where last_seen > 86400 '
|
||||||
|
'| rename clientName as guid '
|
||||||
|
'| fields guid')
|
||||||
|
try:
|
||||||
|
service.parse(search, parse_only=True)
|
||||||
|
except HTTPError as e:
|
||||||
|
print(f"query '{search}' is invalid:\n\t{str(e)}")
|
||||||
|
return
|
||||||
|
|
||||||
|
job = service.jobs.create(search)
|
||||||
|
while not job.is_done():
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
result_stream = job.results(output_mode='json')
|
||||||
|
results_reader = JSONResultsReader(result_stream)
|
||||||
|
|
||||||
|
guids = list()
|
||||||
|
for result in results_reader:
|
||||||
|
if isinstance(result, dict) and 'guid' in result:
|
||||||
|
guids.append(result['guid'])
|
||||||
|
|
||||||
|
return guids
|
||||||
|
|
||||||
|
def remove_client(service, guid):
|
||||||
|
print(f'Removing: {guid}')
|
||||||
|
endpoint = f'/services/deployment/server/clients/{guid}'
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = service.delete(endpoint)
|
||||||
|
print(f'Status: {response.status}')
|
||||||
|
except HTTPError as e:
|
||||||
|
print(f'Failed to remove client {guid}: {str(e)}')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
service = connectSplunk()
|
||||||
|
if service:
|
||||||
|
old_clients = searchOldClient(service)
|
||||||
|
for guid in old_clients:
|
||||||
|
remove_client(service, guid)
|
||||||
3
test.py
3
test.py
@@ -2,7 +2,7 @@ import requests
|
|||||||
|
|
||||||
deployment_server = "10.218.7.194"
|
deployment_server = "10.218.7.194"
|
||||||
splunk_username = "usr-splunkadm"
|
splunk_username = "usr-splunkadm"
|
||||||
splunk_password = "5_jXFo5C9.W2P8!6JVt.U_oX10S2v5"
|
splunk_password = ""
|
||||||
ds_auth = (splunk_username, splunk_password)
|
ds_auth = (splunk_username, splunk_password)
|
||||||
|
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ def find_old_clients():
|
|||||||
'| rename clientName as guid '
|
'| rename clientName as guid '
|
||||||
'| fields guid')
|
'| fields guid')
|
||||||
data = { 'search': search }
|
data = { 'search': search }
|
||||||
|
print(data)
|
||||||
header = {
|
header = {
|
||||||
'Content-Type: application/json'
|
'Content-Type: application/json'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user