miércoles, 12 de agosto de 2020

Certificados en Java (2). Configurar Tomcat (tambien en Eclipse) https autentificacion cliente certificado. Tarjeta, Smartcard cliente

1. Configurar Tomcat  para https

Segun Namecheap  podemos instalar en Tomcat certificados .jks y tembién .p12 (pkcs12)

1.a con certificado jks

Supongamos que tenemos un certificado p12 llamado mykeystore.jks con contraseña "mypassword", entonces:

Modificamos el conector en el fichero server.xml de la carpeta conf de tomcat y para el puerto 8443 para que quede así

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!-- Define a SSL HTTP/1.1 Connector on port 8443
        This connector uses the JSSE configuration, when using APR, the
        connector should be using the OpenSSL style configuration
        described in the APR documentation -->
    <Connector port="8443" 
              protocol="HTTP/1.1"
              SSLEnabled="true"
              maxThreads="150" 
              scheme="https" 
              secure="true"
              clientAuth="false" <!-- true to read client certificate -->
              sslProtocol="TLS" <!--"TLSv1.2" -->
              keyAlias="tomcat" <!-- Alias cuando se crea mykeystore,jks -->
	      keystoreFile="/home/ximo/mykeystore.jks"
	      keystorePass="mypassword" 
              
    /> 

Y ahora vamos al directorio "bin" del tomcat y paramos y rearrancamos el servicio

./shutdown.sh
./startup.sh

1.b con certificado pem

Supongamos que hemos obtenido de LetsEncrypt, estos certificados que estan en la carpeta  /etc/letsencrypt/live/midominio.es
  • cert.pem (certificado "solo")
  • chain.pem (cadena de certificados del root)
  • fullchain.pem (certificado "solo" + cadena de certificados del root. Equivale a los 2 ficheros anteriores juntos)
  • privkey.pem (clave privada)
Modificamos el conector en el fichero server.xml de la carpeta conf de tomcat y para el puerto 19443 para que quede así

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 <Connector port="19443"
      protocol="HTTP/1.1"
      SSLEnabled="true"
      maxThreads="150"
      scheme="https"
      secure="true"
      sslProtocol="TLS"

      clientAuth="true"
      keyAlias="tomcat"


      SSLCertificateFile="/etc/letsencrypt/live/midominio.es/cert.pem"
      SSLCertificateChainFile="/etc/letsencrypt/live/midominio.es/chain.pem"
      SSLCertificateKeyFile="/etc/letsencrypt/live/midominio.es/privkey.pem"
   />

  
Como vemos,:
  1.  No nos ha hecho falta el fullchain.pem
  2. Tampoco nos ha hecho falta ninguna contraseña
  3. Estamos trabajando en un puerto https adicional 19443 (junto con el anterior 8443) sin ningún problema

Y ahora vamos al directorio "bin" del tomcat y paramos y rearrancamos el servicio

./shutdown.sh
./startup.sh


2. Obtener un certificado jks versión fácil


En un blog anterior hemos creeado una entidad certificadora. 


Para ello hay que seguir las instrucciones de Mkyong :

Nos situamos en el directorio /home/ximo/mycerts y creamos un keystore con un certificado auto firmado:

keytool -genkey -alias tomcat -keyalg RSA -keystore mykeystore.jks

OJO: El alias tomcat del mykeystore es el que se debe de indicar en el "keyAlias" del web.xml del tomcat
nos pide una nueva contraseña para el nuevo keystore por ejemplo "mypassword"

podemos listar el contenido del keystore con

keytool -list -v -keystore mykeystore.jks



3. Obtener un certificado jks con un certificado emitido por nuestra entidad certificadora.

Aprovechamos todos los pasos anteriores y generamos el Certificate Signing Request CSR. Para ello volvemos al directorio  /home/ximo/mycerts y tecleamos

keytool -certreq -alias tomcat1 -file mytomcat.csr -keystore mykeystore.jks

Observar que el alias el mismo que hemos creado antes (tomcat)  y nos ha creado el fichero mytomcat.csr


OJO: Para obtener cada una de las DNS, debemos hacer este comando:

