Páginas

jueves, 19 de junio de 2025

GLPI (V): Tareas programadas

Introducción

El ENS exige una serie de tareas periódicas para comprobar ciertos niveles de aceptación del sistema:

En el procedimiento 3 de seguridad lógica se establecen planes:

  • Anuales (plan de mantenimiento anual)
  • Trimestrales:
    • SAIs 
  • Mensuales (?)
  • Semanales:
    • Servidor: Parches, espacio en disco, antivirus, consumo de memoria ..
    • Copias de seguridad 
    • Cortafuegos (logs, ...)

  • Diarias (?)
Manos a la obra

No se pueden crear tareas programadas de por si. Estas tienen que estar asociadas a un tiquet, para ello empezamos creando un tiquet:

Vamos a Soporte > Tiquet  botón "+Añadir"

Creamos una tarea llamada "ENS - Tareas semanales"
Podemos especificicar la categoría "ENS", y podemos seleccionar uno varios ordenadores sobre los que establecer  las tareas de mantenimiento semanal

Una vez creado el tiquet, vamos a Asistencia (Suport) > Tiquets Recurrentes > "+ Añadir"
Damos un nombre, periodicidad de 7 días,

Ahora se activan las notificaciones para que el responsable las verifique:
Configuració > Notificacions >



miércoles, 18 de junio de 2025

GLPI (IV) Base de Conocimiento

Tenemos que ir a Herramients (Eines) > Base de Conocimientos y botón de Añadir en la parte superior

