Se va a migrar el login para que utilice un token OAuth, por lo que debemos adaptar nuestros backends para que acepten tanto token POSE (actual) como token OAuth. Para ello, aparte de lo que se indica en la guía en la que nos encontramos, debemos seguir también esta: Migración del backend a soporte oAuth

Además, hay que cambiar el pipeline, pasarlo a 2.0 y generar un despliegue por Helm. Para esto, se debe poner un Jira a MNCS solicitándolo.

Explicación en vídeo

En el vídeo no se incluye la parte de log4j2 ni del certificado autofirmado, pero también hay que incluirlas.

pom.xml

En el bloque <properties> (si no existe, lo creamos), tenemos que añadir la siguiente:

		<log4j2.version>2.17.1</log4j2.version>

Después, tendremos que añadir las siguientes dependencias, reposiorios y plugins en el pom.xml (podemos reemplazar todo lo que hay entre </properties> y </project>, manteniendo esas dos):

	<properties>
		<log4j2.version>2.17.1</log4j2.version>
    <dependencies>
		<!-- JWT -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
		</dependency>

		<!-- Data JPA -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-jpamodelgen</artifactId>
			<version>5.4.12.Final</version>
			<scope>provided</scope>
		</dependency>

		<!-- Real DB -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>jdbc.driver</artifactId>
			<version>11.2.0.3.0</version>
		</dependency>

        <!-- TOMCAT -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>    

        <!-- SECURITY -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- TEST -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- Test DB -->
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- Selenium -->
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<!-- <version>3.141.59</version> -->
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>

        <!-- Log4j2 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-layout-template-json</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- frontLogger -->
		<dependency>
			<groupId>es.um.atica.fundewebjs.fundewebjs-api</groupId>
			<artifactId>fundewebjs-lagar</artifactId>
			<version>1.0.0-SNAPSHOT</version>
		</dependency>

		<!-- Lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

	</dependencies>

	<repositories>
		<repository>
			<id>archiva.atica.umu.es</id>
			<name>ATICA - UMU Repository</name>
			<url>https://archiva.um.es/archiva/repository/FundeWeb/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>fundewebjs.archiva.atica.umu.es</id>
			<name>ATICA - UMU Repository - FundeWebJS</name>
			<url>https://archiva.um.es/archiva/repository/FundeWebJS/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>  </repositories>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.hibernate.orm.tooling</groupId>
				<artifactId>hibernate-enhance-maven-plugin</artifactId>
				<version>${hibernate.version}</version>
				<executions>
					<execution>
						<configuration>
							<failOnError>true</failOnError>
							<enableLazyInitialization>true</enableLazyInitialization>
							<enableDirtyTracking>true</enableDirtyTracking>
							<enableAssociationManagement>true</enableAssociationManagement>
							<enableExtendedEnhancement>false</enableExtendedEnhancement>
						</configuration>
						<goals>
							<goal>enhance</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<!-- JaCoCo configuration -->
			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>0.7.7.201606060606</version>
				<executions>
					<execution>
						<goals>
							<goal>prepare-agent</goal>
						</goals>
					</execution>
					<execution>
						<id>report</id>
						<phase>prepare-package</phase>
						<goals>
							<goal>report</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<!-- Enunciate -->
			<plugin>
				<groupId>com.webcohesion.enunciate</groupId>
				<artifactId>enunciate-maven-plugin</artifactId>
				<version>2.13.0</version>
				<dependencies>
					<dependency>
						<groupId>com.webcohesion.enunciate</groupId>
						<artifactId>enunciate-lombok</artifactId>
						<version>2.9.1</version>
					</dependency>
				</dependencies>
				<executions>
					<execution>
						<id>fdwjs</id>
						<configuration>
							<docsDir>${basedir}/src/main/resources/</docsDir>
							<docsSubdir>static/docs/</docsSubdir>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<!-- FIN Enunciate -->

		</plugins>
	</build>

application.properties

Como hemos visto en el apartado anterior, en el archivo application.properties incluiremos algunas variables de configuración del proyecto:

########## RUTA BASE REST ##########
server.servlet.context-path=/api

########## BASE DE DATOS ##########
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.Oracle10gDialect
spring.jpa.hibernate.ddl-auto = validate
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver

spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA
spring.datasource.username=USER
spring.datasource.password=PASSWORD

########## ACTUATOR ##########
management.endpoints.enabled-by-default=false
management.endpoint.health.enabled=true
management.endpoints.web.exposure.include=health
management.health.probes.enabled=true
management.endpoint.health.group.liveness.include=livenessstate,ping
management.endpoint.health.group.readiness.include=readinessstate,ping
management.endpoint.health.group.custom.include=db

########## FRONT-LOGGER ##########
# FundeWebJS Habilitar endpoint jsn.logger
fdwjs.api.frontLogger.enable=true

# FundeWebJS Habilitar filtro para cabeceras en logs MDC de lagar 
fdwjs.api.lagar.enable=true 
fdwjs.api.lagar.headers=UMU-User-UUID,UMU-Client-APP

Si queremos cambiar el puerto que utiliza nuestra aplicación, que por defecto es el 8080, podemos hacerlo con la propiedad server.port. Otras propiedades que haya que definirse para otras funcionalidades, como para el login, se incluyen en su página de documentación correspondiente. Si queremos ver las propiedades de configuración que ofrece Spring podemos consultarlas aquí.