nslookup 192.168.2.2

siendo 182.168.2.2 la dirección IP del servidor que queremos crear el certificado, y nos devuelve:

ws.ximodante.es
otro.ximodante.es

Y con esta información de los DNS creamos el fichero de configuración siguiente (mytomcat.conf):

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = 192.168.2.2
DNS.2 = localhost --> SOLO PARA PUEBAS en PRE
DNS.3 = otro.ximodante.es
DNS.4 = ws.ximodante.es

Por tanto debeis cambiar a la IP que realmente está usando el servidor 

Ahora generamos el certificado

openssl x509 -req -in mytomcat.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out mytomcat.crt -days 825 -sha256 -extfile mytomcat.conf
 
Hay que tener en cuenta que debemos disponer de los certificados de nuestra entidad certificadora (myCA.key y myCA.pem) obtenidos en el post anterior.

Finalmente importamos el certificado generado usando el mismo alias "tomcat" a nuestro almacén de claves.

keytool -import -alias tomcat1 -file mytomcat.crt -keystore mykeysore.jks

Y rearrancamos el servicio de Tomcat como hemos hecho antes:


./shutdown.sh
./startup.sh

Y si entramos en el navegador se quejará, salvo que le indiquemos al navegador que confie en nuestra entidad certificadora.

4. Autentificación en el servidor con certificado de cliente.


Si queremos que el cliente nos muestre su certificado, hay que indicarle en la línea 11 del fragmento anterior de servers.xml:

clientAuth="true" 

Con lo que nos pide el certificado de cliente y podemos autenticarnos en el servidor mediante certificado.

5. Autentificación en el servidor con tarjeta criptográfica (en cliente).

Cuando se intenta acceder con tarjeta criptográfica en el cliente, nos da este error en el cliente:
SSL_ERROR_BAD_CERT_ALERT

Supongo que tal vez haya que indicar un truststore que contenga el certificado raíz.
Parece ser que tomcat utiliza el alacen de certificados de java.

Se va a copiar el fichero keystore  java_path/lib/security/cacerts a una carpeta de pruebas y con el programa keystore explorer, añadimos los certificados raiz de la etidad certificadora de la tarjeta obtenidas de la ACCV 

En concreto añadimos el certificado raiz, los 110 y 120

y vamos a modificar el server.xml para que tenga un truststore


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!-- Define a SSL HTTP/1.1 Connector on port 8443
        This connector uses the JSSE configuration, when using APR, the
        connector should be using the OpenSSL style configuration
        described in the APR documentation -->
    <Connector port="8443" 
              protocol="HTTP/1.1"
              SSLEnabled="true"
              maxThreads="150" 
              scheme="https" 
              secure="true"
              clientAuth="false" <!-- true to read client certificate -->
              sslProtocol="TLS" <!--"TLSv1.2" -->
              keyAlias="tomcat" <!-- Alias cuando se crea mykeystore,jks -->
	      keystoreFile="/home/ximo/mykeystore.jks"
	      keystorePass="mypassword" 
              
    /> 



6. Configurar el tomcat de Eclipse.



"If you've already created the server, you can edit the server.xml template it copies. If you use the project explorer, It is under Other Projects->Servers->Tomcat Server Name->server.xml"

Así de fácil localizamos el server.xml y lo configuramos como si fuera un tomcat normal.








lunes, 3 de agosto de 2020

La API de JPA 2.1 (VII) Copiar entidades de una base de datos a otra

1. Introducción 

Este problema parece sencillo pero no lo es, sobre todo cuando una entidad tiene colecciones y además los ID son generados automáticamente:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

2. Proceso

  
  1. Ejecutar una consulta y obtener una lista (colección) de objetos de la entidad a copiar
  2. Para cada instancia:
    2.1 Se crea un objeto igual al de la instancia
    2.1 Mediante recursividad, se copian todos todos los campos del objeto y se asigna NULL al Id propio y de cada una de las colecciones que tenga en el objeto copia.
    2.3 Hacer un persist del nuevo objeto en la nueva EntityManager (EntityManager.persist(obj))

