Exemple #1
0
    def decrypt_file(self, filename):
        '''
        解密文件
        :parm
            filename:需要解密的文件
        '''

        content = read_file(filename)
        if content[0]:
            ciphertext = content[1]
        else:
            self.logger.error('解密文件' + filename + '失败,在读取文件过程中出错,原因:' +
                              content[1])
            return (False, "解密文件失败,在读取文件过程中出错," + content[1])

        plaintext = self.decrypt(ciphertext)
        if not plaintext[0]:
            self.logger.error('解密文件' + filename + '失败,在解密过程中出错,原因:' +
                              plaintext[1])
            return (False, "解密文件失败,在解密过程中出错," + plaintext[1])

        result = self._write_file(filename, plaintext[1])
        if not result[0]:
            self.logger.error('解密文件' + filename + '失败,在解密后回写文件过程中出错,原因:' +
                              result[1])
            return (False, "解密文件失败,在解密后回写文件过程中出错," + result[1])
        else:
            self.logger.info('解密文件' + filename + '成功')
            return (True, "解密文件成功")
Exemple #2
0
    def _get_vault_pwd(self):
        '''
        获取vault密码,并初始化vault密码
        '''

        vault_pwd_file = self.options_dict.get('vault_password_file', False)
        ask_vault_pass = self.options_dict.get('ask_vault_pass', False)

        if ask_vault_pass:
            vault_password = ask_vault_pass
        else:
            if vault_pwd_file:
                this_path = os.path.realpath(
                    os.path.expanduser(vault_pwd_file))
                if os.path.exists(this_path):
                    mode = self.loader.is_executable(this_path)
                    result = read_file(this_path,
                                       mode=mode,
                                       sprfmt=b'\r\n',
                                       outfmt='bytes')
                    if result[0]:
                        vault_password = result[1]
                    else:
                        vault_password = None
                else:
                    vault_password = None
            else:
                vault_password = None

        if vault_password:
            b_vault_password = string2bytes(vault_password)
            self.loader.set_vault_password(b_vault_password)
            self.vault_password = vault_password
        else:
            self.vault_password = None
Exemple #3
0
    def encrypt_file(self, filename):
        '''
        加密文件
        :parm
            filename:需要加密的文件
        '''

        content = read_file(filename)
        if content[0]:
            plaintext = content[1]
        else:
            self.logger.error('加密文件' + filename + '失败,在读取文件过程中出错,原因:' +
                              content[1])
            return (False, "加密文件失败,在读取文件过程中出错," + content[1])

        ciphertext = self.encrypt(plaintext)

        if not ciphertext[0]:
            self.logger.error('加密文件' + filename + '失败,在加密过程中出错,原因:' +
                              ciphertext[1])
            return (False, "加密文件失败,在加密过程中出错," + ciphertext[1])
        else:
            ciphertext = ciphertext[1]

        result = self._write_file(filename, ciphertext)
        if not result[0]:
            self.logger.error('加密文件' + filename + '失败,在加密后回写文件过程中出错,原因:' +
                              result[1])
            return (False, "加密文件失败,在加密后回写文件过程中出错," + result[1])
        else:
            self.logger.info('加密文件' + filename + '成功')
            return (True, "加密文件成功")
Exemple #4
0
def yaml_loader(data, data_type='data'):
    '''
    解析yaml,把yaml文件或者字符串解析成为yaml列表格式
    :参数
        data:yaml文件或任意类型数据
        data_type:数据类型,目前只能接受file或者data,默认为data
    :返回
        元组:(bool, 列表或者错误信息)
    '''

    if data_type not in ('file', 'data'):
        return (False, 'data_type参数不正确,只能为file或者data')

    if data_type == 'file':
        result = read_file(data)
        if result[0]:
            data = result[1]
        else:
            return result

    try:
        yaml_data = yaml.load(data)
        return (True, yaml_data)
    except Exception as e:
        try:
            reuslt = yaml.dump(data)
            if reuslt:
                return (True, data)
            else:
                return (False, '不能被yaml加载,原因:' + str(e))
        except Exception as e:
            return (False, '不能被yaml加载,原因:' + str(e))
