You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/11/18 20:02:03 UTC
[6/6] nifi git commit: NIFI-655: - Refactoring key service to expose
the key id. - Handling client side expiration better. - Removing specialized
active directory provider and abstract ldap provider.
NIFI-655:
- Refactoring key service to expose the key id.
- Handling client side expiration better.
- Removing specialized active directory provider and abstract ldap provider.
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/c94d0271
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/c94d0271
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/c94d0271
Branch: refs/heads/NIFI-655
Commit: c94d0271d990df6d6cd9a1dfee7b1706f451483c
Parents: 7d04dfe
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Nov 18 14:01:45 2015 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Nov 18 14:01:45 2015 -0500
----------------------------------------------------------------------
.../nifi/security/util/CertificateUtils.java | 31 ++---
.../java/org/apache/nifi/admin/dao/KeyDAO.java | 18 ++-
.../nifi/admin/dao/impl/StandardKeyDAO.java | 67 ++++++++--
.../apache/nifi/admin/service/KeyService.java | 8 +-
.../nifi/admin/service/action/GetKeyAction.java | 41 -------
.../admin/service/action/GetKeyByIdAction.java | 42 +++++++
.../service/action/GetKeyByIdentityAction.java | 42 +++++++
.../service/action/GetOrCreateKeyAction.java | 7 +-
.../admin/service/impl/StandardKeyService.java | 19 ++-
.../src/main/java/org/apache/nifi/key/Key.java | 69 +++++++++++
.../org/apache/nifi/web/api/AccessResource.java | 82 ++++++-------
.../InvalidAuthenticationExceptionMapper.java | 44 +++++++
.../src/main/resources/nifi-web-api-context.xml | 1 +
.../InvalidAuthenticationException.java | 35 ++++++
.../web/security/NiFiAuthenticationFilter.java | 5 +-
.../security/jwt/JwtAuthenticationFilter.java | 9 +-
.../nifi/web/security/jwt/JwtService.java | 20 ++-
.../security/x509/X509AuthenticationFilter.java | 4 +-
.../nifi/web/security/jwt/JwtServiceTest.java | 11 +-
.../webapp/js/nf/canvas/nf-canvas-header.js | 2 +-
.../src/main/webapp/js/nf/canvas/nf-canvas.js | 14 +--
.../src/main/webapp/js/nf/login/nf-login.js | 12 +-
.../src/main/webapp/js/nf/nf-common.js | 112 ++++++++++-------
.../src/main/webapp/js/nf/nf-dialog.js | 23 ++--
.../src/main/webapp/js/nf/nf-storage.js | 75 ++++++++----
.../apache/nifi/ldap/AbstractLdapProvider.java | 106 ----------------
.../nifi/ldap/ActiveDirectoryProvider.java | 51 --------
.../java/org/apache/nifi/ldap/LdapProvider.java | 122 ++++++++++++++-----
...he.nifi.authentication.LoginIdentityProvider | 3 +-
29 files changed, 627 insertions(+), 448 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
index 5126933..ea3a6c6 100644
--- a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
+++ b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
@@ -87,30 +87,21 @@ public final class CertificateUtils {
*/
public static String extractUsername(String dn) {
String username = dn;
- String cn = "";
// ensure the dn is specified
if (StringUtils.isNotBlank(dn)) {
-
- // attempt to locate the cn
- if (dn.startsWith("CN=")) {
- cn = StringUtils.substringBetween(dn, "CN=", ",");
- } else if (dn.startsWith("/CN=")) {
- cn = StringUtils.substringBetween(dn, "CN=", "/");
- } else if (dn.startsWith("C=") || dn.startsWith("/C=")) {
- cn = StringUtils.substringAfter(dn, "CN=");
- } else if (dn.startsWith("/") && StringUtils.contains(dn, "CN=")) {
- cn = StringUtils.substringAfter(dn, "CN=");
- }
-
- // attempt to get the username from the cn
- if (StringUtils.isNotBlank(cn)) {
- if (cn.endsWith(")")) {
- username = StringUtils.substringBetween(cn, "(", ")");
- } else if (cn.contains(" ")) {
- username = StringUtils.substringAfterLast(cn, " ");
+ // determine the separate
+ final String separator = StringUtils.indexOfIgnoreCase(dn, "/cn=") > 0 ? "/" : ",";
+
+ // attempt to locate the cd
+ final String cnPattern = "cn=";
+ final int cnIndex = StringUtils.indexOfIgnoreCase(dn, cnPattern);
+ if (cnIndex >= 0) {
+ int separatorIndex = StringUtils.indexOf(dn, separator, cnIndex);
+ if (separatorIndex > 0) {
+ username = StringUtils.substring(dn, cnIndex + cnPattern.length(), separatorIndex);
} else {
- username = cn;
+ username = StringUtils.substring(dn, cnIndex + cnPattern.length());
}
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/KeyDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/KeyDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/KeyDAO.java
index 0bc6e99..2a24e0b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/KeyDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/KeyDAO.java
@@ -16,18 +16,28 @@
*/
package org.apache.nifi.admin.dao;
+import org.apache.nifi.key.Key;
+
/**
* Key data access.
*/
public interface KeyDAO {
/**
- * Gets the key for the specified user identity. Returns null if no key exists for the user identity.
+ * Gets the key for the specified user identity. Returns null if no key exists for the key id.
*
- * @param identity The user identity
+ * @param id The key id
+ * @return The key or null
+ */
+ Key findKeyById(int id);
+
+ /**
+ * Gets the latest key for the specified identity. Returns null if no key exists for the user identity.
+ *
+ * @param identity The identity
* @return The key or null
*/
- String getKey(String identity);
+ Key findLatestKeyByIdentity(String identity);
/**
* Creates a key for the specified user identity.
@@ -35,5 +45,5 @@ public interface KeyDAO {
* @param identity The user identity
* @return The key
*/
- String createKey(String identity);
+ Key createKey(String identity);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
index 994e95b..f4bdc1d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
@@ -20,17 +20,23 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
import java.util.UUID;
import org.apache.nifi.admin.RepositoryUtils;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.KeyDAO;
+import org.apache.nifi.key.Key;
/**
*
*/
public class StandardKeyDAO implements KeyDAO {
- private static final String SELECT_KEY_FOR_USER = "SELECT KEY "
+ private static final String SELECT_KEY_FOR_USER_BY_ID = "SELECT ID, IDENTITY, KEY "
+ + "FROM KEY "
+ + "WHERE ID = ?";
+
+ private static final String SELECT_KEY_FOR_USER_BY_IDENTITY = "SELECT ID, IDENTITY, KEY "
+ "FROM KEY "
+ "WHERE IDENTITY = ?";
@@ -47,18 +53,49 @@ public class StandardKeyDAO implements KeyDAO {
}
@Override
- public String getKey(String identity) {
+ public Key findKeyById(int id) {
+ Key key = null;
+
+ PreparedStatement statement = null;
+ ResultSet rs = null;
+ try {
+ // add each authority for the specified user
+ statement = connection.prepareStatement(SELECT_KEY_FOR_USER_BY_ID);
+ statement.setInt(1, id);
+
+ // execute the query
+ rs = statement.executeQuery();
+
+ // if the key was found, add it
+ if (rs.next()) {
+ key = new Key();
+ key.setId(rs.getInt("ID"));
+ key.setIdentity(rs.getString("IDENTITY"));
+ key.setKey(rs.getString("KEY"));
+ }
+ } catch (SQLException sqle) {
+ throw new DataAccessException(sqle);
+ } finally {
+ RepositoryUtils.closeQuietly(rs);
+ RepositoryUtils.closeQuietly(statement);
+ }
+
+ return key;
+ }
+
+ @Override
+ public Key findLatestKeyByIdentity(String identity) {
if (identity == null) {
throw new IllegalArgumentException("Specified identity cannot be null.");
}
- String key = null;
+ Key key = null;
PreparedStatement statement = null;
ResultSet rs = null;
try {
// add each authority for the specified user
- statement = connection.prepareStatement(SELECT_KEY_FOR_USER);
+ statement = connection.prepareStatement(SELECT_KEY_FOR_USER_BY_IDENTITY);
statement.setString(1, identity);
// execute the query
@@ -66,7 +103,10 @@ public class StandardKeyDAO implements KeyDAO {
// if the key was found, add it
if (rs.next()) {
- key = rs.getString("KEY");
+ key = new Key();
+ key.setId(rs.getInt("ID"));
+ key.setIdentity(rs.getString("IDENTITY"));
+ key.setKey(rs.getString("KEY"));
}
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
@@ -79,20 +119,27 @@ public class StandardKeyDAO implements KeyDAO {
}
@Override
- public String createKey(final String identity) {
+ public Key createKey(final String identity) {
PreparedStatement statement = null;
ResultSet rs = null;
try {
- final String key = UUID.randomUUID().toString();
+ final String keyValue = UUID.randomUUID().toString();
// add each authority for the specified user
- statement = connection.prepareStatement(INSERT_KEY);
+ statement = connection.prepareStatement(INSERT_KEY, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, identity);
- statement.setString(2, key);
+ statement.setString(2, keyValue);
// insert the key
int updateCount = statement.executeUpdate();
- if (updateCount == 1) {
+ rs = statement.getGeneratedKeys();
+
+ // verify the results
+ if (updateCount == 1 && rs.next()) {
+ final Key key = new Key();
+ key.setId(rs.getInt(1));
+ key.setIdentity(identity);
+ key.setKey(keyValue);
return key;
} else {
throw new DataAccessException("Unable to add key for user.");
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/KeyService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/KeyService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/KeyService.java
index 9346625..ae64c41 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/KeyService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/KeyService.java
@@ -16,6 +16,8 @@
*/
package org.apache.nifi.admin.service;
+import org.apache.nifi.key.Key;
+
/**
* Supports retrieving and issues keys for signing user tokens.
*/
@@ -24,10 +26,10 @@ public interface KeyService {
/**
* Gets a key for the specified user identity. Returns null if the user has not had a key issued
*
- * @param identity The user identity
+ * @param id The key id
* @return The key or null
*/
- String getKey(String identity);
+ Key getKey(int id);
/**
* Gets a key for the specified user identity. If a key does not exist, one will be created.
@@ -36,5 +38,5 @@ public interface KeyService {
* @return The key
* @throws AdministrationException if it failed to get/create the key
*/
- String getOrCreateKey(String identity);
+ Key getOrCreateKey(String identity);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyAction.java
deleted file mode 100644
index f12b1ef..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyAction.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-package org.apache.nifi.admin.service.action;
-
-import org.apache.nifi.admin.dao.DAOFactory;
-import org.apache.nifi.authorization.AuthorityProvider;
-
-import org.apache.nifi.admin.dao.KeyDAO;
-
-/**
- * Gets a key for the specified user identity.
- */
-public class GetKeyAction implements AdministrationAction<String> {
-
- private final String identity;
-
- public GetKeyAction(String identity) {
- this.identity = identity;
- }
-
- @Override
- public String execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
- final KeyDAO keyDao = daoFactory.getKeyDAO();
- return keyDao.getKey(identity);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdAction.java
new file mode 100644
index 0000000..8763b9d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdAction.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.authorization.AuthorityProvider;
+
+import org.apache.nifi.admin.dao.KeyDAO;
+import org.apache.nifi.key.Key;
+
+/**
+ * Gets a key for the specified key id.
+ */
+public class GetKeyByIdAction implements AdministrationAction<Key> {
+
+ private final int id;
+
+ public GetKeyByIdAction(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
+ final KeyDAO keyDao = daoFactory.getKeyDAO();
+ return keyDao.findKeyById(id);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdentityAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdentityAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdentityAction.java
new file mode 100644
index 0000000..9bcb0b3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetKeyByIdentityAction.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.authorization.AuthorityProvider;
+
+import org.apache.nifi.admin.dao.KeyDAO;
+import org.apache.nifi.key.Key;
+
+/**
+ * Gets a key for the specified key id.
+ */
+public class GetKeyByIdentityAction implements AdministrationAction<Key> {
+
+ private final String identity;
+
+ public GetKeyByIdentityAction(String identity) {
+ this.identity = identity;
+ }
+
+ @Override
+ public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
+ final KeyDAO keyDao = daoFactory.getKeyDAO();
+ return keyDao.findLatestKeyByIdentity(identity);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
index 209cbcd..bb85b6f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
@@ -20,11 +20,12 @@ import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.admin.dao.KeyDAO;
+import org.apache.nifi.key.Key;
/**
* Gets a key for the specified user identity.
*/
-public class GetOrCreateKeyAction implements AdministrationAction<String> {
+public class GetOrCreateKeyAction implements AdministrationAction<Key> {
private final String identity;
@@ -33,10 +34,10 @@ public class GetOrCreateKeyAction implements AdministrationAction<String> {
}
@Override
- public String execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
+ public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
final KeyDAO keyDao = daoFactory.getKeyDAO();
- String key = keyDao.getKey(identity);
+ Key key = keyDao.findLatestKeyByIdentity(identity);
if (key == null) {
key = keyDao.createKey(identity);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardKeyService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardKeyService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardKeyService.java
index 7dff9d8..ca0a124 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardKeyService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardKeyService.java
@@ -19,7 +19,7 @@ package org.apache.nifi.admin.service.impl;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.admin.service.KeyService;
-import org.apache.nifi.admin.service.action.GetKeyAction;
+import org.apache.nifi.admin.service.action.GetKeyByIdAction;
import org.apache.nifi.admin.service.action.GetOrCreateKeyAction;
import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.admin.service.transaction.TransactionBuilder;
@@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.nifi.key.Key;
/**
*
@@ -44,19 +45,17 @@ public class StandardKeyService implements KeyService {
private TransactionBuilder transactionBuilder;
@Override
- public String getKey(String identity) {
- // TODO: Change this service to look up by "key ID" instead of identity
- // TODO: Change the return type to a Key POJO to support key rotation
+ public Key getKey(int id) {
Transaction transaction = null;
- String key = null;
+ Key key = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
- // seed the accounts
- GetKeyAction addActions = new GetKeyAction(identity);
+ // get the key
+ GetKeyByIdAction addActions = new GetKeyByIdAction(id);
key = transaction.execute(addActions);
// commit the transaction
@@ -76,11 +75,9 @@ public class StandardKeyService implements KeyService {
}
@Override
- public String getOrCreateKey(String identity) {
- // TODO: Change this service to look up by "key ID" instead of identity
- // TODO: Change the return type to a Key POJO to support key rotation
+ public Key getOrCreateKey(String identity) {
Transaction transaction = null;
- String key = null;
+ Key key = null;
writeLock.lock();
try {
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/key/Key.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/key/Key.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/key/Key.java
new file mode 100644
index 0000000..b7158c2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/key/Key.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.key;
+
+import java.io.Serializable;
+
+/**
+ * An signing key for a NiFi user.
+ */
+public class Key implements Serializable {
+
+ private int id;
+ private String identity;
+ private String key;
+
+ /**
+ * The key id.
+ *
+ * @return the id
+ */
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * The identity of the user this key is associated with.
+ *
+ * @return the identity
+ */
+ public String getIdentity() {
+ return identity;
+ }
+
+ public void setIdentity(String identity) {
+ this.identity = identity;
+ }
+
+ /**
+ * The signing key.
+ *
+ * @return the signing key
+ */
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
index 2e1c44e..27d7d29 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
@@ -55,6 +55,7 @@ import org.apache.nifi.web.api.dto.RevisionDTO;
import org.apache.nifi.web.api.entity.AccessStatusEntity;
import org.apache.nifi.web.api.entity.AccessConfigurationEntity;
import org.apache.nifi.web.api.request.ClientIdParameter;
+import org.apache.nifi.web.security.InvalidAuthenticationException;
import org.apache.nifi.web.security.ProxiedEntitiesUtils;
import org.apache.nifi.web.security.UntrustedProxyException;
import org.apache.nifi.web.security.jwt.JwtService;
@@ -185,55 +186,52 @@ public class AccessResource extends ApplicationResource {
accessStatus.setStatus(AccessStatusDTO.Status.UNKNOWN.name());
accessStatus.setMessage("No credentials supplied, unknown user.");
} else {
- // Extract the Base64 encoded token from the Authorization header
- final String token = StringUtils.substringAfterLast(authorization, " ");
-
try {
+ // Extract the Base64 encoded token from the Authorization header
+ final String token = StringUtils.substringAfterLast(authorization, " ");
final String principal = jwtService.getAuthenticationFromToken(token);
- // ensure we have something we can work with (certificate or credentials)
- if (principal == null) {
- throw new IllegalArgumentException("The specific token is not valid.");
- } else {
- // set the user identity
- accessStatus.setIdentity(principal);
- accessStatus.setUsername(CertificateUtils.extractUsername(principal));
+ // set the user identity
+ accessStatus.setIdentity(principal);
+ accessStatus.setUsername(CertificateUtils.extractUsername(principal));
- // without a certificate, this is not a proxied request
- final List<String> chain = Arrays.asList(principal);
+ // without a certificate, this is not a proxied request
+ final List<String> chain = Arrays.asList(principal);
- // check authorization for this user
- checkAuthorization(chain);
+ // check authorization for this user
+ checkAuthorization(chain);
- // no issues with authorization
- accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
- accessStatus.setMessage("Account is active and authorized");
- }
+ // no issues with authorization
+ accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
+ accessStatus.setMessage("Account is active and authorized");
} catch (JwtException e) {
- // TODO: Handle the exception from a failed JWT verification
- throw new AccessDeniedException("The JWT could not be verified", e);
+ throw new InvalidAuthenticationException(e.getMessage(), e);
}
}
} else {
- final AuthenticationResponse authenticationResponse = certificateIdentityProvider.authenticate(certificates);
-
- // get the proxy chain and ensure its populated
- final List<String> proxyChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(httpServletRequest, authenticationResponse.getIdentity());
- if (proxyChain.isEmpty()) {
- logger.error(String.format("Unable to parse the proxy chain %s from the incoming request.", authenticationResponse.getIdentity()));
- throw new IllegalArgumentException("Unable to determine the user from the incoming request.");
- }
+ try {
+ final AuthenticationResponse authenticationResponse = certificateIdentityProvider.authenticate(certificates);
+
+ // get the proxy chain and ensure its populated
+ final List<String> proxyChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(httpServletRequest, authenticationResponse.getIdentity());
+ if (proxyChain.isEmpty()) {
+ logger.error(String.format("Unable to parse the proxy chain %s from the incoming request.", authenticationResponse.getIdentity()));
+ throw new IllegalArgumentException("Unable to determine the user from the incoming request.");
+ }
- // ensure the proxy chain is authorized
- checkAuthorization(proxyChain);
+ // set the user identity
+ accessStatus.setIdentity(proxyChain.get(0));
+ accessStatus.setUsername(CertificateUtils.extractUsername(proxyChain.get(0)));
- // set the user identity
- accessStatus.setIdentity(proxyChain.get(0));
- accessStatus.setUsername(CertificateUtils.extractUsername(proxyChain.get(0)));
+ // ensure the proxy chain is authorized
+ checkAuthorization(proxyChain);
- // no issues with authorization
- accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
- accessStatus.setMessage("Account is active and authorized");
+ // no issues with authorization
+ accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
+ accessStatus.setMessage("Account is active and authorized");
+ } catch (final IllegalArgumentException iae) {
+ throw new InvalidAuthenticationException(iae.getMessage(), iae);
+ }
}
} catch (final UsernameNotFoundException unfe) {
accessStatus.setStatus(AccessStatusDTO.Status.UNREGISTERED.name());
@@ -323,20 +321,20 @@ public class AccessResource extends ApplicationResource {
final AuthenticationResponse authenticationResponse = loginIdentityProvider.authenticate(new LoginCredentials(username, password));
final long maxExpiration = TimeUnit.MILLISECONDS.convert(12, TimeUnit.HOURS);
final long minExpiration = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
-
+
long expiration = authenticationResponse.getExpiration();
if (expiration > maxExpiration) {
expiration = maxExpiration;
-
- logger.warn(String.format("Max token expiration exceeded. Setting expiration to %s from %s for %s", expiration,
+
+ logger.warn(String.format("Max token expiration exceeded. Setting expiration to %s from %s for %s", expiration,
authenticationResponse.getExpiration(), authenticationResponse.getIdentity()));
} else if (expiration < minExpiration) {
expiration = minExpiration;
-
- logger.warn(String.format("Min token expiration not met. Setting expiration to %s from %s for %s", expiration,
+
+ logger.warn(String.format("Min token expiration not met. Setting expiration to %s from %s for %s", expiration,
authenticationResponse.getExpiration(), authenticationResponse.getIdentity()));
}
-
+
// create the authentication token
// TODO: Some Spring beans return "" for getClass().getSimpleName(). Using getName() temporarily
loginAuthenticationToken = new LoginAuthenticationToken(authenticationResponse.getIdentity(), expiration, loginIdentityProvider.getClass().getName());
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/InvalidAuthenticationExceptionMapper.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/InvalidAuthenticationExceptionMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/InvalidAuthenticationExceptionMapper.java
new file mode 100644
index 0000000..14d5139
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/InvalidAuthenticationExceptionMapper.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.web.api.config;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.web.security.InvalidAuthenticationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Maps access denied exceptions into a client response.
+ */
+@Provider
+public class InvalidAuthenticationExceptionMapper implements ExceptionMapper<InvalidAuthenticationException> {
+
+ private static final Logger logger = LoggerFactory.getLogger(InvalidAuthenticationExceptionMapper.class);
+
+ @Override
+ public Response toResponse(InvalidAuthenticationException exception) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(StringUtils.EMPTY, exception);
+ }
+
+ return Response.status(Response.Status.UNAUTHORIZED).entity(exception.getMessage()).type("text/plain").build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
index 73929d8..9f3d2f5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
@@ -255,6 +255,7 @@
<!-- exception mapping -->
<bean class="org.apache.nifi.web.api.config.AccessDeniedExceptionMapper" scope="singleton"/>
+ <bean class="org.apache.nifi.web.api.config.InvalidAuthenticationExceptionMapper" scope="singleton"/>
<bean class="org.apache.nifi.web.api.config.AuthenticationCredentialsNotFoundExceptionMapper" scope="singleton"/>
<bean class="org.apache.nifi.web.api.config.AccountNotFoundExceptionMapper" scope="singleton"/>
<bean class="org.apache.nifi.web.api.config.AdministrationExceptionMapper" scope="singleton"/>
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/InvalidAuthenticationException.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/InvalidAuthenticationException.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/InvalidAuthenticationException.java
new file mode 100644
index 0000000..1065152
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/InvalidAuthenticationException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.web.security;
+
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * Thrown if the authentication of a given request is invalid. For instance,
+ * an expired certificate or token.
+ */
+public class InvalidAuthenticationException extends AuthenticationException {
+
+ public InvalidAuthenticationException(String msg) {
+ super(msg);
+ }
+
+ public InvalidAuthenticationException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
index ec34ace..f09d610 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
@@ -36,7 +36,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AccountStatusException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
-import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -134,8 +133,8 @@ public abstract class NiFiAuthenticationFilter implements Filter {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
out.println("Access is denied.");
}
- } else if (ae instanceof BadCredentialsException) {
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ } else if (ae instanceof InvalidAuthenticationException) {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
out.println(ae.getMessage());
} else if (ae instanceof AccountStatusException) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationFilter.java
index dea5bba..20675fb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationFilter.java
@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
+import org.apache.nifi.web.security.InvalidAuthenticationException;
/**
*/
@@ -49,7 +50,6 @@ public class JwtAuthenticationFilter extends NiFiAuthenticationFilter {
// TODO: Refactor request header extraction logic to shared utility as it is duplicated in AccessResource
// get the principal out of the user token
- // look for an authorization token
final String authorization = request.getHeader(AUTHORIZATION);
// if there is no authorization header, we don't know the user
@@ -61,9 +61,6 @@ public class JwtAuthenticationFilter extends NiFiAuthenticationFilter {
try {
final String jwtPrincipal = jwtService.getAuthenticationFromToken(token);
- if (jwtPrincipal == null) {
- return null;
- }
if (isNewAccountRequest(request)) {
return new NewAccountAuthenticationRequestToken(new NewAccountRequest(Arrays.asList(jwtPrincipal), getJustification(request)));
@@ -71,9 +68,7 @@ public class JwtAuthenticationFilter extends NiFiAuthenticationFilter {
return new NiFiAuthenticationRequestToken(Arrays.asList(jwtPrincipal));
}
} catch (JwtException e) {
- // TODO: Is this the correct way to handle an unverified token?
- logger.error("Could not verify JWT", e);
- return null;
+ throw new InvalidAuthenticationException(e.getMessage(), e);
}
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtService.java
index f006e5b..9635354 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtService.java
@@ -35,6 +35,7 @@ import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
+import org.apache.nifi.key.Key;
/**
*
@@ -88,17 +89,16 @@ public class JwtService {
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
final String identity = claims.getSubject();
- // TODO: Currently the kid field is identical to identity, but will be a unique key ID when key rotation is implemented
- final String keyId = claims.get(KEY_ID_CLAIM, String.class);
- // The key is unique per identity and should be retrieved from the key service
- final String key = keyService.getKey(keyId);
+ // Get the key based on the key id in the claims
+ final Integer keyId = claims.get(KEY_ID_CLAIM, Integer.class);
+ final Key key = keyService.getKey(keyId);
// Ensure we were able to find a key that was previously issued by this key service for this user
- if (key == null) {
+ if (key == null || key.getKey() == null) {
throw new UnsupportedJwtException("Unable to determine signing key for " + identity + " [kid: " + keyId + "]");
}
- return key.getBytes(StandardCharsets.UTF_8);
+ return key.getKey().getBytes(StandardCharsets.UTF_8);
}
}).parseClaimsJws(base64EncodedToken);
} catch (final MalformedJwtException | UnsupportedJwtException | SignatureException | ExpiredJwtException | IllegalArgumentException | AdministrationException e) {
@@ -137,21 +137,19 @@ public class JwtService {
try {
// Get/create the key for this user
- final String key = keyService.getOrCreateKey(identity);
- final byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
+ final Key key = keyService.getOrCreateKey(identity);
+ final byte[] keyBytes = key.getKey().getBytes(StandardCharsets.UTF_8);
logger.trace("Generating JWT for " + authenticationToken);
// TODO: Implement "jti" claim with nonce to prevent replay attacks and allow blacklisting of revoked tokens
- // TODO: Change kid field to key ID when KeyService is refactored
-
// Build the token
return Jwts.builder().setSubject(identity)
.setIssuer(authenticationToken.getIssuer())
.setAudience(authenticationToken.getIssuer())
.claim(USERNAME_CLAIM, username)
- .claim(KEY_ID_CLAIM, identity)
+ .claim(KEY_ID_CLAIM, key.getId())
.setExpiration(expiration.getTime())
.setIssuedAt(Calendar.getInstance().getTime())
.signWith(SIGNATURE_ALGORITHM, keyBytes).compact();
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationFilter.java
index e626f74..dd7d47e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationFilter.java
@@ -21,6 +21,7 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.nifi.authentication.AuthenticationResponse;
+import org.apache.nifi.web.security.InvalidAuthenticationException;
import org.apache.nifi.web.security.NiFiAuthenticationFilter;
import org.apache.nifi.web.security.ProxiedEntitiesUtils;
import org.apache.nifi.web.security.token.NewAccountAuthenticationRequestToken;
@@ -28,7 +29,6 @@ import org.apache.nifi.web.security.token.NiFiAuthenticationRequestToken;
import org.apache.nifi.web.security.user.NewAccountRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.authentication.BadCredentialsException;
/**
* Custom X509 filter that will inspect the HTTP headers for a proxied user before extracting the user details from the client certificate.
@@ -58,7 +58,7 @@ public class X509AuthenticationFilter extends NiFiAuthenticationFilter {
try {
authenticationResponse = certificateIdentityProvider.authenticate(certificates);
} catch (final IllegalArgumentException iae) {
- throw new BadCredentialsException(iae.getMessage(), iae);
+ throw new InvalidAuthenticationException(iae.getMessage(), iae);
}
final List<String> proxyChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(request, authenticationResponse.getIdentity());
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/JwtServiceTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/JwtServiceTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/JwtServiceTest.java
index c9107b9..ea3e122 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/JwtServiceTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/JwtServiceTest.java
@@ -22,10 +22,12 @@ import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;
+import org.apache.nifi.key.Key;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
/**
@@ -117,9 +119,14 @@ public class JwtServiceTest {
@Before
public void setUp() throws Exception {
+ final Key key = new Key();
+ key.setId(0);
+ key.setIdentity(HMAC_SECRET);
+ key.setKey(HMAC_SECRET);
+
mockKeyService = Mockito.mock(KeyService.class);
- when(mockKeyService.getKey(anyString())).thenReturn(HMAC_SECRET);
- when(mockKeyService.getOrCreateKey(anyString())).thenReturn(HMAC_SECRET);
+ when(mockKeyService.getKey(anyInt())).thenReturn(key);
+ when(mockKeyService.getOrCreateKey(anyString())).thenReturn(key);
jwtService = new JwtService(mockKeyService);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
index eab5297..7d63534 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
@@ -142,7 +142,7 @@ nf.CanvasHeader = (function () {
});
// show the login link if supported and user is currently anonymous
- var isAnonymous = $('#current-user').text() === nf.Canvas.ANONYMOUS_USER_TEXT;
+ var isAnonymous = $('#current-user').text() === nf.Common.ANONYMOUS_USER_TEXT;
if (supportsLogin === true && isAnonymous) {
// login link
$('#login-link').click(function () {
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index 09a8212..c9498fe 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -936,7 +936,6 @@ nf.Canvas = (function () {
};
return {
- ANONYMOUS_USER_TEXT: 'Anonymous user',
CANVAS_OFFSET: 0,
/**
* Determines if the current broswer supports SVG.
@@ -1056,17 +1055,8 @@ nf.Canvas = (function () {
$('#logout-link-container').show();
}
} else {
- // alert user's of anonymous access
- $('#anonymous-user-alert').show().qtip($.extend({}, nf.Common.config.tooltipConfig, {
- content: 'You are accessing with limited authority. Log in or request an account to access with additional authority granted to you by an administrator.',
- position: {
- my: 'top right',
- at: 'bottom left'
- }
- }));
-
- // render the anonymous user text
- $('#current-user').text(nf.Canvas.ANONYMOUS_USER_TEXT).show();
+ // set the anonymous user label
+ nf.Common.setAnonymousUserLabel();
}
deferred.resolve();
}).fail(function (xhr, status, error) {
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
index 89db6ce..bd39a44 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
@@ -96,8 +96,10 @@ nf.Login = (function () {
'password': $('#password').val()
}
}).done(function (jwt) {
- // store the jwt and reload the page
- nf.Storage.setItem('jwt', jwt, nf.Common.getJwtExpiration(jwt));
+ // get the payload and store the token with the appropirate expiration
+ var token = nf.Common.getJwtPayload(jwt);
+ var expiration = parseInt(token['exp'], 10) * nf.Common.MILLIS_PER_SECOND;
+ nf.Storage.setItem('jwt', jwt, expiration);
// check to see if they actually have access now
$.ajax({
@@ -112,8 +114,7 @@ nf.Login = (function () {
nf.Common.scheduleTokenRefresh();
// show the user
- var user = nf.Common.getJwtSubject(jwt);
- $('#nifi-user-submit-justification').text(user);
+ $('#nifi-user-submit-justification').text(token['preferred_username']);
// show the registration form
initializeNiFiRegistration();
@@ -133,8 +134,7 @@ nf.Login = (function () {
nf.Common.scheduleTokenRefresh();
// show the user
- var user = nf.Common.getJwtSubject(jwt);
- $('#nifi-user-submit-justification').text(user);
+ $('#nifi-user-submit-justification').text(token['preferred_username']);
if (xhr.status === 401) {
initializeNiFiRegistration();
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 3be6b91..9202819 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -54,9 +54,17 @@ $(document).ready(function () {
// include jwt when possible
$.ajaxSetup({
'beforeSend': function(xhr) {
+ var hadToken = nf.Storage.hasItem('jwt');
+
+ // get the token to include in all requests
var token = nf.Storage.getItem('jwt');
- if (token) {
+ if (token !== null) {
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
+ } else {
+ // if the current user was logged in with a token and the token just expired, reload
+ if (hadToken === true) {
+ return false;
+ }
}
}
});
@@ -83,6 +91,8 @@ nf.Common = (function () {
var tokenRefreshInterval = null;
return {
+ ANONYMOUS_USER_TEXT: 'Anonymous user',
+
config: {
sensitiveText: 'Sensitive value set',
tooltipConfig: {
@@ -100,9 +110,6 @@ nf.Common = (function () {
at: 'top right',
my: 'bottom left'
}
- },
- urls: {
- token: '../nifi-api/access/token'
}
},
@@ -148,7 +155,7 @@ nf.Common = (function () {
}
// set the interval to one hour
- var interval = nf.Common.MILLIS_PER_HOUR;
+ var interval = 10 * nf.Common.MILLIS_PER_MINUTE;
var checkExpiration = function () {
var expiration = nf.Storage.getItemExpiration('jwt');
@@ -161,13 +168,16 @@ nf.Common = (function () {
// get the time remainging plus a little bonus time to reload the token
var timeRemaining = expirationDate.valueOf() - now.valueOf() - nf.Common.MILLIS_PER_MINUTE;
if (timeRemaining < interval) {
- // if the token will expire before the next interval minus some bonus time, refresh now
- $.ajax({
- type: 'POST',
- url: nf.Common.config.urls.token
- }).done(function (jwt) {
- nf.Storage.setItem('jwt', jwt, nf.Common.getJwtExpiration(jwt));
- });
+ if ($('#current-user').text() !== nf.Common.ANONYMOUS_USER_TEXT && !$('#anonymous-user-alert').is(':visible')) {
+ // if the token will expire before the next interval minus some bonus time, notify the user to re-login
+ $('#anonymous-user-alert').show().qtip($.extend({}, nf.Common.config.tooltipConfig, {
+ content: 'Your session will expire soon. Please log in again to avoid being automatically logged out.',
+ position: {
+ my: 'top right',
+ at: 'bottom left'
+ }
+ }));
+ }
}
}
};
@@ -180,56 +190,46 @@ nf.Common = (function () {
},
/**
- * Extracts the subject from the specified jwt. If the jwt is not as expected
- * an empty string is returned.
- *
- * @param {string} jwt
- * @returns {string}
+ * Sets the anonymous user label.
*/
- getJwtSubject: function (jwt) {
- if (nf.Common.isDefinedAndNotNull(jwt)) {
- var segments = jwt.split(/\./);
- if (segments.length !== 3) {
- return '';
- }
-
- var rawPayload = $.base64.atob(segments[1]);
- var payload = JSON.parse(rawPayload);
-
- if (nf.Common.isDefinedAndNotNull(payload['preferred_username'])) {
- return payload['preferred_username'];
- } else {
- '';
- }
+ setAnonymousUserLabel: function () {
+ var anonymousUserAlert = $('#anonymous-user-alert');
+ if (anonymousUserAlert.data('qtip')) {
+ anonymousUserAlert.qtip('api').destroy(true);
}
+
+ // alert user's of anonymous access
+ anonymousUserAlert.show().qtip($.extend({}, nf.Common.config.tooltipConfig, {
+ content: 'You are accessing with limited authority. Log in or request an account to access with additional authority granted to you by an administrator.',
+ position: {
+ my: 'top right',
+ at: 'bottom left'
+ }
+ }));
- return '';
+ // render the anonymous user text
+ $('#current-user').text(nf.Common.ANONYMOUS_USER_TEXT).show();
},
/**
- * Extracts the expiration from the specified jwt. If the jwt is not as expected
- * a null value is returned.
+ * Extracts the subject from the specified jwt. If the jwt is not as expected
+ * an empty string is returned.
*
* @param {string} jwt
- * @returns {integer}
+ * @returns {string}
*/
- getJwtExpiration: function (jwt) {
+ getJwtPayload: function (jwt) {
if (nf.Common.isDefinedAndNotNull(jwt)) {
var segments = jwt.split(/\./);
if (segments.length !== 3) {
- return null;
+ return '';
}
var rawPayload = $.base64.atob(segments[1]);
var payload = JSON.parse(rawPayload);
- if (nf.Common.isDefinedAndNotNull(payload['exp'])) {
- try {
- // jwt exp is in seconds
- return parseInt(payload['exp'], 10) * nf.Common.MILLIS_PER_SECOND;
- } catch (e) {
- return null;
- }
+ if (nf.Common.isDefinedAndNotNull(payload)) {
+ return payload;
} else {
return null;
}
@@ -313,6 +313,28 @@ nf.Common = (function () {
* @argument {string} error The error
*/
handleAjaxError: function (xhr, status, error) {
+ if (status === 'canceled') {
+ if ($('#splash').is(':visible')) {
+ $('#message-title').text('Session Expired');
+ $('#message-content').text('Your session has expired. Please reload to log in again.');
+
+ // show the error pane
+ $('#message-pane').show();
+
+ // close the canvas
+ nf.Common.closeCanvas();
+ } else {
+ nf.Dialog.showOkDialog({
+ dialogContent: 'Your session has expired. Please press Ok to log in again.',
+ overlayBackground: false,
+ okHandler: function () {
+ window.location = '/nifi';
+ }
+ });
+ }
+ return;
+ }
+
// if an error occurs while the splash screen is visible close the canvas show the error message
if ($('#splash').is(':visible')) {
if (xhr.status === 401) {
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js
index 2d1183f..d305e4d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js
@@ -23,15 +23,6 @@ $(document).ready(function () {
// configure the ok dialog
$('#nf-ok-dialog').modal({
- buttons: [{
- buttonText: 'Ok',
- handler: {
- click: function () {
- // close the dialog
- $('#nf-ok-dialog').modal('hide');
- }
- }
- }],
handler: {
close: function () {
// clear the content
@@ -77,6 +68,20 @@ nf.Dialog = (function () {
var content = $('<p></p>').append(options.dialogContent);
$('#nf-ok-dialog-content').append(content);
+ // update the button model
+ $('#nf-ok-dialog').modal('setButtonModel', [{
+ buttonText: 'Ok',
+ handler: {
+ click: function () {
+ // close the dialog
+ $('#nf-ok-dialog').modal('hide');
+ if (typeof options.okHandler === 'function') {
+ options.okHandler.call(this);
+ }
+ }
+ }
+ }]);
+
// show the dialog
$('#nf-ok-dialog').modal('setHeaderText', options.headerText).modal('setOverlayBackground', options.overlayBackground).modal('show');
},
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js
index cdb2e9e..7b0c3f6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js
@@ -42,32 +42,18 @@ nf.Storage = (function () {
};
/**
- * If the item at key is not expired, the value of field is returned. Otherwise, null.
+ * Gets an enty for the key. The entry expiration is not checked.
*
* @param {string} key
- * @param {string} field
- * @return {object} the value
*/
- var getEntryField = function (key, field) {
+ var getEntry = function (key) {
try {
// parse the entry
var entry = JSON.parse(localStorage.getItem(key));
// ensure the entry and item are present
if (nf.Common.isDefinedAndNotNull(entry)) {
-
- // if the entry is expired, drop it and return null
- if (checkExpiration(entry)) {
- nf.Storage.removeItem(key);
- return null;
- }
-
- // if the entry has the specified field return its value
- if (nf.Common.isDefinedAndNotNull(entry[field])) {
- return entry[field];
- } else {
- return null;
- }
+ return entry;
} else {
return null;
}
@@ -75,7 +61,7 @@ nf.Storage = (function () {
return null;
}
};
-
+
return {
/**
* Initializes the storage. Items will be persisted for two days. Once the scripts runs
@@ -86,11 +72,9 @@ nf.Storage = (function () {
try {
// get the next item
var key = localStorage.key(i);
- var entry = JSON.parse(localStorage.getItem(key));
-
- if (checkExpiration(entry)) {
- nf.Storage.removeItem(key);
- }
+
+ // attempt to get the item which will expire if necessary
+ nf.Storage.getItem(key);
} catch (e) {
}
}
@@ -118,6 +102,17 @@ nf.Storage = (function () {
},
/**
+ * Returns whether there is an entry for this key. This will not check the expiration. If
+ * the entry is expired, it will return null on a subsequent getItem invocation.
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ hasItem: function (key) {
+ return getEntry(key) !== null;
+ },
+
+ /**
* Gets the item with the specified key. If an item with this key does
* not exist, null is returned. If an item exists but cannot be parsed
* or is malformed/unrecognized, null is returned.
@@ -125,18 +120,44 @@ nf.Storage = (function () {
* @param {type} key
*/
getItem: function (key) {
- return getEntryField(key, 'item');
+ var entry = getEntry(key);
+ if (entry === null) {
+ return null;
+ }
+
+ // if the entry is expired, drop it and return null
+ if (checkExpiration(entry)) {
+ nf.Storage.removeItem(key);
+ return null;
+ }
+
+ // if the entry has the specified field return its value
+ if (nf.Common.isDefinedAndNotNull(entry['item'])) {
+ return entry['item'];
+ } else {
+ return null;
+ }
},
/**
- * Gets the expiration for the specified item. If the item does not exists our could
- * not be parsed, returns null.
+ * Gets the expiration for the specified item. This will not check the expiration. If
+ * the entry is expired, it will return null on a subsequent getItem invocation.
*
* @param {string} key
* @returns {integer}
*/
getItemExpiration: function (key) {
- return getEntryField(key, 'expires');
+ var entry = getEntry(key);
+ if (entry === null) {
+ return null;
+ }
+
+ // if the entry has the specified field return its value
+ if (nf.Common.isDefinedAndNotNull(entry['expires'])) {
+ return entry['expires'];
+ } else {
+ return null;
+ }
},
/**
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/AbstractLdapProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/AbstractLdapProvider.java b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/AbstractLdapProvider.java
deleted file mode 100644
index 64c48bf..0000000
--- a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/AbstractLdapProvider.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.
- */
-package org.apache.nifi.ldap;
-
-import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authentication.AuthenticationResponse;
-import org.apache.nifi.authentication.LoginCredentials;
-import org.apache.nifi.authentication.LoginIdentityProvider;
-import org.apache.nifi.authentication.LoginIdentityProviderConfigurationContext;
-import org.apache.nifi.authentication.LoginIdentityProviderInitializationContext;
-import org.apache.nifi.authentication.exception.IdentityAccessException;
-import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException;
-import org.apache.nifi.authorization.exception.ProviderCreationException;
-import org.apache.nifi.authorization.exception.ProviderDestructionException;
-import org.apache.nifi.util.FormatUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.ldap.CommunicationException;
-import org.springframework.security.authentication.AuthenticationServiceException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider;
-import org.springframework.security.ldap.userdetails.LdapUserDetails;
-
-/**
- * Abstract LDAP based implementation of a login identity provider.
- */
-public abstract class AbstractLdapProvider implements LoginIdentityProvider {
-
- private static final Logger logger = LoggerFactory.getLogger(AbstractLdapProvider.class);
-
- private AbstractLdapAuthenticationProvider provider;
- private long expiration;
-
- @Override
- public final void initialize(final LoginIdentityProviderInitializationContext initializationContext) throws ProviderCreationException {
- }
-
- @Override
- public final void onConfigured(final LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException {
- final String rawExpiration = configurationContext.getProperty("Expiration Duration");
- if (StringUtils.isBlank(rawExpiration)) {
- throw new ProviderCreationException("The Expiration Duration must be specified.");
- }
-
- try {
- expiration = FormatUtils.getTimeDuration(rawExpiration, TimeUnit.MILLISECONDS);
- } catch (final IllegalArgumentException iae) {
- throw new ProviderCreationException(String.format("The Expiration Duration '%s' is not a valid time duration", rawExpiration));
- }
-
- provider = getLdapAuthenticationProvider(configurationContext);
- }
-
- protected abstract AbstractLdapAuthenticationProvider getLdapAuthenticationProvider(LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException;
-
- @Override
- public final AuthenticationResponse authenticate(final LoginCredentials credentials) throws InvalidLoginCredentialsException, IdentityAccessException {
- if (provider == null) {
- throw new IdentityAccessException("The LDAP authentication provider is not initialized.");
- }
-
- try {
- // perform the authentication
- final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
- final Authentication authentication = provider.authenticate(token);
-
- // attempt to get the ldap user details to get the DN
- if (authentication.getPrincipal() instanceof LdapUserDetails) {
- final LdapUserDetails userDetails = (LdapUserDetails) authentication.getPrincipal();
- return new AuthenticationResponse(userDetails.getDn(), credentials.getUsername(), expiration);
- } else {
- return new AuthenticationResponse(authentication.getName(), credentials.getUsername(), expiration);
- }
- } catch (final CommunicationException | AuthenticationServiceException e) {
- logger.error(e.getMessage());
- if (logger.isDebugEnabled()) {
- logger.debug(StringUtils.EMPTY, e);
- }
- throw new IdentityAccessException("Unable to query the configured directory server. See the logs for additional details.", e);
- } catch (final BadCredentialsException bce) {
- throw new InvalidLoginCredentialsException(bce.getMessage(), bce);
- }
- }
-
- @Override
- public final void preDestruction() throws ProviderDestructionException {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/nifi/blob/c94d0271/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ActiveDirectoryProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ActiveDirectoryProvider.java b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ActiveDirectoryProvider.java
deleted file mode 100644
index e43c1ee..0000000
--- a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ActiveDirectoryProvider.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-package org.apache.nifi.ldap;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authentication.LoginIdentityProviderConfigurationContext;
-import org.apache.nifi.authorization.exception.ProviderCreationException;
-import org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider;
-import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
-
-/**
- * Active Directory based implementation of a login identity provider.
- */
-public class ActiveDirectoryProvider extends AbstractLdapProvider {
-
- @Override
- protected AbstractLdapAuthenticationProvider getLdapAuthenticationProvider(LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException {
-
- final String url = configurationContext.getProperty("Url");
- if (StringUtils.isBlank(url)) {
- throw new ProviderCreationException("The Active Directory 'Url' must be specified.");
- }
-
- final String domain = configurationContext.getProperty("Domain");
- final String userSearchBase = configurationContext.getProperty("User Search Base");
-
- final ActiveDirectoryLdapAuthenticationProvider activeDirectoryAuthenticationProvider
- = new ActiveDirectoryLdapAuthenticationProvider(StringUtils.isBlank(domain) ? null : domain, url, StringUtils.isBlank(userSearchBase) ? null : userSearchBase);
-
- final String userSearchFilter = configurationContext.getProperty("User Search Filter");
- if (StringUtils.isNotBlank(userSearchFilter)) {
- activeDirectoryAuthenticationProvider.setSearchFilter(userSearchFilter);
- }
-
- return activeDirectoryAuthenticationProvider;
- }
-}