Al recorrer todos los campos del objeto y los campos de los objetos anidados conseguimos que se haya cargado completamente el objeto (pues el "Lazy Loading", solo carga lo que se necesita. 

El objeto original NO DEBE ESTAR DETACHED, pues no haria el "lazy loading" mientras el objeto no està "detached"), 

Para cada instancia (que llamamos "obj") se hará:

1
2
3
T copy=obj; //Define a copy object
ReflectionUtilsEdu.setSameValueToAllNestedBaseFields(copy,"id",null); //Copy by reflection to force lazy Loading
em.persist(copy); //Save the copy

3. Función para hacer nulls los Ids

En esta función le pasamos de parámetros:
  1. El objeto a modificar el atributo recursivamente
  2. Nombre del atributo
  3. Valor del atributo
Si el nombre del atributo le indicamos "id" y al valor "null" entonces hay que tener en cuenta que cualquier campo que se llame id se va a hacer nulo, indepenedienntemente que esté en dicho objeto o en cualquiera de sus colecciones!!!

Aqui le pasamos el objeto y el nombre del campo y valor
Este és el código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public static Object ObjectCloneAndsetSameValueToAllNestedBaseFields(Object obj,String fldName,Object value) throws Exception {
		
	if (obj==null) return null;
		
	//Create the clone object
	Object clone=obj.getClass().getDeclaredConstructor().newInstance();

	//Get all fields
	List<Field> lFlds= new ArrayList<>(Arrays.asList(FieldUtils.getAllFields(obj.getClass())));
		
	for (Field fld:lFlds) {
			
		// 1. The field value has to be changed
		if (fld.getName().equals(fldName)) FieldUtils.writeField(fld, clone, value, true);
			
		// 2. The field  is a descendant of Base
		else if (Base.class.isAssignableFrom(fld.getType())) {
			Object myObjA=FieldUtils.readField(fld, obj, true);
			Object myObjB=ObjectCloneAndsetSameValueToAllNestedBaseFields(myObjA,fldName, value);
			FieldUtils.writeField(fld, clone, myObjB, true);
			
		// 3. the field is a Collection: let's copy the collection
		}else if (Collection.class.isAssignableFrom(fld.getType())) {
			Collection<?> collA=(Collection<?>)FieldUtils.readField(fld, obj, true);
			// Presume collections as Lists !!!!!!!! May fail if Sets or other Collections type !!!!!!
			Collection<Object> collB=new ArrayList<Object>(); 
			if (collA!=null) {
				Iterator<?> iter=collA.iterator();
				Object myObjA=iter.next();
				Object myObjB=ObjectCloneAndsetSameValueToAllNestedBaseFields(myObjA,fldName, value);
				collB.add(myObjB);
			}
			FieldUtils.writeField(fld, clone, collB, true);
			
		// 4. If the class is serializable, let's use SerializationUtils from Apache	
		}else if (Serializable.class.isAssignableFrom(fld.getType())) {
			Serializable myObjA=(Serializable) FieldUtils.readField(fld, obj, true);
			Serializable myObjB=SerializationUtils.clone(myObjA);
			FieldUtils.writeField(fld, clone, myObjA, true);
		
		// 5. A primitive type or not serializable is assigned without cloning	
		}else if (ClassUtils.isPrimitiveOrWrapper(fld.getType()) 
			  || !Serializable.class.isAssignableFrom(fld.getType())){
			Object myObjA=FieldUtils.readField(fld, obj, true);
			FieldUtils.writeField(fld, clone, myObjA, true);
			
		// 5. Throw exception for other fields
		} else {
			throw new Exception("EDU: The object " + fld.getName() + "(" +fld.getType() + ") is not clonable");
		}
	}
	return clone;
}

4. Posibles errores

1. Verificar que exista un esquema general (en posgres "public") que pueda albergar las relaciones que no entran en un esquema particular. Esto me pasó por borrar el esquema "public" en Postgres.
2. Hibernate hace un proxy del objeto, lo que significa que altera su estructura. Las colecciones las mete en una especie de saco, y és difícil averiguar si son Lists, Sets o otra estructura. En principio se ha supuesto aue son Lists, por tanto si falla , hay que rehacer el código para que acepte otra clase de estructura para las colecciones.