Exemple #5
0
 def yaml_loader(self, data, data_type='file'):
     
     '''
     将文件或者原始数据解析成yaml数据,如果是vault数据,将在这里解密
     :parm
         data:路径或者原始数据
         data_type:指定类型,文件或者原始数据
     '''
     
     
     if data_type == 'file' :
         log_prefix = '将yaml文件' + data + '的内容(必须为原始数据)解析为yaml格式的数据,'
         result = check_fileaccessible(data)
         if result[0] :
             filename = result[1]
         else :
             self.logger.error(log_prefix + '读取文件时失败,原因:' + result[1])
             return (False, '读取文件时失败,' + result[1])
         
         result = read_file(filename)
         if result[0] :
             content = result[1]
         else :
             self.logger.error(log_prefix + '读取文件时失败,原因:' + result[1])
             return (False, '读取文件时失败,' + result[1])
     else :
         log_prefix = '将原始yaml数据解析为yaml格式的数据,'
         content = data
         filename = ''
         # 是否写入文件中
     
     result = yaml_loader(content, data_type='data')
     if result[0] :
         yaml_data = result[1]
     else :
         self.logger.error(log_prefix + '解析失败,原因:' + result[1])
         return (False, '解析成yaml失败,' + result[1])
     
     if not isinstance(yaml_data, (dict, list, tuple)) :
         self.logger.error(log_prefix + '解析失败,原因:该文件内容不是ansible支持的yaml数据')
         return (False, '解析成yaml失败,该文件内容不是ansible支持的yaml数据')
     
     self.logger.info(log_prefix + '解析成功')
     return (True, filename, content, yaml_data)
Exemple #6
0
    def _ansible_vault_encrpyt(self, data):
        '''
        while True :
            vault_tempfile = tempdir + '/vault' + random_str(ranlen=20) + '_' + str(int(time.time()))
            result = write_file(vault_tempfile, 'w', data)
            if result[0] :
                break
        '''
        result = write_random_file(data)
        if not result[0]:
            return result

        vault_tempfile = result[1]

        ansible_vault = VaultEditor(self.password)
        ansible_vault.decrypt_file(vault_tempfile)
        result = read_file(vault_tempfile)
        os.remove(vault_tempfile)
        return result
Exemple #7
0
    def rekey_file(self, filename, new_password):
        '''
        更改加密文件的valut密码
        :parm
            new_password:新密码
            filename:需要更换的文件
        '''

        if not new_password or new_password is None:
            self.logger.error('更改加密文件' + filename + '的valut密码失败,原因:新密码为空')
            return (False, "更改加密文件的valut密码失败,新密码为空")

        content = read_file(filename)
        if content[0]:
            ciphertext = content[1]
        else:
            self.logger.error('更改加密文件' + filename +
                              '的valut密码失败,在读取文件过程中出错,原因:' + content[1])
            return (False, "更改加密文件失败,在读取文件过程中出错," + content[1])

        new_ciphertext = self.rekey(ciphertext, new_password)

        if not new_ciphertext[0]:
            self.logger.error('更改加密文件' + filename + '的valut密码失败,在加密过程中出错,原因:' +
                              str(new_ciphertext[1]))
            return (False,
                    '更改加密文件的valut密码失败,在加密过程中出错,' + str(new_ciphertext[1]))
        else:
            new_ciphertext = new_ciphertext[1]

        result = self._write_file(filename, new_ciphertext)
        if not result[0]:
            self.logger.error('更改加密文件' + filename +
                              '的valut密码失败,在写入文件过程中出错,原因:' + result[1])
            return (False, "更改加密文件的valut密码失败,在写入文件过程中出错," + result[1])
        else:
            self.logger.info('更改加密文件' + filename + '的valut密码成功')
            return (True, "更改加密文件的valut密码成功")
Exemple #8
0
    def decrypt_file2text(self, filename):
        '''
        解密文件的内容,成功后直接输出
        :parm
            filename:需要解密的文件
        '''

        content = read_file(filename)
        if content[0]:
            ciphertext = content[1]
        else:
            self.logger.error('解密文件' + filename +
                              '的内容(成功后直接输出)失败,在读取文件过程中出错,原因:' + content[1])
            return (False, "解密文件的内容(成功后直接输出)失败,在读取文件过程中出错," + content[1])

        plaintext = self.decrypt(ciphertext)
        if not plaintext[0]:
            self.logger.error('解密文件' + filename +
                              '的内容(成功后直接输出)失败,在解密过程中出错,原因:' + ciphertext[1])
            return (False, "解密文件的内容(成功后直接输出)失败,在解密过程中出错," + plaintext[1])
        else:
            self.logger.info('解密文件' + filename + ' 的内容(成功后直接输出)成功')
            return (True, "解密文件的内容(成功后直接输出)成功")
Exemple #9
0
    def encrypt_file2text(self, filename):
        '''
        加密文件的内容,成功后直接输出
        :parm
            filename:需要加密的文件
        '''

        content = read_file(filename)
        if content[0]:
            plaintext = content[1]
        else:
            self.logger.error('加密文件' + filename +
                              '的内容(成功后直接输出)失败,在读取文件过程中出错,原因:' + content[1])
            return (False, "加密文件的内容(成功后直接输出)失败,在读取文件过程中出错," + content[1])

        ciphertext = self.encrypt(plaintext)
        if not ciphertext[0]:
            self.logger.error('加密文件' + filename +
                              '的内容(成功后直接输出)失败,在加密过程中出错,原因:' + ciphertext[1])
            return (False, "加密文件的内容(成功后直接输出)失败,在加密过程中出错," + ciphertext[1])
        else:
            self.logger.info('加密文件' + filename + ' 的内容(成功后直接输出)成功')
            return (True, "加密文件的内容(成功后直接输出)成功")
Exemple #10
0
    def roles(self,
              roles_path,
              this_basedir=None,
              preserve=True,
              together=False,
              name='',
              describe=''):
        '''
        检测单个roles的语法等是否正确
        :参数
            this_basedir:引用该roles的main文件的上级目录,例如/opt/devops/example/ansible/roles/nginx/main.yaml引用一个roles,那么该值为/opt/devops/example/ansible/roles/nginx/
            roles_path:引用该roles的main文件写的roles路径
            preserve:是否写入数据库
            together:是否返回该roles下所有文件内容
            name:yaml文件内容写入数据的名称
            describe:yaml文件内容写入数据的描述
            zhname:yaml文件内容写入数据的中文名称,很简短说明
        :return
            元组,第一个为执行结果,
                成功为true,返回内容为(True,roles下所有文件内容(格式为字典,可能为空), roles下所有文件中include文件内容(格式为字典,可能为空))
                失败为False,返回失败原因
        '''

        content_dict = {}

        if preserve and together:
            sub_preserve = False
        else:
            sub_preserve = preserve

        if not name:
            name = roles_path

        result = self._isrolesname(name)
        if not result:
            self.logger.error('检测yaml文件roles名为' + roles_path +
                              '失败,roles名不符合本系统要求的,注:虽然原生ansible支持这样写')
            return (False, '语法错误,roles名不符合本系统要求的,注:虽然原生ansible支持这样写')
        else:
            if this_basedir is None or not this_basedir:
                this_roles_path = roles_path
            else:
                try:
                    this_roles_path = this_basedir + '/roles/' + roles_path
                except:
                    this_roles_path = roles_path

        include_content = {}
        for this_dir in ('tasks', 'vars', 'handlers', 'meta', 'defaults'):
            yaml_file = this_roles_path + '/' + this_dir + '/main.yaml'
            result = read_file(yaml_file)
            if not result[0]:
                if this_dir == 'tasks':
                    self.logger.error('检测yaml文件roles名为' + roles_path + '失败,' +
                                      this_dir + '/main.yaml不存在')
                    return (False, this_dir + '/main.yaml不存在')
                continue
            else:
                content_dict[this_dir] = result[1]

        temp_dir = this_roles_path + '/templates/'
        content_dict['templates'] = {}
        result = get_pathlist(temp_dir, get_death=0, max_size=4 * 1024 * 1024)
        if result[0]:
            temp_list = result[1]
            for temp in temp_list:
                result = read_file(temp)
                if result[0]:
                    temp_file = os.path.basename(temp)
                    content_dict['templates'][temp_file] = result[1]

        if not content_dict['templates']:
            del content_dict['templates']

        result = self.check_roles(content_dict)
        if result[0]:
            includefile_dict = result[1]
            for file, file_type in includefile_dict.items():
                result = self.include(file,
                                      this_basedir=this_basedir,
                                      file_type=file_type,
                                      preserve=sub_preserve)
                if not result[0]:
                    self.logger.error('检测yaml文件roles名为' + roles_path +
                                      '失败,roles包含的include文件' + file +
                                      '未通过语法检测,原因:' + result[1])
                    return (False, 'roles包含的include文件' + file + '未通过语法检测,' +
                            result[1])
                else:
                    include_content.update({file: result[1]})
        else:
            self.logger.error('检测yaml文件roles名为' + roles_path + '失败,' +
                              this_dir + '/main.yaml语法错误,原因:' + result[1])
            return (False, this_dir + '/main.yaml语法错误,' + result[1])

        data = {
            'main': {},
            'include': include_content,
            'roles': {
                name: content_dict
            },
        }

        if preserve:
            result = self.write2db(name, data, 'roles', describe=describe)
            if not result[0]:
                self.logger.error('检测yaml文件roles名为' + roles_path +
                                  '失败,无法写入数据库,' + result[1])
                return (False, '无法写入数据库,' + result[1])

        self.logger.info('检测yaml文件roles名为' + roles_path + '成功')
        if together:
            return (True, content_dict, include_content)
        else:
            return (True, {}, {})
Exemple #11
0
    def _handle_ciphertext(self, data=None, filename=None):
        '''
        对加密数据/文件内容的头部进行判断使用哪种方式加密
        data或者filename其中一个可以为空,至少一个不能为空
        如果两个均不为空,默认使用filename
        :parm
            data:加密数据
            filename:加密文件
        :return
            算法或者False
        '''

        if data is None and filename is None:
            self.logger.error('解密ansible加密数据时出错,原因:参数data和filename不能同时为空')
            return (False, False, '参数data和filename不能同时为空')

        if filename is not None:
            result = read_file(filename)
            if result[0]:
                data = result[1]
            else:
                if data is None:
                    self.logger.error('解密ansible文件' + filename +
                                      '时出错,无法读取文件,原因:' + result[1])
                    return (False, False, '无法读取文件')

        result = obj2bytes(data)
        if result[0]:
            b_data = result[1]
        else:
            b_data = string2bytes(data)

        b_data = b_data.split(b'\n')
        b_vault_header = b_data[0].strip()
        b_ciphertext = b''.join(b_data[1:])

        vault_header = obj2string(b_vault_header)[1]

        if b_vault_header in self.b_vault_header:
            #这是自定义加密数据
            self.logger.info('解密ansible加密数据成功,注:加密数据使用本系统自定义方法加密的')
            return (True, True, b_data)
        elif re.search('ANSIBLE_VAULT;1.1;', vault_header):
            #这是ansible2.3版本加密数据
            # return (False, True, data)

            #在ansible 2.3版本中,vault加密后头部为'$ANSIBLE_VAULT;1.1;AES256',其他版本未知
            if vault_header == '$ANSIBLE_VAULT;1.1;AES256':
                #说明加密方式为AES256,自定义加密算法一直,直接使用自定义方式进行解密
                data = self.b_vault_header + b'\n' + b_ciphertext
                result = obj2bytes(data)
                if result[0]:
                    self.logger.info('解密ansible加密数据成功,注:加密数据使用ansible2.3版本加密的')
                    return (True, False, result[1])
                else:
                    self.logger.error(
                        '解密ansible加密数据时失败,原因:加密数据使用ansible2.3版本加密的,' +
                        str(result[1]))
                    return (False, True, data)
            else:
                self.logger.error('解密ansible加密数据时失败,原因:未知格式的加密方法')
                return (False, True, data)
        else:
            self.logger.error('解密ansible加密数据时失败,原因:未知格式的加密方法')
            return (False, False, '未知格式的加密数据')