# -*- coding: utf-8 -*- # # some internal functions are copied from salt.states.file from Crypto.PublicKey import RSA import os def _check_user(user, group): ''' Checks if the named user and group are present on the minion ''' err = '' if user: uid = __salt__['file.user_to_uid'](user) if uid == '': err += 'User {0} is not available '.format(user) if group: gid = __salt__['file.group_to_gid'](group) if gid == '': err += 'Group {0} is not available'.format(group) return err def _error(ret, err_msg): ret['result'] = False ret['comment'] = err_msg return ret def _calculate_umask(mode): mode = str(mode).lstrip('0') if not mode: mode = '0' modeint = int(mode, 8) return modeint ^ 0777 def valid_key(name, bits=2048, user=None, group=None, mode='0700'): """ Make sure that the given key file exists and contains a valid RSA key. name The name of the key file to check bits Minimum bits for the RSA key user The user to own the file, this defaults to the user salt is running as on the minion group The group ownership set for the file, this defaults to the group salt is running on the minion mode The permissions set on the file, this defaults to 0600 """ mode = __salt__['config.manage_mode'](mode) ret = { 'name': name, 'changes': {}, 'result': None, 'comment': ''} if not os.path.isfile(name) and __opts__['test']: ret['comment'] = 'would create RSA key in file {0}'.format(name) return ret u_check = _check_user(user, group) if u_check: return _error(ret, u_check) if not os.path.isabs(name): return _error( ret, 'Specified file {0} is not an absolute path'.format(name)) if os.path.isdir(name): return _error( ret, 'Specified target {0} is a directory'.format(name)) if os.path.exists(name): ret, perms = __salt__['file.check_perms']( name, ret, user, group, mode) if __opts__['test']: ret['comment'] = 'File {0} not updated'.format(name) return ret if not os.path.isfile(name): rsa = RSA.generate(bits) oldumask = os.umask(_calculate_umask(mode)) with open(name, 'w') as rsafile: rsafile.write(rsa.exportKey()) os.umask(oldumask) ret['comment'] = 'created new RSA key and saved PEM file {0}'.format( name) ret['changes']['created'] = name ret['result'] = True return ret try: with open(name, 'r') as rsafile: rsa = RSA.importKey(rsafile.read()) except Exception as e: ret['comment'] = 'error loading RSA key from file {0}: {1}'.format( name, e) ret['result'] = False return ret keysize = rsa.size() + 1 if keysize < bits: ret['comment'] = ( 'RSA key in {0} is only {1} bits, which is less than the ' 'required {2} bits'.format(name, keysize, bits)) ret['result'] = False else: ret['comment'] = 'RSA key in file {0} is ok ({1} bits)'.format( name, keysize) ret['result'] = True return ret