domingo, 2 de agosto de 2020

Maven (3) Proyectos multi-módulo. Copia de seguridad y restauración del proyecto

1. Introducción

Cuando creamos un proyecto multimódulo, es conveniente copiar solamente aquello que es importante como los archovos de configuración (pom.xml), recursos (carpetas resources), carpeta front end ... y no copiar las clases compiladas. Mas tarde el proceso de restauración debe de poder crear un proyecto en condiciones.

2. Programa shell de copia de ficheros importantes.

Veamos un shell script para linux (Ubuntu) donde se hace un tar con compresión y se excluyen los ficheros que se pueden regenerar (como las clases compiladas y otros ficherps que se pueden descargar con Maven)

Para ello hay que rellenar los parámetros del nombre del proyecto (carpeta), carpeta del workspace y carpeta donde se va a guardar el tar


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash

#--Explicación
#-------------------------------------------------------------------------------------------
# 1. Indicar project_name, workspace_folder i tar_folder
# 2. Se guardaran en la carpeta tar_folder indicando la fecha
# 3. Utilizamos las opciones cJf para guardar en formato comprimido "xy" que es mas efectivo
#-------------------------------------------------------------------------------------------

#--Parameters

project_name='MyVaadin15_02Parent'
workspace_folder='/home/eduard/Workspace202006/'
tar_folder='/home/eduard/BACKUPS/'

#--Calculations

project_file=${workspace_folder}${project_name}
my_time=`date +"%Y%m%d_%H%M"`
tar_file=${tar_folder}${project_name}"_"${my_time}".tar"


echo $tar_file
echo $project_file

#--Execution

cd ${workspace_folder}
tar -cJvf ${tar_file} --exclude='*/target' --exclude='*/.*' --exclude='*/node_modules' ${project_name}


3. Restauración

Tener en cuenta que los proyectos multi-módulo son un poco especiales a la hora de importarlos y no todos los métodos de imporación de Eclipse funcionan bien.

Para ello descomprimimos la copia de seguridad en la carpeta de nuestro WORKSPACE en Eclipse y hacemos:

File - Import - General - Projects from Folder or Archive



Y seleccionamos la carpeta del proyecto



Tenemos que seleccionar  tanto el proyecto padre como cada uno de los hijos a la vez. Una vez que Eclipse ve el proyecto padre y sus módulos hijos, tenenmos que verificar que encuentra el Java JDK correcto. Para ello hacemos

Window - Preferences - Java - Installed JREs


Ahora si queremos, se puede hacer clik_derecho sobre el proyecto (a veces no aparece la opción y hay que hacer el click derecho sobre el fichero pom.xml) y le damos Run As - Maven clean y repetimos con el  click derecho y Maven - Update Project 

4. Resolución de problemas


1. Si se ha instalado una nueva versión de Eclipse, verificar que se ha instalado Lombok!
2. Si se ha descomprimido el proyecto ebn otra carpeta, este proyecto NO SE COPIA a nuestro workspace, sino que queda vinculada, por eso hay que tener mucho cuidado.
3. Verificar que se apunta al JDK correcto Window - Preferences - Java - Installed JREs
 

martes, 14 de julio de 2020

La API de JPA 2.1 (VI) Persistence.xml, definiendo la conexión a algunas BDs. Maven multimódulo

Veamos como solucionar algunos casos que me han pasado y que me han requerido bastante tiempo para solucionarlos o al menos para medianamente entenderlos. Recordar que en "maven", le persistence.xml es conveniete colocarlos en "src/main/resources

Caso 1º. Acceso a H2 (en linux). Ruta absoluta


