Add cache to radius (#210)

This commit is contained in:
Firstyear 2020-05-08 17:16:33 +10:00 committed by GitHub
parent e08b5c14f5
commit d5c46545e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View file

@ -117,6 +117,8 @@ The config.ini has the following template:
dh = # Path to the radius servers dh params dh = # Path to the radius servers dh params
required_group = # name of a kanidm group which you must be a member of to required_group = # name of a kanidm group which you must be a member of to
# use radius. # use radius.
cache_path = # A path to an area where cached user records can be stored.
# If in doubt, use /dev/shm/kanidmradiusd
; [client.localhost] # client.<nas name> configures wifi/vpn consumers ; [client.localhost] # client.<nas name> configures wifi/vpn consumers
; ipaddr = # ipv4 or ipv6 address of the NAS ; ipaddr = # ipv4 or ipv6 address of the NAS
@ -146,6 +148,7 @@ A fully configured example is:
cert = /data/certs/cert.pem cert = /data/certs/cert.pem
dh = /data/certs/dh dh = /data/certs/dh
required_group = radius_access_allowed required_group = radius_access_allowed
cache_path = /dev/shm/kanidmradiusd
[client.localhost] [client.localhost]
ipaddr = 127.0.0.1 ipaddr = 127.0.0.1

View file

@ -18,6 +18,7 @@ key =
cert = cert =
dh = dh =
required_group = required_group =
cache_path =
; [client.localhost] ; [client.localhost]
; ipaddr = ; ipaddr =

View file

@ -2,6 +2,7 @@ import sys
import requests import requests
import logging import logging
import os import os
import json
MAJOR, MINOR, _, _, _ = sys.version_info MAJOR, MINOR, _, _, _ = sys.version_info
@ -33,6 +34,8 @@ else:
USER = CONFIG.get("kanidm_client", "user") USER = CONFIG.get("kanidm_client", "user")
SECRET = CONFIG.get("kanidm_client", "secret") SECRET = CONFIG.get("kanidm_client", "secret")
DEFAULT_VLAN = CONFIG.get("radiusd", "vlan") DEFAULT_VLAN = CONFIG.get("radiusd", "vlan")
CACHE_PATH = CONFIG.get("radiusd", "cache_path")
TIMEOUT = 8
URL = CONFIG.get('kanidm_client', 'url') URL = CONFIG.get('kanidm_client', 'url')
AUTH_URL = "%s/v1/auth" % URL AUTH_URL = "%s/v1/auth" % URL
@ -40,13 +43,13 @@ AUTH_URL = "%s/v1/auth" % URL
def _authenticate(s, acct, pw): def _authenticate(s, acct, pw):
init_auth = {"step": { "Init": [acct, None]}} init_auth = {"step": { "Init": [acct, None]}}
r = s.post(AUTH_URL, json=init_auth, verify=CA) r = s.post(AUTH_URL, json=init_auth, verify=CA, timeout=TIMEOUT)
if r.status_code != 200: if r.status_code != 200:
print(r.json()) print(r.json())
raise Exception("AuthInitFailed") raise Exception("AuthInitFailed")
cred_auth = {"step": { "Creds": [{"Password": pw}]}} cred_auth = {"step": { "Creds": [{"Password": pw}]}}
r = s.post(AUTH_URL, json=cred_auth, verify=CA) r = s.post(AUTH_URL, json=cred_auth, verify=CA, timeout=TIMEOUT)
if r.status_code != 200: if r.status_code != 200:
print(r.json()) print(r.json())
raise Exception("AuthCredFailed") raise Exception("AuthCredFailed")
@ -58,12 +61,40 @@ def _get_radius_token(username):
_authenticate(s, USER, SECRET) _authenticate(s, USER, SECRET)
# Now get the radius token # Now get the radius token
rtok_url = "%s/v1/account/%s/_radius/_token" % (URL, username) rtok_url = "%s/v1/account/%s/_radius/_token" % (URL, username)
r = s.get(rtok_url) r = s.get(rtok_url, verify=CA, timeout=TIMEOUT)
if r.status_code != 200: if r.status_code != 200:
raise Exception("Failed to get RadiusAuthToken") raise Exception("Failed to get RadiusAuthToken")
tok = r.json() tok = r.json()
return(tok) return(tok)
def _update_cache(token):
# Ensure the dir exists
try:
os.makedirs(CACHE_PATH, mode=0o700)
except:
# Already exists
pass
# User Item
item = os.path.join(CACHE_PATH, token["uuid"])
uitem = os.path.join(CACHE_PATH, token["name"])
# Token to json.
with open(item, 'w') as f:
json.dump(token, f)
# Symlink username -> uuid
try:
os.symlink(item, uitem)
except Exception as e:
print(e)
def _get_cache(username):
print("Getting cached token ...")
uitem = os.path.join(CACHE_PATH, username)
try:
with open(uitem, 'r') as f:
return json.load(f)
except:
None
def check_vlan(acc, group): def check_vlan(acc, group):
if CONFIG.has_section("group.%s" % group['name']): if CONFIG.has_section("group.%s" % group['name']):
if CONFIG.has_option("group.%s" % group['name'], "vlan"): if CONFIG.has_option("group.%s" % group['name'], "vlan"):
@ -84,10 +115,18 @@ def authorize(args):
username = dargs['User-Name'] username = dargs['User-Name']
tok = None
try: try:
tok = _get_radius_token(username) tok = _get_radius_token(username)
# Update the cache?
_update_cache(tok)
except Exception as e: except Exception as e:
print(e) print(e)
# Attempt the cache.
tok = _get_cache(username)
if tok == None:
return radiusd.RLM_MODULE_NOTFOUND return radiusd.RLM_MODULE_NOTFOUND
# print("got token %s" % tok) # print("got token %s" % tok)