5
5
6
6
7
7
from __future__ import print_function
8
+ import os
8
9
import sys
9
10
import time
10
11
import itertools
12
+ import uuid
13
+ import base64
11
14
12
15
from opsbro .characters import CHARACTERS
13
16
from opsbro .log import cprint , logger , sprintf
@@ -234,6 +237,65 @@ def do_zone_list():
234
237
cprint (sub_zname , color = 'cyan' )
235
238
236
239
240
+ def _save_key (key_string , zone_name , key_path ):
241
+ with open (key_path , 'wb' ) as f :
242
+ f .write (key_string )
243
+
244
+ cprint ('%s OK the key is saved as file %s' % (CHARACTERS .check , key_path ))
245
+
246
+ # Try to send the information to the agent, so it can reload the key
247
+ try :
248
+ get_opsbro_json ('/agent/zones-keys/reload/%s' % zone_name )
249
+ except get_request_errors ():
250
+ cprint (' | The agent seems to not be started. Skipping hot key reload.' , color = 'grey' )
251
+ return
252
+
253
+
254
+ def do_zone_key_generate (zone , erase = False ):
255
+ from opsbro .defaultpaths import DEFAULT_CFG_DIR
256
+ from opsbro .configurationmanager import ZONE_KEYS_DIRECTORY_NAME
257
+ print_h1 ('Generate a new key for the zone %s' % zone )
258
+
259
+ key_path = os .path .join (DEFAULT_CFG_DIR , ZONE_KEYS_DIRECTORY_NAME , '%s.key' % zone )
260
+
261
+ if os .path .exists (key_path ) and not erase :
262
+ cprint ('ERROR: the key %s is already existing' , color = 'red' )
263
+ cprint (' %s Note: You can use the --erase parameter to erase over an existing key' % (CHARACTERS .corner_bottom_left ), color = 'grey' )
264
+ sys .exit (2 )
265
+
266
+ k = uuid .uuid1 ().hex [:16 ]
267
+ b64_k = base64 .b64encode (k )
268
+ cprint ('Encryption key for the zone ' , end = '' )
269
+ cprint (zone , color = 'magenta' , end = '' )
270
+ cprint (' :' , end = '' )
271
+ cprint (b64_k , color = 'green' )
272
+ _save_key (b64_k , zone , key_path )
273
+
274
+
275
+ def do_zone_key_import (zone , key , erase = False ):
276
+ from opsbro .defaultpaths import DEFAULT_CFG_DIR
277
+ from opsbro .configurationmanager import ZONE_KEYS_DIRECTORY_NAME
278
+
279
+ key_path = os .path .join (DEFAULT_CFG_DIR , ZONE_KEYS_DIRECTORY_NAME , '%s.key' % zone )
280
+
281
+ if os .path .exists (key_path ) and not erase :
282
+ cprint ('ERROR: the key %s is already existing' , color = 'red' )
283
+ cprint (' %s Note: You can use the --erase parameter to erase over an existing key' % (CHARACTERS .corner_bottom_left ), color = 'grey' )
284
+ sys .exit (2 )
285
+ # check key is base64(len16)
286
+ try :
287
+ raw_key = base64 .b64decode (key )
288
+ except TypeError : # bad key
289
+ cprint ('ERROR: the key is not valid. (not base4 encoded)' , color = 'red' )
290
+ sys .exit (2 )
291
+ if len (raw_key ) != 16 :
292
+ cprint ('ERROR: the key is not valid. (not 128bits)' , color = 'red' )
293
+ sys .exit (2 )
294
+
295
+ # Note: key is the original b64 encoded one, we did check it
296
+ _save_key (key , zone , key_path )
297
+
298
+
237
299
def __print_detection_spinner (timeout ):
238
300
spinners = itertools .cycle (CHARACTERS .spinners )
239
301
start = time .time ()
@@ -430,30 +492,30 @@ def do_wait_members(name='', display_name='', group='', count=1, timeout=30):
430
492
431
493
432
494
exports = {
433
- do_members : {
495
+ do_members : {
434
496
'keywords' : ['gossip' , 'members' ],
435
497
'args' : [
436
498
{'name' : '--detail' , 'type' : 'bool' , 'default' : False , 'description' : 'Show detail mode for the cluster members' },
437
499
],
438
500
'description' : 'List the cluster members'
439
501
},
440
502
441
- do_members_history : {
503
+ do_members_history : {
442
504
'keywords' : ['gossip' , 'history' ],
443
505
'args' : [
444
506
],
445
507
'description' : 'Show the history of the gossip nodes'
446
508
},
447
509
448
- do_join : {
510
+ do_join : {
449
511
'keywords' : ['gossip' , 'join' ],
450
512
'description' : 'Join another node cluster' ,
451
513
'args' : [
452
514
{'name' : 'seed' , 'default' : '' , 'description' : 'Other node to join. For example 192.168.0.1:6768' },
453
515
],
454
516
},
455
517
456
- do_leave : {
518
+ do_leave : {
457
519
'keywords' : ['gossip' , 'leave' ],
458
520
'description' : 'Put in leave a cluster node' ,
459
521
'args' : [
@@ -462,7 +524,7 @@ def do_wait_members(name='', display_name='', group='', count=1, timeout=30):
462
524
],
463
525
},
464
526
465
- do_zone_change : {
527
+ do_zone_change : {
466
528
'keywords' : ['gossip' , 'zone' , 'change' ],
467
529
'args' : [
468
530
{'name' : 'name' , 'default' : '' , 'description' : 'Change to the zone' },
@@ -471,15 +533,34 @@ def do_wait_members(name='', display_name='', group='', count=1, timeout=30):
471
533
'description' : 'Change the zone of the node'
472
534
},
473
535
474
- do_zone_list : {
536
+ do_zone_list : {
475
537
'keywords' : ['gossip' , 'zone' , 'list' ],
476
538
'args' : [
477
539
],
478
540
'allow_temporary_agent' : {'enabled' : True , },
479
541
'description' : 'List all known zones of the node'
480
542
},
481
543
482
- do_detect_nodes : {
544
+ do_zone_key_generate : {
545
+ 'keywords' : ['gossip' , 'zone' , 'key' , 'generate' ],
546
+ 'args' : [
547
+ {'name' : '--zone' , 'description' : 'Name of zone to generate a key for' },
548
+ {'name' : '--erase' , 'type' : 'bool' , 'default' : False , 'description' : 'Erase the key if already exiting.' },
549
+ ],
550
+ 'description' : 'Generate a gossip encryption key for the zone'
551
+ },
552
+
553
+ do_zone_key_import : {
554
+ 'keywords' : ['gossip' , 'zone' , 'key' , 'import' ],
555
+ 'args' : [
556
+ {'name' : '--zone' , 'description' : 'Name of zone to import the key for' },
557
+ {'name' : '--key' , 'description' : 'Key to import.' },
558
+ {'name' : '--erase' , 'type' : 'bool' , 'default' : False , 'description' : 'Erase the key if already exiting.' },
559
+ ],
560
+ 'description' : 'Import a gossip encryption key for the zone'
561
+ },
562
+
563
+ do_detect_nodes : {
483
564
'keywords' : ['gossip' , 'detect' ],
484
565
'args' : [
485
566
{'name' : '--auto-join' , 'default' : False , 'description' : 'Try to join the first detected proxy node. If no proxy is founded, join the first one.' , 'type' : 'bool' },
@@ -488,7 +569,7 @@ def do_wait_members(name='', display_name='', group='', count=1, timeout=30):
488
569
'description' : 'Try to detect (broadcast) others nodes in the network'
489
570
},
490
571
491
- do_wait_event : {
572
+ do_wait_event : {
492
573
'keywords' : ['gossip' , 'events' , 'wait' ],
493
574
'args' : [
494
575
{'name' : 'event-type' , 'description' : 'Name of the event to wait for' },
@@ -497,15 +578,15 @@ def do_wait_members(name='', display_name='', group='', count=1, timeout=30):
497
578
'description' : 'Wait until the event is detected'
498
579
},
499
580
500
- do_gossip_add_event : {
581
+ do_gossip_add_event : {
501
582
'keywords' : ['gossip' , 'events' , 'add' ],
502
583
'args' : [
503
584
{'name' : 'event-type' , 'description' : 'Name of the event to add' },
504
585
],
505
586
'description' : 'Add a event to the gossip members'
506
587
},
507
588
508
- do_wait_members : {
589
+ do_wait_members : {
509
590
'keywords' : ['gossip' , 'wait-members' ],
510
591
'args' : [
511
592
{'name' : '--name' , 'description' : 'Name of the members to wait for be alive' },
0 commit comments