You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by bp...@apache.org on 2022/04/14 04:22:26 UTC
[ranger] branch ranger-2.3 updated: RANGER-3687: Password Policy Best Practices for Strong Security
This is an automated email from the ASF dual-hosted git repository.
bpatel pushed a commit to branch ranger-2.3
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.3 by this push:
new 88fa08cf9 RANGER-3687: Password Policy Best Practices for Strong Security
88fa08cf9 is described below
commit 88fa08cf93ffbacf79ded8ca5452f0365a06bafa
Author: Bhavik Patel <bh...@gmail.com>
AuthorDate: Fri Apr 8 19:23:41 2022 +0530
RANGER-3687: Password Policy Best Practices for Strong Security
---
.../optimized/current/ranger_core_db_mysql.sql | 3 ++
.../patches/059-update-x-portal-user-table.sql | 32 ++++++++++++++
.../optimized/current/ranger_core_db_oracle.sql | 3 ++
.../patches/059-update-x-portal-user-table..sql | 26 ++++++++++++
.../optimized/current/ranger_core_db_postgres.sql | 3 ++
.../patches/059-update-x-portal-user-table.sql | 32 ++++++++++++++
.../current/ranger_core_db_sqlanywhere.sql | 4 ++
.../patches/059-update-x-portal-user-table.sql | 21 ++++++++++
.../optimized/current/ranger_core_db_sqlserver.sql | 3 ++
.../patches/059-update-x-portal-user-table.sql | 23 ++++++++++
.../main/java/org/apache/ranger/biz/UserMgr.java | 49 +++++++++++++++++++---
.../org/apache/ranger/entity/XXPortalUser.java | 29 +++++++++++++
.../conf.dist/ranger-admin-default-site.xml | 5 +++
.../java/org/apache/ranger/biz/TestUserMgr.java | 1 +
14 files changed, 229 insertions(+), 5 deletions(-)
diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
index f6d384c06..0a6d17ffc 100644
--- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
+++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
@@ -118,6 +118,8 @@ CREATE TABLE `x_portal_user` (
`notes` varchar(4000) DEFAULT NULL,
`other_attributes` varchar(4000) DEFAULT NULL,
`sync_source` varchar(4000) DEFAULT NULL,
+ `old_passwords` varchar(4000) DEFAULT NULL,
+ `password_updated_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `x_portal_user_UK_login_id` (`login_id`),
UNIQUE KEY `x_portal_user_UK_email` (`email`),
@@ -1809,6 +1811,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('056',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('057',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('058',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10001',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
diff --git a/security-admin/db/mysql/patches/059-update-x-portal-user-table.sql b/security-admin/db/mysql/patches/059-update-x-portal-user-table.sql
new file mode 100644
index 000000000..103abb5f7
--- /dev/null
+++ b/security-admin/db/mysql/patches/059-update-x-portal-user-table.sql
@@ -0,0 +1,32 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+drop procedure if exists add_old_passwords_column_to_x_portal_user_table;
+
+delimiter ;;
+create procedure add_old_passwords_column_to_x_portal_user_table() begin
+
+ if exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_portal_user') then
+ if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_portal_user' and column_name = 'old_passwords') then
+ ALTER TABLE `x_portal_user` ADD `old_passwords` varchar(4000) DEFAULT NULL;
+ ALTER TABLE `x_portal_user` ADD `password_updated_time` datetime DEFAULT NULL;
+ end if;
+ end if;
+end;;
+
+delimiter ;
+call add_old_passwords_column_to_x_portal_user_table();
+
+drop procedure if exists add_old_passwords_column_to_x_portal_user_table;
\ No newline at end of file
diff --git a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
index 28538eda5..e9a2b7e3d 100644
--- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
+++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
@@ -310,6 +310,8 @@ CREATE TABLE x_portal_user (
notes VARCHAR(4000) DEFAULT NULL NULL ,
other_attributes VARCHAR(4000) DEFAULT NULL NULL,
sync_source VARCHAR(4000) DEFAULT NULL NULL,
+ old_passwords varchar(4000) DEFAULT NULL,
+ password_updated_time DATE DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT x_portal_user_UK_login_id UNIQUE (login_id) ,
CONSTRAINT x_portal_user_UK_email UNIQUE (email),
@@ -1969,6 +1971,7 @@ INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,act
INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '056',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '057',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '058',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
+INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '059',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, 'DB_PATCHES',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_user_module_perm (id,user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (X_USER_MODULE_PERM_SEQ.nextval,getXportalUIdByLoginId('admin'),getModulesIdByName('Reports'),sys_extract_utc(systimestamp),sys_extract_utc(systimestamp),getXportalUIdByLoginId('admin'),getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/oracle/patches/059-update-x-portal-user-table..sql b/security-admin/db/oracle/patches/059-update-x-portal-user-table..sql
new file mode 100644
index 000000000..f1dce75da
--- /dev/null
+++ b/security-admin/db/oracle/patches/059-update-x-portal-user-table..sql
@@ -0,0 +1,26 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DECLARE
+ v_count number:=0;
+BEGIN
+ v_count:=0;
+ select count(*) into v_count from user_tab_cols where table_name='X_PORTAL_USER' and column_name='OLD_PASSWORDS';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_portal_user ADD old_passwords VARCHAR(4000) DEFAULT NULL';
+ execute immediate 'ALTER TABLE x_portal_user ADD password_updated_time DATE DEFAULT NULL';
+ end if;
+ commit;
+END;/
diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
index 047b7d403..9f3d713e6 100644
--- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
+++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
@@ -193,6 +193,8 @@ user_src INT DEFAULT '0' NOT NULL,
notes VARCHAR(4000) DEFAULT NULL NULL,
other_attributes VARCHAR(4000) DEFAULT NULL NULL,
sync_source VARCHAR(4000) DEFAULT NULL NULL,
+old_passwords VARCHAR(4000) DEFAULT NULL,
+password_updated_time TIMESTAMP DEFAULT NULL,
PRIMARY KEY(id),
CONSTRAINT x_portal_user_UK_login_id UNIQUE(login_id),
CONSTRAINT x_portal_user_UK_email UNIQUE(email),
@@ -1892,6 +1894,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('056',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('057',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('058',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES
diff --git a/security-admin/db/postgres/patches/059-update-x-portal-user-table.sql b/security-admin/db/postgres/patches/059-update-x-portal-user-table.sql
new file mode 100644
index 000000000..b28b50d9a
--- /dev/null
+++ b/security-admin/db/postgres/patches/059-update-x-portal-user-table.sql
@@ -0,0 +1,32 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+select 'delimiter start';
+CREATE OR REPLACE FUNCTION add_old_passwords_column_to_x_portal_user_table()
+RETURNS void AS $$
+DECLARE
+ v_column_exists integer := 0;
+BEGIN
+ select count(*) into v_column_exists from pg_attribute where attrelid in(select oid from pg_class where relname='x_portal_user') and attname='old_passwords';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_portal_user ADD COLUMN old_passwords VARCHAR(4000) DEFAULT NULL;
+ ALTER TABLE x_portal_user ADD COLUMN password_updated_time TIMESTAMP DEFAULT NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+select 'delimiter end';
+
+select add_old_passwords_column_to_x_portal_user_table();
+select 'delimiter end';
\ No newline at end of file
diff --git a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
index fabc5bf7e..980e38265 100644
--- a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
+++ b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
@@ -218,6 +218,8 @@ create table dbo.x_portal_user(
notes varchar(4000) DEFAULT NULL NULL,
other_attributes varchar(4000) DEFAULT NULL NULL,
sync_source varchar(4000) DEFAULT NULL NULL,
+ old_passwords varchar(4000) DEFAULT NULL,
+ password_updated_time datetime DEFAULT NULL,
CONSTRAINT x_portal_user_PK_id PRIMARY KEY CLUSTERED(id),
CONSTRAINT x_portal_user_UK_login_id UNIQUE NONCLUSTERED (login_id)
)
@@ -2261,6 +2263,8 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
GO
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('058',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
GO
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+GO
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
GO
INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Reports'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/sqlanywhere/patches/059-update-x-portal-user-table.sql b/security-admin/db/sqlanywhere/patches/059-update-x-portal-user-table.sql
new file mode 100644
index 000000000..a207b8f03
--- /dev/null
+++ b/security-admin/db/sqlanywhere/patches/059-update-x-portal-user-table.sql
@@ -0,0 +1,21 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_portal_user' and cname = 'old_passwords') THEN
+ ALTER TABLE dbo.x_portal_user ADD old_passwords varchar(4000) DEFAULT NULL;
+ ALTER TABLE dbo.x_portal_user ADD password_updated_time datetime DEFAULT NULL;
+END IF;
+GO
+exit
diff --git a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
index f57f59ab6..ab5b39840 100644
--- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
+++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
@@ -967,6 +967,8 @@ CREATE TABLE [dbo].[x_portal_user](
[notes] [varchar](4000) DEFAULT NULL NULL,
[other_attributes] [varchar](4000) DEFAULT NULL NULL,
[sync_source] [varchar](4000) DEFAULT NULL NULL,
+ [old_passwords] [varchar](4000) DEFAULT NULL,
+ [password_updated_time] [datetime2] DEFAULT NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
@@ -4111,6 +4113,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('056',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('057',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('058',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Reports'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Resource Based Policies'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/sqlserver/patches/059-update-x-portal-user-table.sql b/security-admin/db/sqlserver/patches/059-update-x-portal-user-table.sql
new file mode 100644
index 000000000..bac2c0f1f
--- /dev/null
+++ b/security-admin/db/sqlserver/patches/059-update-x-portal-user-table.sql
@@ -0,0 +1,23 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+GO
+IF NOT EXISTS(select * from INFORMATION_SCHEMA.columns where table_name = 'x_portal_user' and column_name = 'other_attributes')
+BEGIN
+ ALTER TABLE [dbo].[x_portal_user] ADD [old_passwords] [varchar](4000) DEFAULT NULL;
+ ALTER TABLE [dbo].[x_portal_user] ADD [password_updated_time] [datetime2] DEFAULT NULL;
+END
+GO
+exit
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
index 2c50f2cab..7e55b5e1e 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
@@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -117,6 +118,8 @@ public class UserMgr {
GUIDUtil guidUtil;
private final boolean isFipsEnabled;
+ private static final int DEFAULT_PASSWORD_HISTORY_COUNT = 4;
+ private int passwordHistoryCount = PropertiesUtil.getIntProperty("ranger.password.history.count", DEFAULT_PASSWORD_HISTORY_COUNT);
String publicRoles[] = new String[] { RangerConstants.ROLE_USER,
RangerConstants.ROLE_OTHER };
@@ -140,6 +143,9 @@ public class UserMgr {
logger.debug("UserMgr()");
}
this.isFipsEnabled = RangerAdminConfig.getInstance().isFipsEnabled();
+ if (passwordHistoryCount < 0) {
+ passwordHistoryCount = 0;
+ }
}
public XXPortalUser createUser(VXPortalUser userProfile, int userStatus,
@@ -160,6 +166,7 @@ public class UserMgr {
String saltEncodedpasswd = encrypt(user.getLoginId(),
user.getPassword());
user.setPassword(saltEncodedpasswd);
+ user.setPasswordUpdatedTime(DateUtil.getUTCDate());
daoManager.getXXPortalUser().create(user);
XXPortalUser xXPortalUser = daoManager.getXXPortalUser().findByLoginId(user.getLoginId());
// Create the XXPortalUserRole entries for this user
@@ -437,13 +444,29 @@ public class UserMgr {
}
String encryptedNewPwd = encrypt(pwdChange.getLoginId(),pwdChange.getUpdPassword());
- //check current password and provided new password different
- boolean isNewPasswordDifferent;
- if (this.isFipsEnabled) {
- isNewPasswordDifferent = isNewPasswordDifferent(pwdChange.getLoginId(), pwdChange.getOldPassword(), pwdChange.getUpdPassword());
+ String oldPasswordStr = gjUser.getOldPasswords();
+ List<String> oldPasswords;
+
+ if (StringUtils.isNotEmpty(oldPasswordStr)) {
+ oldPasswords = new ArrayList<>(Arrays.asList(oldPasswordStr.split(",")));
+ } else {
+ oldPasswords = new ArrayList<>();
+ }
+ oldPasswords.add(gjUser.getPassword());
+ while (oldPasswords.size() > this.passwordHistoryCount) {
+ oldPasswords.remove(0);
+ }
+ boolean isNewPasswordDifferent = oldPasswords.isEmpty();
+ for (String oldPassword : oldPasswords) {
+ if (this.isFipsEnabled) {
+ isNewPasswordDifferent = isNewPasswordDifferent(pwdChange.getLoginId(), oldPassword, encryptedNewPwd);
} else {
- isNewPasswordDifferent = !encryptedNewPwd.equals(currentPassword);
+ isNewPasswordDifferent = !encryptedNewPwd.equals(oldPassword);
}
+ if (!isNewPasswordDifferent){
+ break;
+ }
+ }
if (isNewPasswordDifferent) {
List<XXTrxLog> trxLogList = new ArrayList<XXTrxLog>();
XXTrxLog xTrxLog = new XXTrxLog();
@@ -457,6 +480,7 @@ public class UserMgr {
trxLogList.add(xTrxLog);
rangerBizUtil.createTrxLog(trxLogList);
gjUser.setPassword(encryptedNewPwd);
+ updateOldPasswords(gjUser, oldPasswords);
gjUser = daoManager.getXXPortalUser().update(gjUser);
ret.setMsgDesc("Password successfully updated");
ret.setStatusCode(VXResponse.STATUS_SUCCESS);
@@ -469,6 +493,12 @@ public class UserMgr {
return ret;
}
+ private void updateOldPasswords(XXPortalUser gjUser, List<String> oldPasswords) {
+ String oldPasswordStr = CollectionUtils.isNotEmpty(oldPasswords) ? StringUtils.join(oldPasswords, ",") : null;
+ gjUser.setOldPasswords(oldPasswordStr);
+ gjUser.setPasswordUpdatedTime(DateUtil.getUTCDate());
+ }
+
/**
* @param gjUser
* @param changeEmail
@@ -1338,6 +1368,15 @@ public class UserMgr {
String encryptedNewPwd = encrypt(xXPortalUser.getLoginId(),
updatedPassword);
if (xXPortalUser.getUserSource() != RangerCommonEnums.USER_EXTERNAL) {
+ String oldPasswordsStr = xXPortalUser.getOldPasswords();
+ List<String> oldPasswords;
+ if (StringUtils.isNotEmpty(oldPasswordsStr)) {
+ oldPasswords = new ArrayList<>(Arrays.asList(oldPasswordsStr.split(",")));
+ } else {
+ oldPasswords = new ArrayList<>();
+ }
+ oldPasswords.add(encryptedNewPwd);
+ updateOldPasswords(xXPortalUser, oldPasswords);
xXPortalUser.setPassword(encryptedNewPwd);
}
xXPortalUser = daoManager.getXXPortalUser().update(xXPortalUser);
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXPortalUser.java b/security-admin/src/main/java/org/apache/ranger/entity/XXPortalUser.java
index d0451b4d2..2ff3f6996 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXPortalUser.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXPortalUser.java
@@ -31,11 +31,16 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.ranger.common.AppConstants;
+import org.apache.ranger.common.DateUtil;
import org.apache.ranger.common.RangerConstants;
+import java.util.Date;
+
@Entity
@Table(name="x_portal_user")
@@ -165,6 +170,13 @@ public class XXPortalUser extends XXDBBase implements java.io.Serializable {
@Column(name="SYNC_SOURCE")
protected String syncSource;
+ @Column(name="OLD_PASSWORDS")
+ protected String oldPasswords;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name="PASSWORD_UPDATED_TIME")
+ protected Date passwordUpdatedTime = DateUtil.getUTCDate();
+
/**
* Default constructor. This will set all the attributes to default value.
*/
@@ -363,6 +375,22 @@ public class XXPortalUser extends XXDBBase implements java.io.Serializable {
*/
public String getSyncSource() { return syncSource; }
+ public String getOldPasswords() {
+ return oldPasswords;
+ }
+
+ public void setOldPasswords(String oldPasswords) {
+ this.oldPasswords = oldPasswords;
+ }
+
+ public Date getPasswordUpdatedTime() {
+ return passwordUpdatedTime;
+ }
+
+ public void setPasswordUpdatedTime(Date passwordUpdatedTime) {
+ this.passwordUpdatedTime = passwordUpdatedTime;
+ }
+
/**
* This return the bean content in string format
* @return formatedStr
@@ -381,6 +409,7 @@ public class XXPortalUser extends XXDBBase implements java.io.Serializable {
str += "notes={" + notes + "} ";
str += "otherAttributes={" + otherAttributes + "} ";
str += "syncSource={" + syncSource + "} ";
+ str += "passwordUpdatedTime={" + passwordUpdatedTime + "} ";
str += "}";
return str;
}
diff --git a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
index bf72ff3b0..58f434da5 100644
--- a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
+++ b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
@@ -511,6 +511,11 @@
<value>false</value>
<description></description>
</property>
+ <property>
+ <name>ranger.password.history.count</name>
+ <value>4</value>
+ <description></description>
+ </property>
<!-- # DB Info for audit_DB -->
<property>
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestUserMgr.java
index f43b30196..b6c43133b 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestUserMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestUserMgr.java
@@ -2036,6 +2036,7 @@ public class TestUserMgr {
user.setLoginId(userProfile.getLoginId());
String encryptCred = userMgr.encrypt(userProfile.getLoginId(), userProfile.getPassword());
user.setPassword(encryptCred);
+ user.setOldPasswords(encryptCred);
Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
Mockito.when(userDao.findByLoginId(Mockito.anyString())).thenReturn(user);
Mockito.when(stringUtil.equals(Mockito.anyString(), Mockito.nullable(String.class))).thenReturn(true);