Otro post más, se verá algo de bases de datos, springboot, java, xml, h2, flyway para la migracion de h2 a postgreSQL, securizar un poco en postgreSQL y listo, más de lo mismo.
Migrando Script de h2 a PostgreSQL
Migracion
|
Propiedades para el h2
### spring config
spring:
datasource:
url: jdbc:h2:mem:db (1)
username: test
password: test
1 | db: es el nombre de nuestra bases de datos. |
Depedencias para nuestro pom.xml
Ya estoy esta con un parent de spring y por lo tanto la version la hereda, por eso no esta el tag <version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.6</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
En esta versión de springboot 3.3.6 debe estar habilitado en nuestra seguridad la consola de h2 , para poder acceder a ella
al menos en desarrollo. |
@Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().requestMatchers("/h2-console/**");
}
Desde la UI cuando nos conectamos podemos hacer esto
Tips
|
SCRIPT TO 'dump.sql' (1)
1 | Esto creará un fichero llamado dump.sql dentro el directorio del proyecto, no hace falta copiar y pegar 😚 |
Renombrado
|
El Docker compose
Necesitamos tener postgresql levantado al menos en local, o usar testcontainer.
services:
postgres:
image: 'postgres:latest'
environment:
- 'POSTGRES_DB=mydatabase'
- 'POSTGRES_PASSWORD=secret'
- 'POSTGRES_USER=myuser'
ports:
- '5432:5432'
Reconfigurando properties de Springboot
Flyway debe encargarse de la estructura de la base de datos, por lo que es importante desactivar la auto-creación de Hibernate.
### spring config
spring:
jpa:
defer-datasource-initialization: true
show-sql: true
generate-ddl: false (1)
hibernate
ddl-auto: none (2)
properties:
hibernate:
format_sql: true
#Config Flyway
flyway:
enabled: true
baseline-on-migrate: true
out-of-order: true
datasource:
url: jdbc:postgresql://localhost:5432/mydatabase
username: myuser
password: secret
driverClassName: org.postgresql.Driver (3)
1 | desactivado. |
2 | desactivado. |
3 | Esta propiedad se supone que ya es opcional. |
Esto evita que Hibernate intente modificar la base de datos antes de que Flyway haga su trabajo.
Actualizamos el pom.xml
Con estas dependencias del driver de postgresql y flyway
<!--<dependency>
<groupId>com.h2database</groupId> (1)
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency> -->
<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>11.3.0</version> (2)
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId> (3)
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
1 | Dependencia de h2 comentada. |
2 | Importante tenerla para evitar errores tipo Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: PostgreSQL 17.2 |
3 | Importante también. |
Posible error en el arranque, con jpa y flyway
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flyway' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flyway' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Circular depends-on relationship between 'flyway' and 'entityManagerFactory'
Lo más probable es que estés posponiendo la inicialización del Datasource agregando:
defer-datasource-initialization: false
Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: PostgreSQL 17.2
Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: PostgreSQL 15.10
Instalando PostgreSQL FreeBSD
La wiki en nuestra amiga PostgreSQL/Setup
Un poco de postgres con springboot para securizar |
La seguridad suele ser importante siempre se usar para la prueba la version de postgres 15, para ellos habilitamos rapidamente un jail con bastille usando la template por ejemplo esta
aplicandolo al jail existente llamado postgresql
bastille template TARGET yaazkal/bastille-postgres (1)
1 | TARGET es el nombre de nuestro jail |
Solo con acceso desde localhost
Si, tengo solo habilitado usar el psql
desde el propio server con esta linea en el fichero pg_hba.conf
# "local" is for Unix domain socket connections only
local all all trust (1)
1 | las otra lineas por recomendación mejor que esten con scram-sha-256 por trust o MD5 |
Migrando password a SCRAM
Revisar esto |
El fichero postgresql.conf
toca actualizar la línea
# - Authentication -
#authentication_timeout = 1min # 1s-600s
password_encryption = scram-sha-256 # scram-sha-256 or md5 (1)
1 | Aqui descomentar y usar scram-sha-256 |
postgres=#
SELECT rolname, rolpassword ~ '^SCRAM-SHA-256\$' AS has_upgraded
FROM pg_authid
WHERE rolcanlogin;
rolname | has_upgraded
----------+--------------
postgres |
admin | t (1)
(2 rows)
1 | Indica true, que ya esta actualizada |
Posiblemente para autenticarnos desde nuestro cliente java con spring tengas ciertos problemas como
Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "admin"
Actualizacion recomentada
$ psql
psql (14.15)
Type "help" for help.
postgres=# \password admin (1)
Enter new password for user "admin":
1 | Usando \password se hace la actualizacion correcta de las password 🔥 |
ALTER ROLE admin WITH PASSWORD 'tu_contraseña'; (1)
1 | Esto no es recomendado para la actualización, ademas de dejar rastro en el histórico. |
Para reiniciar db
service postgresql reload
Cargando correctamente el .bashrc del IDE
Es importante para asegurar nos que nuestro ide carge el .bashrc correctamente donde tenemos las variables de entorno establecidas como en la imagen, es bastante util.
/bin/bash --login
/home/rubn/.local/share/applications/IntelliJ.desktop
#!/usr/bin/env xdg-open
[Desktop Entry]
Type=Application
Name=IntelliJ
StartupWMClass=jetbrains-idea-ce
Exec=/bin/bash -i -c "/home/rubn/Downloads/jdk-ide/idea/bin/idea" %f (1)
Icon=/home/rubn/Downloads/jdk-ide/idea/bin/idea.svg
Categories=Network;Application;
1 | Aquí forzamos la carga de modo interactivo con el parametro -i |
Cada cambio en dichero fichero le toca un reinicio con
El comando \du
Nos permite ver los roles con sus atributos
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
admin | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
Importanto Schemas
Para hacerlo podemos usar el comando
psql -U \ (1)
admin -d \ (2)
ott -a -f /var/db/postgres/ott-schema.sql (3)
1 | PostgreSQL en modo interactivo, con el parametro de -U de usuario. |
2 | El comando -d para la database ott. |
3 | El comando -a imprime todas la lineas, y -f es la ruta donde el usuario postgres tiene permisos de lectura, necesario para import dicho .sql . |
Purpose: Run SQL script to create/modify database schema while showing each command.
Encoding para la password
Si usamos por defecto el bean JdbcUserDetailsManager
por el InMemoryUserDetailsManager
@Bean
public JdbcUserDetailsManager jdbcUserDetailsManager(DataSource dataSource) {
return new JdbcUserDetailsManager(dataSource);
}
Debemos añadir un encoder por defecto al menos
java.lang.IllegalArgumentException: Given that there is no default password encoder configured, each password must have a password encoding prefix. Please either prefix this password with '{noop}' or set a default password encoder in `DelegatingPasswordEncoder`.
En el hash por defecto de spring security es un SHA-256
username|password |enabled|
--------+--------------------------------------------------------------------------------+-------+
boby |843b103f6c09de407d366f8ff6553691767a35dbaf870cad47e86945c4103be85ee8ea49509b9502|true |
chispa |a94f80ed1a6677dedb489a6912e6c83a7c2a7ada2c4d739dd4a4ab9e454d3d875134fa4480b19c55|true |
Actualizamos añadiendo un template del hash
UPDATE users SET password = '{sha256}' || password;
username|password |enabled|
--------+----------------------------------------------------------------------------------------+-------+
boby |{sha256}843b103f6c09de407d366f8ff6553691767a35dbaf870cad47e86945c4103be85ee8ea49509b9502|true |
chispa |{sha256}a94f80ed1a6677dedb489a6912e6c83a7c2a7ada2c4d739dd4a4ab9e454d3d875134fa4480b19c55|true |
Si aplicamos este otro bean y nos logueamos en el login de spring security el password encoder se cambiara a bcrypt
bajo fondo.
@Bean
public UserDetailsPasswordService userDetailsPasswordService(UserDetailsManager userDetailsManager) {
return (user, newPassword) -> {
var updated = User.withUserDetails(user)
.password(newPassword)
.build();
userDetailsManager.updateUser(updated);
return updated;
};
}
Migración bajo fondo a bcrypt
username|password |enabled|
--------+----------------------------------------------------------------------------------------+-------+
boby |{sha256}843b103f6c09de407d366f8ff6553691767a35dbaf870cad47e86945c4103be85ee8ea49509b9502|true |
chispa |{bcrypt}$2a$10$dMqSFw875ZLvpsADb24XDezNMacIYqC4bIUkbb24QOLYE3pmlZInS |true |
Ya ese bcrypt nos dice que fue un update existoso