@@ -507,6 +507,21 @@ def _update(self, json_response):
507507
508508
509509class 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+
510525 def __init__ (self , api ):
511526 self .api = api
512527
@@ -524,6 +539,49 @@ def provision(self, secret, requester_specified_id=None, otp_type='totp', otp_di
524539 result = self .api .advanced .raw .post (url , ** params )
525540 return OathOtpValidator (result , self .api )
526541
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+
527585 def get_by_id (self , validator_id ):
528586 url = '/oath_otp_validators/{0}' .format (validator_id )
529587 return OathOtpValidator (self .api .advanced .raw .get (url ), api )
0 commit comments