@@ -507,6 +507,21 @@ def _update(self, json_response):
507
507
508
508
509
509
class OathOtpValidators (object ):
510
+ class ImportFormat (object ):
511
+ SAFENET = {
512
+ 'secret_format' : 'hex' ,
513
+ 'header_map' : {
514
+ 'Serial' : 'requester_specified_id' ,
515
+ 'Seed' : 'secret'
516
+ },
517
+ 'defaults' : {
518
+ 'otp_type' : 'hotp' ,
519
+ 'otp_digits' : 6 ,
520
+ 'algorithm' : 'sha1'
521
+ }
522
+ }
523
+
524
+
510
525
def __init__ (self , api ):
511
526
self .api = api
512
527
@@ -524,6 +539,49 @@ def provision(self, secret, requester_specified_id=None, otp_type='totp', otp_di
524
539
result = self .api .advanced .raw .post (url , ** params )
525
540
return OathOtpValidator (result , self .api )
526
541
542
+
543
+
544
+ def bulk_provision_from_csv (self , file_or_filename , style ):
545
+ def decode_validator_secret (encoded_secret , encoding ):
546
+ if encoding == 'hex' :
547
+ return encoded_secret
548
+ elif encoding == 'ascii' :
549
+ import binascii
550
+ return binascii .hexlify (bytearray (encoded_secret , 'utf-8' ))
551
+ else :
552
+ raise ValueError ('Unsupport secret encoding {0}' .format (encoding ))
553
+
554
+ def read_csv (f ):
555
+ import csv
556
+ dialect = csv .Sniffer ().sniff (f .read (1024 ))
557
+ f .seek (0 )
558
+ reader = csv .DictReader (f , dialect )
559
+ validators = []
560
+ for row in reader :
561
+ validator = style ['defaults' ].copy ()
562
+ for csv_field_name , api_field_name in style ['header_map' ].iteritems ():
563
+ validator [api_field_name ] = row [csv_field_name ]
564
+ if 'secret_format' in style :
565
+ validator ['secret' ] = decode_validator_secret (validator ['secret' ], style ['secret_format' ])
566
+ validators .append (validator )
567
+ return validators
568
+
569
+ if isinstance (file_or_filename , basestring ):
570
+ with open (file_or_filename ) as f :
571
+ validators = read_csv (f )
572
+ else :
573
+ validators = read_csv (file_or_filename )
574
+
575
+ url = '/oath_otp_validators/bulk_provision'
576
+ params = {
577
+ 'oath_otp_validators' : json .dumps (validators )
578
+ }
579
+ response = self .api .advanced .raw .post (url , ** params )
580
+ validators_json_list = response ['oath_otp_validators' ]
581
+ validators_list = [OathOtpValidator (json_validator , api ) for json_validator in validators_json_list ]
582
+ return validators_list
583
+
584
+
527
585
def get_by_id (self , validator_id ):
528
586
url = '/oath_otp_validators/{0}' .format (validator_id )
529
587
return OathOtpValidator (self .api .advanced .raw .get (url ), api )
0 commit comments