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.

97 lines
3.9 KiB

# Copyright (C) 2005-2021 Splunk Inc. All Rights Reserved.
import sys
try:
from urllib.request import urlopen, Request, build_opener
except ImportError:
from urllib2 import urlopen, Request, build_opener
from splunk import getDefault
import splunk.admin as admin
from splunk.entity import controlEntity
from splunk.clilib.bundle_paths import make_splunkhome_path
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-Hydra-inframon', 'bin']))
import hydra_inframon
from hydra_inframon.models import HydraGatewayStanza
logger = hydra_inframon.setupLogger(log_format='%(asctime)s %(levelname)s [HydraGatekeeper] %(message)s', level="INFO",
log_name="hydra_inframon_gatekeeper.log", logger_name="hydra_inframon-gatekeeper")
class HydraGatekeeperHandler(admin.MConfigHandler):
def setup(self):
pass
def handleList(self, confInfo):
"""
Provide an authentication proxy for the hydra gateway service, as a
side effect validate the gateway is turned on and running properly.
If the gateway is either not on or configured properly return an key
value of DEFER indicating a client should wait before reauthenticating.
"""
# Get the hydra gateway config
stanza = HydraGatewayStanza.from_name("gateway", "SA-Hydra-inframon", session_key=self.getSessionKey())
if stanza is not None and stanza.port is not None:
port = stanza.port
else:
port = 8008
gateway_uri = "https://" + getDefault("host") + ":" + str(port)
#Get the Key File
challenge_key, auth_key = self.get_keys()
#Validate System
if not self.validate_challenge_key(gateway_uri, challenge_key):
#Gateway failed challenge and must be restarted
logger.warning(
"gateway failed challenge validation and will be restarted, deferring current authentication request")
self.restart_gateway()
#Let the client know they need to re-authenticate
auth_key = "DEFER"
#Return the gateway information
gateway = confInfo["hydra_gateway"]
gateway['key'] = auth_key
def get_keys(self):
"""
Read the challenge and auth keys from the filesystem
RETURNS tuple of challenge and auth keys
"""
try:
with open(make_splunkhome_path(["etc", "apps", "SA-Hydra-inframon", "local", "run", "hydra_gateway.key"]), 'r') as f:
challenge_key = f.readline().strip("\r\n")
auth_key = f.readline().strip("\r\n")
return (challenge_key, auth_key)
except IOError:
return ("", "")
def validate_challenge_key(self, gateway_uri, key):
"""
Challenge the local gateway on the expected port and ensure that it is
running under the proper configuration
RETURNS True if challenge passes, False otherwise.
"""
try:
opener = build_opener()
req = Request(gateway_uri + "/hydra/admin/challenge")
resp = opener.open(req)
gateway_challenge_key = resp.read().decode('utf-8').strip("\r\n")
return gateway_challenge_key == key
except Exception as e:
logger.exception("[ValidateChallengeKey] could not validate hydra gateway challenge: %s", str(e))
return False
def restart_gateway(self):
"""
Restart the gateway by disabling and enabling the scripted input process
"""
input_uri = '/servicesNS/nobody/SA-Hydra-inframon/data/inputs/script/%24SPLUNK_HOME%252Fetc%252Fapps%252FSA-Hydra-inframon%252Fbin%252Fbootstrap_hydra_gateway.py/'
controlEntity('disable', input_uri + "disable", sessionKey=self.getSessionKey())
controlEntity('enable', input_uri + "enable", sessionKey=self.getSessionKey())
admin.init(HydraGatekeeperHandler, admin.CONTEXT_NONE)