mirror of https://github.com/apache/nifi.git
NIFI-11735 Refactored Identity Provider Groups Handling (#7419)
- Removed H2 database approach in favor of passing groups in Application Bearer Token
This commit is contained in:
parent
9709bd6fb7
commit
0f736e060a
|
@ -50,10 +50,6 @@
|
|||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-properties</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-security-utils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
|
@ -78,10 +74,6 @@
|
|||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
|
|
|
@ -1,152 +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;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.h2.jdbcx.JdbcConnectionPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class IdpDataSourceFactoryBean implements FactoryBean<JdbcConnectionPool> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(IdpDataSourceFactoryBean.class);
|
||||
private static final String NF_USERNAME_PASSWORD = "nf";
|
||||
private static final int MAX_CONNECTIONS = 5;
|
||||
|
||||
// database file name
|
||||
private static final String IDP_DATABASE_FILE_NAME = "nifi-identity-providers";
|
||||
|
||||
// ----------
|
||||
// idp tables
|
||||
// ----------
|
||||
|
||||
private static final String IDP_USER_GROUP_TABLE_NAME = "IDENTITY_PROVIDER_USER_GROUP";
|
||||
|
||||
private static final String CREATE_IDP_USER_GROUP_TABLE = "CREATE TABLE " + IDP_USER_GROUP_TABLE_NAME + " ("
|
||||
+ "ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
|
||||
+ "IDENTITY VARCHAR2(4096) NOT NULL, "
|
||||
+ "IDP_TYPE VARCHAR2(200) NOT NULL, "
|
||||
+ "GROUP_NAME VARCHAR2(4096) NOT NULL, "
|
||||
+ "CREATED TIMESTAMP NOT NULL, "
|
||||
+ "CONSTRAINT UK__IDENTITY_GROUP_NAME UNIQUE (IDENTITY, GROUP_NAME)" +
|
||||
")";
|
||||
|
||||
private JdbcConnectionPool connectionPool;
|
||||
|
||||
private NiFiProperties properties;
|
||||
|
||||
@Override
|
||||
public JdbcConnectionPool getObject() throws Exception {
|
||||
if (connectionPool == null) {
|
||||
|
||||
// locate the repository directory
|
||||
String repositoryDirectoryPath = properties.getProperty(NiFiProperties.REPOSITORY_DATABASE_DIRECTORY);
|
||||
|
||||
// ensure the repository directory is specified
|
||||
if (repositoryDirectoryPath == null) {
|
||||
throw new NullPointerException("Database directory must be specified.");
|
||||
}
|
||||
|
||||
// create a handle to the repository directory
|
||||
File repositoryDirectory = new File(repositoryDirectoryPath);
|
||||
|
||||
// create a handle to the database directory and file
|
||||
File dbFileNoExtension = new File(repositoryDirectory, IDP_DATABASE_FILE_NAME);
|
||||
String databaseUrl = getDatabaseUrl(dbFileNoExtension);
|
||||
|
||||
// create the pool
|
||||
connectionPool = JdbcConnectionPool.create(databaseUrl, NF_USERNAME_PASSWORD, NF_USERNAME_PASSWORD);
|
||||
connectionPool.setMaxConnections(MAX_CONNECTIONS);
|
||||
|
||||
Connection connection = null;
|
||||
ResultSet rs = null;
|
||||
Statement statement = null;
|
||||
try {
|
||||
// get a connection
|
||||
connection = connectionPool.getConnection();
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
// create a statement for creating/updating the database
|
||||
statement = connection.createStatement();
|
||||
|
||||
// determine if the idp tables need to be created
|
||||
rs = connection.getMetaData().getTables(null, null, IDP_USER_GROUP_TABLE_NAME, null);
|
||||
if (!rs.next()) {
|
||||
statement.execute(CREATE_IDP_USER_GROUP_TABLE);
|
||||
}
|
||||
|
||||
// commit any changes
|
||||
connection.commit();
|
||||
} catch (SQLException sqle) {
|
||||
RepositoryUtils.rollback(connection, logger);
|
||||
throw sqle;
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(rs);
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
RepositoryUtils.closeQuietly(connection);
|
||||
}
|
||||
}
|
||||
|
||||
return connectionPool;
|
||||
}
|
||||
|
||||
private String getDatabaseUrl(File databaseFile) {
|
||||
String databaseUrl = "jdbc:h2:" + databaseFile + ";AUTOCOMMIT=OFF;DB_CLOSE_ON_EXIT=FALSE;LOCK_MODE=3";
|
||||
String databaseUrlAppend = properties.getProperty(NiFiProperties.H2_URL_APPEND);
|
||||
if (StringUtils.isNotBlank(databaseUrlAppend)) {
|
||||
databaseUrl += databaseUrlAppend;
|
||||
}
|
||||
return databaseUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getObjectType() {
|
||||
return JdbcConnectionPool.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setProperties(NiFiProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
// shutdown the connection pool
|
||||
if (connectionPool != null) {
|
||||
try {
|
||||
connectionPool.dispose();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to dispose of connection pool: " + e.getMessage());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(StringUtils.EMPTY, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,4 @@ package org.apache.nifi.admin.dao;
|
|||
public interface DAOFactory {
|
||||
|
||||
ActionDAO getActionDAO();
|
||||
|
||||
IdpUserGroupDAO getIdpUserGroupDAO();
|
||||
|
||||
}
|
||||
|
|
|
@ -32,8 +32,4 @@ public class DataAccessException extends RuntimeException {
|
|||
public DataAccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DataAccessException() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +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.dao;
|
||||
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IdpUserGroupDAO {
|
||||
|
||||
IdpUserGroup createUserGroup(IdpUserGroup userGroup) throws DataAccessException;
|
||||
|
||||
List<IdpUserGroup> createUserGroups(List<IdpUserGroup> userGroups) throws DataAccessException;
|
||||
|
||||
IdpUserGroup findUserGroupById(int id) throws DataAccessException;
|
||||
|
||||
List<IdpUserGroup> findUserGroupsByIdentity(String identity) throws DataAccessException;
|
||||
|
||||
int deleteUserGroupById(int id) throws DataAccessException;
|
||||
|
||||
int deleteUserGroupsByIdentity(String identity) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@ package org.apache.nifi.admin.dao.impl;
|
|||
|
||||
import org.apache.nifi.admin.dao.ActionDAO;
|
||||
import org.apache.nifi.admin.dao.DAOFactory;
|
||||
import org.apache.nifi.admin.dao.IdpUserGroupDAO;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
|
@ -37,9 +36,4 @@ public class DAOFactoryImpl implements DAOFactory {
|
|||
public ActionDAO getActionDAO() {
|
||||
return new StandardActionDAO(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdpUserGroupDAO getIdpUserGroupDAO() {
|
||||
return new StandardIdpUserGroupDAO(connection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,244 +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.dao.impl;
|
||||
|
||||
import org.apache.nifi.admin.RepositoryUtils;
|
||||
import org.apache.nifi.admin.dao.DataAccessException;
|
||||
import org.apache.nifi.admin.dao.IdpUserGroupDAO;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class StandardIdpUserGroupDAO implements IdpUserGroupDAO {
|
||||
|
||||
private static final String INSERT_USER_GROUP = "INSERT INTO IDENTITY_PROVIDER_USER_GROUP " +
|
||||
"(IDENTITY, IDP_TYPE, GROUP_NAME, CREATED) VALUES (?, ?, ?, ?)";
|
||||
|
||||
private static final String SELECT_USER_GROUP_BY_ID = "SELECT ID, IDENTITY, IDP_TYPE, GROUP_NAME, CREATED " +
|
||||
"FROM IDENTITY_PROVIDER_USER_GROUP " +
|
||||
"WHERE ID =?";
|
||||
|
||||
private static final String SELECT_USER_GROUP_BY_IDENTITY = "SELECT ID, IDENTITY, IDP_TYPE, GROUP_NAME, CREATED " +
|
||||
"FROM IDENTITY_PROVIDER_USER_GROUP " +
|
||||
"WHERE IDENTITY =?";
|
||||
|
||||
private static final String DELETE_USER_GROUPS_BY_ID = "DELETE FROM IDENTITY_PROVIDER_USER_GROUP " +
|
||||
"WHERE ID = ?";
|
||||
|
||||
private static final String DELETE_USER_GROUPS_BY_IDENTITY = "DELETE FROM IDENTITY_PROVIDER_USER_GROUP " +
|
||||
"WHERE IDENTITY = ?";
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
public StandardIdpUserGroupDAO(final Connection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdpUserGroup createUserGroup(final IdpUserGroup userGroup) throws DataAccessException {
|
||||
if (userGroup == null) {
|
||||
throw new IllegalArgumentException("UserGroup cannot be null");
|
||||
}
|
||||
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// populate the parameters
|
||||
statement = connection.prepareStatement(INSERT_USER_GROUP, Statement.RETURN_GENERATED_KEYS);
|
||||
populateStatement(statement, userGroup);
|
||||
|
||||
// execute the insert
|
||||
int updateCount = statement.executeUpdate();
|
||||
rs = statement.getGeneratedKeys();
|
||||
|
||||
// verify the results
|
||||
if (updateCount == 1 && rs.next()) {
|
||||
userGroup.setId(rs.getInt(1));
|
||||
return userGroup;
|
||||
} else {
|
||||
throw new DataAccessException("Unable to save IDP User Group.");
|
||||
}
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(rs);
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> createUserGroups(final List<IdpUserGroup> userGroups) throws DataAccessException {
|
||||
if (userGroups == null) {
|
||||
throw new IllegalArgumentException("UserGroups cannot be null");
|
||||
}
|
||||
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// populate the parameters
|
||||
statement = connection.prepareStatement(INSERT_USER_GROUP, Statement.RETURN_GENERATED_KEYS);
|
||||
|
||||
for (final IdpUserGroup userGroup : userGroups) {
|
||||
populateStatement(statement, userGroup);
|
||||
statement.addBatch();
|
||||
}
|
||||
|
||||
int[] updateCounts = statement.executeBatch();
|
||||
if (updateCounts.length != userGroups.size()) {
|
||||
throw new DataAccessException("Unable to save IDP User Groups");
|
||||
}
|
||||
|
||||
for (int i=0; i < updateCounts.length; i++) {
|
||||
if (updateCounts[i] == 0) {
|
||||
throw new DataAccessException("Unable to save IDP User Groups");
|
||||
}
|
||||
}
|
||||
|
||||
rs = statement.getGeneratedKeys();
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
final int id = rs.getInt(1);
|
||||
final IdpUserGroup userGroup = userGroups.get(count);
|
||||
userGroup.setId(id);
|
||||
count++;
|
||||
}
|
||||
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(rs);
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
|
||||
return userGroups;
|
||||
}
|
||||
|
||||
private void populateStatement(PreparedStatement statement, IdpUserGroup userGroup) throws SQLException {
|
||||
statement.setString(1, userGroup.getIdentity());
|
||||
statement.setString(2, userGroup.getType().name());
|
||||
statement.setString(3, userGroup.getGroupName());
|
||||
statement.setTimestamp(4, new java.sql.Timestamp(userGroup.getCreated().getTime()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdpUserGroup findUserGroupById(final int id) throws DataAccessException {
|
||||
IdpUserGroup userGroup = null;
|
||||
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// set parameters
|
||||
statement = connection.prepareStatement(SELECT_USER_GROUP_BY_ID);
|
||||
statement.setInt(1, id);
|
||||
|
||||
// execute the query
|
||||
rs = statement.executeQuery();
|
||||
|
||||
// if the group was found, add it
|
||||
if (rs.next()) {
|
||||
userGroup = new IdpUserGroup();
|
||||
populateUserGroup(rs, userGroup);
|
||||
}
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(rs);
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
|
||||
return userGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> findUserGroupsByIdentity(final String identity) throws DataAccessException {
|
||||
final List<IdpUserGroup> userGroups = new ArrayList<>();
|
||||
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// set parameters
|
||||
statement = connection.prepareStatement(SELECT_USER_GROUP_BY_IDENTITY);
|
||||
statement.setString(1, identity);
|
||||
|
||||
// execute the query
|
||||
rs = statement.executeQuery();
|
||||
|
||||
// add any found groups to the result list
|
||||
while (rs.next()) {
|
||||
final IdpUserGroup userGroup = new IdpUserGroup();
|
||||
populateUserGroup(rs, userGroup);
|
||||
userGroups.add(userGroup);
|
||||
}
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(rs);
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
|
||||
return userGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteUserGroupById(int id) throws DataAccessException {
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
statement = connection.prepareStatement(DELETE_USER_GROUPS_BY_ID);
|
||||
statement.setInt(1, id);
|
||||
return statement.executeUpdate();
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} catch (DataAccessException dae) {
|
||||
throw dae;
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteUserGroupsByIdentity(final String identity) throws DataAccessException {
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
statement = connection.prepareStatement(DELETE_USER_GROUPS_BY_IDENTITY);
|
||||
statement.setString(1, identity);
|
||||
return statement.executeUpdate();
|
||||
} catch (SQLException sqle) {
|
||||
throw new DataAccessException(sqle);
|
||||
} catch (DataAccessException dae) {
|
||||
throw dae;
|
||||
} finally {
|
||||
RepositoryUtils.closeQuietly(statement);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateUserGroup(final ResultSet rs, final IdpUserGroup userGroup) throws SQLException {
|
||||
userGroup.setId(rs.getInt("ID"));
|
||||
userGroup.setIdentity(rs.getString("IDENTITY"));
|
||||
userGroup.setType(IdpType.valueOf(rs.getString("IDP_TYPE")));
|
||||
userGroup.setGroupName(rs.getString("GROUP_NAME"));
|
||||
userGroup.setCreated(new Date(rs.getTimestamp("CREATED").getTime()));
|
||||
}
|
||||
}
|
|
@ -1,71 +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;
|
||||
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Manages IDP User Groups.
|
||||
*/
|
||||
public interface IdpUserGroupService {
|
||||
|
||||
/**
|
||||
* Creates the given user group.
|
||||
*
|
||||
* @param userGroup the user group to create
|
||||
* @return the created user group
|
||||
*/
|
||||
IdpUserGroup createUserGroup(IdpUserGroup userGroup);
|
||||
|
||||
/**
|
||||
* Creates the given user groups.
|
||||
*
|
||||
* @param userGroups the user group to create
|
||||
* @return the created user group
|
||||
*/
|
||||
List<IdpUserGroup> createUserGroups(List<IdpUserGroup> userGroups);
|
||||
|
||||
/**
|
||||
* Gets the user groups for the given identity.
|
||||
*
|
||||
* @param identity the user identity
|
||||
* @return the list of user groups
|
||||
*/
|
||||
List<IdpUserGroup> getUserGroups(String identity);
|
||||
|
||||
/**
|
||||
* Deletes the user groups for the given identity.
|
||||
*
|
||||
* @param identity the user identity
|
||||
*/
|
||||
void deleteUserGroups(String identity);
|
||||
|
||||
/**
|
||||
* Replaces any existing groups for the given user identity with a new set specified by the set of group names.
|
||||
*
|
||||
* @param userIdentity the user identity
|
||||
* @param idpType the idp type for the groups
|
||||
* @param groupNames the group names, should already have identity mappings applied if necessary
|
||||
* @return the created groups
|
||||
*/
|
||||
List<IdpUserGroup> replaceUserGroups(String userIdentity, IdpType idpType, Set<String> groupNames);
|
||||
|
||||
}
|
|
@ -1,37 +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.admin.dao.IdpUserGroupDAO;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
public class CreateIdpUserGroup implements AdministrationAction<IdpUserGroup> {
|
||||
|
||||
final IdpUserGroup userGroup;
|
||||
|
||||
public CreateIdpUserGroup(final IdpUserGroup userGroup) {
|
||||
this.userGroup = userGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdpUserGroup execute(DAOFactory daoFactory) {
|
||||
final IdpUserGroupDAO userGroupDAO = daoFactory.getIdpUserGroupDAO();
|
||||
return userGroupDAO.createUserGroup(userGroup);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +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.admin.dao.IdpUserGroupDAO;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CreateIdpUserGroups implements AdministrationAction<List<IdpUserGroup>> {
|
||||
|
||||
private final List<IdpUserGroup> userGroups;
|
||||
|
||||
public CreateIdpUserGroups(List<IdpUserGroup> userGroups) {
|
||||
this.userGroups = userGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> execute(DAOFactory daoFactory) {
|
||||
final IdpUserGroupDAO userGroupDAO = daoFactory.getIdpUserGroupDAO();
|
||||
return userGroupDAO.createUserGroups(userGroups);
|
||||
}
|
||||
}
|
|
@ -1,35 +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.admin.dao.IdpUserGroupDAO;
|
||||
|
||||
public class DeleteIdpUserGroupsByIdentity implements AdministrationAction<Integer> {
|
||||
|
||||
final String identity;
|
||||
|
||||
public DeleteIdpUserGroupsByIdentity(String identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer execute(DAOFactory daoFactory) {
|
||||
final IdpUserGroupDAO userGroupDAO = daoFactory.getIdpUserGroupDAO();
|
||||
return userGroupDAO.deleteUserGroupsByIdentity(identity);
|
||||
}
|
||||
}
|
|
@ -1,38 +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.admin.dao.IdpUserGroupDAO;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GetIdpUserGroupsByIdentity implements AdministrationAction<List<IdpUserGroup>> {
|
||||
|
||||
final String identity;
|
||||
|
||||
public GetIdpUserGroupsByIdentity(String identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> execute(DAOFactory daoFactory) {
|
||||
final IdpUserGroupDAO userGroupDAO = daoFactory.getIdpUserGroupDAO();
|
||||
return userGroupDAO.findUserGroupsByIdentity(identity);
|
||||
}
|
||||
}
|
|
@ -1,247 +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.impl;
|
||||
|
||||
import org.apache.nifi.admin.dao.DataAccessException;
|
||||
import org.apache.nifi.admin.service.AdministrationException;
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.admin.service.action.CreateIdpUserGroup;
|
||||
import org.apache.nifi.admin.service.action.CreateIdpUserGroups;
|
||||
import org.apache.nifi.admin.service.action.DeleteIdpUserGroupsByIdentity;
|
||||
import org.apache.nifi.admin.service.action.GetIdpUserGroupsByIdentity;
|
||||
import org.apache.nifi.admin.service.transaction.Transaction;
|
||||
import org.apache.nifi.admin.service.transaction.TransactionBuilder;
|
||||
import org.apache.nifi.admin.service.transaction.TransactionException;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class StandardIdpUserGroupService implements IdpUserGroupService {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(StandardIdpUserGroupService.class);
|
||||
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = lock.readLock();
|
||||
private final Lock writeLock = lock.writeLock();
|
||||
|
||||
private TransactionBuilder transactionBuilder;
|
||||
|
||||
@Override
|
||||
public IdpUserGroup createUserGroup(final IdpUserGroup userGroup) {
|
||||
Transaction transaction = null;
|
||||
IdpUserGroup createdUserGroup;
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
// ensure the created date is set
|
||||
if (userGroup.getCreated() == null) {
|
||||
userGroup.setCreated(new Date());
|
||||
}
|
||||
|
||||
// start the transaction
|
||||
transaction = transactionBuilder.start();
|
||||
|
||||
// create the user group
|
||||
final CreateIdpUserGroup action = new CreateIdpUserGroup(userGroup);
|
||||
createdUserGroup = transaction.execute(action);
|
||||
|
||||
// commit the transaction
|
||||
transaction.commit();
|
||||
} catch (TransactionException | DataAccessException te) {
|
||||
rollback(transaction);
|
||||
throw new AdministrationException(te);
|
||||
} catch (Throwable t) {
|
||||
rollback(transaction);
|
||||
throw t;
|
||||
} finally {
|
||||
closeQuietly(transaction);
|
||||
writeLock.unlock();
|
||||
}
|
||||
|
||||
return createdUserGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> createUserGroups(final List<IdpUserGroup> userGroups) {
|
||||
Transaction transaction = null;
|
||||
List<IdpUserGroup> createdUserGroups;
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
// ensure the created date is set
|
||||
for (final IdpUserGroup userGroup : userGroups) {
|
||||
if (userGroup.getCreated() == null) {
|
||||
userGroup.setCreated(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
// start the transaction
|
||||
transaction = transactionBuilder.start();
|
||||
|
||||
// create the user group
|
||||
final CreateIdpUserGroups action = new CreateIdpUserGroups(userGroups);
|
||||
createdUserGroups = transaction.execute(action);
|
||||
|
||||
// commit the transaction
|
||||
transaction.commit();
|
||||
} catch (TransactionException | DataAccessException te) {
|
||||
rollback(transaction);
|
||||
throw new AdministrationException(te);
|
||||
} catch (Throwable t) {
|
||||
rollback(transaction);
|
||||
throw t;
|
||||
} finally {
|
||||
closeQuietly(transaction);
|
||||
writeLock.unlock();
|
||||
}
|
||||
|
||||
return createdUserGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> getUserGroups(final String identity) {
|
||||
Transaction transaction = null;
|
||||
List<IdpUserGroup> userGroups;
|
||||
|
||||
readLock.lock();
|
||||
try {
|
||||
// start the transaction
|
||||
transaction = transactionBuilder.start();
|
||||
|
||||
// get the user groups
|
||||
final GetIdpUserGroupsByIdentity action = new GetIdpUserGroupsByIdentity(identity);
|
||||
userGroups = transaction.execute(action);
|
||||
|
||||
// commit the transaction
|
||||
transaction.commit();
|
||||
} catch (TransactionException | DataAccessException te) {
|
||||
rollback(transaction);
|
||||
throw new AdministrationException(te);
|
||||
} catch (Throwable t) {
|
||||
rollback(transaction);
|
||||
throw t;
|
||||
} finally {
|
||||
closeQuietly(transaction);
|
||||
readLock.unlock();
|
||||
}
|
||||
|
||||
return userGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUserGroups(final String identity) {
|
||||
Transaction transaction = null;
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
// start the transaction
|
||||
transaction = transactionBuilder.start();
|
||||
|
||||
// delete the credential
|
||||
final DeleteIdpUserGroupsByIdentity action = new DeleteIdpUserGroupsByIdentity(identity);
|
||||
Integer rowsDeleted = transaction.execute(action);
|
||||
LOGGER.debug("Deleted {} user groups for identity {}", rowsDeleted, identity);
|
||||
|
||||
// commit the transaction
|
||||
transaction.commit();
|
||||
} catch (TransactionException | DataAccessException te) {
|
||||
rollback(transaction);
|
||||
throw new AdministrationException(te);
|
||||
} catch (Throwable t) {
|
||||
rollback(transaction);
|
||||
throw t;
|
||||
} finally {
|
||||
closeQuietly(transaction);
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdpUserGroup> replaceUserGroups(final String userIdentity, final IdpType idpType, final Set<String> groupNames) {
|
||||
Transaction transaction = null;
|
||||
List<IdpUserGroup> createdUserGroups;
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
// start the transaction
|
||||
transaction = transactionBuilder.start();
|
||||
|
||||
// delete the existing groups
|
||||
final DeleteIdpUserGroupsByIdentity deleteAction = new DeleteIdpUserGroupsByIdentity(userIdentity);
|
||||
Integer rowsDeleted = transaction.execute(deleteAction);
|
||||
LOGGER.debug("Deleted {} user groups for identity {}", rowsDeleted, userIdentity);
|
||||
|
||||
// create the user groups
|
||||
final List<IdpUserGroup> idpUserGroups = new ArrayList<>();
|
||||
for (final String groupName : groupNames) {
|
||||
final IdpUserGroup idpUserGroup = new IdpUserGroup();
|
||||
idpUserGroup.setIdentity(userIdentity);
|
||||
idpUserGroup.setType(idpType);
|
||||
idpUserGroup.setGroupName(groupName);
|
||||
idpUserGroup.setCreated(new Date());
|
||||
idpUserGroups.add(idpUserGroup);
|
||||
LOGGER.debug("{} belongs to {}", userIdentity, groupName);
|
||||
}
|
||||
|
||||
final CreateIdpUserGroups createAction = new CreateIdpUserGroups(idpUserGroups);
|
||||
createdUserGroups = transaction.execute(createAction);
|
||||
|
||||
// commit the transaction
|
||||
transaction.commit();
|
||||
} catch (TransactionException | DataAccessException te) {
|
||||
rollback(transaction);
|
||||
throw new AdministrationException(te);
|
||||
} catch (Throwable t) {
|
||||
rollback(transaction);
|
||||
throw t;
|
||||
} finally {
|
||||
closeQuietly(transaction);
|
||||
writeLock.unlock();
|
||||
}
|
||||
|
||||
return createdUserGroups;
|
||||
}
|
||||
|
||||
private void rollback(final Transaction transaction) {
|
||||
if (transaction != null) {
|
||||
transaction.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
private void closeQuietly(final Transaction transaction) {
|
||||
if (transaction != null) {
|
||||
try {
|
||||
transaction.close();
|
||||
} catch (final IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTransactionBuilder(TransactionBuilder transactionBuilder) {
|
||||
this.transactionBuilder = transactionBuilder;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +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.idp;
|
||||
|
||||
/**
|
||||
* Types of identity providers.
|
||||
*/
|
||||
public enum IdpType {
|
||||
|
||||
OIDC,
|
||||
SAML;
|
||||
|
||||
}
|
|
@ -1,85 +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.idp;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class IdpUserGroup {
|
||||
|
||||
private int id;
|
||||
private String identity;
|
||||
private IdpType type;
|
||||
private String groupName;
|
||||
private Date created;
|
||||
|
||||
public IdpUserGroup() {
|
||||
|
||||
}
|
||||
|
||||
public IdpUserGroup(int id, String identity, IdpType type, String groupName) {
|
||||
this(id, identity, type, groupName, new Date());
|
||||
}
|
||||
|
||||
public IdpUserGroup(int id, String identity, IdpType type, String groupName, Date created) {
|
||||
this.id = id;
|
||||
this.identity = identity;
|
||||
this.type = type;
|
||||
this.groupName = groupName;
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public void setIdentity(String identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
public IdpType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(IdpType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,29 +23,14 @@
|
|||
<property name="properties" ref="nifiProperties"/>
|
||||
</bean>
|
||||
|
||||
<!-- initialize the idp data source -->
|
||||
<bean id="idpDataSource" class="org.apache.nifi.admin.IdpDataSourceFactoryBean" destroy-method="shutdown">
|
||||
<property name="properties" ref="nifiProperties"/>
|
||||
</bean>
|
||||
|
||||
<!-- initialize the audit transaction builder -->
|
||||
<bean id="auditTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
|
||||
<property name="dataSource" ref="auditDataSource"/>
|
||||
</bean>
|
||||
|
||||
<!-- initialize the idp transaction builder -->
|
||||
<bean id="idpTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
|
||||
<property name="dataSource" ref="idpDataSource"/>
|
||||
</bean>
|
||||
|
||||
<!-- audit service -->
|
||||
<bean id="auditService" class="org.apache.nifi.admin.service.impl.StandardAuditService">
|
||||
<property name="transactionBuilder" ref="auditTransactionBuilder"/>
|
||||
</bean>
|
||||
|
||||
<!-- idp user group service -->
|
||||
<bean id="idpUserGroupService" class="org.apache.nifi.admin.service.impl.StandardIdpUserGroupService">
|
||||
<property name="transactionBuilder" ref="idpTransactionBuilder"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
|
|
@ -22,7 +22,6 @@ import com.nimbusds.jwt.proc.DefaultJWTClaimsVerifier;
|
|||
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
|
||||
import com.nimbusds.jwt.proc.JWTClaimsSetVerifier;
|
||||
import com.nimbusds.jwt.proc.JWTProcessor;
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.Authorizer;
|
||||
import org.apache.nifi.components.state.StateManager;
|
||||
import org.apache.nifi.components.state.StateManagerProvider;
|
||||
|
@ -79,15 +78,14 @@ public class JwtAuthenticationSecurityConfiguration {
|
|||
SupportedClaim.EXPIRATION.getClaim(),
|
||||
SupportedClaim.NOT_BEFORE.getClaim(),
|
||||
SupportedClaim.ISSUED_AT.getClaim(),
|
||||
SupportedClaim.JWT_ID.getClaim()
|
||||
SupportedClaim.JWT_ID.getClaim(),
|
||||
SupportedClaim.GROUPS.getClaim()
|
||||
));
|
||||
|
||||
private final NiFiProperties niFiProperties;
|
||||
|
||||
private final Authorizer authorizer;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final StateManagerProvider stateManagerProvider;
|
||||
|
||||
private final Duration keyRotationPeriod;
|
||||
|
@ -96,12 +94,10 @@ public class JwtAuthenticationSecurityConfiguration {
|
|||
public JwtAuthenticationSecurityConfiguration(
|
||||
final NiFiProperties niFiProperties,
|
||||
final Authorizer authorizer,
|
||||
final IdpUserGroupService idpUserGroupService,
|
||||
final StateManagerProvider stateManagerProvider
|
||||
) {
|
||||
this.niFiProperties = niFiProperties;
|
||||
this.authorizer = authorizer;
|
||||
this.idpUserGroupService = idpUserGroupService;
|
||||
this.stateManagerProvider = stateManagerProvider;
|
||||
this.keyRotationPeriod = niFiProperties.getSecurityUserJwsKeyRotationPeriod();
|
||||
}
|
||||
|
@ -180,7 +176,7 @@ public class JwtAuthenticationSecurityConfiguration {
|
|||
|
||||
@Bean
|
||||
public StandardJwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||
return new StandardJwtAuthenticationConverter(authorizer, idpUserGroupService, niFiProperties);
|
||||
return new StandardJwtAuthenticationConverter(authorizer, niFiProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.apache.nifi.web.security.configuration;
|
|||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMappingUtil;
|
||||
import org.apache.nifi.components.state.StateManager;
|
||||
import org.apache.nifi.components.state.StateManagerProvider;
|
||||
|
@ -129,8 +128,6 @@ public class OidcSecurityConfiguration {
|
|||
|
||||
private final BearerTokenResolver bearerTokenResolver;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final JwtDecoder jwtDecoder;
|
||||
|
||||
private final LogoutRequestManager logoutRequestManager;
|
||||
|
@ -142,7 +139,6 @@ public class OidcSecurityConfiguration {
|
|||
final PropertyEncryptor propertyEncryptor,
|
||||
final BearerTokenProvider bearerTokenProvider,
|
||||
final BearerTokenResolver bearerTokenResolver,
|
||||
final IdpUserGroupService idpUserGroupService,
|
||||
final JwtDecoder jwtDecoder,
|
||||
final LogoutRequestManager logoutRequestManager
|
||||
) {
|
||||
|
@ -151,7 +147,6 @@ public class OidcSecurityConfiguration {
|
|||
this.propertyEncryptor = Objects.requireNonNull(propertyEncryptor, "Property Encryptor required");
|
||||
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, "Bearer Token Provider required");
|
||||
this.bearerTokenResolver = Objects.requireNonNull(bearerTokenResolver, "Bearer Token Resolver required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
this.jwtDecoder = Objects.requireNonNull(jwtDecoder, "JWT Decoder required");
|
||||
this.logoutRequestManager = Objects.requireNonNull(logoutRequestManager, "Logout Request Manager required");
|
||||
this.keyRotationPeriod = properties.getSecurityUserJwsKeyRotationPeriod();
|
||||
|
@ -261,7 +256,6 @@ public class OidcSecurityConfiguration {
|
|||
public LogoutSuccessHandler oidcLogoutSuccessHandler() {
|
||||
return new OidcLogoutSuccessHandler(
|
||||
logoutRequestManager,
|
||||
idpUserGroupService,
|
||||
clientRegistrationRepository(),
|
||||
authorizedClientRepository(),
|
||||
tokenRevocationResponseClient()
|
||||
|
@ -480,7 +474,6 @@ public class OidcSecurityConfiguration {
|
|||
|
||||
return new OidcAuthenticationSuccessHandler(
|
||||
bearerTokenProvider,
|
||||
idpUserGroupService,
|
||||
IdentityMappingUtil.getIdentityMappings(properties),
|
||||
IdentityMappingUtil.getGroupMappings(properties),
|
||||
userClaimNames,
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.apache.nifi.web.security.configuration;
|
|||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMappingUtil;
|
||||
import org.apache.nifi.util.FormatUtils;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
|
@ -93,19 +92,15 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
|
||||
private final LogoutRequestManager logoutRequestManager;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
@Autowired
|
||||
public SamlAuthenticationSecurityConfiguration(
|
||||
final NiFiProperties properties,
|
||||
final BearerTokenProvider bearerTokenProvider,
|
||||
final LogoutRequestManager logoutRequestManager,
|
||||
final IdpUserGroupService idpUserGroupService
|
||||
final LogoutRequestManager logoutRequestManager
|
||||
) {
|
||||
this.properties = Objects.requireNonNull(properties, "Properties required");
|
||||
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, "Bearer Token Provider required");
|
||||
this.logoutRequestManager = Objects.requireNonNull(logoutRequestManager, "Logout Request Manager required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,7 +331,7 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
*/
|
||||
@Bean
|
||||
public Saml2LogoutSuccessHandler saml2LogoutSuccessHandler() {
|
||||
return new Saml2LogoutSuccessHandler(logoutRequestManager, idpUserGroupService);
|
||||
return new Saml2LogoutSuccessHandler(logoutRequestManager);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -373,7 +368,6 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
final String issuer = entityId == null ? Saml2RegistrationProperty.REGISTRATION_ID.getProperty() : entityId;
|
||||
final Saml2AuthenticationSuccessHandler handler = new Saml2AuthenticationSuccessHandler(
|
||||
bearerTokenProvider,
|
||||
idpUserGroupService,
|
||||
IdentityMappingUtil.getIdentityMappings(properties),
|
||||
IdentityMappingUtil.getGroupMappings(properties),
|
||||
expiration,
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.jwt.converter;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.Authorizer;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserDetails;
|
||||
|
@ -24,15 +23,16 @@ import org.apache.nifi.authorization.user.StandardNiFiUser;
|
|||
import org.apache.nifi.authorization.util.IdentityMapping;
|
||||
import org.apache.nifi.authorization.util.IdentityMappingUtil;
|
||||
import org.apache.nifi.authorization.util.UserGroupUtil;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.security.jwt.provider.SupportedClaim;
|
||||
import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Standard Converter from JSON Web Token to NiFi Authentication Token
|
||||
|
@ -40,13 +40,10 @@ import java.util.stream.Collectors;
|
|||
public class StandardJwtAuthenticationConverter implements Converter<Jwt, NiFiAuthenticationToken> {
|
||||
private final Authorizer authorizer;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final List<IdentityMapping> identityMappings;
|
||||
|
||||
public StandardJwtAuthenticationConverter(final Authorizer authorizer, final IdpUserGroupService idpUserGroupService, final NiFiProperties properties) {
|
||||
public StandardJwtAuthenticationConverter(final Authorizer authorizer, final NiFiProperties properties) {
|
||||
this.authorizer = authorizer;
|
||||
this.idpUserGroupService = idpUserGroupService;
|
||||
this.identityMappings = IdentityMappingUtil.getIdentityMappings(properties);
|
||||
}
|
||||
|
||||
|
@ -65,16 +62,23 @@ public class StandardJwtAuthenticationConverter implements Converter<Jwt, NiFiAu
|
|||
private NiFiUser getUser(final Jwt jwt) {
|
||||
final String identity = IdentityMappingUtil.mapIdentity(jwt.getSubject(), identityMappings);
|
||||
|
||||
final Set<String> providedGroups = getProvidedGroups(jwt);
|
||||
return new StandardNiFiUser.Builder()
|
||||
.identity(identity)
|
||||
.groups(UserGroupUtil.getUserGroups(authorizer, identity))
|
||||
.identityProviderGroups(getIdentityProviderGroups(identity))
|
||||
.identityProviderGroups(providedGroups)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Set<String> getIdentityProviderGroups(final String identity) {
|
||||
return idpUserGroupService.getUserGroups(identity).stream()
|
||||
.map(IdpUserGroup::getGroupName)
|
||||
.collect(Collectors.toSet());
|
||||
private Set<String> getProvidedGroups(final Jwt jwt) {
|
||||
final List<String> claimGroups = jwt.getClaimAsStringList(SupportedClaim.GROUPS.getClaim());
|
||||
|
||||
final Set<String> providedGroups;
|
||||
if (claimGroups == null) {
|
||||
providedGroups = Collections.emptySet();
|
||||
} else {
|
||||
providedGroups = new LinkedHashSet<>(claimGroups);
|
||||
}
|
||||
return providedGroups;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,19 @@ import org.apache.nifi.web.security.jwt.jws.JwsSignerProvider;
|
|||
import org.apache.nifi.web.security.token.LoginAuthenticationToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Standard Bearer Token Provider supports returning serialized and signed JSON Web Tokens
|
||||
|
@ -68,6 +72,7 @@ public class StandardBearerTokenProvider implements BearerTokenProvider {
|
|||
final String subject = Objects.requireNonNull(loginAuthenticationToken.getPrincipal(), "Principal required").toString();
|
||||
final String username = loginAuthenticationToken.getName();
|
||||
|
||||
final List<String> groups = getGroups(loginAuthenticationToken.getAuthorities());
|
||||
final String issuer = getUrlEncoded(loginAuthenticationToken.getIssuer());
|
||||
final Date now = new Date();
|
||||
final Date expirationTime = getExpirationTime(loginAuthenticationToken);
|
||||
|
@ -80,6 +85,7 @@ public class StandardBearerTokenProvider implements BearerTokenProvider {
|
|||
.issueTime(now)
|
||||
.expirationTime(expirationTime)
|
||||
.claim(SupportedClaim.PREFERRED_USERNAME.getClaim(), username)
|
||||
.claim(SupportedClaim.GROUPS.getClaim(), groups)
|
||||
.build();
|
||||
return getSignedBearerToken(claims);
|
||||
}
|
||||
|
@ -131,4 +137,8 @@ public class StandardBearerTokenProvider implements BearerTokenProvider {
|
|||
throw new IllegalArgumentException(String.format("URL Encoding [%s] Failed", string), e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getGroups(final Collection<? extends GrantedAuthority> authorities) {
|
||||
return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,10 @@ public enum SupportedClaim {
|
|||
JWT_ID("jti"),
|
||||
|
||||
/** Preferred Username defined in OpenID Connect Core 1.0 Standard Claims */
|
||||
PREFERRED_USERNAME("preferred_username");
|
||||
PREFERRED_USERNAME("preferred_username"),
|
||||
|
||||
/** RFC 7643 Section 4.1.2 */
|
||||
GROUPS("groups");
|
||||
|
||||
private final String claim;
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.oidc.logout;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieService;
|
||||
import org.apache.nifi.web.security.cookie.StandardApplicationCookieService;
|
||||
|
@ -71,8 +70,6 @@ public class OidcLogoutSuccessHandler implements LogoutSuccessHandler {
|
|||
|
||||
private final LogoutRequestManager logoutRequestManager;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
private final OAuth2AuthorizedClientRepository authorizedClientRepository;
|
||||
|
@ -83,20 +80,17 @@ public class OidcLogoutSuccessHandler implements LogoutSuccessHandler {
|
|||
* OpenID Connect Logout Success Handler with RP-Initiated Logout 1.0 and RFC 7009 Token Revocation
|
||||
*
|
||||
* @param logoutRequestManager Application Logout Request Manager
|
||||
* @param idpUserGroupService User Group Service for clearing cached groups
|
||||
* @param clientRegistrationRepository OIDC Client Registry Repository for configuration information
|
||||
* @param authorizedClientRepository OIDC Authorized Client Repository for cached tokens
|
||||
* @param tokenRevocationResponseClient OIDC Revocation Response Client for revoking Refresh Tokens
|
||||
*/
|
||||
public OidcLogoutSuccessHandler(
|
||||
final LogoutRequestManager logoutRequestManager,
|
||||
final IdpUserGroupService idpUserGroupService,
|
||||
final ClientRegistrationRepository clientRegistrationRepository,
|
||||
final OAuth2AuthorizedClientRepository authorizedClientRepository,
|
||||
final TokenRevocationResponseClient tokenRevocationResponseClient
|
||||
) {
|
||||
this.logoutRequestManager = Objects.requireNonNull(logoutRequestManager, "Logout Request Manager required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
this.clientRegistrationRepository = Objects.requireNonNull(clientRegistrationRepository, "Client Registration Repository required");
|
||||
this.authorizedClientRepository = Objects.requireNonNull(authorizedClientRepository, "Authorized Client Repository required");
|
||||
this.tokenRevocationResponseClient = Objects.requireNonNull(tokenRevocationResponseClient, "Revocation Response Client required");
|
||||
|
@ -123,7 +117,6 @@ public class OidcLogoutSuccessHandler implements LogoutSuccessHandler {
|
|||
targetUrl = getPostLogoutRedirectUri(request);
|
||||
} else {
|
||||
final String mappedUserIdentity = logoutRequest.getMappedUserIdentity();
|
||||
idpUserGroupService.deleteUserGroups(mappedUserIdentity);
|
||||
targetUrl = processLogoutRequest(request, response, requestIdentifier, mappedUserIdentity);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.oidc.web.authentication;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMapping;
|
||||
import org.apache.nifi.authorization.util.IdentityMappingUtil;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieService;
|
||||
import org.apache.nifi.web.security.cookie.StandardApplicationCookieService;
|
||||
|
@ -28,6 +26,8 @@ import org.apache.nifi.web.security.oidc.OidcConfigurationException;
|
|||
import org.apache.nifi.web.security.token.LoginAuthenticationToken;
|
||||
import org.apache.nifi.web.util.RequestUriBuilder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2Token;
|
||||
|
@ -59,8 +59,6 @@ public class OidcAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
|
|||
|
||||
private final BearerTokenProvider bearerTokenProvider;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final List<IdentityMapping> userIdentityMappings;
|
||||
|
||||
private final List<IdentityMapping> groupIdentityMappings;
|
||||
|
@ -73,7 +71,6 @@ public class OidcAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
|
|||
* OpenID Connect Authentication Success Handler requires Bearer Token Provider and expiration for generated tokens
|
||||
*
|
||||
* @param bearerTokenProvider Bearer Token Provider
|
||||
* @param idpUserGroupService User Group Service for persisting groups from the Identity Provider
|
||||
* @param userIdentityMappings User Identity Mappings
|
||||
* @param groupIdentityMappings Group Identity Mappings
|
||||
* @param userClaimNames Claim Names for User Identity
|
||||
|
@ -81,14 +78,12 @@ public class OidcAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
|
|||
*/
|
||||
public OidcAuthenticationSuccessHandler(
|
||||
final BearerTokenProvider bearerTokenProvider,
|
||||
final IdpUserGroupService idpUserGroupService,
|
||||
final List<IdentityMapping> userIdentityMappings,
|
||||
final List<IdentityMapping> groupIdentityMappings,
|
||||
final List<String> userClaimNames,
|
||||
final String groupsClaimName
|
||||
) {
|
||||
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, "Bearer Token Provider required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
this.userIdentityMappings = Objects.requireNonNull(userIdentityMappings, "User Identity Mappings required");
|
||||
this.groupIdentityMappings = Objects.requireNonNull(groupIdentityMappings, "Group Identity Mappings required");
|
||||
this.userClaimNames = Objects.requireNonNull(userClaimNames, "User Claim Names required");
|
||||
|
@ -117,17 +112,17 @@ public class OidcAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
|
|||
final OidcUser oidcUser = getOidcUser(authenticationToken);
|
||||
final String identity = getIdentity(oidcUser);
|
||||
final Set<String> groups = getGroups(oidcUser);
|
||||
idpUserGroupService.replaceUserGroups(identity, IdpType.OIDC, groups);
|
||||
|
||||
final OAuth2AccessToken accessToken = getAccessToken(authenticationToken);
|
||||
final String bearerToken = getBearerToken(identity, oidcUser, accessToken);
|
||||
final String bearerToken = getBearerToken(identity, oidcUser, accessToken, groups);
|
||||
applicationCookieService.addSessionCookie(resourceUri, response, ApplicationCookieName.AUTHORIZATION_BEARER, bearerToken);
|
||||
}
|
||||
|
||||
private String getBearerToken(final String identity, final OidcUser oidcUser, final OAuth2AccessToken accessToken) {
|
||||
private String getBearerToken(final String identity, final OidcUser oidcUser, final OAuth2AccessToken accessToken, final Set<String> groups) {
|
||||
final long sessionExpiration = getSessionExpiration(accessToken);
|
||||
final String issuer = oidcUser.getIssuer().toString();
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(identity, identity, sessionExpiration, issuer);
|
||||
final Set<? extends GrantedAuthority> authorities = groups.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(identity, identity, sessionExpiration, issuer, authorities);
|
||||
return bearerTokenProvider.getBearerToken(loginAuthenticationToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.saml2.web.authentication;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMapping;
|
||||
import org.apache.nifi.authorization.util.IdentityMappingUtil;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieService;
|
||||
import org.apache.nifi.web.security.cookie.StandardApplicationCookieService;
|
||||
|
@ -29,6 +27,7 @@ import org.apache.nifi.web.util.RequestUriBuilder;
|
|||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||
|
||||
|
@ -53,8 +52,6 @@ public class Saml2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSu
|
|||
|
||||
private final BearerTokenProvider bearerTokenProvider;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private final List<IdentityMapping> userIdentityMappings;
|
||||
|
||||
private final List<IdentityMapping> groupIdentityMappings;
|
||||
|
@ -69,7 +66,6 @@ public class Saml2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSu
|
|||
* SAML 2 Authentication Success Handler requires Bearer Token Provider and expiration for generated tokens
|
||||
*
|
||||
* @param bearerTokenProvider Bearer Token Provider
|
||||
* @param idpUserGroupService User Group Service for persisting groups from the Identity Provider
|
||||
* @param userIdentityMappings User Identity Mappings
|
||||
* @param groupIdentityMappings Group Identity Mappings
|
||||
* @param expiration Expiration for generated tokens
|
||||
|
@ -77,14 +73,12 @@ public class Saml2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSu
|
|||
*/
|
||||
public Saml2AuthenticationSuccessHandler(
|
||||
final BearerTokenProvider bearerTokenProvider,
|
||||
final IdpUserGroupService idpUserGroupService,
|
||||
final List<IdentityMapping> userIdentityMappings,
|
||||
final List<IdentityMapping> groupIdentityMappings,
|
||||
final Duration expiration,
|
||||
final String issuer
|
||||
) {
|
||||
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, "Bearer Token Provider required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
this.userIdentityMappings = Objects.requireNonNull(userIdentityMappings, "User Identity Mappings required");
|
||||
this.groupIdentityMappings = Objects.requireNonNull(groupIdentityMappings, "Group Identity Mappings required");
|
||||
this.expiration = Objects.requireNonNull(expiration, "Expiration required");
|
||||
|
@ -120,14 +114,14 @@ public class Saml2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSu
|
|||
private void processAuthentication(final HttpServletResponse response, final Authentication authentication, final URI resourceUri) {
|
||||
final String identity = getIdentity(authentication);
|
||||
final Set<String> groups = getGroups(authentication);
|
||||
idpUserGroupService.replaceUserGroups(identity, IdpType.SAML, groups);
|
||||
|
||||
final String bearerToken = getBearerToken(identity);
|
||||
final String bearerToken = getBearerToken(identity, groups);
|
||||
applicationCookieService.addSessionCookie(resourceUri, response, ApplicationCookieName.AUTHORIZATION_BEARER, bearerToken);
|
||||
}
|
||||
|
||||
private String getBearerToken(final String identity) {
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(identity, identity, expiration.toMillis(), issuer);
|
||||
private String getBearerToken(final String identity, final Set<String> groups) {
|
||||
final Set<? extends GrantedAuthority> authorities = groups.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(identity, identity, expiration.toMillis(), issuer, authorities);
|
||||
return bearerTokenProvider.getBearerToken(loginAuthenticationToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.saml2.web.authentication.logout;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieService;
|
||||
import org.apache.nifi.web.security.cookie.StandardApplicationCookieService;
|
||||
|
@ -47,14 +46,10 @@ public class Saml2LogoutSuccessHandler implements LogoutSuccessHandler {
|
|||
|
||||
private final LogoutRequestManager logoutRequestManager;
|
||||
|
||||
private final IdpUserGroupService idpUserGroupService;
|
||||
|
||||
public Saml2LogoutSuccessHandler(
|
||||
final LogoutRequestManager logoutRequestManager,
|
||||
final IdpUserGroupService idpUserGroupService
|
||||
final LogoutRequestManager logoutRequestManager
|
||||
) {
|
||||
this.logoutRequestManager = Objects.requireNonNull(logoutRequestManager, "Logout Request Manager required");
|
||||
this.idpUserGroupService = Objects.requireNonNull(idpUserGroupService, "User Group Service required");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,8 +71,6 @@ public class Saml2LogoutSuccessHandler implements LogoutSuccessHandler {
|
|||
logger.warn("Logout Request [{}] not found", requestIdentifier);
|
||||
} else {
|
||||
final String mappedUserIdentity = logoutRequest.getMappedUserIdentity();
|
||||
|
||||
idpUserGroupService.deleteUserGroups(mappedUserIdentity);
|
||||
logger.info("Logout Request [{}] Identity [{}] completed", requestIdentifier, mappedUserIdentity);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.apache.nifi.web.security.jwt.converter;
|
|||
|
||||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import com.nimbusds.jwt.PlainJWT;
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.AccessPolicyProvider;
|
||||
import org.apache.nifi.authorization.Group;
|
||||
import org.apache.nifi.authorization.ManagedAuthorizer;
|
||||
|
@ -26,9 +25,9 @@ import org.apache.nifi.authorization.UserAndGroups;
|
|||
import org.apache.nifi.authorization.UserGroupProvider;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserDetails;
|
||||
import org.apache.nifi.idp.IdpUserGroup;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.apache.nifi.web.security.jwt.provider.SupportedClaim;
|
||||
import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -39,6 +38,7 @@ import org.springframework.security.oauth2.jwt.Jwt;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -71,16 +71,13 @@ public class StandardJwtAuthenticationConverterTest {
|
|||
@Mock
|
||||
private UserAndGroups userAndGroups;
|
||||
|
||||
@Mock
|
||||
private IdpUserGroupService idpUserGroupService;
|
||||
|
||||
private StandardJwtAuthenticationConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void setConverter() {
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
final NiFiProperties niFiProperties = NiFiProperties.createBasicNiFiProperties(StringUtils.EMPTY, properties);
|
||||
converter = new StandardJwtAuthenticationConverter(authorizer, idpUserGroupService, niFiProperties);
|
||||
converter = new StandardJwtAuthenticationConverter(authorizer, niFiProperties);
|
||||
|
||||
when(authorizer.getAccessPolicyProvider()).thenReturn(accessPolicyProvider);
|
||||
when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider);
|
||||
|
@ -88,21 +85,21 @@ public class StandardJwtAuthenticationConverterTest {
|
|||
|
||||
final Group group = new Group.Builder().name(AUTHORIZER_GROUP).identifier(AUTHORIZER_GROUP).build();
|
||||
when(userAndGroups.getGroups()).thenReturn(Collections.singleton(group));
|
||||
|
||||
final IdpUserGroup idpUserGroup = new IdpUserGroup();
|
||||
idpUserGroup.setGroupName(PROVIDER_GROUP);
|
||||
when(idpUserGroupService.getUserGroups(eq(USERNAME))).thenReturn(Collections.singletonList(idpUserGroup));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
final List<String> providerGroups = Collections.singletonList(PROVIDER_GROUP);
|
||||
|
||||
final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
|
||||
.subject(USERNAME)
|
||||
.claim(SupportedClaim.GROUPS.getClaim(), providerGroups)
|
||||
.build();
|
||||
final String token = new PlainJWT(claimsSet).serialize();
|
||||
final Jwt jwt = Jwt.withTokenValue(token)
|
||||
.header(TYPE_FIELD, JWT_TYPE)
|
||||
.subject(USERNAME)
|
||||
.claim(SupportedClaim.GROUPS.getClaim(), providerGroups)
|
||||
.build();
|
||||
|
||||
final NiFiAuthenticationToken authenticationToken = converter.convert(jwt);
|
||||
|
|
|
@ -27,11 +27,14 @@ import com.nimbusds.jwt.SignedJWT;
|
|||
import org.apache.nifi.web.security.jwt.jws.JwsSignerContainer;
|
||||
import org.apache.nifi.web.security.jwt.jws.JwsSignerProvider;
|
||||
import org.apache.nifi.web.security.token.LoginAuthenticationToken;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
|
@ -40,9 +43,12 @@ import java.security.interfaces.RSAPublicKey;
|
|||
import java.text.ParseException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
@ -71,6 +77,10 @@ public class StandardBearerTokenProviderTest {
|
|||
|
||||
private static final JWSAlgorithm JWS_ALGORITHM = JWSAlgorithm.PS512;
|
||||
|
||||
private static final String GROUP = "ProviderGroup";
|
||||
|
||||
private static KeyPair keyPair;
|
||||
|
||||
@Mock
|
||||
private JwsSignerProvider jwsSignerProvider;
|
||||
|
||||
|
@ -78,49 +88,50 @@ public class StandardBearerTokenProviderTest {
|
|||
|
||||
private JWSVerifier jwsVerifier;
|
||||
|
||||
private JWSSigner jwsSigner;
|
||||
|
||||
@BeforeEach
|
||||
public void setProvider() throws NoSuchAlgorithmException {
|
||||
provider = new StandardBearerTokenProvider(jwsSignerProvider);
|
||||
|
||||
@BeforeAll
|
||||
public static void setKeyPair() throws NoSuchAlgorithmException {
|
||||
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
|
||||
keyPairGenerator.initialize(KEY_SIZE);
|
||||
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
keyPair = keyPairGenerator.generateKeyPair();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setProvider() {
|
||||
provider = new StandardBearerTokenProvider(jwsSignerProvider);
|
||||
|
||||
jwsVerifier = new RSASSAVerifier((RSAPublicKey) keyPair.getPublic());
|
||||
jwsSigner = new RSASSASigner(keyPair.getPrivate());
|
||||
final JWSSigner jwsSigner = new RSASSASigner(keyPair.getPrivate());
|
||||
|
||||
final String keyIdentifier = UUID.randomUUID().toString();
|
||||
final JwsSignerContainer jwsSignerContainer = new JwsSignerContainer(keyIdentifier, JWS_ALGORITHM, jwsSigner);
|
||||
when(jwsSignerProvider.getJwsSignerContainer(isA(Instant.class))).thenReturn(jwsSignerContainer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBearerToken() throws ParseException, JOSEException {
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(IDENTITY, USERNAME, EXPIRATION.toMillis(), ISSUER);
|
||||
setSignerProvider();
|
||||
|
||||
final String bearerToken = provider.getBearerToken(loginAuthenticationToken);
|
||||
|
||||
final SignedJWT signedJwt = assertTokenVerified(bearerToken);
|
||||
final JWTClaimsSet claims = signedJwt.getJWTClaimsSet();
|
||||
assertNotNull(claims.getIssueTime(), "Issue Time not found");
|
||||
assertNotNull(claims.getNotBeforeTime(), "Not Before Time not found");
|
||||
assertTokenMatched(bearerToken, loginAuthenticationToken);
|
||||
}
|
||||
|
||||
final Date claimExpirationTime = claims.getExpirationTime();
|
||||
assertNotNull(claimExpirationTime, "Expiration Time not found");
|
||||
@Test
|
||||
public void testGetBearerTokenGroups() throws ParseException, JOSEException {
|
||||
final GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(GROUP);
|
||||
final Collection<GrantedAuthority> authorities = Collections.singletonList(grantedAuthority);
|
||||
|
||||
final Date loginExpirationTime = new Date(loginAuthenticationToken.getExpiration());
|
||||
assertEquals(loginExpirationTime.toString(), claimExpirationTime.toString(), "Expiration Time not matched");
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(IDENTITY, USERNAME, EXPIRATION.toMillis(), ISSUER, authorities);
|
||||
|
||||
assertEquals(ISSUER, claims.getIssuer());
|
||||
assertEquals(Collections.singletonList(ISSUER), claims.getAudience());
|
||||
assertEquals(IDENTITY, claims.getSubject());
|
||||
assertEquals(USERNAME, claims.getClaim(SupportedClaim.PREFERRED_USERNAME.getClaim()));
|
||||
assertNotNull("JSON Web Token Identifier not found", claims.getJWTID());
|
||||
final String bearerToken = provider.getBearerToken(loginAuthenticationToken);
|
||||
|
||||
assertTokenMatched(bearerToken, loginAuthenticationToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBearerTokenExpirationMaximum() throws ParseException, JOSEException {
|
||||
final long expiration = MAXIMUM_DURATION_EXCEEDED.toMillis();
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(IDENTITY, USERNAME, expiration, ISSUER);
|
||||
setSignerProvider();
|
||||
|
||||
final String bearerToken = provider.getBearerToken(loginAuthenticationToken);
|
||||
|
||||
|
@ -139,7 +150,6 @@ public class StandardBearerTokenProviderTest {
|
|||
public void testGetBearerTokenExpirationMinimum() throws ParseException, JOSEException {
|
||||
final long expiration = MINIMUM_DURATION_EXCEEDED.toMillis();
|
||||
final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(IDENTITY, USERNAME, expiration, ISSUER);
|
||||
setSignerProvider();
|
||||
|
||||
final String bearerToken = provider.getBearerToken(loginAuthenticationToken);
|
||||
|
||||
|
@ -154,15 +164,36 @@ public class StandardBearerTokenProviderTest {
|
|||
assertTrue(claimExpirationTime.toInstant().isAfter(loginExpirationTime.toInstant()), "Claim Expiration before Login Expiration");
|
||||
}
|
||||
|
||||
private void setSignerProvider() {
|
||||
final String keyIdentifier = UUID.randomUUID().toString();
|
||||
final JwsSignerContainer jwsSignerContainer = new JwsSignerContainer(keyIdentifier, JWS_ALGORITHM, jwsSigner);
|
||||
when(jwsSignerProvider.getJwsSignerContainer(isA(Instant.class))).thenReturn(jwsSignerContainer);
|
||||
}
|
||||
|
||||
private SignedJWT assertTokenVerified(final String bearerToken) throws ParseException, JOSEException {
|
||||
final SignedJWT signedJwt = SignedJWT.parse(bearerToken);
|
||||
assertTrue(signedJwt.verify(jwsVerifier), "Verification Failed");
|
||||
return signedJwt;
|
||||
}
|
||||
|
||||
private void assertTokenMatched(final String bearerToken, final LoginAuthenticationToken loginAuthenticationToken) throws ParseException, JOSEException {
|
||||
final SignedJWT signedJwt = assertTokenVerified(bearerToken);
|
||||
final JWTClaimsSet claims = signedJwt.getJWTClaimsSet();
|
||||
assertNotNull(claims.getIssueTime(), "Issue Time not found");
|
||||
assertNotNull(claims.getNotBeforeTime(), "Not Before Time not found");
|
||||
|
||||
final Date claimExpirationTime = claims.getExpirationTime();
|
||||
assertNotNull(claimExpirationTime, "Expiration Time not found");
|
||||
|
||||
final Date loginExpirationTime = new Date(loginAuthenticationToken.getExpiration());
|
||||
assertEquals(loginExpirationTime.toString(), claimExpirationTime.toString(), "Expiration Time not matched");
|
||||
|
||||
assertEquals(ISSUER, claims.getIssuer());
|
||||
assertEquals(Collections.singletonList(ISSUER), claims.getAudience());
|
||||
assertEquals(IDENTITY, claims.getSubject());
|
||||
assertEquals(USERNAME, claims.getClaim(SupportedClaim.PREFERRED_USERNAME.getClaim()));
|
||||
assertNotNull(claims.getJWTID(), "JSON Web Token Identifier not found");
|
||||
|
||||
final List<String> groups = claims.getStringListClaim(SupportedClaim.GROUPS.getClaim());
|
||||
assertNotNull(groups);
|
||||
|
||||
final Collection<GrantedAuthority> grantedAuthorities = loginAuthenticationToken.getAuthorities();
|
||||
final List<String> authorities = grantedAuthorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
|
||||
assertEquals(authorities, groups);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.oidc.logout;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.logout.LogoutRequest;
|
||||
import org.apache.nifi.web.security.logout.LogoutRequestManager;
|
||||
|
@ -58,7 +57,6 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
@ -91,9 +89,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
|
||||
private static final String END_SESSION_REDIRECT_URL = String.format("%s?id_token_hint=%s&post_logout_redirect_uri=%s", END_SESSION_URI, ID_TOKEN, REDIRECTED_URL);
|
||||
|
||||
@Mock
|
||||
IdpUserGroupService idpUserGroupService;
|
||||
|
||||
@Mock
|
||||
ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
|
@ -131,7 +126,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
logoutRequestManager = new LogoutRequestManager();
|
||||
handler = new OidcLogoutSuccessHandler(
|
||||
logoutRequestManager,
|
||||
idpUserGroupService,
|
||||
clientRegistrationRepository,
|
||||
authorizedClientRepository,
|
||||
tokenRevocationResponseClient
|
||||
|
@ -150,8 +144,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(REDIRECTED_URL, redirectedUrl);
|
||||
|
||||
verifyNoInteractions(idpUserGroupService);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -167,7 +159,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(REDIRECTED_URL, redirectedUrl);
|
||||
assertUserGroupAuthorizedClientRemoved();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -184,7 +175,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(REDIRECTED_URL, redirectedUrl);
|
||||
assertUserGroupAuthorizedClientRemoved();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -220,7 +210,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(END_SESSION_REDIRECT_URL, redirectedUrl);
|
||||
assertUserGroupAuthorizedClientRemoved();
|
||||
verify(authorizedClientRepository).removeAuthorizedClient(eq(OidcRegistrationProperty.REGISTRATION_ID.getProperty()), any(), eq(httpServletRequest), eq(httpServletResponse));
|
||||
verify(tokenRevocationResponseClient, times(2)).getRevocationResponse(revocationRequestCaptor.capture());
|
||||
|
||||
|
@ -235,10 +224,6 @@ class OidcLogoutSuccessHandlerTest {
|
|||
assertEquals(ACCESS_TOKEN, secondRevocationRequest.getToken());
|
||||
}
|
||||
|
||||
void assertUserGroupAuthorizedClientRemoved() {
|
||||
verify(idpUserGroupService).deleteUserGroups(eq(USER_IDENTITY));
|
||||
}
|
||||
|
||||
void setRequestCookie() {
|
||||
final Cookie cookie = new Cookie(ApplicationCookieName.LOGOUT_REQUEST_IDENTIFIER.getCookieName(), REQUEST_IDENTIFIER);
|
||||
httpServletRequest.setCookies(cookie);
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.oidc.web.authentication;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMapping;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider;
|
||||
import org.apache.nifi.web.security.oidc.client.web.OidcRegistrationProperty;
|
||||
|
@ -66,9 +64,6 @@ class OidcAuthenticationSuccessHandlerTest {
|
|||
@Mock
|
||||
BearerTokenProvider bearerTokenProvider;
|
||||
|
||||
@Mock
|
||||
IdpUserGroupService idpUserGroupService;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<LoginAuthenticationToken> authenticationTokenCaptor;
|
||||
|
||||
|
@ -98,12 +93,8 @@ class OidcAuthenticationSuccessHandlerTest {
|
|||
|
||||
private static final String IDENTITY = Authentication.class.getSimpleName();
|
||||
|
||||
private static final String IDENTITY_UPPER = IDENTITY.toUpperCase();
|
||||
|
||||
private static final String AUTHORITY = GrantedAuthority.class.getSimpleName();
|
||||
|
||||
private static final String AUTHORITY_LOWER = AUTHORITY.toLowerCase();
|
||||
|
||||
private static final String ACCESS_TOKEN = "access-token";
|
||||
|
||||
private static final Duration TOKEN_EXPIRATION = Duration.ofHours(1);
|
||||
|
@ -142,7 +133,6 @@ class OidcAuthenticationSuccessHandlerTest {
|
|||
void setHandler() {
|
||||
handler = new OidcAuthenticationSuccessHandler(
|
||||
bearerTokenProvider,
|
||||
idpUserGroupService,
|
||||
Collections.singletonList(UPPER_IDENTITY_MAPPING),
|
||||
Collections.singletonList(LOWER_IDENTITY_MAPPING),
|
||||
Collections.singletonList(USER_NAME_CLAIM),
|
||||
|
@ -159,7 +149,6 @@ class OidcAuthenticationSuccessHandlerTest {
|
|||
|
||||
assertTargetUrlEquals(TARGET_URL);
|
||||
assertBearerCookieAdded(ROOT_PATH);
|
||||
assertReplaceUserGroupsInvoked();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -172,11 +161,6 @@ class OidcAuthenticationSuccessHandlerTest {
|
|||
|
||||
assertTargetUrlEquals(FORWARDED_TARGET_URL);
|
||||
assertBearerCookieAdded(FORWARDED_COOKIE_PATH);
|
||||
assertReplaceUserGroupsInvoked();
|
||||
}
|
||||
|
||||
void assertReplaceUserGroupsInvoked() {
|
||||
verify(idpUserGroupService).replaceUserGroups(eq(IDENTITY_UPPER), eq(IdpType.OIDC), eq(Collections.singleton(AUTHORITY_LOWER)));
|
||||
}
|
||||
|
||||
void assertTargetUrlEquals(final String expectedTargetUrl) {
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.saml2.web.authentication;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.authorization.util.IdentityMapping;
|
||||
import org.apache.nifi.idp.IdpType;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider;
|
||||
import org.apache.nifi.web.util.WebUtils;
|
||||
|
@ -41,8 +39,6 @@ import java.util.regex.Pattern;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class Saml2AuthenticationSuccessHandlerTest {
|
||||
|
@ -52,12 +48,8 @@ class Saml2AuthenticationSuccessHandlerTest {
|
|||
|
||||
private static final String IDENTITY = Authentication.class.getSimpleName();
|
||||
|
||||
private static final String IDENTITY_UPPER = IDENTITY.toUpperCase();
|
||||
|
||||
private static final String AUTHORITY = GrantedAuthority.class.getSimpleName();
|
||||
|
||||
private static final String AUTHORITY_LOWER = AUTHORITY.toLowerCase();
|
||||
|
||||
private static final String REQUEST_URI = "/nifi-api";
|
||||
|
||||
private static final String UI_PATH = "/nifi/";
|
||||
|
@ -99,9 +91,6 @@ class Saml2AuthenticationSuccessHandlerTest {
|
|||
@Mock
|
||||
BearerTokenProvider bearerTokenProvider;
|
||||
|
||||
@Mock
|
||||
IdpUserGroupService idpUserGroupService;
|
||||
|
||||
MockHttpServletRequest httpServletRequest;
|
||||
|
||||
MockHttpServletResponse httpServletResponse;
|
||||
|
@ -112,7 +101,6 @@ class Saml2AuthenticationSuccessHandlerTest {
|
|||
void setHandler() {
|
||||
handler = new Saml2AuthenticationSuccessHandler(
|
||||
bearerTokenProvider,
|
||||
idpUserGroupService,
|
||||
Collections.singletonList(UPPER_IDENTITY_MAPPING),
|
||||
Collections.singletonList(LOWER_IDENTITY_MAPPING),
|
||||
EXPIRATION,
|
||||
|
@ -129,7 +117,6 @@ class Saml2AuthenticationSuccessHandlerTest {
|
|||
|
||||
assertTargetUrlEquals(TARGET_URL);
|
||||
assertBearerCookieAdded(ROOT_PATH);
|
||||
assertReplaceUserGroupsInvoked();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,11 +129,6 @@ class Saml2AuthenticationSuccessHandlerTest {
|
|||
|
||||
assertTargetUrlEquals(FORWARDED_TARGET_URL);
|
||||
assertBearerCookieAdded(FORWARDED_COOKIE_PATH);
|
||||
assertReplaceUserGroupsInvoked();
|
||||
}
|
||||
|
||||
void assertReplaceUserGroupsInvoked() {
|
||||
verify(idpUserGroupService).replaceUserGroups(eq(IDENTITY_UPPER), eq(IdpType.SAML), eq(Collections.singleton(AUTHORITY_LOWER)));
|
||||
}
|
||||
|
||||
void assertTargetUrlEquals(final String expectedTargetUrl) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.saml2.web.authentication.logout;
|
||||
|
||||
import org.apache.nifi.admin.service.IdpUserGroupService;
|
||||
import org.apache.nifi.web.security.cookie.ApplicationCookieName;
|
||||
import org.apache.nifi.web.security.logout.LogoutRequest;
|
||||
import org.apache.nifi.web.security.logout.LogoutRequestManager;
|
||||
|
@ -34,9 +33,6 @@ import java.io.IOException;
|
|||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class Saml2LogoutSuccessHandlerTest {
|
||||
|
@ -50,9 +46,6 @@ class Saml2LogoutSuccessHandlerTest {
|
|||
|
||||
private static final String REDIRECTED_URL = "http://localhost:8080/nifi/logout-complete";
|
||||
|
||||
@Mock
|
||||
IdpUserGroupService idpUserGroupService;
|
||||
|
||||
@Mock
|
||||
Authentication authentication;
|
||||
|
||||
|
@ -67,7 +60,7 @@ class Saml2LogoutSuccessHandlerTest {
|
|||
@BeforeEach
|
||||
void setHandler() {
|
||||
logoutRequestManager = new LogoutRequestManager();
|
||||
handler = new Saml2LogoutSuccessHandler(logoutRequestManager, idpUserGroupService);
|
||||
handler = new Saml2LogoutSuccessHandler(logoutRequestManager);
|
||||
httpServletRequest = new MockHttpServletRequest();
|
||||
httpServletRequest.setServerPort(SERVER_PORT);
|
||||
httpServletResponse = new MockHttpServletResponse();
|
||||
|
@ -84,8 +77,6 @@ class Saml2LogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(REDIRECTED_URL, redirectedUrl);
|
||||
|
||||
verifyNoInteractions(idpUserGroupService);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,6 +93,5 @@ class Saml2LogoutSuccessHandlerTest {
|
|||
final String redirectedUrl = httpServletResponse.getRedirectedUrl();
|
||||
|
||||
assertEquals(REDIRECTED_URL, redirectedUrl);
|
||||
verify(idpUserGroupService).deleteUserGroups(eq(USER_IDENTITY));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue