Source code for pyfva.clientes.validadorv2

'''
Created on 19 jul. 2017

@author: luis
'''

from pyfva.soap.validador_certificado import ValideElServicio as ValideServicioCertificado,\
    ValidadorDeCertificadoSoapServiceStub,\
    SoliciteLaValidacionDelCertificadoDeAutenticacion
from pyfva.soap.validador_documento_v2 import ValideElServicio as ValideServicioDocumento,\
    ValideElDocumentoXmlEnvelopedCoFirma,\
    ValideElDocumentoXmlEnvelopedContraFirma, ValideElDocumentoMSOffice, ValideElDocumentoOdf, \
    ValideElDocumentoPdf

from pyfva.soap import settings
from pyfva.constants import get_text_representation, ERRORES_VALIDA_CERTIFICADO,\
    ERRORES_VALIDAR_ODF, ERRORES_VALIDAR_MSOFFICE,\
    ERRORES_VALIDAR_XMLCONTRAFIRMA, ERRORES_VALIDAR_XMLCOFIRMA,\
    ERRORES_VALIDAR_PDF
import traceback

from pyfva import logger
from pyfva.soap.validador_documento_v2 import ValidadorDeDocumentosSoapServiceStub


[docs]class ClienteValidador(object): """Permite validar una firma o un documento utilizando los servicios del BCCR Los documentos que se pueden validar son: * Certificados digitales (CA nacional) * XML: con cofirma y contrafirma * MSOffice: .docx, .xlsx y .pptx * ODF: .odt, .ods y .odp * PDF: .pdf .. note:: Los parámetros negocio y entidad de momento no son requeridos, pero puede que en un futuro cercano lo sean, por lo que se recomienda suministrarlos. :param negocio: número de identificación del negocio (provisto por el BCCR) :param entidad: número de identificación de la entidad (provisto por el BCCR) """ DEFAULT_CERTIFICATE_ERROR = { 'codigo_error': 1, 'texto_codigo_error': get_text_representation( ERRORES_VALIDA_CERTIFICADO, 1), 'exitosa': False, 'certificado': None }
[docs] def DEFAULT_DOCUMENT_ERROR(self, ERRORES_VALIDA): return { 'exitosa': False, 'codigo_error': 1, 'texto_codigo_error': get_text_representation(ERRORES_VALIDA, 1), 'advertencias': None, 'errores_encontrados': None, 'firmantes': None, }
def __init__(self, negocio=settings.DEFAULT_BUSSINESS, entidad=settings.DEFAULT_ENTITY): self.negocio = negocio self.entidad = entidad
[docs] def validar_documento(self, documento, formato): """Valida si el documento está firmado correctamente. :param documento: documento xml en base64 :param formato: tipo de documento a validar (cofirma, contrafirma, msoffice, odf). Retorna una diccionario con los siguientes elementos, en caso de error retorna **DEFAULT_DOCUMENT_ERROR**. .. note:: Observe que en caso de no ser exitosa la operación los atributos 'advertencias', 'errores_encontrados' y 'firmantes' retornarán None :returns: **codigo_error**: Es 0 si el resultado fue exitoso, 1 si existe algún error. **texto_codigo_error**: Texto de información sobre el código de error. **exitosa**: La transacción fue exitosa. **firmas**: Listado de firmas en el documento. - es_valida: La firma encontrada es válida. - es_avanzada: Es una firma avanzada. - error: Ha ocurrido un error al validar la firma. - detalle_de_error: Texto de detalle del error encontrado si existe. - garantia_de_integridad_y_autenticidad: La firma garantiza la integridad y autenticidad del documento - garantia_de_validez_tiempo: Datos de la garantía del tiempo. - detalle: Detalle de la firma. - autoria_del_firmante: La firma garantiza la autoría del firmante **resumen**: Resumen de resultados de validación del documento, contiene los elementos 'integridad', 'jerarquia_de_confianza', 'vigencia', 'tipo_de_certificado', 'revocacion', 'fecha_de_firma' Cada uno de los elementos tiene los siguientes campos ('estado', 'se_evalua', 'respuesta', 'codigo') **errores**: Errores encontrados al validar el documento """ logger.debug({'message':"Validador: validar_documento", 'data': {'format': formato, 'data': repr(locals())}, 'location': __file__}) try: if formato == 'cofirma': dev = self._validar_documento_cofirma(documento) elif formato == 'contrafirma': dev = self._validar_documento_contrafirma(documento) elif formato == 'msoffice': dev = self._validar_documento_msoffice(documento) elif formato == 'odf': dev = self._validar_documento_odf(documento) elif formato == 'pdf': dev = self._validar_documento_pdf(documento) else: logger.error({'message':"Validador: validando documento", 'data': {'format': formato, 'message':"No existe formato especificado"}, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA) except Exception as e: logger.error({'message':"Validador: validando documento", 'data': {'format': formato, 'message': e}, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA) logger.info({'message': "Validador: validar_documento", 'data': {'format': formato, 'result': dev}, 'location': __file__}) return dev
[docs] def validar_certificado_autenticacion(self, certificado): """Valida si el certificado de autenticación es válido y no está revocado. :param certificado: Certificado en base64 Retorna una diccionario con los siguientes elementos, en caso de error retorna **DEFAULT_CERTIFICATE_ERROR**. :returns: **codigo_error:** Número con el código de error 0 es éxito **texto_codigo_error:** Descripción del error **exitosa:** True si fue exitosa, False si no lo fue **certificado:** Si la operación no fue exitosa retorna None, si lo fue retorna un diccionario con: **identificacion:** Número de identificación del suscriptor dueño del certificado **nombre:** Nombre completo del suscriptor dueño del certificado **inicio_vigencia:** Fecha de inicio del vigencia del certificado **fin_vigencia:** Fecha de finalización de la vigencia del certificado """ logger.debug({'message': "Validador: validar_certificado_autenticacion", 'data': repr(locals()), 'location': __file__}) try: dev = self._validar_certificado_autenticacion(certificado) except Exception as e: logger.error({'message': "Validador: validando certificado", 'data': e, 'location': __file__}) dev = self.DEFAULT_CERTIFICATE_ERROR logger.info({'message': "Validador: validar_certificado_autenticacion result ", 'data': dev, 'location': __file__}) return dev
[docs] def validar_servicio(self, servicio): """Valida si el servicio está disponible. :param servicio: tipo de servicio a validar, puede ser 'certificado' o 'documento' :returns: True si lo está o False si ocurrió algún error contactando al BCCR o el servicio no está disponible """ dev = False if servicio.lower() == 'certificado': dev = self._validar_servicio_certificado() elif servicio.lower() == 'documento': dev = self._validar_servicio_documento() logger.info({'message': "Validador: Validar servicio", 'data': {'servicio':servicio, 'result':dev}, 'location': __file__}) return dev
# Private methods def _validar_documento_cofirma(self, documento): stub = ValidadorDeDocumentosSoapServiceStub() options = ValideElDocumentoXmlEnvelopedCoFirma() options.elDocumento = documento try: status = stub.ValideElDocumentoXmlEnvelopedCoFirma(options) dev = self._extract_documento( status.soap_body.ValideElDocumentoXmlEnvelopedCoFirmaResult, ERRORES_VALIDAR_XMLCOFIRMA) except Exception as e: logger.error({'message':"Validador: validando cofirma", 'data': e, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA) dev['extrar_error'] = str(e) return dev def _validar_documento_contrafirma(self, documento): stub = ValidadorDeDocumentosSoapServiceStub() options = ValideElDocumentoXmlEnvelopedContraFirma() options.elDocumento = documento try: status = stub.ValideElDocumentoXmlEnvelopedContraFirma(options) dev = self._extract_documento( status.soap_body.ValideElDocumentoXmlEnvelopedContraFirmaResult, ERRORES_VALIDAR_XMLCONTRAFIRMA) except Exception as e: traceback.print_exc() logger.error({'message':"Validador: validando contrafirma", 'data': e, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCONTRAFIRMA) dev['extrar_error'] = str(e) return dev def _validar_documento_msoffice(self, documento): stub = ValidadorDeDocumentosSoapServiceStub() options = ValideElDocumentoMSOffice() options.elDocumento = documento try: status = stub.ValideElDocumentoMSOffice(options) dev = self._extract_documento( status.soap_body.ValideElDocumentoMSOfficeResult, ERRORES_VALIDAR_MSOFFICE) except Exception as e: logger.error({'message':"Validador: validando MSOffice", 'data': e, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_MSOFFICE) dev['extrar_error'] = str(e) return dev def _validar_documento_odf(self, documento): stub = ValidadorDeDocumentosSoapServiceStub() options = ValideElDocumentoOdf() options.elDocumento = documento try: status = stub.ValideElDocumentoOdf(options) dev = self._extract_documento( status.soap_body.ValideElDocumentoOdfResult, ERRORES_VALIDAR_ODF) except Exception as e: logger.error({'message':"Validador: validando ODF", 'data':e, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_ODF) dev['extrar_error'] = str(e) return dev def _validar_documento_pdf(self, documento): stub = ValidadorDeDocumentosSoapServiceStub() options = ValideElDocumentoPdf() options.elDocumentoPdf = documento try: status = stub.ValideElDocumentoPdf(options) dev = self._extract_documento( status.soap_body.ValideElDocumentoPdfResult, ERRORES_VALIDAR_PDF) except Exception as e: logger.error({'message':"Validador: validando PDF", 'data': e, 'location': __file__}) dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_PDF) dev['extrar_error'] = str(e) return dev def _extract_firma_detalle(self, Detalle): dev = { 'integridad': None, 'jerarquia_de_confianza': None, 'vigencia': None, 'tipo_de_certificado': None, 'revocacion': None, 'fecha_de_firma': None } if Detalle.Integridad: dev['integridad']={ 'estado': Detalle.Integridad.EstadoRespuesta, 'se_evalua': Detalle.Integridad.SeEvalua, 'respuesta': Detalle.Integridad.Respuesta or '', 'codigo': Detalle.Integridad.CodigoRespuesta } if Detalle.JerarquiaDeConfianza: dev['jerarquia_de_confianza'] = { 'estado': Detalle.JerarquiaDeConfianza.EstadoRespuesta, 'se_evalua': Detalle.JerarquiaDeConfianza.SeEvalua, 'respuesta': Detalle.JerarquiaDeConfianza.Respuesta or '', 'codigo': Detalle.JerarquiaDeConfianza.CodigoRespuesta } if Detalle.Vigencia: dev['vigencia'] = { 'estado': Detalle.Vigencia.EstadoRespuesta, 'se_evalua': Detalle.Vigencia.SeEvalua, 'respuesta': Detalle.Vigencia.Respuesta or '', 'codigo': Detalle.Vigencia.CodigoRespuesta } if Detalle.TipoDeCertificado: dev['tipo_de_certificado'] = { 'estado': Detalle.TipoDeCertificado.EstadoRespuesta, 'se_evalua': Detalle.TipoDeCertificado.SeEvalua, 'respuesta': Detalle.TipoDeCertificado.Respuesta or '', 'codigo': Detalle.TipoDeCertificado.CodigoRespuesta } if Detalle.Revocacion: dev['revocacion'] = { 'estado': Detalle.Revocacion.EstadoRespuesta, 'se_evalua': Detalle.Revocacion.SeEvalua, 'respuesta': Detalle.Revocacion.Respuesta or '', 'codigo': Detalle.Revocacion.CodigoRespuesta } if Detalle.FechaOficialDeLaFirma: dev['fecha_de_firma'] = { 'estado': Detalle.FechaOficialDeLaFirma.EstadoRespuesta, 'se_evalua': Detalle.FechaOficialDeLaFirma.SeEvalua, 'respuesta': Detalle.FechaOficialDeLaFirma.Respuesta or '', 'codigo': Detalle.FechaOficialDeLaFirma.CodigoRespuesta, 'fecha_de_estama': Detalle.FechaOficialDeLaFirma.FechaDeLaEstamaDeTiempo } return dev def _extract_firmas(self, Firma): dev = { 'es_valida': Firma.EsValida, 'es_avanzada': Firma.EsAvanzada, 'error': Firma.OcurrioUnError, 'detalle_de_error': Firma.DetalleDelError or '', 'garantia_de_integridad_y_autenticidad': Firma.GarantiaDeIntegridadYAutenticidad, 'garantia_de_validez_tiempo': [], 'detalle': [], 'autoria_del_firmante': None, } if Firma.GarantiaDeValidezEnElTiempo: dev['garantia_de_validez_tiempo'].append(Firma.GarantiaDeValidezEnElTiempo.Resultado) dev['garantia_de_validez_tiempo'].append(Firma.GarantiaDeValidezEnElTiempo.MensajeDeAdvertencia or '') if Firma.AutoriaDelFirmante: dev['autoria_del_firmante'] = { 'nombre': Firma.AutoriaDelFirmante.Nombre, 'identificacion': Firma.AutoriaDelFirmante.Identificacion, 'tiene_autoria': Firma.AutoriaDelFirmante.SeObtuvoAutoria } if Firma.Detalle: dev['detalle'] = self._extract_firma_detalle(Firma.Detalle) return dev def _extract_resumen(self, Resumen): dev = { 'firmante': Resumen.Firmante, 'identificacion': Resumen.Identificacion, 'garantia_de_integridad_y_autenticidad': Resumen.GarantiaDeIntegridadYAutenticidad, 'garantia_validez_en_el_tiempo': Resumen.GarantiaDeValidezEnElTiempo, 'resultado': Resumen.ResultadoValidacion, 'fecha_estampa_de_tiempo': Resumen.FechaEstampaDeTiempo, 'tipo_identificacion': Resumen.TipoIdentificacion, 'tiene_fecha_estampa_de_tiempo': Resumen.TieneFechaEstampaDeTiempo } return dev def _extract_resultado_resumen(self, Resumen): dev = { 'garantia_de_integridad_y_autenticidad': Resumen.GarantiaDeIntegridadYAutenticidad, 'garantia_validez_en_el_tiempo': Resumen.GarantiaDeValidezEnElTiempo, 'resultado_de_validacion': Resumen.ResultadoValidacionDelDocumentoFirmado } if Resumen.ResumenDeFirmas: dev['resumen'] = [self._extract_resumen(firma) for firma in Resumen.ResumenDeFirmas.ResumenDeFirma] return dev def _extract_documento(self, result, ERRORES_VALIDACION): dev = {} # dev.update(self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDACION)) dev['codigo_error'] = 0 if result.FueExitosa else 1 dev['texto_codigo_error'] = get_text_representation( ERRORES_VALIDACION, dev['codigo_error']), dev['exitosa'] = result.FueExitosa dev['firmas'] = None dev['resumen'] = None dev['errores'] = None if result.ErrorGeneradoAlValidar: dev['errores'] = result.ErrorGeneradoAlValidar if result.Firmas: dev['firmas'] = [self._extract_firmas(firma) for firma in result.Firmas.Firma] if result.Resumen: dev['resumen'] = self._extract_resultado_resumen(result.Resumen) return dev def _validar_certificado_autenticacion(self, certificado): stub = ValidadorDeCertificadoSoapServiceStub() options = SoliciteLaValidacionDelCertificadoDeAutenticacion() options.elCertificadoDeAutenticacion = certificado status = stub.SoliciteLaValidacionDelCertificadoDeAutenticacion( options) result = status.soap_body.SoliciteLaValidacionDelCertificadoDeAutenticacionResult return self._extract_certificado_autenticacion(result) def _extract_certificado_autenticacion(self, result): dev = { 'codigo_error': result.CodigoDeError, 'texto_codigo_error': get_text_representation( ERRORES_VALIDA_CERTIFICADO, result.CodigoDeError), 'exitosa': result.FueExitosa, 'certificado': None } if result.FueExitosa: cert = result.InformacionDelCertificado dev['certificado'] = { 'tipo_identificacion': cert.TipoDeIdentificacion, 'identificacion': cert.Identificacion or 'N/D', 'nombre': cert.NombreCompleto or 'N/D', 'inicio_vigencia': cert.FechaInicioDeLaVigencia, 'fin_vigencia': cert.FechaFinalDeLaVigencia} return dev def _validar_servicio_certificado(self): stub = ValidadorDeCertificadoSoapServiceStub() option = ValideServicioCertificado() try: status = stub.ValideElServicio(option) dev = status.soap_body.ValideElServicioResult except Exception as e: logger.error({'message': "Validador: Servicio de validado de certificado fallando", 'data': e, 'location': __file__}) dev = False return dev def _validar_servicio_documento(self): stub = ValidadorDeDocumentosSoapServiceStub() option = ValideServicioDocumento() try: status = stub.ValideElServicio(option) dev = status.soap_body.ValideElServicioResult except Exception as e: logger.error({'message': "Validador: Servicio de validado de documentos fallando", 'data': e, 'location': __file__}) dev = False return dev