En este caso , nuestra base de datos está situado en el directorio DB del directorio del usuario (/home/usuario) y se llama "myh2", en el persistence.xml se tenía:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<persistence-unit name="myh2" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
     
  <properties>
    <!-- (FUNCIONA EN MODO LOCAL) property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/DBs/myh2" /> -->
    <!-- (FUNCIONA EN MODO LOCAL) property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://192.168.100.100/~/DBs/myh2" /> -->
    <!-- OJO una ruta absoluta necessita // despres del server !!! -->
    <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://192.168.100.100//home/eduard/DBs/myh2" />
    <property name="javax.persistence.jdbc.user" value="myuser"/>
    <property name="javax.persistence.jdbc.password" value="mypassword"/>
    <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
    <!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->
    <property name="javax.persistence.schema-generation.database.action" value="none"/>
  
    <!-- Provider specific properties -->
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            
			        
  </properties>
      
 </persistence-unit>


Se pueden ver como en las líneas  5 y 6 se puede acceder de forma local y usando el mismo usuario (pues se está usando el símbolo "~" que indica que es el directorio del usuario que se ha conectado. Si nos conectamos como otro usuario, la conexión falla.

Para evitarnos sustos debemos indicar la ruta absoluta como se indica en la línea 8, donde despues de la dirección del server (o del puerto del server si se ha indicado), hay que dar doble barra "//" 

Caso 2º. Acceso a una BD Postgres por JNDI

JNDI permite asociar nombres a objectos. Estos objetos pueden ser contenedores de datos. En este caso particular, le decimos a nuestro Tomcat que sea él el encargado de gestionar la connexión a la base de datos. Veamos el "persistence.xml".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<persistence-unit name="jndi_postgres" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  <!-- BEGIN: FOR Data Source in Tomcat -->
  <jta-data-source>java:comp/env/mypostgres</jta-data-source>
      
  <!--????? OJO: Revisar el context.xml de webapp/META-INF que apunta al servidor 192.168.100.101 -->
        
  <!-- END:   FOR Data Source in Tomcat-->
  <properties>
    <property name="hibernate.dialect"	value="org.hibernate.dialect.PostgreSQLDialect" />
    <property name="hibernate.hbm2ddl.auto" value="update" />
    <property name="hibernate.show_sql" value="true" />				  
  </properties>
    
</persistence-unit>

Observar la línea 4 que tiene la etioqueta "<jta-data-source> le descarga la responsabilidad al JDNI. La nomenclatura empleada es "java:comp/env/nombre_recurso"

Ahora muchas propiedades han desaparecido, ya que se supone que se encarga el JNDI de apañárselas.

Para definir el JNDI, en Deployed Resources - webapp - META_INF tenemos que crear el fichero "context.xml" 



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/mypath" docBase="mypath" debug="5" reloadable="true" crossContext="true">
        
   
    <!-- PRIMER RECURSO (el que hace referencia en persistence.xml-->
    <Resource 
      name="mypostgres"
      auth="Container"
      type="javax.sql.DataSource"
      username="mysuser"
      password="mypassword"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.168.100.101:5432/mypostgresdb" 
    />

    <!-- SEGUNDO RECURSO -->
    <Resource 
      name="mypostgres2"
      auth="Container"
      type="javax.sql.DataSource"
      username="mysuser2"
      password="mypassword2"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.168.100.102:5432/mypostgres2db" 
    />
      
    
</Context>


Como se puede ver, se pueden definir múltiples recursos, en este caso el primero es el que hace referencia el "persistence.xml". Se observa que se ha delegado la URL de acceso a la BD al "context.xml".

Caso 3º. Maven multimódulo, no puede mapear las clases!

El proceso de mapeado (reconocimiento) de las clases que entran en juego en la persistencia, es un poco complejo. En principio no hay ningun problema cuanto tenemos un olo módulo maven y una sola "persistence unit".

Cuando complicamos un poco la cosa y le metemos una segunda "persistence unit" en el "persistence.xml", a la hora de crear las clases automáticamente, se lia la cosa y crea las clases en las 2 persistence units a la vez. Para solucionar esto, se puede hacer:
  1. Trabajar con esquemas, onde le decimos cada clase a que esquema pertenece.
  2. Definir con la etiqueta <class> cada clase que interviene en cada persistence unit.
Si ademas tenemos bastantes módulos y las clases de cada persistence unit las tenemos separadas en módulos... entonces únicamente he podido conseguir que mapaeara las clasess creando una etiqueta <class> con cada una de las clases a mapear en el persistence unit. Si alguien encuentra una solución mejor que me lo diga. También se podria utilizar la etiqueta <jar-file> si somos capaces de crear un jar de cada módulo.


miércoles, 27 de mayo de 2020

Putty: Copiar y pegar en Putty de Linux. Problema: PuTTY: unable to load font "server:fixed"

1. Copia y pega


Según Capy:

1. Con el ratón seleccionamos el texto a copiar (dentro de la ventana de putty)
2. Nos vamos a la aplicación donde queramos copiar y apretamos la rueda que está en el botón central y se pega.
3. También podemos pegar a putty desde otra aplicación, apretando la rueda.

Muuuuuuuuuuuuuuuy útil.

2. PuTTY: unable to load font "server:fixed"


Para cada uno de los servidores:
  • Ir a Category: Session
  • Marcar con el boton izquierdo del raton (sobre el nombre del servidor)
  • Apretar el boton Load
  • En Category:Fonts
  • Apretar el boton Change ... de "Font used for ordinary text"
Y seleccionar la fuente que se muestra junto con el tamaño y darle al boton OK

Le damos al boton Open y a funcionar








Ubuntu Server. Definir IP estática

Cuando se copian máquinas virtuales de Ubuntu Server 18.04, parece ser que la configuración de la dirección IP ya no se puede cambiar por el entorno gráfico, ya que cuando se reinicia se pierde la configuración de la IP.

Para ello he tenido que recurrir al blog de Gorka Izquierdo.

En resumidas cuentas hay que hacer lo siguiente:

1. Buscar en /etc/netplan un fichero que termine en .yaml

En mi caso se llama 50-cloud-init.yaml. su contenido es:

    ethernets:
        ens192:                        # verificar nombre arjeta de red con ifconfig   
            addresses:
                - 192.168.28.201/24    # IP estática a asignar
            gateway4: 192.168.28.100   # IP del gateway o puerta de enlace
            nameservers:
                addresses:
                    - 192.168.28.207   # IPs de los DNS
                    - 192.168.28.210
                search:
                    - mi.dominio
    version: 2


2. Ejecutar ifconfig para obtener el nombre de la tarjeta de red

Obtenenos el nombre de nuestra tarjeta de red, en este caso ens192


 ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.28.201  netmask 255.255.255.0  broadcast 192.168.28.255
        inet6 fe80::250:56ff:feb5:3a1e  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:b5:3a:1e  txqueuelen 1000  (Ethernet)
        RX packets 7950  bytes 580000 (580.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 371  bytes 46630 (46.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 842  bytes 218267 (218.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 842  bytes 218267 (218.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


3. Editar el fichero con el editor nano

Este editor funciona con putty y hay que darle el nombre de la tarjeta de red, y las IPs a asignarle al servidor, del gateway y de los DNS


4. Activar la configuración

Hay  que aplicar cambios y reiniciar la red para ello ejecutamos estos 2 comandos


netplan apply

systemctl restart networking

y ya está.

lunes, 25 de mayo de 2020

Certificados en java (1). Crear mi propia Autoridad de Certificados (CA)

Veamos los pasos a seguir (basándonos en Deliciousbrains)

1. Generar la clave privada


openssl genrsa -des3 -out myCA.key 2048

y nos sale esta ratahila solicitándonos una contraseña que por ejemplo damos  "mi-contraseña"


Generating RSA private key, 2048 bit long modulus (2 primes)
.......................................+++++
.................................................+++++
e is 65537 (0x010001)
Enter pass phrase for myCA.key:
Verifying - Enter pass phrase for myCA.key:

2. Generar el certificado raiz (Root certifcate)

openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

(en vez de myCA.pem podríamos haber indicado myCA.crt)

y nos pide la contraseña

Enter pass phrase for myCA.key: 
Can't load /home/ximo/.rnd into RNG
140017841828288:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:88:Filename=/home/eduard/.rnd
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:Teruel
Locality Name (eg, city) []:Escorihuela
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Informatica Dantesca
Organizational Unit Name (eg, section) []:Informatica Dantesca
Common Name (e.g. server FQDN or YOUR name) []:Ximo Dante
Email Address []:ximodante@gmail.com

OJO con el CN (Common name), convien darle el nombre completo de la máquina con el dominio, como por ejemplo informatica.dantesca.es

Ya tenemos 2 ficheros:
  1. myCA.key (mi clave privada)
  2. myCA.pem (mi certificado raíz)

3. Instalar el certificado raiz en el keystore de Java

Solamente para que nuestro Java reconozca el certificado raiz, en mi caso me interesa para ser cliente de WS de un servidor que le vamos a instalar un certificado nuestro.

Veamos donde tenemos el Java instalado:

sudo update-alternatives --config java

y observamos que tenemos 2 versiones de Java y conviene actualizarlo en los 2 keystores

  Selecció    Camí                                           Prioritat  Estat
------------------------------------------------------------
* 0            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      mode automàtic
  1            /usr/java/jdk-13.0.2/bin/java                    1         mode manual

Para el java 8 hacemos:

/usr/lib/jvm/java-8-openjdk-amd64/bin/keytool -import -trustcacerts -alias RootCert -file myCA.pem -storepass changeit -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts

y nos contesta:

Owner: EMAILADDRESS=ximodante@gamil.com, CN=Ximo Dante, OU=Informatica Dantesca, O=Informatica Dantesca, L=Escorihuela, ST=Teruel, C=ES
Issuer: EMAILADDRESS=ximodante@gamil.com, CN=Ximo Dante, OU=Informatica Dantesca, O=Informatica Dantesca, L=Escorihuela, ST=Teruel, C=ES
Serial number: 2f70e1318bee92310bb278db98597b48bdd0575c
Valid from: Fri May 22 08:48:23 CEST 2020 until: Wed May 21 08:48:23 CEST 2025
Certificate fingerprints:
	 MD5:  A7:81:46:75:34:28:C1:73:DB:26:11:3B:A5:1C:44:8A
	 SHA1: E1:82:8C:A0:5A:97:9D:6D:A0:F9:08:B6:ED:4B:C6:38:39:AC:28:76
	 SHA256: D4:42:33:6A:B7:86:98:42:17:B3:0C:39:7D:2C:3E:7D:06:3D:89:6B:52:40:77:34:61:04:81:4A:0D:77:46:39
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: B0 E6 C3 22 E5 18 E6 10   AF 95 E2 AD 75 00 29 63  ..."........u.)c
0010: 64 A4 91 A7                                        d...
]
]

#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: B0 E6 C3 22 E5 18 E6 10   AF 95 E2 AD 75 00 29 63  ..."........u.)c
0010: 64 A4 91 A7                                        d...
]
]

Trust this certificate? [no]:  yes
Certificate was added to keystore

Y para el java 13

sudo /usr/java/jdk-13.0.2/bin/keytool -import -trustcacerts -alias RootCert -file myCA.pem -storepass changeit -keystore /usr/java/jdk-13.0.2/lib/security/cacerts

Y nos devuelve una ratahila parecida.

(para crear un jks desde cero (aunque no recomendable)
 keytool -keystore ximodante.jks -genkey -alias ximodante


4. Instalar el certificado raiz en Chrome

Vamos a Configuración - Privacidad y seguridad - Más V - Administra certificados - (Tab)Entidades emisoras - (Botón) Importa

Y nos situamos donde está el certificado.

5. Instalar el certificado raiz en Mozilla Firefox

Vamos a Prefencias - Privacidad y seguridad - Certificados - Muestra Certificados - Entidades -(Boon) Importar

Y nos situamos donde está el certificado.


6. Crear certificados firmados por nuestra entidad certificadora (CA)  

Primero, creamos una clave privada:

openssl genrsa -out ximo.dante.key 2048

y nos contesta

Generating RSA private key, 2048 bit long modulus (2 primes)
..............................................................+++++
..........................+++++
e is 65537 (0x010001)


Ahora generamos el CSR (Certificate Signing Request)


openssl req -new -key ximo.dante.key -out ximo.dante.csr

Nos pregunta lo mismo que al generar el certificado raiz, pero las contestaciones parece que no sirven para mucho, porqué es un CSR y no un certificado. De todas formas contestar lo más adecuadamente posible.

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:Teruel
Locality Name (eg, city) []:Escorihuela
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Informatica Dantesca
Organizational Unit Name (eg, section) []:Informatica Dantesca
Common Name (e.g. server FQDN or YOUR name) []:ws.ximodante.es        
Email Address []:ximodante@gmail.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

OJO con el common name (CN) que debería de ser el nombre de la máquina.!!

Nos puede que hace falta también un fichero de configuración, pues necesitamos el SAN (Subject Alternative File). sinó no reconocerá al servidor de https. Le llamaremos ximo.dante.conf

NOTA: En la versión 3 del formato X509 podemos indicarle varios dominios a un certificado, con lo que parece ser que prodríamos utilizar un solo certificado par varias máquinas y ahorrarnos una pasta en caso de que compremos los certificados... Pero todo tiene su cara y su cruz, ya que si queremos convertir dicho certificado X509v3 al estándard PKCS12, APARENTEMENTE se pierde toda la información de los dominios alternativos. Por eso es muy importante colocar el nombre y dominio de la máquina en del CN (Common Name). Digo "aparentemente", pues si mostramos la información del certificado con " openssl -nokeys -info -in ximo.dante.p12 " NO MUESTRA LA INFORMACION DE LOS DOMINIOS ALTERNATIVOS... pero si lo instalamos en un tomcat y miramos el certificado con Firefox, SI QUE APARECEN !!!!

OJO: Para obtener cada una de las DNS, debemos hacer este comando:

nslookup 192.168.2.2

siendo 192.168.2.2 la dirección IP del servidor que queremos crear el certificado, y nos devuelve:

server.interno.ximodante.es  --> Dominio Interno
server.externo.ximodante.es  --> Dominio Externo

Ahora ya podemos ver el fichero de configuración para el caso de darle varios nombres y dominio de equipos. Esto puede ser útil cuando estamos en una DMZ y se tienen 2 dominios, uno por lo que las máquinas acceden entre si dentro de la DMZ y otro para las máquinas que estan fuera de este DMZ.

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = server.interno.ximodante.es
DNS.2 = server.externo.ximodante.es


Vamos a generar nuestro preciado certificado usando el CSR, la clave privada y certificado de Entidad Certificadora y el fichero de configuración.


openssl x509 -req -in ximo.dante.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out ximo.dante.crt -days 825 -sha256 -extfile ximo.dante.conf

 Y nos escribe en la consola datos del "subject".... 

Y ya tenemos el certificado.

Si queremos ver todos los detalles del certificado escribimos

openssl x509 -in ximo.dante.crt -text

 
7. Convertir el certificado X509 a PKCS12

Algunas veces, nos hace falta tener el certificado en formato PKCS12, con la ratahila de certificados raiz de la entidad certificadora... Pero todo tiene un pero en esta vida, si hacemos la conversión, PARECE FALSEMENTE que se pierde la información de los SAN o "nombre de máquina+ dominio" alternativos, y parece solo conserva la información de "máquina+dominio" del campo CN!!  PERO SI SE CONSERVA!!!


openssl pkcs12 -export -in ximo.dante.crt -inkey ximo.dante.key -out ximo.dante.p12 -name servercert -CAfile myCA.pem -caname root -chain

Y nos pide una contrasseña y que la verifiquemos

Si queremos ver el certificado, podemos comprobar que pierde gran parte de la información adicional que tiene la versión 3 del X509. Para ello ejecutamos el comando y le damos la contraseña que le hemos dado antes (mypassword) o si no le ponemos "-passin pass:", nos pedirá la contraseña al ejecutar el comando.


openssl pkcs12 -nokeys -info -in ximo.dante.p12 -passin pass:mypassword

No nos muestra los dominios alternativos SAN pero si instalamos el certificado en tomcat y vemos desde Firefox el certificado, SI QUE APARECEN los DNS alternativos.

8. Opcionalmente copiar el certificado a un jks

Veamos

keytool -importcert -alias ximo.dante -file ximo.dante.crt -keystore ximodante.jks