Nos pide:

  1. Categoría de la base de conocimiento. Se puede crear la categoría. Si se quiere modificar hay que buscar en "Encuentra el menu" de la parte superior izquierda e indicarle:
    Configuración> Llistas desplegables > Categorías de la base de conocimiento.
  2. Tema
  3. Contenido a mostrar
  4. Ficheros de adicionales 
  5. Destinos (a nivel de entidad, grupo, perfil o usuario
Para mejorar el tema hay que definir las categorias anidadas, en mi caso se establece el primer nivel consistente en "Desatacados"(novedades etc), "Público" (Para todos los usuarios) y "Privado" (que es solo para administradores)

En el segundo nivel se establece los programas o temática sobre los que versa la documentación (Correo, contabilidad, tickets, seguridad, ...)

viernes, 13 de junio de 2025

GLPI (III) Formularios

Se ha seguido el vídeo de Paul Portales 

1. Agregar el plugin

Según Paul Portales se debe ir a :

Configuración >Plugins (o complementos) > Tienda (si no se ha registrado hay que registrarse) >Botón de duscubrir

Pero para instalar el plugin es mejor seguir estos pasos:

1. Ir a la página de descargas del plugin

https://github.com/pluginsGLPI/formcreator/releases

2. Descargar una versión compatible que está en formato zip y descomprimirla en una carpeta. Renombrar esta carpeta si es necesario a "formcreator"

3. Copiar esta carpeta "formcreator" dentro de la carpeta de plugins de GLPI

/var/www/html/glpi/plugins/

y dar permisos:

sudo chown -R www-data:www-data /var/www/html/glpi/plugins/formcreator

sudo chmod -R 755 /var/www/html/glpi/plugins/formcreator

4. Instalar el plugin desde la interfaz de GLI. Para ello inicia sesión en GLPI como administrador.

Ve a Configuración > Plugins. Busca el plugin Formcreator en la lista. 

Haz clic en Instalar. Luego, haz clic en Habilitar.

2. Crear un formulario

En GLPI ir a Administración> Formularios > Boton (+ Añadir)

Nos pide los siguientes datos generales: Nombre del formulario, icono, idioma, si está activo, si se ve en la página de inicio del usuario, color, encabezado, y le damos a guardar.

También podemos restringir el acceso a un perfil determinado de usuarios o grupos en "Tipos de accesos" del menú lateral izquierdo

Hay una opción del menú lateral izquierdo de validadadores (Validadors)o aprobación, que tiene un campo por si se quiere que otra persona o grupo valide la información que l usuario ha introducido en el formulario. Para ello, hay un apartado en el menú vertical de la izquierda que se llama "Respuestas de formulario"(Resposta de formulari), y en dicho apartado hay que aprobar lo que el usuario ha introducido.

3. Agregar Campos (Preguntas)

Hay una opción en el menú lateral izquierdo de Questions o Preguntas que son los campos a introducir al formulario. Desde aquí podemos añadir y modificar secciones donde se incluirán los campos y añadir campos (preguntas).

Para los campos se piede:
  • Nombre del campo
  • La sección donde se va a incluir
  • Si su relleno es obligaorio (no puede ir en blanco)
  • Tipo de campo:
    • Actor (glpi,normal,post-only,tech,informatic y Plugion_GLPI_Inventory)
    • Additional Fields (No está acivado el componente para este tipo de campos)
    • DIrecciones IP
    • Campo oculto (como es oculto, hay que darle un valor por defecto)
    • CheckBoxes ( y le damos cada una de las opciones separadas por salto de línea)
    • Email
    • Fecha
    • Fecha y hora
    • Descripcion (Campo de solo lectura, por ejemplo las condiciones del contrato)
    • Enter donde se indica una expresión regular que dicho campo tiene que validar
    • Fichero (para adjuntar uno varios ficheros)
    • Float (que también pide una expresión regular)
    • Hostname
    • LDAP Select: Pide un Directorio de LDAP, un filtro y un atributo (Como (AD) User ID 
    • Lista desplegable (Donde se elige una lista desplegable existente)
    • MultiSelet (Se le da los valores separados consalto de línea)
    • Objeto GLPI (Pide el tipo de objeto, ordenadores, programas, contratos ...)
    • Select (Se le da valores con salto de línea)
    • Tags ???
    • Hora
    • Text
    • TextArea
    • Tipo de petición (Incidencia, Solicitud)
    • Urgencia (Alta, baja,...)
  • Valor por defecto
  • Descripción detallada
  • Expresión regular (solo en algunos tipos de campos)
  • Máximo y mínimo número de caractres del campo
Lo bueno que tiene es que se pueden dar longitud de los campos (justo despues de los 3 iconos hay un símbolo de medio cuadarado rayado que deslizandolo cambia la longitud) y organizar la pantalla como máximo 4 campos por línea. 


Los 3 iconos que aparecen son para borrar, copiar o indicar si el campo es obligado

4. Generar tickets (Objetivos)

En el menú lateral izquierdo del formulario en Objetivos se añade un objetivo y se le da un nombre (por ejemplo "tiquet indcidencias") y tipo "Target ticket" y le damos al botón añadir.
Ahora se le da click sobre el objetivo y nos muestra una pantalla nueva y nos cambia el menú lateral
En el menu lateral "Propiedades" nos pide:
  • Entidad de destino, tiempo que debe responder el tiquet, SLA y OLA (acuerdos de nivel de servicio) ...
En el menu de "Actores" se indican solicitante, supervisor y asignado 

5. Tratamiento de respuestas de formulario

En Administracion > Formularios, elegimos el formulario en cuestión y en el menú lateral izquierdo entramos en "Respuestas de formulario" y al final hay un campo textarea que es un comentario por parte del que tiene que aprobar el formulario.

Una vez aprobado, ya aparece como ticket en el apartado Tiquets de la pantalla del usuario.
Para el usuario administrador se puede ver en Suport > Tiquets
Y en la pantalla de la izquierda se puede reasignar el tiquet a otro actor.
El actor que se le ha asignado, puede apretar el botón de "Responder" y crea unmensaje mediante una textarea con la infomación pertinente para resolver el problema. Tambien se puede adjuntar un archivo para completar la informacfión de resolución del problema.

6. Generar un PDF del Formulario

Si queremos guardar el formulario como PDF vamos a:
Administracion > Formularios y en el menú lateral izquierdo buscamos Formulario y en el campo cabecera marcamos los tres puntitos "..." y le damos al icono de pantalla completa (que es el último)

Podemos añadir tablas, emoticonos, vínculos, imágens etc.

Para añadir una imagen, hay que:
  1. Darle al icono de la imagen
  2. Nos pide un nombre, el cual será el nombre simple del fichero de la imagen con su extensión (sin su ruta), por ejemplo logo01.jpg y opcionalemente una descripción alternativa y tamaño horizontal y vertical
  3. Una vez añadido, nos vamos al icono "<>" para ver el código fuente y vemos que hay un fragmento de código que dice:
    <img src="http://192.168.XXX.XXX/glpi/plugins/formcreator/front/logo01.jpg" alt="Prova Edu" width="50" height="100">
  4. Como en nuestro caso se ha instalado el glpi en la ruta:
    /var/www/glpi del servidor, tenemos que copiar el fichero de la imagen a la carpeta indicada pero con la siguiente ruta: 
    /var/www/glpi/plugins/formcreator/front
    pero hay que cambiarle el usuario a www-data y el grupo a www-data al fichero copiado con el comando chown 
Pero todo esto que hemos añadido se verá solo en la cabecera del formulario.

No hacía falta tanta historia. Pero si se quiere tener documentos con el logo de la empresa y se quieren guardar, esto le daría un poco mas de adaptación del formulario a la imagen dela empresa.

Para impriomir el formulario, aparwece el símbolo de la impresora en el título del formulario y al hacer click se imprime y se puede elegir imprimirlo a PDF









martes, 10 de junio de 2025

GLPI (II). Chuleta de utilización

1. Uso básico

1.1 Acceso

http://192.xxx.xxx.xxx/glpi

usuario glpi

contraseña: mi_contraseña

2. Gestión de usuarios

En Administración > Usuarios > Acciones - Botón Añadir Usuario

Se le indica nombre, login, email, perfil (técnico, admin, usuario,..), Entidad

Desde el usuario en la pestaña perfiles se le pueden añadir múltiples permisos por entidad

3. Gestión de entidades

En Administración > Entidades 

Se puede configurar la separación de usuarios y formularios

4. Gestión de tickets

En Asistencias > Tickets

Se pueden crear tickets, asignar a un técnico, cambiar estado, definir reglas de automatización

5. Formularios personalizados

En Configuración > Formularios

Crear campos adicionales por tipo (ticket, equipo, usuario ..)

Utilizar campos tipo (texto, números, listas estáticas y dinámicas

6. Inventario de equipos 

Para ello hay que instalar el agente a cada ordenador.


lunes, 9 de junio de 2025

GPLI (I). Instalar el agente en Ubuntu y Windows. Crear política de grupo

1. Instalar el agente en Ubuntu

Tenemos un ciente Ubuntu (no un servidor) y queremos que aparezca en el inventario.

 Vamops a la URL 

https://github.com/glpi-project/glpi-agent/releases

y descargamos:

glpi-agent_1.14-2_all.deb

Ahora ejecutamos:

sudo dpkg -i glpi-agent_1.14-2_all.deb

y nos da algunos errores. Para solucionarlo ejecutamos:

sudo apt-get install -f --fix-missing

y volvemos a ejecutar:

sudo dpkg -i glpi-agent_1.14-2_all.deb

Y probamos a ver si funciona:

sudo systemctl status glpi-agent

y nos da error:

× glpi-agent.service - GLPI agent
     Loaded: loaded (/usr/lib/systemd/system/glpi-agent.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Mon 2025-06-09 13:47:51 CEST; 12s ago
   Duration: 144ms
       Docs: man:glpi-agent
    Process: 550431 ExecStart=/usr/bin/glpi-agent --daemon --no-fork $OPTIONS (code=exited, status=1/FA>
   Main PID: 550431 (code=exited, status=1/FAILURE)
        CPU: 111ms
de juny 09 13:47:51 a03-inf-005 systemd[1]: Started glpi-agent.service - GLPI agent.
de juny 09 13:47:51 a03-inf-005 glpi-agent[550431]: [error] No target defined, aborting
de juny 09 13:47:51 a03-inf-005 systemd[1]: glpi-agent.service: Main process exited, code=exited, statu>
de juny 09 13:47:51 a03-inf-005 systemd[1]: glpi-agent.service: Failed with result 'exit-code'.


Para solucionarlo, modificamos el fichero de configuración:

sudo nano /etc/glpi-agent/agent.cfg

y añadimos la línea 

server = http://192.168.28.28/glpi

guardamos y rearrancamos el servicio y vemos el estado

sudo systemctl start glpi-agent

sudo systemctl status glpi-agent 

y funciona bien

● glpi-agent.service - GLPI agent
     Loaded: loaded (/usr/lib/systemd/system/glpi-agent.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-06-09 14:27:54 CEST; 4s ago
       Docs: man:glpi-agent
   Main PID: 569553 (glpi-agent: wai)
      Tasks: 1 (limit: 38323)
     Memory: 62.8M (peak: 62.9M)
        CPU: 343ms
     CGroup: /system.slice/glpi-agent.service
             └─569553 "glpi-agent: waiting"
de juny 09 14:27:54 a03-inf-005 systemd[1]: Started glpi-agent.service - GLPI agent.
de juny 09 14:27:54 a03-inf-005 glpi-agent[569553]: [info] GLPI Agent starting
de juny 09 14:27:54 a03-inf-005 glpi-agent[569553]: [info] [http server] HTTPD service started on port >
de juny 09 14:27:54 a03-inf-005 glpi-agent[569553]: [info] target server0: next run: Tue Jun 10 13:11:5>

2. Instalar el agente en Windows

Vamos a esta URL

https://github.com/glpi-project/glpi-agent/releases

y descargamos

GLPI-Agent-1.14-x64.msi

Lo ejecutamos como administrador, damos todos los valores por omisión excepto la dirección del servidor que le damos:

http://192.168.28.28/glpi 



Pero no nos hace caso pues no lo ha copiado en el fichero de configuración.
Cuando se ha instalado ya hay que ediar este fichero en modo administrador:
C:\Program Files\GLPI-Agent\etc\agent.cfg
y añadimos la línea 
server = http://192.168.28.28/glpi
y guardamos.

Forzamos el servicio con el modo administrador:

cd "C:\Program Files\GLPI-Agent"
glpi-agent.bat --debug --force

puede que de algunos avisos sin importancia como 

C:\Program Files\GLPI-Agent>glpi-agent.bat --debug --force Use of uninitialized value $category in array element at C:/Program Files/GLPI-Agent/perl/agent/GLPI/Agent/Task/Inventory/Win32/Firewall.pm line 115. 

Pero lo importnte es ver si se ha aparecido en el GLPI en la parte de ordenadores


3. Instalar con política de grupo GPO

1. Primeramente se crea una capeta compartida en SYSVOL por ejemplo XIMO-GLPI-agent-deployment. La ruta de esta carpeta vista desde el servidor de dominio es:

C:\Windows\SYSVOL\sysvol\<TuDominio>\Policies\XIMO-GLPI-agent-deployment

donde <TuDominio> es el nombre que se le haya dado al dominio

2. Se copia el GLPI-Agent-1.14-x64.msi a dicha carpeta. Para ello se utiliza xcopy en una consola ejecutada como administrador.

3. Crear un archivo de transformación (MST) para la configuracion del servidor GLPI

1. Primeramente se guarda el programa GLPI_Agent-1.14-x64.msi en una carpeta del sistema que todo el mundo pueda acceder.

2. Se crea este programa instalar_glpi_agent.bat en una ruta compartida

@echo off
msiexec /i "\\servidor\instaladores\GLPI-Agent-1.14-x64.msi" /qn /norestart SERVER=http://192.168.28.28/glpi

3. Se crea una política de grupo:

3.1 Abre GPMC (Group Policy Management Console).

3.2 Crea una nueva GPO: Instalación GLPI Agent.

3.3 Edita la GPO y ve a:

Configuración del equipo > Configuración de Windows > Scripts (Inicio/Apagado) > Inicio

3.4 Añade el script instalar_glpi_agent.bat desde la ruta compartida.

3.5 Aplica la GPO a las unidades organizativas (OU) con tus ordenadores.

3.6 Forzar actualización de GPO. En los clientes, puedes probar con:

gpupdate /force


jueves, 15 de mayo de 2025

OSTicket (2) Estructura de la BD

 1. Relación de tablas:

Estas son las tablas:

ost__search             
ost_api_key             
ost_attachment          
ost_canned_response     
ost_config              
ost_content             
ost_department          
ost_draft               
ost_email               
ost_email_account       
ost_email_template      
ost_email_template_group
ost_event               
ost_faq                 
ost_faq_category        
ost_faq_topic           
ost_file                
ost_file_chunk          
ost_filter              
ost_filter_action       
ost_filter_rule         
ost_form                
ost_form_entry          
ost_form_entry_values   
ost_form_field          
ost_group               
ost_help_topic          
ost_help_topic_form     
ost_list                
ost_list_items          
ost_lock                
ost_note                
ost_organization        
ost_organization__cdata 
ost_plugin              
ost_plugin_instance     
ost_queue               
ost_queue_column        
ost_queue_columns       
ost_queue_config        
ost_queue_export        
ost_queue_sort          
ost_queue_sorts         
ost_role                
ost_schedule            
ost_schedule_entry      
ost_sequence            
ost_session             
ost_sla                 
ost_staff               
ost_staff_dept_access   
ost_syslog              
ost_task                
ost_task__cdata         
ost_team                
ost_team_member         
ost_thread              
ost_thread_collaborator 
ost_thread_entry        
ost_thread_entry_email  
ost_thread_entry_merge  
ost_thread_event        
ost_thread_referral     
ost_ticket              
ost_ticket__cdata       
ost_ticket_priority     
ost_ticket_status       
ost_translation         
ost_user                
ost_user__cdata         
ost_user_account        
ost_user_email          

martes, 6 de mayo de 2025

OSTicket (I) API

1. Introducción

La API de OsTicket es poco funcional ya que de momento solo permite crear tickets

Para utilizar la API de OsTicket hay que primeramente crear una clave

Existen proyectos para dar mas funcionalidad a la API como la de BMSVieira que está en Github y en documentación. Pero no he podido hacerlo funcionar

2. Creación de una clave para usar la API

Nos vamos a Tauler de l'administrador



Nos vamos Administració-API y le indicamos el campo Adreça IP

Y obternemos una clave para una determinada IP



3. Crear un ticket


Veamos un programa en python para crear un ticket. 

import requests

def display_response(response):
	try:
		print(response.json())
	except Exception:
		print(response.text)

def get_new_tiket_old():
	headers = {
		"X-API-Key": "XXXXXXXXXXXX",
		"Content-Type": "application/json",  # Lo que envío
    	        "Accept": "application/json"         # Lo que quiero recibir
	}
	data = {
		"name": "Ximo",
		"email": "ximodante@gmail.com",
		"subject": "2ª Prueba llamada a API de creación de tickets",
		"message": "A ver si crea el ticket por 2ª vez",
	}	
	url='http://192.168.XXX.XXX/osticket/api/http.php/tickets.json'
	response = requests.post(url, json=data, headers=headers)
	display_response(response)
	
if __name__ == "__main__":
	get_new_tiket_old()

Y crea un ticket y nos devuelve el id del ticket, en mi caso:

CAU-460357

4. Instalacion de BMSVieira API (no funciona!!!)


Vamos al git , descargamos el proyecto y descomprimimos el fichero zip.

Nos vamos a la carpeta donde se ha descomprimimdo y hacemosun scp para copiarlo al directorio /www del servidor de osticket

scp -r ./ost_wbs usuario@ip_del_servidor:/var/www/osticket

Pero no me funciona !!!!!!!




miércoles, 30 de abril de 2025

Gitlab(5): Problemas

1. Después de funcionar bien VS con gitlab durante una temporada, se produce este error:

Node.js v20.18.3

git@gitlab.municipio.es: Permission denied (publickey,password).

fatal: No s'ha pogut llegir del repositori remot.


Assegureu-vos que tingueu els permisos

d'accés correctes i que el repositori existeixi.


SOLUCIÓN: Parece ser que se ha perdido la clave ssh. Para ello, se busc el nombre del fichero de clave ssh (en mi caso es id_ed25519.ximo) y  se ejecuta:

ssh-add ~/.ssh/id_ed25519.ximo

NOTA: Cuando se crea un usuario dentro de Gitlab, se le puede crear una clave ssh para que no vuelva a pedir más la contraseña. Esta clave se guarda en la carpeta ~/.ssh

Esto sucede si en VS se ha configurado para acceder a gitlab con ssh. Para comprobar que estamos accediendo con ssh se ejecuta dentro de la carpeta principal del proyecto

git remote -v

y si el resultado comienza por origin  git@   entonces es ssh y si empieza por origin https entonces es https




martes, 29 de abril de 2025

INAP curso seguridad (II) Introducción al ENS

 1. Definiciones:

  • Política de seguridad:
  • Principios:
    • Asegurar acceso
    • Confidencialidad
    • Integridad
    • Trazabilidad
    • Autenticidad
    • Disponibilidad
    • Conservación de datos
  • Requisitos mínimos:

2. Principios básicos del ENS

  • Seguridad como proceso integeral
  • Gestión de la seguridad basada en riesgos
  • Prevención, detección, respuesta y conservacion
  • Gerstión de incidentes
  • Existencia de líneas de defensa en varias capas
  • Vigilancia continua
  • Reevaluación periódica
  • Diferenciación de responsabilidades: 
    • 3 niveles: 
      • Gobierno (dirección)
      • Supervisión (RESEG responsable de seguridad  y DPDP delegado de protección de datos).
      • Operativo (RS Responsable de sistemas, AD Administrador de seguridad y OS Operadores del sistema)
    • 3 roles: Dirección , responsable de información y responsable de servicio
    • Otros roles: Responsable de seguridad física, Responsable de gestión de personal, responsable de contratación y adquisición, usuarios del sistema. 
    • No se puede ser responsable de sistemas y de seguridead
    • La política de seguridad detallará las atribuciones de cada rol
    • 4 responsables:
      • Información
      • Servicio
      • Seguridad
      • Sistema (pueden ser varias personas delegadas)

lunes, 28 de abril de 2025

INAP curso seguridad (I) Protección de datos personales

 Créditos: https://sede.inap.gob.es/proteccion-de-datos-personales

1. Fuentes de derecho

Constitución española. Su artículo 18.4 otorga el carácter de derecho fundamental a la protección de datos de carácter personal.

Ley Orgánica 3/2018, de 5 de diciembre, de Protección de Datos Personales y garantía de los derechos digitales.

Reglamento (UE) n.º 2016/679 del Parlamento Europeo y del Consejo, de 27 de abril de 2016, relativo a la protección de las personas físicas en lo que respecta al tratamiento de datos personales y a la libre circulación de estos datos y por el que se deroga la Directiva 95/46/CE

2. Responsable del tratamiento de los datos de carácter personal (RTDP)

Es la persona física o jurídica, autoridad pública, servicio u otro organismo que, solo o junto con otros, determine los fines y medios del tratamiento (RUE 2016/679)

3. Delegado de protección de datos (DPD)

El RGPD establece además la obligación de designar un delegado de protección de datos (DPD) a toda autoridad u organismo del sector público que lleve a cabo tratamiento de datos personales

4. Registro de actividades de tratamiento

Primeramente de clasifican las actividades de tratamiento, que antiguamente correspodían a ficheros. Dichas actividades pueden ser:
  • Gestión tributaria y recaudatoria
  • Gestión de Personal
  • Servicios sociales
Para cada actividad se describen los siguientes datos:
  • Nombre de la actividad
  • Fecha de actualización
  • Responsable de tratamiento (normalmente es el responsable del tratamiento (visto en el punto 2)
  • Corresponsable: Normalmente la persona o departamento encargado de dicha actividad
  • Delegado de protección de datos (normalmente es la persona del punto 3)
  • Fines del tratamiento. La gestión de dicha actividad
  • Base legal: Normalmente la legislación que ampara dicha actividad (reglamento de reaudación, etc)
  • Catagoría de los interesados: Personas físicas, jurídicas ...
  • Categoría de los datos personales: (Datos identificativosm y de contacto, datos académicos, datos fiscales,..)
  • Categoría de los destinatarios:(Bases dwe convocatorias etc)
  • Transferencias internacionales: (solo cuando sw precean)
  • Medidas técnicas y organizativas de seguriead:Normalmente:Las medidas de seguridad corresponden a las aplicadas de acuerdo al Anexo II (Medidas de seguridad) del Real Decreto 3/2010, de 8 de enero, por el que se regula el Esquema Nacional de Seguridad en el ámbito de la Administración Electrónica.
Ejemplo para el INAP

5. Derechos del interesado. Vías para ejercer los derechos

Los derechos de los interesados se establecen en los artículos 15 al 22 del RGPD
Para ejercer los derechos se dirigirán a:
  • RTDP por vía electrónica o Red de oficinas en materia de registro (https://administracion.gob.es)
  • DPD (art. 38.4 RGPD)
  • AEPD (Agencia Española de protección de Datos) para reclamaciones




 

jueves, 24 de abril de 2025

Certificados: Instalar el certificado raiz en Chrome, Mozilla, Edge y Brave

1. Windows (Resto de navegadores -Chrome, Edge, Brave ..)



  1. Crear/Editar GPO

    • Abra Administración de Directivas de Grupo (gpmc.msc)

    • Vincule un GPO nuevo/existente a la OU objetivo

  2. Importar certificado al almacén del sistema
    Navegue a:
    Configuración del equipo → Políticas → Configuración de Windows → Configuración de seguridad → Directivas de clave pública → Entidades de certificación raíz de confianza

    • Click derecho → Importar

    • Seleccione el archivo .cer desde una ruta de red accesible (ej: \\servidor\certificados\rootCA.cer)

  3. Opciones clave de implementación

    • Almacén destino: Autoridades de Certificación Raíz de Confianza

    • Actualización automática: 90-120 minutos (default) o forzar con gpupdate /force

Verificación en Edge

  • Acceda a edge://settings/privacyAdministrar certificados

  • En Autoridades de certificación raíz, confirme la presencia del certificado

Notas técnicas:

  • Edge usa el almacén de certificados de Windows (Cert:\LocalMachine\Root)

  • Formatos compatibles: .cer, .crt, .der (evite .pem sin conversión)

  • Para instalaciones masivas:

certutil -f -addstore "Root" \\network\path\rootCA.cer


Este método garantiza compatibilidad con Edge 94+ y versiones Chromium-based, sin requerir configuraciones adicionales en el navegador[1][2][3].

  1. https://learn.microsoft.com/es-es/windows-server/identity/ad-fs/deployment/distribute-certificates-to-client-computers-by-using-group-policy

  2. https://techexpert.tips/es/windows-es/gpo-instalacion-de-un-certificado-raiz/

  3. https://woshub.com/how-to-deploy-certificate-by-using-group-policy/


2. Mozilla Firefox en Windows

Lo mas común es crear una GPO para que acepte el certificado raiz del repositorio de Windows. Como ya se instaló antes mediante una GPO, ahora hay que hacer otra GPO para que admita los certificados del repositorio de Windows. Veamos los pasos

1. Descargar las plantillas administrativas del almacén de Firefox
OJO: Según David hay que copiar dichas plantillas ern el SYSVOL compartido del servidor!!!!

2. Ejecutar en una consola de comandos gpmc.msc

3. Ir a una unidad organizativa (OU) de prueba y con el botón derecho indicar "Crear un GPO en este dominio y vincularlo aqui .. "

4. Darle un nombre por ejemplo EDU-Arrel-Firefox y editar

5. Ir a:
  • Configuración de equipo
  • Directivas
  • Plantillas administrativas: definiciones de equipo
  • Mozilla
  • Firefox
  • Certificates
  • Import Enterprise Roots : Habilitada


6. En los PCs de los usuarios hay que ejcutar gpupdate /force


OJO: Si entramos en Firefox a ver las entidades certificadoras raíz, NO APARECERÁ la nuestra, pues solo muestra los certificados de su base de datos y no los del repositorio de Windows aunque si hace referencia a ellos !!!

3. Corrección de Problemas

1. Verificar que en el cliente se han instalado las GPO

Ejecutar en el cliente en modo administrador gpresult /R /scope:computer 
 Y ver si se muestran las GPO aplicadas al equipo

2. Verificar que el certificado raíz esté instalado en al repositorio de windows del cliente.

En el cliente ejecutar en modo administrador:

certmgr.msc

Y vemos que se ha instalado en entidfades de certificación raiz de confianza:


Si entramos en Firefox a ver los certificados raiz instalados, NO APARECERÁ nuestro certificado raíz, pues Firefox se está nutriendo de 2 repositorios de certificados: el suyo propio y el de Wiindows. Cuando consulamos los certificados desde Firefox no aparecerá, pues aunque admite los certificados del repositorio de windows, NO LOS MUESTRA.

Si no va, no queda mas remedio que instalar manaulmente el certificado de la entidad certificadora.!!!1

NO USAR LO QUE VIENE A CONTINUACIÓN

1.1 Idea principal

Se tiene que crear el fichero "policies.json" en la carpeta de instalacioón del Mozilla Firefox: 

"C:\Program Files\Mozilla Firefox\distribution\"

que tendrá este contenido:

{
  "policies": {
    "Certificates": {
      "Install": ["C:\\ruta\\certificado\\rootCA.cer"]
    }
  }
}

Siendo "C:\\ruta\\certificado\\rootCA.cer" la ruta del retificdo raiz a instalar.


1.2 Utilizar una GPO

Lo más cómodo es utilizar una GPO. Vale la pena crear una OU de pruebas y meter un ordenador dentro.

Veamos el fichero power shell que se ejecuta como administrador de la máquina, y busca en las posibles rutas de instalación de Firefox y si lo encuentra crea este fichero para que el certificado raiz se instale en el Mozilla Firefox:

#Requires -RunAsAdministrator

# 1. Posibles rutas de instalación de firefox
$firefoxPaths = @(
    "C:\Program Files\Mozilla Firefox",
    "C:\Program Files (x86)\Mozilla Firefox"
)

# 2. Ruta del certificado a instalar
$certPath = "\\servidor\red\certificados\rootCA.pem"

# 3. Verificar ejecución como administrador
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Error "Ejecutar como Administrador"
    exit 1
}

try {
    # 4. Buscar instalación existente de Firefox
    $firefoxInstallPath = $firefoxPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if ($firefoxInstallPath) {
        $distPath = Join-Path $firefoxInstallPath "distribution"
        
        if (-Not (Test-Path $distPath)) {
            New-Item -ItemType Directory -Path $distPath | Out-Null
        }
		# 5. Contenido del fichero json para copiar el certificado al directorio de distribución
        $jsonContent = @"
{
    "policies": {
        "Certificates": {
            "Install": ["$certPath"]
        }
    }
}
"@
        # 6. Escribir el fichero json en el directorio de distribución
		#    Para que al rearrancar firefox se instale el certificado
		$jsonContent | Out-File -FilePath "$distPath\policies.json" -Encoding utf8 -Force
		
		# 7. Copiar el certificado al directorio de distribución
		Copy-Item -Path $certPath -Destination $distPath -Force

		# 8. Crear el fichero policies.json en el directorio de distribución
		#    y escribir el contenido del json en él
		$jsonContent | Set-Content -Path "$distPath\policies.json" -Force
        Write-Output "Política aplicada en: $distPath\policies.json"
    }
    else {
        Write-Warning "Firefox no está instalado en rutas estándar"
    }
}
catch {
    Write-Error "Error en la implementación: $_"
    exit 1
}

ahora guardamos el fichero como Deploy-FirefoxCert.ps1

Ahora vamos al Windows 2019 server y en el Administrador de Directivas de Grupo:

  • Crear nueva GPO > Editar
  • Navegar a: Configuración del equipo/Preferencias/Configuración de Windows/Tareas programadas 
  • Crear tarea:
    • Acción: Iniciar programa
    • Programa/script: powershell.exe
    • Argumentos: -ExecutionPolicy Bypass -File "\\ruta\netlogon\Deploy-FirefoxCert.ps1"
    • Ejecutar con privilegios más altos: Habilitado
Vincular GPO a la OU correspondiente


Verificación post-implementación:

En cliente Windows, abrir "about:policies en Firefox" y verificar certificado en "about:certificate"

Consideraciones clave:

El certificado debe estar accesible desde todas las estaciones ([ruta de red])

Para actualizaciones de certificado, modificar el archivo rootCA.pem y forzar reimplementación GPO


martes, 22 de abril de 2025

Python(XXVII). Beforeware. Aplicando el ENI (II). Comprobación de las entradas de datos. FastHTML beforeware

 1. Beforeware en FastHTML

Cuando creamos una aplicacion FastHTML utilizando app = FastHTML(), podemos pasar un parámetro que es "before=Beforeware(función)" siendo "función" el nombre de una función que hemos definido para ejecutarse justo antes de ejecutar una ruta. Si la función devuelve "None", la petición sigue normalmente. Andreas Stokl lo explica muy bien.

Uno de nuestros objetivos a verificar es que el "tab_id" sea el correcto y que tengamos un usuario correcto.Para ello, sino se cumplen estos requisitos, se redirigirá a la pantalla de login.

Para ello se define una función que será la del beforeware:

#2. Beforeware function to be executed in all endpoints
def my_before_function(req, tab_id, sess):
	'''
	Beforeware function: checks that the user is authenticated
	'''
	print('Des de beforeware, la URL es:', req.url)
	# 1. Validem que haja tab_id i que l'usuari estiga en la sessió de la BD
	my_response,myerror=xmsession.validate(tab_id=tab_id, req=req)
	if (len(myerror.strip())>1):
		print ("redirecting from my_before_function " )
		return my_response

Otra cosa importante, es decirle al beforeware que regex hay que saltarse "skip"para que no haga comprobaciones en cada caso. En AnswerDotAi se puede ver mirando el comentario del código.

# To create a Beforeware object, we pass the function itself, and optionally a list of regexes to skip.
my_before_function = Beforeware(my_before_function, skip=[r'/favicon\.ico', r'/static/.*', r'.*\.css', '/login'])

Ahora hay que indicarselo a la aplicación:

app = fh.FastHTML(
	hdrs=my_headers, 
	before=my_before_function,
	secret_key=xmother.new_id(25), 
	exception_handlers=exception_handlers)

 2. Lo que se puede hacer con beforeware:

Se puede:
  • Guardar para auditar en la BD, las peticiones (url, usuario, fecha y hotra, IP ...)
  • Verificar si el usuario tiene permisos para acceder a dicha URL
  • Detectar si hay código malicioso en la petición (inyección de SQL ...)



martes, 15 de abril de 2025

Python (XXVI) Sqlalchemy: Localizar e importar todas las clases a persistir. Modificar las tablas cuando la clase asociada cambia

1. Importar todas las clases a persistir con sqlalchemy

Para ello debemos tener todos los módulos que definen las clases dentro de una carpeta, en mi caso "models"

Creamos un módulo dentro de la carpeta "models" que recoja toda las clases y así solo tenemos que importar el array de clases a persistri.

El módulo se llama xmallmodels.py, y la variable que contendrá la clases es model_classes  y su código es:

import importlib
import pkgutil
import inspect
#------Imprescindible para poder importar de otras carpetas (de basicutils)
import sys
from pathlib import Path
path_root1 = Path(__file__).parents[1] # Damos un salto de directorio hacia arriba-> ximoutilsmod
sys.path.append(str(path_root1))
path_root0 = Path(__file__).parents[0] # El mismo directorio
sys.path.append(str(path_root0))
from basicutils.xmdb import Base
import models
# ------Fin imprescindible

model_classes = []

for loader, module_name, is_pkg in pkgutil.iter_modules(models.__path__):
    module = importlib.import_module(f"models.{module_name}")
    
    for name, obj in inspect.getmembers(module, inspect.isclass):
        # Ensure it's defined in the current module and is a subclass of Base (but not Base itself)
        if obj.__module__ == module.__name__ and issubclass(obj, Base) and obj is not Base:
            model_classes.append(obj)

# Example: register or print them
for cls in model_classes:
    print(f"Found model class: {cls.__name__} from {cls.__module__}")


Por ejemplo en nuestro programa de arranque, que intenta vincular los modelos con la BD, basta con importar model_classes desde este módulo. El código de este módulo mnu_main.py es:

#!/home/eduard/MyPython/11.softprop-01/venv_softprop/bin/python3

#1. Imports
from sqlalchemy import Table
#------Imprescindible para poder importar de otras carpetas (de basicutils)
import sys
from pathlib import Path
path_root1 = Path(__file__).parents[1] # Damos un salto de directorio hacia arriba-> ximoutilsmod
sys.path.append(str(path_root1))
path_root0 = Path(__file__).parents[0] # El mismo directorio
sys.path.append(str(path_root0))
from menus.mnu_fh import fh, app
#OJO: No eliminar las dependencias marcadas en gris (routes01mnu, routes02form, routes03grid,app) pues, sinó falla el programa
from menus import routes00comp, routes01mnu, routes02form, routes03grid # No eliminar !!!
from menus.mnu_fh import fh, app                         # No eliminar app !!!
from basicutils import xmdb
#--- Definición de tablas de la Base de datos postgres
from models.xmallmodels import model_classes
# ------Fin imprescindible

from basicutils import xmdb 

# Create database tables
xmdb.Base.metadata.create_all(bind=xmdb.engine)

# Execute the web server, but now not using fh.serve but uvicorm.run instead
#fh.serve()
if __name__ == "__main__":
	import uvicorn
	app.mount("/static", fh.StaticFiles(directory="/home/eduard/MyPython/11.softprop-01/static"), name="static")
	#uvicorn.run(app, host="0.0.0.0", port=5001, 
	#    ssl_keyfile="/home/eduard/MyPython/11.softprop-01/static/certs/wildcard2023Nginx.rsa", 
	#    ssl_certfile="/home/eduard/MyPython/11.softprop-01/static/certs/wildcard2023Nginx.crt")

	cert_path="/home/eduard/MyPython/11.softprop-01/static/certs/wildcard.municipio.es."
	#uvicorn.run(app, host="edu.tavernes.es", port=5001,	
	uvicorn.run(app, host="192.168.XXX.XXX", port=5001,	
		ssl_keyfile =cert_path+"key", 
		ssl_certfile=cert_path+"crt")


2. Modificar las tablas cuya clase asociada cambia

Para ello se buscan las clases que deriven de la clase Base, y si estan asociadas a una tabla (tienen el campo __tablename__) y se compara los atributos de la clase con las columnas de la tabla; y se añaden columnas  o se eliminan en base a los atributos de las clases.

Veamos el código del módulo xmdbupdate.py

''' Actualización de la estructura de tablas en función
     de las clases asociadas de SQLAlchemy.
'''

from sqlalchemy.sql import text
from sqlalchemy.inspection import inspect
from sqlalchemy.exc import ProgrammingError


#------Imprescindible para poder importar de otras carpetas (de basicutils)
import sys
from pathlib import Path
path_root1 = Path(__file__).parents[1] # Damos un salto de directorio hacia arriba-> ximoutilsmod
sys.path.append(str(path_root1))
path_root0 = Path(__file__).parents[0] # El mismo directorio
sys.path.append(str(path_root0))
#OJO: No eliminar las dependencias marcadas en gris
#--- Definición de tablas de la Base de datos postgresfrom basicutils.xmdb import Base 
from basicutils import xmdb
from models.xmallmodels import model_classes
# ------Fin imprescindible

#-----------------------------------------------------------
# --- Configuration ---
session = xmdb.session_local()

def all_table_subclasses(cls):
    """Recursively find all subclasses of a class that has a table assigned."""
    subclasses = set()

    for subclass in cls.__subclasses__():
        print (subclass.__name__,getattr(subclass, '__tablename__', ''), getattr(subclass, '__abstract__', False))
        if len(getattr(subclass, '__tablename__', '')) > 0:
            subclasses.add(subclass)
        subclasses.update(all_table_subclasses(subclass))

    return subclasses



# --- Update function ---
def update_table_structure(cls):
    table_name = cls.__tablename__
    table_args = cls.__table_args__
    schema = table_args.get('schema') if isinstance(table_args, dict) else None
    inspector = inspect(xmdb.engine)

    if not inspector.has_table(table_name, schema=schema):
        print(f"Table '{schema}.{table_name}' does not exist. Creating it...")
        cls.__table__.create(xmdb.engine)
        return

    db_columns = {col["name"]: col for col in inspector.get_columns(table_name, schema=schema)}
    model_columns = {col.name: col for col in cls.__table__.columns}

    #Execute a transaction
    with xmdb.engine.begin() as conn:
        # Add missing columns
        for name, column in model_columns.items():
            if name not in db_columns:
                col_type = column.type.compile(xmdb.engine.dialect)
                nullable = "NULL" if column.nullable else "NOT NULL"
                alter = f'ALTER TABLE "{schema}"."{table_name}" ADD COLUMN "{name}" {col_type} {nullable};'
                print("Adding:", alter)
                conn.execute(text(alter))

        # Drop extra columns
        for name in db_columns:
            if name not in model_columns:
                alter = f'ALTER TABLE "{schema}"."{table_name}" DROP COLUMN "{name}";'
                print("Dropping:", alter)
                try:
                    conn.execute(text(alter))
                except ProgrammingError as e:
                    print(f"Could not drop column {name}: {e}")

# --- Run for all subclasses of Base for updating the tables---
def update_all_tables(base):
    for cls in all_table_subclasses(base):
        update_table_structure(cls)

if __name__ == "__main__":
	update_all_tables(xmdb.Base)
	session.close()
	xmdb.engine.dispose()