log4j2.xml

Debemos crear el fichero log4j2.xml en la carpeta /src/main/resources con el siguiente contenido:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorinterval="60" >
    <Properties>
        <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
        <Property name="LOG_LEVEL_PATTERN">%5p</Property>
        <Property name="LOG_DATEFORMAT_PATTERN">dd-MM-yyyy HH:mm:ss.SSS</Property>
        <Property name="CONSOLE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
    </Properties>
    <Appenders>
        <Console name="local" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
        </Console>
         
        <Console name="json" target="SYSTEM_OUT" follow="true">
            <JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json" locationInfoEnabled="true" stackTraceEnabled="true"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
        <Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
        <Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
        <logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
        <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
        <Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
        <Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
        <logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
        <Root level="debug">
            <AppenderRef ref="local" />
        </Root>
    </Loggers>
</Configuration>

Este es un archivo de configuración para los logs, que vienen explicados más detalladamente en esta página.

Clase inicial de la aplicación

En la clase que inicia la aplicación, que será algo como NombreApplication.java, sustituyendo Nombre por el de nuestra aplicación, tendremos que añadir a la clase la anotación @ComponentScan, con el contenido siguiente:

@ComponentScan( basePackages = {
		"es.um.atica.aplicacion", "es.um.atica.fundewebjs"
} )

Ahí, tenemos que cambiar aplicación por el paquete base de nuestra aplicación.

Con esto, un ejemplo de esta clase inicial podría ser el siguiente:

package es.um.atica.pruebaspose;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan( basePackages = {
		"es.um.atica.pruebaspose", "es.um.atica.fundewebjs"
} )
public class PruebasPoseApplication {

	public static void main(String[] args) {
		SpringApplication.run(PruebasPoseApplication.class, args);
	}

}

WebSecurity

Por otro lado, nos haremos una clase java para especificar la configuración de seguridad web, que debe extender a WebSecurityConfigurerAdapter e incluir la anotación @EnableWebSecurity:

package es.um.atica.helloworld.config;
  
import java.util.Arrays;
  
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // CORS y HTTPS obligatorio:
        // http.cors().and().csrf().disable().and().requiresChannel().anyRequest().requiresSecure();
  
        // Solo CORS:
        http.cors().and().csrf().disable();
    }
  
	// Filtro CORS
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Esta configuración tendrá que ser ampliada si se incluye el login con el CAS, pero esa configuración se indicará en la página correspondiente. También hay que ver si en local y en otros entornos tenemos que poner configuración diferente (https obligatorio, por ejemplo). En este caso podemos definirnos una variable en application.properties que indique el entorno en el que estás, y comprobarlo con un if. Por ejemplo, si estás en local, la configuración sin https, si no, con https.

        configuration.setAllowedOriginPatterns( Arrays.asList( "*" ) );
        configuration.setAllowedOrigins(Arrays.asList("*"));
2021-01-08 10:21:50.656 ERROR 10568 --- [  XNIO-1 task-1] io.undertow.request                      : UT005023: Exception handling request to /loquesea
java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*"since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

Así que en función de la versión, podemos encontrarnos algún error, por lo que debemos tener esto en cuenta.

Generar certificado autofirmado

En vez de generar un certificado nuevo, podemos utilizar los que vienen aquí: cert.rar

Contiene keystore.p12, que es el que utilizaremos en el backend, y los dos .pem para el frontend.

Para generar un certificado autofirmado, utilizaremos el comando keytool desde la terminal de Windows:

keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650 -storepass password

Donde:

  • -alias para establecer el nombre del certificado.

  • -keystore para establecer el archivo .p12 que será nuestro almacén de certificados.

  • -storepass para establecer la contraseña del keystore.

Tras introducir el comando nos preguntará una serie de datos, que podemos pasar directamente con Enter, dejándolos sin indicar (no son necesarios). Para confirmar, tendremos que escribir “si” (o “yes”, si es que lo tenemos en inglés). Por último, nos preguntará la contraseña para el certificado, que si pulsamos Enter directamente será la misma que hemos puesto en el comando para el keystore:

¿Cuáles son su nombre y su apellido?
  [Unknown]:
¿Cuál es el nombre de su unidad de organización?
  [Unknown]:
¿Cuál es el nombre de su organización?
  [Unknown]:
¿Cuál es el nombre de su ciudad o localidad?
  [Unknown]:
¿Cuál es el nombre de su estado o provincia?
  [Unknown]:
¿Cuál es el código de país de dos letras de la unidad?
  [Unknown]:
¿Es correcto CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown?
  [no]:  si

Enter key password for <tomcat> 
    (RETURN if same as keystore password):


Añadir certificado a nuestra aplicación

En application.properties debemos añadir lo siguiente (cambiando el valor de server.ssl.key-store por la ruta en nuestra máquina):

# The format used for the keystore. It could be set to JKS in case it is a JKS file
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=C:/Users/guillermo.castillo/keystore.p12
# The password used to generate the keystore
server.ssl.key-store-password=password
# The password used to generate the certificate
server.ssl.key-password=password
# The alias mapped to the certificate
server.ssl.key-alias=tomcat