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:
  1. Un DBA configura un perfil con una política de contraseña que obliga a los usuarios a cambiar su contraseña periódicamente.
  2. 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.
  3. Durante ese período de tiempo rollover, el usuario puede iniciar sesión con la contraseña nueva o la antigua.
  4. 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:

  1. PASSWORD_LIFE_TIME – Ciclo de vida de la contraseña de 3 días
  2. PASSWORD_GRACE_TIME – Período de gracia de 2 días
  3. PASSWORD_ROLLOVER_TIME – Periodo de 1 día en el que la contraseña antigua y nueva van a ser aceptadas.
  4. *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.

Error al hacer duplicate en Oracle. Permission denied
Cardinalidad en ASM – Veo más instancias de las que tengo

Deja un comentario