2
2
# -*- coding: utf-8 -*-
3
3
4
4
import os
5
+ import threading
5
6
import sys
6
7
import subprocess
7
8
import syslog
@@ -22,6 +23,20 @@ TACPLUS_SERVER_PASSKEY_DEFAULT = ""
22
23
TACPLUS_SERVER_TIMEOUT_DEFAULT = "5"
23
24
TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap"
24
25
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
+
25
40
26
41
def is_true (val ):
27
42
if val == 'True' or val == 'true' :
@@ -118,7 +133,7 @@ class Iptables(object):
118
133
.format (err .cmd , err .returncode , err .output ))
119
134
120
135
class AaaCfg (object ):
121
- def __init__ (self ):
136
+ def __init__ (self , config_db ):
122
137
self .auth_default = {
123
138
'login' : 'local' ,
124
139
}
@@ -131,49 +146,42 @@ class AaaCfg(object):
131
146
self .tacplus_global = {}
132
147
self .tacplus_servers = {}
133
148
self .debug = False
149
+ self .config_db = config_db
134
150
135
151
# 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 ):
143
153
self .modify_conf_file ()
144
154
145
- def aaa_update (self , key , data , modify_conf = True ):
155
+ def aaa_update (self , key ):
146
156
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 :
153
157
self .modify_conf_file ()
154
158
155
- def tacacs_global_update (self , key , data , modify_conf = True ):
159
+ def tacacs_global_update (self , key ):
156
160
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 :
169
161
self .modify_conf_file ()
170
162
163
+ def tacacs_server_update (self , key ):
164
+ self .modify_conf_file ()
165
+
171
166
def modify_single_file (self , filename , operations = None ):
172
167
if operations :
173
168
cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}" .format (' -e ' .join (operations ), filename )
174
169
os .system (cmd )
175
170
176
171
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 ):
177
185
auth = self .auth_default .copy ()
178
186
auth .update (self .auth )
179
187
tacplus_global = self .tacplus_global_default .copy ()
@@ -219,33 +227,50 @@ class AaaCfg(object):
219
227
with open (NSS_TACPLUS_CONF , 'w' ) as f :
220
228
f .write (nss_tacplus_conf )
221
229
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
+
222
235
223
236
class HostConfigDaemon :
224
237
def __init__ (self ):
225
238
self .config_db = ConfigDBConnector ()
226
239
self .config_db .connect (wait_for_init = True , retry_on = True )
227
240
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 )
234
243
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' )
235
259
self .iptables .load (lpbk_table )
236
260
237
261
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 ))
239
264
240
265
def tacacs_server_handler (self , key , data ):
241
- self .aaacfg .tacacs_server_update (key , data )
266
+ self .aaacfg .tacacs_server_update (key )
242
267
log_data = copy .deepcopy (data )
243
268
if log_data .has_key ('passkey' ):
244
269
log_data ['passkey' ] = obfuscate (log_data ['passkey' ])
245
270
syslog .syslog (syslog .LOG_INFO , 'value of {} changed to {}' .format (key , log_data ))
246
271
247
272
def tacacs_global_handler (self , key , data ):
248
- self .aaacfg .tacacs_global_update (key , data )
273
+ self .aaacfg .tacacs_global_update (key )
249
274
log_data = copy .deepcopy (data )
250
275
if log_data .has_key ('passkey' ):
251
276
log_data ['passkey' ] = obfuscate (log_data ['passkey' ])
@@ -263,10 +288,20 @@ class HostConfigDaemon:
263
288
self .iptables .iptables_handler (key , data , add )
264
289
265
290
def start (self ):
291
+ global global_lock
292
+
266
293
self .config_db .subscribe ('AAA' , lambda table , key , data : self .aaa_handler (key , data ))
267
294
self .config_db .subscribe ('TACPLUS_SERVER' , lambda table , key , data : self .tacacs_server_handler (key , data ))
268
295
self .config_db .subscribe ('TACPLUS' , lambda table , key , data : self .tacacs_global_handler (key , data ))
269
296
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
+
270
305
self .config_db .listen ()
271
306
272
307
0 commit comments