Skip to content

Commit e71d4f3

Browse files
porting PR sonic-net#8223, which uses one shot timer to reaload tacacs config
1 parent 2ed7f53 commit e71d4f3

File tree

1 file changed

+72
-37
lines changed

1 file changed

+72
-37
lines changed

files/image_config/hostcfgd/hostcfgd

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# -*- coding: utf-8 -*-
33

44
import os
5+
import threading
56
import sys
67
import subprocess
78
import syslog
@@ -22,6 +23,20 @@ TACPLUS_SERVER_PASSKEY_DEFAULT = ""
2223
TACPLUS_SERVER_TIMEOUT_DEFAULT = "5"
2324
TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap"
2425

26+
global_lock = None
27+
28+
class lock_mgr:
29+
def __init__(self):
30+
self.lock = global_lock
31+
32+
def __enter__( self ):
33+
if self.lock:
34+
self.lock.acquire()
35+
36+
def __exit__( self, exc_type, exc_value, traceback ):
37+
if self.lock:
38+
self.lock.release()
39+
2540

2641
def is_true(val):
2742
if val == 'True' or val == 'true':
@@ -118,7 +133,7 @@ class Iptables(object):
118133
.format(err.cmd, err.returncode, err.output))
119134

120135
class AaaCfg(object):
121-
def __init__(self):
136+
def __init__(self, config_db):
122137
self.auth_default = {
123138
'login': 'local',
124139
}
@@ -131,49 +146,42 @@ class AaaCfg(object):
131146
self.tacplus_global = {}
132147
self.tacplus_servers = {}
133148
self.debug = False
149+
self.config_db = config_db
134150

135151
# Load conf from ConfigDb
136-
def load(self, aaa_conf, tac_global_conf, tacplus_conf):
137-
for row in aaa_conf:
138-
self.aaa_update(row, aaa_conf[row], modify_conf=False)
139-
for row in tac_global_conf:
140-
self.tacacs_global_update(row, tac_global_conf[row], modify_conf=False)
141-
for row in tacplus_conf:
142-
self.tacacs_server_update(row, tacplus_conf[row], modify_conf=False)
152+
def load(self):
143153
self.modify_conf_file()
144154

145-
def aaa_update(self, key, data, modify_conf=True):
155+
def aaa_update(self, key):
146156
if key == 'authentication':
147-
self.auth = data
148-
if 'failthrough' in data:
149-
self.auth['failthrough'] = is_true(data['failthrough'])
150-
if 'debug' in data:
151-
self.debug = is_true(data['debug'])
152-
if modify_conf:
153157
self.modify_conf_file()
154158

155-
def tacacs_global_update(self, key, data, modify_conf=True):
159+
def tacacs_global_update(self, key):
156160
if key == 'global':
157-
self.tacplus_global = data
158-
if modify_conf:
159-
self.modify_conf_file()
160-
161-
def tacacs_server_update(self, key, data, modify_conf=True):
162-
if data == {}:
163-
if key in self.tacplus_servers:
164-
del self.tacplus_servers[key]
165-
else:
166-
self.tacplus_servers[key] = data
167-
168-
if modify_conf:
169161
self.modify_conf_file()
170162

163+
def tacacs_server_update(self, key):
164+
self.modify_conf_file()
165+
171166
def modify_single_file(self, filename, operations=None):
172167
if operations:
173168
cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}".format(' -e '.join(operations), filename)
174169
os.system(cmd)
175170

176171
def modify_conf_file(self):
172+
with lock_mgr():
173+
self.auth = self.config_db.get_table('AAA').get("authentication", {})
174+
if 'failthrough' in self.auth:
175+
self.auth['failthrough'] = is_true(self.auth['failthrough'])
176+
if 'debug' in self.auth:
177+
self.debug = is_true(self.auth['debug'])
178+
179+
self.tacplus_global = self.config_db.get_table('TACPLUS').get(
180+
"global", {})
181+
self.tacplus_servers = self.config_db.get_table('TACPLUS_SERVER')
182+
self._modify_conf_file()
183+
184+
def _modify_conf_file(self):
177185
auth = self.auth_default.copy()
178186
auth.update(self.auth)
179187
tacplus_global = self.tacplus_global_default.copy()
@@ -219,33 +227,50 @@ class AaaCfg(object):
219227
with open(NSS_TACPLUS_CONF, 'w') as f:
220228
f.write(nss_tacplus_conf)
221229

230+
if 'passkey' in tacplus_global:
231+
tacplus_global['passkey'] = obfuscate(tacplus_global['passkey'])
232+
syslog.syslog(syslog.LOG_INFO, 'pam.d files updated auth={} global={}'.
233+
format(auth, tacplus_global))
234+
222235

223236
class HostConfigDaemon:
224237
def __init__(self):
225238
self.config_db = ConfigDBConnector()
226239
self.config_db.connect(wait_for_init=True, retry_on=True)
227240
syslog.syslog(syslog.LOG_INFO, 'ConfigDB connect success')
228-
aaa = self.config_db.get_table('AAA')
229-
tacacs_global = self.config_db.get_table('TACPLUS')
230-
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
231-
self.aaacfg = AaaCfg()
232-
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
233-
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
241+
242+
self.aaacfg = AaaCfg(self.config_db)
234243
self.iptables = Iptables()
244+
245+
246+
def timer_load(self):
247+
global global_lock
248+
249+
syslog.syslog(syslog.LOG_INFO, 'reloading tacacs from timer thread')
250+
self.aaacfg.load()
251+
252+
# Remove lock as timer is one shot
253+
global_lock = None
254+
255+
256+
def load(self):
257+
self.aaacfg.load()
258+
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
235259
self.iptables.load(lpbk_table)
236260

237261
def aaa_handler(self, key, data):
238-
self.aaacfg.aaa_update(key, data)
262+
self.aaacfg.aaa_update(key)
263+
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, data))
239264

240265
def tacacs_server_handler(self, key, data):
241-
self.aaacfg.tacacs_server_update(key, data)
266+
self.aaacfg.tacacs_server_update(key)
242267
log_data = copy.deepcopy(data)
243268
if log_data.has_key('passkey'):
244269
log_data['passkey'] = obfuscate(log_data['passkey'])
245270
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))
246271

247272
def tacacs_global_handler(self, key, data):
248-
self.aaacfg.tacacs_global_update(key, data)
273+
self.aaacfg.tacacs_global_update(key)
249274
log_data = copy.deepcopy(data)
250275
if log_data.has_key('passkey'):
251276
log_data['passkey'] = obfuscate(log_data['passkey'])
@@ -263,10 +288,20 @@ class HostConfigDaemon:
263288
self.iptables.iptables_handler(key, data, add)
264289

265290
def start(self):
291+
global global_lock
292+
266293
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
267294
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
268295
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
269296
self.config_db.subscribe('LOOPBACK_INTERFACE', lambda table, key, data: self.lpbk_handler(key, data))
297+
298+
# Defer load until subscribe
299+
self.load()
300+
301+
global_lock = threading.Lock()
302+
self.tmr_thread = threading.Timer(30, self.timer_load)
303+
self.tmr_thread.start()
304+
270305
self.config_db.listen()
271306

272307

0 commit comments

Comments
 (0)