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
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) |