mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-28 20:39:40 +00:00
Implement offload of compute-intensive authentication.
With this change, an instance under pressure from new or bad authentication attempts will continue to be viable to authenticated sessions and clients with tokens (e.g. any http client that honors cookies).
This commit is contained in:
parent
7d9b355bed
commit
c514c2c121
21
TODO
21
TODO
@ -1,11 +1,3 @@
|
||||
-user can bog down all requests by hammering it with bad auth requests causing
|
||||
the auth facility to get bogged down in PBKDF
|
||||
Option:
|
||||
-a multiprocessing pool to handle new authentications. The auth action
|
||||
itself would be stalled out whilst an attack was underway, but once
|
||||
in, the respective session layers will provide a caching session that
|
||||
should accelerate things after the client gets in once
|
||||
-penalizing a client clearly trying to break in
|
||||
-other auth
|
||||
-pam if user exists but has no passphrase
|
||||
-keystone?
|
||||
@ -14,13 +6,6 @@
|
||||
-When a user account is changed, have httpapi and sockapi notified of changes
|
||||
to kill off related sessions. password changes are given a pass, but user
|
||||
deletion will result in immediate session termination
|
||||
-need event notification for config change- e.g. set attribute triggers consol
|
||||
session object check to see if credentials changed
|
||||
design is that calling code on init registers a callback for related node to
|
||||
the in-context config manager object. callback shall be OO so no context
|
||||
object parametr passed in. ipmi will use it for user/password/hardwaremanagement.manager
|
||||
changes to console and command objects. console will use it to hook add/deletion
|
||||
of nodes and/or indicating a different console.method or hardwaremanagement.method
|
||||
-When the time comes to dole out configuration/discovery, take page from xCAT
|
||||
'flexdiscover' command, if possible bring an ipmi device under management
|
||||
by way of ipv6 to eliminate requirement for ip to be specified.
|
||||
@ -40,8 +25,4 @@ Traceback (most recent call last):
|
||||
KeyError: ''
|
||||
|
||||
|
||||
-have pyghmi and friends do multiprocessing pools (particularly the PBKDF stuff in auth)
|
||||
-have console sessions be instructed as to more specific clue for unconnected
|
||||
-misconfigured - console.method probably not set right
|
||||
-unreachable - hardwaremanagement.manager probably wrong
|
||||
-authentication failure - user/passphrase probable not right
|
||||
-have pyghmi and friends do multiprocessing pools
|
@ -21,14 +21,18 @@
|
||||
|
||||
import confluent.config.configmanager as configmanager
|
||||
import eventlet
|
||||
import eventlet.tpool
|
||||
import Crypto.Protocol.KDF as KDF
|
||||
import hashlib
|
||||
import hmac
|
||||
import multiprocessing
|
||||
import time
|
||||
|
||||
_passcache = {}
|
||||
_passchecking = {}
|
||||
|
||||
authworkers = None
|
||||
|
||||
|
||||
def _prune_passcache():
|
||||
# This function makes sure we don't remember a passphrase in memory more
|
||||
@ -143,9 +147,13 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False):
|
||||
# throw it at the worker pool when implemented
|
||||
# maybe a distinct worker pool, wondering about starving out non-auth stuff
|
||||
salt, crypt = ucfg['cryptpass']
|
||||
crypted = KDF.PBKDF2(passphrase, salt, 32, 10000,
|
||||
lambda p, s: hmac.new(p, s, hashlib.sha256).digest()
|
||||
)
|
||||
# execute inside tpool to get greenthreads to give it a special thread
|
||||
# world
|
||||
#TODO(jbjohnso): util function to generically offload a call
|
||||
#such a beast could be passed into pyghmi as a way for pyghmi to
|
||||
#magically get offload of the crypto functions without having
|
||||
#to explicitly get into the eventlet tpool game
|
||||
crypted = eventlet.tpool.execute(_do_pbkdf, passphrase, salt)
|
||||
del _passchecking[(user, tenant)]
|
||||
eventlet.sleep(0.05) # either way, we want to stall so that client can't
|
||||
# determine failure because there is a delay, valid response will
|
||||
@ -154,3 +162,26 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False):
|
||||
_passcache[(user, tenant)] = passphrase
|
||||
return authorize(user, element, tenant)
|
||||
return None
|
||||
|
||||
|
||||
def _apply_pbkdf(passphrase, salt):
|
||||
return KDF.PBKDF2(passphrase, salt, 32, 10000,
|
||||
lambda p, s: hmac.new(p, s, hashlib.sha256).digest())
|
||||
|
||||
|
||||
def _do_pbkdf(passphrase, salt):
|
||||
# we must get it over to the authworkers pool or else get blocked in
|
||||
# compute. However, we do want to wait for result, so we have
|
||||
# one of the exceedingly rare sort of circumstances where 'apply'
|
||||
# actually makes sense
|
||||
return authworkers.apply(_apply_pbkdf, [passphrase, salt])
|
||||
|
||||
|
||||
def init_auth():
|
||||
# have a some auth workers available. Keep them distinct from
|
||||
# the general populace of workers to avoid unauthorized users
|
||||
# starving out productive work
|
||||
global authworkers
|
||||
# for now we'll just have one auth worker and see if there is any
|
||||
# demand for more. I personally doubt it.
|
||||
authworkers = multiprocessing.Pool(processes=1)
|
@ -25,6 +25,7 @@
|
||||
# It also will optionally snoop SLP DA requests
|
||||
|
||||
import atexit
|
||||
import confluent.auth as auth
|
||||
import confluent.consoleserver as consoleserver
|
||||
import confluent.pluginapi as pluginapi
|
||||
import confluent.httpapi as httpapi
|
||||
@ -111,6 +112,7 @@ def run():
|
||||
pluginapi.load_plugins()
|
||||
_daemonize()
|
||||
_updatepidfile()
|
||||
auth.init_auth()
|
||||
signal.signal(signal.SIGINT, terminate)
|
||||
signal.signal(signal.SIGTERM, terminate)
|
||||
#TODO(jbjohnso): eventlet has a bug about unix domain sockets, this code
|
||||
|
Loading…
Reference in New Issue
Block a user