PASSWORD_ROLLOVER_TIME – Dos contraseñas distintas para el mismo usuario

Estas últimas semanas estoy bastante ocupado, mucho trabajo, y fuera del ámbito laboral mucha actividad en mi vida personal.
Llevo tiempo queriendo probar y escribir sobre esto, y aprovechando que estoy estudiando para obtener el OCA 23ai (Oracle Certified Associate 23ai) en el grupo de estudio de CafeDatabase, ha llegado el momento adecuado.
Ayer, entre los muchos temas que tocamos, leyendo la documentación oficial de Oracle, apareció este concepto. A muchos nos sonaba, otros no lo conocían. Es bastante interesante y puede ser muy útil en algunos escenarios.
Se trata de la función conocida como PASSWORD ROLLOVER.
A menudo, te habrás encontrado el problema de que una password caduca o entra en periodo de gracia. Tienes muchas aplicaciones o muchas conexiones distintas donde actualizar la password, y solo es posible provocando un corte de servicio, parando la aplicación o reiniciándola para reconectarla con la nueva contraseña.
Con esta función, esto se acabó.
Ahora puedes hacerlo de forma gradual. Con una configuración adecuada, tras cambiar la contraseña, habrá un periodo en el que funcionará tanto la antigua como la nueva, para que poco a poco puedas ir actualizándola en todas partes, sin perder la disponibilidad de tus servicios/aplicaciones.
La Teoría
Estoy seguro de que has oído hablar de PASSWORD_LIFE_TIME y PASSWORD_GRACE_TIME. Hasta ahora, son los mecanismos que tenemos para controlar el tiempo de expiración de la contraseña de los usuarios en la base de datos.
Por si no los conoces, vamos a definirlos:
- PASSWORD_LIFE_TIME: Número de días que una contraseña es válida antes de que se marque como expirada.
- PASSWORD_GRACE_TIME: Cumplido el tiempo de expiración de la contraseña PASSWORD_LIFE_TIME, número de días (de gracia) en el que Oracle te permite iniciar sesión, avisándote de que debes cambiar la contraseña. En caso de no hacerlo y haber pasado el período de gracia definido, el usuario será bloqueado.
Estos parámetros se definen en el perfil del usuario. Podemos consultarlos en la vista dba_profiles.
En Oracle 21c aparece una nueva funcionalidad que se puede configurar dentro del perfil del usuario. Hablamos del PASSWORD_ROLLOVER_TIME.
Por supuesto, en versiones 21c y posteriores está disponible, pero también se ha hecho un backporting de esta funcionalidad a la versión 19c. En concreto, está disponible a partir de la versión 19.12.
¿Qué es eso del PASSWORD_ROLLOVER_TIME?
En pocas palabras, se trata de una función que permite a un usuario seguir iniciando sesión con su contraseña antigua durante un período de tiempo definido después de haberla cambiado.
Pongamos una situación:
- Un DBA configura un perfil con una política de contraseña que obliga a los usuarios a cambiar su contraseña periódicamente.
- Cuando un usuario cambia su contraseña, la antigua sigue siendo válida por un tiempo determinado, definido en el parámetro PASSWORD_ROLLOVER_TIME del perfil del usuario.
- Durante ese período de tiempo rollover, el usuario puede iniciar sesión con la contraseña nueva o la antigua.
- Una vez que el período expira, solo la nueva contraseña será válida.
¿Qué usos puede tener esta funcionalidad?
- Evitar interrupciones inmediatas en aplicaciones que estén ofreciendo servicio y que aún usen la contraseña anterior.
- Permite realizar los cambios de contraseñas de una forma gradual, proporcionando una transición más suave en entornos con múltiples accesos o integraciones.
¿Cómo funciona?
Como indicaba anteriormente, esta función forma parte de un perfil de usuario.
Para usarla, tendremos que crear un perfil nuevo o editar uno existente estableciendo un valor distinto de 0 para este parámetro.
La configuración de este parámetro indicando cualquier valor numérico entero se tomará como días.
Si deseamos indicar una marca de tiempo inferior a un día, debemos hacerlo con las siguientes directrices:
- El valor mínimo que se puede indicar es de un segundo y el máximo indicando 0 para deshabilitarlo.
- Para especificar un número de horas, debes hacerlo como fracción de un día. Por ejemplo, para indicar 6 horas, el valor debe ser «6/24»
- Si queremos indicar un valor de 10 minutos, el valor será «10/1440».
- Si por el contrario, queremos poner una marca de 5 segundos, sería «5/86400».
Por ejemplo, queremos indicar 4 horas, 29 minutos y 59 segundos. El valor a indicar será:
(4/24) + (29/1440) + (59/86400).
Ejemplos
Nada mejor en esta vida y en la informática, que ver esto con ejemplos, para que quede más claro y sea más fácil de comprender.
En la base de datos consultamos los profiles.
SQL> select distinct(profile) from dba_profiles;
PROFILE
--------------------
ORA_CIS_PROFILE
ORA_STIG_PROFILE
DEFAULT
Observamos qué perfil tienen asignado los usuarios de nuestra base de datos.
SQL> select username, profile from dba_users order by 1 asc
USERNAME PROFILE
------------------------- --------------------
ANONYMOUS DEFAULT
APPQOSSYS DEFAULT
AUDSYS DEFAULT
CTXSYS DEFAULT
DBSNMP DEFAULT
DIP DEFAULT
DVF DEFAULT
GSMADMIN_INTERNAL DEFAULT
GSMCATUSER DEFAULT
GSMUSER DEFAULT
LBACSYS DEFAULT
OJVMSYS DEFAULT
OLAPSYS DEFAULT
OUTLN DEFAULT
PDBADMIN DEFAULT
REMOTE_SCHEDULER_AGENT DEFAULT
SYS DEFAULT
SYSBACKUP DEFAULT
SYSTEM DEFAULT
SYS$UMF DEFAULT
XDB DEFAULT
XS$NULL DEFAULT
Como podemos ver, todos tienen el perfil DEFAULT. Por lo tanto, vamos a ver cuales son los parámetros y límites que tiene configurados este perfil.
SQL> select profile, resource_name, resource_type, limit from dba_profiles where profile='DEFAULT';
PROFILE RESOURCE_NAME RESOURCE LIMIT
-------------------- -------------------------------- -------- ---------------
DEFAULT FAILED_LOGIN_ATTEMPTS PASSWORD 10
DEFAULT COMPOSITE_LIMIT KERNEL UNLIMITED
DEFAULT SESSIONS_PER_USER KERNEL UNLIMITED
DEFAULT CPU_PER_SESSION KERNEL UNLIMITED
DEFAULT CPU_PER_CALL KERNEL UNLIMITED
DEFAULT LOGICAL_READS_PER_SESSION KERNEL UNLIMITED
DEFAULT LOGICAL_READS_PER_CALL KERNEL UNLIMITED
DEFAULT IDLE_TIME KERNEL UNLIMITED
DEFAULT CONNECT_TIME KERNEL UNLIMITED
DEFAULT PRIVATE_SGA KERNEL UNLIMITED
DEFAULT PASSWORD_LIFE_TIME PASSWORD 180
DEFAULT PASSWORD_REUSE_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_REUSE_MAX PASSWORD UNLIMITED
DEFAULT PASSWORD_VERIFY_FUNCTION PASSWORD NULL
DEFAULT PASSWORD_LOCK_TIME PASSWORD 1
DEFAULT PASSWORD_GRACE_TIME PASSWORD 7
DEFAULT INACTIVE_ACCOUNT_TIME PASSWORD 365
DEFAULT PASSWORD_ROLLOVER_TIME PASSWORD 0
Además de este profile, vamos a crear uno nuevo, para comparar el funcionamiento de la contraseña en un profile y otro.
Nuestro nuevo profile va a tener configurado:
- PASSWORD_LIFE_TIME – Ciclo de vida de la contraseña de 3 días
- PASSWORD_GRACE_TIME – Período de gracia de 2 días
- PASSWORD_ROLLOVER_TIME – Periodo de 1 día en el que la contraseña antigua y nueva van a ser aceptadas.
- *El resto de límites adoptarán automáticamente los mismos que tenga el profile DEFAULT.
SQL> create profile APLICACION limit
2 PASSWORD_LIFE_TIME 3
3 PASSWORD_GRACE_TIME 2
4 PASSWORD_ROLLOVER_TIME 1;
Perfil creado.
SQL> select distinct(profile) from dba_profiles;
PROFILE
--------------------
ORA_STIG_PROFILE
ORA_CIS_PROFILE
DEFAULT
APLICACION
SQL> select profile, resource_name, resource_type, limit from dba_profiles where profile='APLICACION';
PROFILE RESOURCE_NAME RESOURCE LIMIT
-------------------- -------------------------------- -------- -----------------------
APLICACION COMPOSITE_LIMIT KERNEL DEFAULT
APLICACION SESSIONS_PER_USER KERNEL DEFAULT
APLICACION CPU_PER_SESSION KERNEL DEFAULT
APLICACION CPU_PER_CALL KERNEL DEFAULT
APLICACION LOGICAL_READS_PER_SESSION KERNEL DEFAULT
APLICACION LOGICAL_READS_PER_CALL KERNEL DEFAULT
APLICACION IDLE_TIME KERNEL DEFAULT
APLICACION CONNECT_TIME KERNEL DEFAULT
APLICACION PRIVATE_SGA KERNEL DEFAULT
APLICACION FAILED_LOGIN_ATTEMPTS PASSWORD DEFAULT
APLICACION PASSWORD_LIFE_TIME PASSWORD 3
APLICACION PASSWORD_REUSE_TIME PASSWORD DEFAULT
APLICACION PASSWORD_REUSE_MAX PASSWORD DEFAULT
APLICACION PASSWORD_VERIFY_FUNCTION PASSWORD DEFAULT
APLICACION PASSWORD_LOCK_TIME PASSWORD DEFAULT
APLICACION PASSWORD_GRACE_TIME PASSWORD 2
APLICACION INACTIVE_ACCOUNT_TIME PASSWORD DEFAULT
APLICACION PASSWORD_ROLLOVER_TIME PASSWORD 1
Práctica con el usuario CELECUEVA y profile APLICACION
Creamos un usuario y le asignamos este nuevo perfil creado. Además, le damos el privilegio de CREATE SESSION para poder iniciar sesión en la base de datos y poder probar las diferentes contraseñas.
18:14:24 SQL> create user CELECUEVA identified by "CELECUEVA" profile APLICACION;
Usuario creado.
18:14:48 SQL> select username, profile from dba_users where username='CELECUEVA';
USERNAME PROFILE
------------------------- --------------------
CELECUEVA APLICACION
18:15:10 SQL> grant create session to CELECUEVA;
Concesión terminada correctamente.
Conectamos a la base de datos con el nuevo usuario que hemos creado y vamos a cambiar la contraseña.
C:\Users\usuario>sqlplus CELECUEVA/CELECUEVA@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on MiÚ Feb 5 18:18:25 2025
Version 23.5.0.24.07
Conectado a:
Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
SQL> alter user CELECUEVA identified by "USUARIONUEVO";
Usuario modificado.
SQL> exit
El usuario CELECUEVA fue creado con la contraseña CELECUEVA y ahora la hemos cambiado por USUARIONUEVO.
Vamos a iniciar sesión con la nueva contraseña que acabamos de establecer.
C:\Users\usuario>sqlplus CELECUEVA/USUARIONUEVO@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on MiÚ Feb 5 18:18:53 2025
Version 23.5.0.24.07
Hora de ┌ltima Conexi¾n Correcta: MiÚ Feb 05 2025 18:18:25 +01:00
Conectado a:
Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
SQL> exit
La conexión es correcta. La contraseña se ha actualizado.
Pero, ¿Qué pasará si intentamos acceder con la contraseña antigua?
C:\Users\usuario>sqlplus CELECUEVA/CELECUEVA@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on MiÚ Feb 5 18:19:03 2025
Version 23.5.0.24.07
Hora de ┌ltima Conexi¾n Correcta: MiÚ Feb 05 2025 18:18:53 +01:00
Conectado a:
Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
SQL> exit
Consultemos la vista dba_users para ver el estado de la cuenta de usuario.
SQL> select username, account_status from dba_users where username='CELECUEVA';
USERNAME ACCOUNT_STATUS
------------------------- --------------------------------
CELECUEVA OPEN & IN ROLLOVER
Aquí está el secreto del PASSWORD_ROLLOVER_TIME.
Durante un día (tal y como hemos indicado en la creación del profile APLICACION) nos va a permitir iniciar sesión con ambas contraseñas.
En el campo account_status de la dba_users aparece el estado IN ROLLOVER para que podamos identificarlo correctamente. Este estado se prolongará durante el tiempo que hayamos indicado en el profile.
Si nos fijamos en la fecha/hora que marca la conexión a SQL*Plus, todas estas prácticas las ejecuté el día 5 de Febrero.
¿Qué ocurrirá si intentamos acceder con la contraseña antigua hoy, 7 de febrero? Ya han pasado dos días, y en el PASSWORD_ROLLOVER_TIME indicamos solo 1 día.
C:\Users\usuario>sqlplus CELECUEVA/CELECUEVA@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on Vie Feb 7 09:15:13 2025
Version 23.5.0.24.07
Copyright (c) 1982, 2024, Oracle. All rights reserved.
ERROR:
ORA-01017: Credenciales no vßlidas o no autorizadas. Conexi¾n denegada
Ayuda: https://docs.oracle.com/error-help/db/ora-01017/
Si consultamos el estado del usuario, veremos que ya no aparece IN ROLLOVER, si no OPEN solamente.
SQL> select username, account_status from dba_users where username='CELECUEVA';
USERNAME ACCOUNT_STATUS
------------------------- --------------------------------
CELECUEVA OPEN
Práctica con el usuario TEST y profile DEFAULT
Para que no quede duda alguna, voy a crear un nuevo usuario. Esta vez será el usuario TEST y va a estar asignado al profile DEFAULT. Este profile tenemos que recordar que no tiene habilitada la opción de PASSWORD_ROLLOVER_TIME, por lo que debería funcionar de la forma tradicional que conocemos.
En el momento en que se cambia la contraseña, la antigua deja de ser válida. Comprobémoslo.
SQL> create user TEST identified by "TEST";
Usuario creado.
SQL> grant create session to TEST;
Concesi¾n terminada correctamente.
SQL> select username, profile from dba_users where username in ('CELECUEVA','TEST')
USERNAME PROFILE
-------------------- --------------------
TEST DEFAULT
CELECUEVA APLICACION
SQL> exit
C:\Users\usuario>sqlplus TEST/TEST@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on Vie Feb 7 09:26:25 2025
Version 23.5.0.24.07
Copyright (c) 1982, 2024, Oracle. All rights reserved.
Conectado a:
Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
SQL> alter user TEST identified by "TESTNUEVA";
Usuario modificado.
SQL> exit
Desconectado de Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
C:\Users\usuario>sqlplus TEST/TESTNUEVA@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on Vie Feb 7 09:26:52 2025
Version 23.5.0.24.07
Copyright (c) 1982, 2024, Oracle. All rights reserved.
Hora de ┌ltima Conexi¾n Correcta: Vie Feb 07 2025 09:26:25 +01:00
Conectado a:
Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
SQL> exit
Desconectado de Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free
Version 23.5.0.24.07
C:\Users\usuario>sqlplus TEST/TEST@192.168.1.229:1522/freepdb1
SQL*Plus: Release 23.0.0.0.0 - Production on Vie Feb 7 09:26:56 2025
Version 23.5.0.24.07
Copyright (c) 1982, 2024, Oracle. All rights reserved.
ERROR:
ORA-01017: Credenciales no vßlidas o no autorizadas. Conexi¾n denegada
Ayuda: https://docs.oracle.com/error-help/db/ora-01017/
Hemos creado el usuario TEST con la contraseña TEST. Al no indicarlo, el usuario es asignado por defecto al profile DEFAULT.
Hemos asignado permisos de create session para que pueda iniciar sesión.
Verificamos que el usuario se ha creado y que está en el profile DEFAULT. Además, vemos también nuestro usuario CELECUEVA que está en el profile APLICACION.
Iniciamos sesión en la base de datos con el usuario TEST y la contraseña TEST.
Cambiamos la contraseña TEST por TESTNUEVA.
Accedemos a la base de datos con la nueva contraseña y el inicio de sesión es satisfactorio.
Volvemos a intentarlo con la contraseña antigua, y obviamente, no nos deja iniciar sesión. Tal y como esperábamos.
El lado oscuro
Pensemos que tenemos un tiempo de rollover superior, por ejemplo 15 días. Esto lo hacemos para gradualmente poder cambiar la contraseña de todas las aplicaciones poco a poco, sin afectar al servicio y sin tener que hacer parada de estas.
El usuario de base de datos, está en estado OPEN & IN ROLLOVER durante esos 15 días y en este periodo de tiempo, funcionan tanto la contraseña antigua como la nueva.
Imagina, que pasados algunos días y por cualquier motivo, esta contraseña se ha filtrado, tenemos una brecha de seguridad y debe desactivarse. Pero aún nos quedan 7 días de rollover en la base de datos, y se puede iniciar sesión con la antigua, que está expuesta.
También puede ser que ya hayamos terminado las tareas de aplicación, y no tenga sentido seguir manteniendo una contraseña antigua disponible, cuando también nos puede ocasionar problemas de seguridad.
¿Hay alguna solución para esto?
Evidentemente, existe una manera de finalizar el tiempo de rollover y propiciar que solo la nueva contraseña sea válida.
ALTER USER CELECUEVA EXPIRE PASSWORD ROLLOVER PERIOD;
De esta forma, el usuario permanecerá con estado OPEN y ya no se podrá usar la contraseña antigua.