Unlock oracle accounts without alter user system privilege

I wanted to give non-DBA users (Servicedesk, Operations) the ability to unlock database user accounts. The ‘alter user’ system privilege allows that, but it also gives out a lot more privileges (change password, kill session, alter DBA accounts) than I thought safe.

So instead I created a pl/sql procedure to handle this securely. Usage for it is just:

SQL> set serverout on
SQL> exec sys.unlock_user('username')
CREATE OR REPLACE PROCEDURE sys.unlock_user
/***************************
|| Name : sys.unlock_user
|| Author : Andrew Fraser
|| Date : 02-Jul-2013
|| Purpose : Allow normal users to unlock database accounts
|| Parameters :
||     p_username - the username of the user - case INsensitive
|| Installation notes:
||     This procedure should be owned by sys and the user account then needs execute privilege on this procedure only.
||     Users other than sys could own this procedure if they are given explicit select on dba_role_privs and dba_users.
|| Change History :
***************************/
   ( p_username IN VARCHAR2 )
AS
   v_num_superusers NUMBER := 0 ;
   v_num_users NUMBER := 0 ;
   v_num_locked NUMBER := 0 ;
BEGIN
   /* Check account exists */
   SELECT COUNT(*) INTO v_num_users FROM dba_users WHERE username = UPPER ( p_username ) ;
   IF v_num_users = 1
   THEN
      /* Check account is currently locked */
      SELECT COUNT(*) INTO v_num_locked FROM dba_users WHERE username = UPPER ( p_username ) and account_status LIKE '%LOCKED%' ;
      IF v_num_locked = 1
      THEN
         /* Check is not a superuser */
         SELECT COUNT(*) INTO v_num_superusers FROM sys.dba_role_privs WHERE grantee = UPPER(p_username) AND granted_role IN ('DBA','IMP_FULL_DATABASE') ;
         IF v_num_superusers = 0
         THEN
            /* Unlock account */
            EXECUTE IMMEDIATE 'alter user ' || p_username || ' account unlock' ;
            dbms_output.put_line ( 'Success : ' || p_username || ' unlocked.' ) ;
         ELSE
            dbms_output.put_line ( 'Warning : ' || p_username || ' is a superuser account, which cannot be unlocked by this utility, so no action taken.' ) ;
         END IF ;
      ELSE
         dbms_output.put_line ( 'Warning : ' || p_username || ' is not currently locked, so no action taken.' ) ;
      END IF ;
   ELSE
     dbms_output.put_line ( 'Error : ' || p_username || ' does not exist, please check input and try again.' ) ;
   END IF ;
END ;
/
sho err
grant execute on sys.unlock_user to my_normal_user ;
July 2, 2013

  • Good procedure. Thank you.

    I am new to this….

    I have need for the following procedure:

    1. check if the user account is locked, if locked, unlock it.
    2. change the user password – irregardless
    3. Change password … .,… I will have crontab to run this procedure?

    Thank you.
    Jack

  • Leave a Reply

    Your email address will not be published. Required fields are marked *