mirror of https://github.com/apache/nifi.git
NIFI-2272:
- Ensuring the appropriate visibilty of the action in the policy management page. NIFI-2273: - Ensuring we load the policy or inform the user of the appropriate permissions of the effective policy. NIFI-2239: - Providing help tooltips for the policies in the management page. NIFI-2283: - Adding auditing for access policies, users, and groups. NIFI-2263: - Not replicating history requests throughout the cluster. NIFI-2096: - Fixing upload template file input in Firefox. NIFI-2301: - Removing relevant policies after component deletion.
This commit is contained in:
parent
5c8636edf4
commit
aa91032cde
|
@ -30,5 +30,8 @@ public enum Component {
|
|||
Funnel,
|
||||
Connection,
|
||||
ControllerService,
|
||||
ReportingTask;
|
||||
ReportingTask,
|
||||
AccessPolicy,
|
||||
User,
|
||||
UserGroup;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* 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.audit;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
import org.apache.nifi.action.Operation;
|
||||
import org.apache.nifi.action.details.ActionDetails;
|
||||
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
|
||||
import org.apache.nifi.authorization.AccessPolicy;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
import org.apache.nifi.web.api.dto.AccessPolicyDTO;
|
||||
import org.apache.nifi.web.dao.AccessPolicyDAO;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Audits policy creation/removal and configuration changes.
|
||||
*/
|
||||
@Aspect
|
||||
public class AccessPolicyAuditor extends NiFiAuditor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AccessPolicyAuditor.class);
|
||||
|
||||
private static final String USERS = "Users";
|
||||
private static final String USER_GROUPS = "User Groups";
|
||||
|
||||
/**
|
||||
* Audits the creation of policies via createAccessPolicy().
|
||||
*
|
||||
* This method only needs to be run 'after returning'. However, in Java 7 the order in which these methods are returned from Class.getDeclaredMethods (even though there is no order guaranteed)
|
||||
* seems to differ from Java 6. SpringAOP depends on this ordering to determine advice precedence. By normalizing all advice into Around advice we can alleviate this issue.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.AccessPolicyDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.AccessPolicy createAccessPolicy(org.apache.nifi.web.api.dto.AccessPolicyDTO))")
|
||||
public AccessPolicy createAccessPolicyAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
|
||||
// create the access policy
|
||||
AccessPolicy policy = (AccessPolicy) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the policy action...
|
||||
final Action action = generateAuditRecord(policy, Operation.Add);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the configuration of a single policy.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param accessPolicyDTO dto
|
||||
* @param accessPolicyDAO dao
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.AccessPolicyDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.AccessPolicy updateAccessPolicy(org.apache.nifi.web.api.dto.AccessPolicyDTO)) && "
|
||||
+ "args(accessPolicyDTO) && "
|
||||
+ "target(accessPolicyDAO)")
|
||||
public AccessPolicy updateAccessPolicyAdvice(ProceedingJoinPoint proceedingJoinPoint, AccessPolicyDTO accessPolicyDTO, AccessPolicyDAO accessPolicyDAO) throws Throwable {
|
||||
// determine the initial values for each property/setting thats changing
|
||||
AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(accessPolicyDTO.getId());
|
||||
final Map<String, String> values = extractConfiguredPropertyValues(accessPolicy, accessPolicyDTO);
|
||||
|
||||
// update the policy state
|
||||
final AccessPolicy updatedAccessPolicy = (AccessPolicy) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the policy action...
|
||||
// get the updated verbose state
|
||||
accessPolicy = accessPolicyDAO.getAccessPolicy(updatedAccessPolicy.getIdentifier());
|
||||
|
||||
// get the current user
|
||||
NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (user != null) {
|
||||
// determine the updated values
|
||||
Map<String, String> updatedValues = extractConfiguredPropertyValues(accessPolicy, accessPolicyDTO);
|
||||
|
||||
// create a policy action
|
||||
Date actionTimestamp = new Date();
|
||||
Collection<Action> actions = new ArrayList<>();
|
||||
|
||||
// go through each updated value
|
||||
for (String property : updatedValues.keySet()) {
|
||||
String newValue = updatedValues.get(property);
|
||||
String oldValue = values.get(property);
|
||||
Operation operation = null;
|
||||
|
||||
// determine the type of operation
|
||||
if (oldValue == null || newValue == null || !newValue.equals(oldValue)) {
|
||||
operation = Operation.Configure;
|
||||
}
|
||||
|
||||
// create a configuration action accordingly
|
||||
if (operation != null) {
|
||||
final FlowChangeConfigureDetails actionDetails = new FlowChangeConfigureDetails();
|
||||
actionDetails.setName(property);
|
||||
actionDetails.setValue(newValue);
|
||||
actionDetails.setPreviousValue(oldValue);
|
||||
|
||||
// create a configuration action
|
||||
FlowChangeAction configurationAction = new FlowChangeAction();
|
||||
configurationAction.setUserIdentity(user.getIdentity());
|
||||
configurationAction.setOperation(operation);
|
||||
configurationAction.setTimestamp(actionTimestamp);
|
||||
configurationAction.setSourceId(accessPolicy.getIdentifier());
|
||||
configurationAction.setSourceName(formatPolicyName(accessPolicy));
|
||||
configurationAction.setSourceType(Component.AccessPolicy);
|
||||
configurationAction.setActionDetails(actionDetails);
|
||||
actions.add(configurationAction);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure there are actions to record
|
||||
if (!actions.isEmpty()) {
|
||||
// save the actions
|
||||
saveActions(actions, logger);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedAccessPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the removal of a policy via deleteAccessPolicy().
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param policyId policy id
|
||||
* @param accessPolicyDAO dao
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.AccessPolicyDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.AccessPolicy deleteAccessPolicy(java.lang.String)) && "
|
||||
+ "args(policyId) && "
|
||||
+ "target(accessPolicyDAO)")
|
||||
public AccessPolicy removePolicyAdvice(ProceedingJoinPoint proceedingJoinPoint, String policyId, AccessPolicyDAO accessPolicyDAO) throws Throwable {
|
||||
// get the policy before removing it
|
||||
AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(policyId);
|
||||
|
||||
// remove the policy
|
||||
final AccessPolicy removedAccessPolicy = (AccessPolicy)proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add removal actions...
|
||||
// audit the policy removal
|
||||
final Action action = generateAuditRecord(accessPolicy, Operation.Remove);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return removedAccessPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a policy.
|
||||
*
|
||||
* @param policy policy
|
||||
* @param operation operation
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(AccessPolicy policy, Operation operation) {
|
||||
return generateAuditRecord(policy, operation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a policy.
|
||||
*
|
||||
* @param policy policy
|
||||
* @param operation operation
|
||||
* @param actionDetails details
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(AccessPolicy policy, Operation operation, ActionDetails actionDetails) {
|
||||
FlowChangeAction action = null;
|
||||
|
||||
// get the current user
|
||||
NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (user != null) {
|
||||
// create the policy action for adding this policy
|
||||
action = new FlowChangeAction();
|
||||
action.setUserIdentity(user.getIdentity());
|
||||
action.setOperation(operation);
|
||||
action.setTimestamp(new Date());
|
||||
action.setSourceId(policy.getIdentifier());
|
||||
action.setSourceName(formatPolicyName(policy));
|
||||
action.setSourceType(Component.AccessPolicy);
|
||||
|
||||
if (actionDetails != null) {
|
||||
action.setActionDetails(actionDetails);
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the name of the specified policy.
|
||||
*
|
||||
* @param policy policy
|
||||
* @return formatted name
|
||||
*/
|
||||
private String formatPolicyName(final AccessPolicy policy) {
|
||||
return policy.getAction().toString() + " " + policy.getResource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the values for the configured properties from the specified policy.
|
||||
*/
|
||||
private Map<String, String> extractConfiguredPropertyValues(AccessPolicy policy, AccessPolicyDTO policyDTO) {
|
||||
Map<String, String> values = new HashMap<>();
|
||||
|
||||
if (policyDTO.getUsers() != null) {
|
||||
// get each of the auto terminated relationship names
|
||||
final List<String> currentUsers = new ArrayList<>(policy.getUsers());
|
||||
|
||||
// sort them and include in the configuration
|
||||
Collections.sort(currentUsers, Collator.getInstance(Locale.US));
|
||||
values.put(USERS, StringUtils.join(currentUsers, ", "));
|
||||
}
|
||||
if (policyDTO.getUserGroups() != null) {
|
||||
// get each of the auto terminated relationship names
|
||||
final List<String> currentUserGroups = new ArrayList<>(policy.getGroups());
|
||||
|
||||
// sort them and include in the configuration
|
||||
Collections.sort(currentUserGroups, Collator.getInstance(Locale.US));
|
||||
values.put(USER_GROUPS, StringUtils.join(currentUserGroups, ", "));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* 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.audit;
|
||||
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
import org.apache.nifi.action.Operation;
|
||||
import org.apache.nifi.action.details.ActionDetails;
|
||||
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
|
||||
import org.apache.nifi.authorization.User;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
import org.apache.nifi.web.api.dto.UserDTO;
|
||||
import org.apache.nifi.web.dao.UserDAO;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Audits user creation/removal and configuration changes.
|
||||
*/
|
||||
@Aspect
|
||||
public class UserAuditor extends NiFiAuditor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UserAuditor.class);
|
||||
|
||||
private static final String IDENTITY = "Identity";
|
||||
|
||||
/**
|
||||
* Audits the creation of policies via createUser().
|
||||
*
|
||||
* This method only needs to be run 'after returning'. However, in Java 7 the order in which these methods are returned from Class.getDeclaredMethods (even though there is no order guaranteed)
|
||||
* seems to differ from Java 6. SpringAOP depends on this ordering to determine advice precedence. By normalizing all advice into Around advice we can alleviate this issue.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.User createUser(org.apache.nifi.web.api.dto.UserDTO))")
|
||||
public User createUserAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
|
||||
// create the access user
|
||||
User user = (User) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the user action...
|
||||
final Action action = generateAuditRecord(user, Operation.Add);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the configuration of a single user.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param userDTO dto
|
||||
* @param userDAO dao
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.User updateUser(org.apache.nifi.web.api.dto.UserDTO)) && "
|
||||
+ "args(userDTO) && "
|
||||
+ "target(userDAO)")
|
||||
public User updateUserAdvice(ProceedingJoinPoint proceedingJoinPoint, UserDTO userDTO, UserDAO userDAO) throws Throwable {
|
||||
// determine the initial values for each property/setting thats changing
|
||||
User user = userDAO.getUser(userDTO.getId());
|
||||
final Map<String, String> values = extractConfiguredPropertyValues(user, userDTO);
|
||||
|
||||
// update the user state
|
||||
final User updatedUser = (User) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the user action...
|
||||
// get the updated verbose state
|
||||
user = userDAO.getUser(updatedUser.getIdentifier());
|
||||
|
||||
// get the current user
|
||||
NiFiUser niFiUser = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (niFiUser != null) {
|
||||
// determine the updated values
|
||||
Map<String, String> updatedValues = extractConfiguredPropertyValues(user, userDTO);
|
||||
|
||||
// create a user action
|
||||
Date actionTimestamp = new Date();
|
||||
Collection<Action> actions = new ArrayList<>();
|
||||
|
||||
// go through each updated value
|
||||
for (String property : updatedValues.keySet()) {
|
||||
String newValue = updatedValues.get(property);
|
||||
String oldValue = values.get(property);
|
||||
Operation operation = null;
|
||||
|
||||
// determine the type of operation
|
||||
if (oldValue == null || newValue == null || !newValue.equals(oldValue)) {
|
||||
operation = Operation.Configure;
|
||||
}
|
||||
|
||||
// create a configuration action accordingly
|
||||
if (operation != null) {
|
||||
final FlowChangeConfigureDetails actionDetails = new FlowChangeConfigureDetails();
|
||||
actionDetails.setName(property);
|
||||
actionDetails.setValue(newValue);
|
||||
actionDetails.setPreviousValue(oldValue);
|
||||
|
||||
// create a configuration action
|
||||
FlowChangeAction configurationAction = new FlowChangeAction();
|
||||
configurationAction.setUserIdentity(niFiUser.getIdentity());
|
||||
configurationAction.setOperation(operation);
|
||||
configurationAction.setTimestamp(actionTimestamp);
|
||||
configurationAction.setSourceId(user.getIdentifier());
|
||||
configurationAction.setSourceName(user.getIdentity());
|
||||
configurationAction.setSourceType(Component.User);
|
||||
configurationAction.setActionDetails(actionDetails);
|
||||
actions.add(configurationAction);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure there are actions to record
|
||||
if (!actions.isEmpty()) {
|
||||
// save the actions
|
||||
saveActions(actions, logger);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the removal of a user via deleteUser().
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param userId user id
|
||||
* @param userDAO dao
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.User deleteUser(java.lang.String)) && "
|
||||
+ "args(userId) && "
|
||||
+ "target(userDAO)")
|
||||
public User removeUserAdvice(ProceedingJoinPoint proceedingJoinPoint, String userId, UserDAO userDAO) throws Throwable {
|
||||
// get the user before removing it
|
||||
User user = userDAO.getUser(userId);
|
||||
|
||||
// remove the user
|
||||
final User removedUser = (User) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add removal actions...
|
||||
// audit the user removal
|
||||
final Action action = generateAuditRecord(user, Operation.Remove);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return removedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a user.
|
||||
*
|
||||
* @param user user
|
||||
* @param operation operation
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(User user, Operation operation) {
|
||||
return generateAuditRecord(user, operation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a user.
|
||||
*
|
||||
* @param user user
|
||||
* @param operation operation
|
||||
* @param actionDetails details
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(User user, Operation operation, ActionDetails actionDetails) {
|
||||
FlowChangeAction action = null;
|
||||
|
||||
// get the current user
|
||||
NiFiUser niFiUser = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (niFiUser != null) {
|
||||
// create the user action for adding this user
|
||||
action = new FlowChangeAction();
|
||||
action.setUserIdentity(niFiUser.getIdentity());
|
||||
action.setOperation(operation);
|
||||
action.setTimestamp(new Date());
|
||||
action.setSourceId(user.getIdentifier());
|
||||
action.setSourceName(user.getIdentity());
|
||||
action.setSourceType(Component.User);
|
||||
|
||||
if (actionDetails != null) {
|
||||
action.setActionDetails(actionDetails);
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the values for the configured properties from the specified user.
|
||||
*/
|
||||
private Map<String, String> extractConfiguredPropertyValues(User user, UserDTO userDTO) {
|
||||
Map<String, String> values = new HashMap<>();
|
||||
|
||||
if (userDTO.getIdentity() != null) {
|
||||
values.put(IDENTITY, user.getIdentity());
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* 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.audit;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
import org.apache.nifi.action.Operation;
|
||||
import org.apache.nifi.action.details.ActionDetails;
|
||||
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
|
||||
import org.apache.nifi.authorization.Group;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
||||
import org.apache.nifi.web.dao.UserGroupDAO;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Audits user creation/removal and configuration changes.
|
||||
*/
|
||||
@Aspect
|
||||
public class UserGroupAuditor extends NiFiAuditor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UserGroupAuditor.class);
|
||||
|
||||
private static final String NAME = "Name";
|
||||
private static final String USERS = "Users";
|
||||
|
||||
/**
|
||||
* Audits the creation of policies via createUser().
|
||||
*
|
||||
* This method only needs to be run 'after returning'. However, in Java 7 the order in which these methods are returned from Class.getDeclaredMethods (even though there is no order guaranteed)
|
||||
* seems to differ from Java 6. SpringAOP depends on this ordering to determine advice precedence. By normalizing all advice into Around advice we can alleviate this issue.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserGroupDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.Group createUserGroup(org.apache.nifi.web.api.dto.UserGroupDTO))")
|
||||
public Group createUserGroupAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
|
||||
// create the access user group
|
||||
Group userGroup = (Group) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the user action...
|
||||
final Action action = generateAuditRecord(userGroup, Operation.Add);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return userGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the configuration of a single user.
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param userGroupDTO dto
|
||||
* @param userGroupDAO dao
|
||||
* @return node
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserGroupDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.Group updateUserGroup(org.apache.nifi.web.api.dto.UserGroupDTO)) && "
|
||||
+ "args(userGroupDTO) && "
|
||||
+ "target(userGroupDAO)")
|
||||
public Group updateUserAdvice(ProceedingJoinPoint proceedingJoinPoint, UserGroupDTO userGroupDTO, UserGroupDAO userGroupDAO) throws Throwable {
|
||||
// determine the initial values for each property/setting thats changing
|
||||
Group user = userGroupDAO.getUserGroup(userGroupDTO.getId());
|
||||
final Map<String, String> values = extractConfiguredPropertyValues(user, userGroupDTO);
|
||||
|
||||
// update the user state
|
||||
final Group updatedUserGroup = (Group) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add the user group action...
|
||||
// get the updated verbose state
|
||||
user = userGroupDAO.getUserGroup(updatedUserGroup.getIdentifier());
|
||||
|
||||
// get the current user
|
||||
NiFiUser niFiUser = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (niFiUser != null) {
|
||||
// determine the updated values
|
||||
Map<String, String> updatedValues = extractConfiguredPropertyValues(user, userGroupDTO);
|
||||
|
||||
// create a user action
|
||||
Date actionTimestamp = new Date();
|
||||
Collection<Action> actions = new ArrayList<>();
|
||||
|
||||
// go through each updated value
|
||||
for (String property : updatedValues.keySet()) {
|
||||
String newValue = updatedValues.get(property);
|
||||
String oldValue = values.get(property);
|
||||
Operation operation = null;
|
||||
|
||||
// determine the type of operation
|
||||
if (oldValue == null || newValue == null || !newValue.equals(oldValue)) {
|
||||
operation = Operation.Configure;
|
||||
}
|
||||
|
||||
// create a configuration action accordingly
|
||||
if (operation != null) {
|
||||
final FlowChangeConfigureDetails actionDetails = new FlowChangeConfigureDetails();
|
||||
actionDetails.setName(property);
|
||||
actionDetails.setValue(newValue);
|
||||
actionDetails.setPreviousValue(oldValue);
|
||||
|
||||
// create a configuration action
|
||||
FlowChangeAction configurationAction = new FlowChangeAction();
|
||||
configurationAction.setUserIdentity(niFiUser.getIdentity());
|
||||
configurationAction.setOperation(operation);
|
||||
configurationAction.setTimestamp(actionTimestamp);
|
||||
configurationAction.setSourceId(user.getIdentifier());
|
||||
configurationAction.setSourceName(user.getName());
|
||||
configurationAction.setSourceType(Component.UserGroup);
|
||||
configurationAction.setActionDetails(actionDetails);
|
||||
actions.add(configurationAction);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure there are actions to record
|
||||
if (!actions.isEmpty()) {
|
||||
// save the actions
|
||||
saveActions(actions, logger);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedUserGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audits the removal of a user via deleteUser().
|
||||
*
|
||||
* @param proceedingJoinPoint join point
|
||||
* @param userGroupId user id
|
||||
* @param userGroupDAO dao
|
||||
* @throws Throwable ex
|
||||
*/
|
||||
@Around("within(org.apache.nifi.web.dao.UserGroupDAO+) && "
|
||||
+ "execution(org.apache.nifi.authorization.Group deleteUserGroup(java.lang.String)) && "
|
||||
+ "args(userGroupId) && "
|
||||
+ "target(userGroupDAO)")
|
||||
public Group removeUserAdvice(ProceedingJoinPoint proceedingJoinPoint, String userGroupId, UserGroupDAO userGroupDAO) throws Throwable {
|
||||
// get the user group before removing it
|
||||
Group userGroup = userGroupDAO.getUserGroup(userGroupId);
|
||||
|
||||
// remove the user group
|
||||
final Group removedUserGroup = (Group) proceedingJoinPoint.proceed();
|
||||
|
||||
// if no exceptions were thrown, add removal actions...
|
||||
// audit the user removal
|
||||
final Action action = generateAuditRecord(userGroup, Operation.Remove);
|
||||
|
||||
// save the actions
|
||||
if (action != null) {
|
||||
saveAction(action, logger);
|
||||
}
|
||||
|
||||
return removedUserGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a user group.
|
||||
*
|
||||
* @param userGroup userGroup
|
||||
* @param operation operation
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(Group userGroup, Operation operation) {
|
||||
return generateAuditRecord(userGroup, operation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an audit record for the creation of a user group.
|
||||
*
|
||||
* @param userGroup userGroup
|
||||
* @param operation operation
|
||||
* @param actionDetails details
|
||||
* @return action
|
||||
*/
|
||||
public Action generateAuditRecord(Group userGroup, Operation operation, ActionDetails actionDetails) {
|
||||
FlowChangeAction action = null;
|
||||
|
||||
// get the current user
|
||||
NiFiUser niFiUser = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
// ensure the user was found
|
||||
if (niFiUser != null) {
|
||||
// create the user action for adding this user
|
||||
action = new FlowChangeAction();
|
||||
action.setUserIdentity(niFiUser.getIdentity());
|
||||
action.setOperation(operation);
|
||||
action.setTimestamp(new Date());
|
||||
action.setSourceId(userGroup.getIdentifier());
|
||||
action.setSourceName(userGroup.getName());
|
||||
action.setSourceType(Component.UserGroup);
|
||||
|
||||
if (actionDetails != null) {
|
||||
action.setActionDetails(actionDetails);
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the values for the configured properties from the specified user group.
|
||||
*/
|
||||
private Map<String, String> extractConfiguredPropertyValues(Group group, UserGroupDTO userGroupDTO) {
|
||||
Map<String, String> values = new HashMap<>();
|
||||
|
||||
if (userGroupDTO.getIdentity() != null) {
|
||||
values.put(NAME, group.getName());
|
||||
}
|
||||
if (userGroupDTO.getUsers() != null) {
|
||||
// get each of the auto terminated relationship names
|
||||
final List<String> currentUsers = new ArrayList<>(group.getUsers());
|
||||
|
||||
// sort them and include in the configuration
|
||||
Collections.sort(currentUsers, Collator.getInstance(Locale.US));
|
||||
values.put(USERS, StringUtils.join(currentUsers, ", "));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,28 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
|
@ -215,7 +194,26 @@ import org.apache.nifi.web.util.SnippetUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Implementation of NiFiServiceFacade that performs revision checking.
|
||||
|
@ -978,6 +976,20 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
controllerFacade.save();
|
||||
logger.debug("Deletion of component {} was successful", authorizable);
|
||||
|
||||
try {
|
||||
// since the component is being deleted, also delete any relevant access policies
|
||||
final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, authorizable);
|
||||
if (authorizable.getResource().getIdentifier().equals(readPolicy.getResource())) {
|
||||
accessPolicyDAO.deleteAccessPolicy(readPolicy.getIdentifier());
|
||||
}
|
||||
final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, authorizable);
|
||||
if (authorizable.getResource().getIdentifier().equals(writePolicy.getResource())) {
|
||||
accessPolicyDAO.deleteAccessPolicy(writePolicy.getIdentifier());
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.warn(String.format("Unable to remove access policy for %s after component removal.", authorizable.getResource().getIdentifier()), e);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
});
|
||||
|
@ -2650,6 +2662,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
case Connection:
|
||||
authorizable = authorizableLookup.getConnection(sourceId);
|
||||
break;
|
||||
case AccessPolicy:
|
||||
authorizable = authorizableLookup.getAccessPolicyById(sourceId);
|
||||
break;
|
||||
case User:
|
||||
case UserGroup:
|
||||
authorizable = authorizableLookup.getTenant();
|
||||
break;
|
||||
default:
|
||||
throw new WebApplicationException(Response.serverError().entity("An unexpected type of component is the source of this action.").build());
|
||||
}
|
||||
|
|
|
@ -646,9 +646,7 @@ public class ControllerResource extends ApplicationResource {
|
|||
throw new IllegalArgumentException("The end date must be specified.");
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.DELETE);
|
||||
}
|
||||
// Note: History requests are not replicated throughout the cluster and are instead handled by the nodes independently
|
||||
|
||||
// handle expects request (usually from the cluster manager)
|
||||
final boolean validationPhase = isValidationPhase(httpServletRequest);
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.apache.nifi.authorization.AuthorizationResult;
|
|||
import org.apache.nifi.authorization.AuthorizationResult.Result;
|
||||
import org.apache.nifi.authorization.Authorizer;
|
||||
import org.apache.nifi.authorization.RequestAction;
|
||||
import org.apache.nifi.authorization.Resource;
|
||||
import org.apache.nifi.authorization.UserContextKeys;
|
||||
import org.apache.nifi.authorization.resource.Authorizable;
|
||||
import org.apache.nifi.authorization.resource.ResourceFactory;
|
||||
|
@ -50,8 +49,8 @@ import org.apache.nifi.web.api.dto.AboutDTO;
|
|||
import org.apache.nifi.web.api.dto.BannerDTO;
|
||||
import org.apache.nifi.web.api.dto.BulletinBoardDTO;
|
||||
import org.apache.nifi.web.api.dto.BulletinQueryDTO;
|
||||
import org.apache.nifi.web.api.dto.ClusterSummaryDTO;
|
||||
import org.apache.nifi.web.api.dto.ClusterDTO;
|
||||
import org.apache.nifi.web.api.dto.ClusterSummaryDTO;
|
||||
import org.apache.nifi.web.api.dto.NodeDTO;
|
||||
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
|
||||
import org.apache.nifi.web.api.dto.RevisionDTO;
|
||||
|
@ -237,30 +236,6 @@ public class FlowResource extends ApplicationResource {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isAuthorized(final RequestAction action, final Resource resource) {
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
|
||||
final Map<String,String> userContext;
|
||||
if (!StringUtils.isBlank(user.getClientAddress())) {
|
||||
userContext = new HashMap<>();
|
||||
userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), user.getClientAddress());
|
||||
} else {
|
||||
userContext = null;
|
||||
}
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.resource(resource)
|
||||
.identity(user.getIdentity())
|
||||
.anonymous(user.isAnonymous())
|
||||
.accessAttempt(false)
|
||||
.action(action)
|
||||
.userContext(userContext)
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
return Result.Approved.equals(result.getResult());
|
||||
}
|
||||
|
||||
// ----
|
||||
// flow
|
||||
// ----
|
||||
|
@ -2146,9 +2121,7 @@ public class FlowResource extends ApplicationResource {
|
|||
}
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
// Note: History requests are not replicated throughout the cluster and are instead handled by the nodes independently
|
||||
|
||||
// create a history query
|
||||
final HistoryQueryDTO query = new HistoryQueryDTO();
|
||||
|
@ -2231,9 +2204,7 @@ public class FlowResource extends ApplicationResource {
|
|||
throw new IllegalArgumentException("The action id must be specified.");
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
// Note: History requests are not replicated throughout the cluster and are instead handled by the nodes independently
|
||||
|
||||
// get the specified action
|
||||
final ActionDTO action = serviceFacade.getAction(id.getInteger());
|
||||
|
@ -2284,9 +2255,7 @@ public class FlowResource extends ApplicationResource {
|
|||
|
||||
authorizeFlow();
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
// Note: History requests are not replicated throughout the cluster and are instead handled by the nodes independently
|
||||
|
||||
// create the response entity
|
||||
final ComponentHistoryEntity entity = new ComponentHistoryEntity();
|
||||
|
|
|
@ -491,6 +491,21 @@
|
|||
<property name="auditService" ref="auditService"/>
|
||||
<property name="processGroupDAO" ref="processGroupDAO"/>
|
||||
</bean>
|
||||
<bean id="policyAuditor" class="org.apache.nifi.audit.AccessPolicyAuditor">
|
||||
<property name="serviceFacade" ref="serviceFacade"/>
|
||||
<property name="auditService" ref="auditService"/>
|
||||
<property name="processGroupDAO" ref="processGroupDAO"/>
|
||||
</bean>
|
||||
<bean id="userAuditor" class="org.apache.nifi.audit.UserAuditor">
|
||||
<property name="serviceFacade" ref="serviceFacade"/>
|
||||
<property name="auditService" ref="auditService"/>
|
||||
<property name="processGroupDAO" ref="processGroupDAO"/>
|
||||
</bean>
|
||||
<bean id="userGroupAuditor" class="org.apache.nifi.audit.UserGroupAuditor">
|
||||
<property name="serviceFacade" ref="serviceFacade"/>
|
||||
<property name="auditService" ref="auditService"/>
|
||||
<property name="processGroupDAO" ref="processGroupDAO"/>
|
||||
</bean>
|
||||
|
||||
<!-- NiFi locking -->
|
||||
<bean id="serviceFacadeLock" class="org.apache.nifi.web.NiFiServiceFacadeLock"/>
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
<div class="button-spacer-small"> </div>
|
||||
<div id="operate-policy" class="action-button" title="Access Policies">
|
||||
<button ng-click="appCtrl.nf.Actions['managePolicies'](appCtrl.nf.CanvasUtils.getSelection());"
|
||||
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().size() > 1">
|
||||
ng-disabled="!(appCtrl.nf.CanvasUtils.getSelection().size() <= 1 && appCtrl.nf.Common.canAccessTenants())">
|
||||
<div class="graph-control-action-icon fa fa-key"></div></button>
|
||||
</div>
|
||||
<div class="button-spacer-large"> </div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div id="global-policy-controls" class="hidden policy-controls">
|
||||
<div id="policy-type-list"></div>
|
||||
<div id="controller-policy-target"></div>
|
||||
<div id="controller-policy-target" class="hidden"></div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div id="component-policy-controls" class="hidden policy-controls">
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
<div id="select-template-container">
|
||||
<div id="template-browse-container">
|
||||
<span id="select-template-label">Select Template</span>
|
||||
<button id="select-template-button" class="fa fa-search">
|
||||
<div id="select-template-button">
|
||||
<button class="fa fa-search"></button>
|
||||
<form id="template-upload-form" enctype="multipart/form-data" method="post">
|
||||
<input type="file" name="template" id="template-file-field"/>
|
||||
</form>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="submit-template-container">
|
||||
|
|
|
@ -213,29 +213,41 @@ nf.PolicyManagement = (function () {
|
|||
// policy type listing
|
||||
$('#policy-type-list').combo({
|
||||
options: [{
|
||||
text: 'access the user interface',
|
||||
value: 'flow'
|
||||
text: 'view the user interface',
|
||||
value: 'flow',
|
||||
description: 'Allows users to view the user interface'
|
||||
}, {
|
||||
text: 'access the controller',
|
||||
value: 'controller'
|
||||
value: 'controller',
|
||||
description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, and Nodes in the Cluster'
|
||||
}, {
|
||||
text: 'query provenance',
|
||||
value: 'provenance'
|
||||
value: 'provenance',
|
||||
description: 'Allows users to submit a Provenance Search and request Event Lineage'
|
||||
}, {
|
||||
text: 'access all policies',
|
||||
value: 'policies'
|
||||
value: 'policies',
|
||||
description: 'Allows users to view/modify the policies for all components'
|
||||
}, {
|
||||
text: 'access users/user groups',
|
||||
value: 'tenants',
|
||||
description: 'Allows users to view/modify the users and user groups'
|
||||
}, {
|
||||
text: 'retrieve site-to-site details',
|
||||
value: 'site-to-site'
|
||||
value: 'site-to-site',
|
||||
description: 'Allows other NiFi instances to retrieve Site-To-Site details of this NiFi'
|
||||
}, {
|
||||
text: 'view system diagnostics',
|
||||
value: 'system'
|
||||
value: 'system',
|
||||
description: 'Allows users to view System Diagnostics'
|
||||
}, {
|
||||
text: 'proxy user requests',
|
||||
value: 'proxy'
|
||||
value: 'proxy',
|
||||
description: 'Allows proxy machines to send requests on the behalf of others'
|
||||
}, {
|
||||
text: 'access counters',
|
||||
value: 'counters'
|
||||
value: 'counters',
|
||||
description: 'Allows users to view/modify Counters'
|
||||
}],
|
||||
select: function (option) {
|
||||
if (initialized) {
|
||||
|
@ -243,7 +255,7 @@ nf.PolicyManagement = (function () {
|
|||
$('#selected-policy-type').text(option.value);
|
||||
|
||||
// if the option is for a specific component
|
||||
if (option.value === 'controller' || option.value === 'counters' || option.value === 'policies') {
|
||||
if (option.value === 'controller' || option.value === 'counters' || option.value === 'policies' || option.value === 'tenants') {
|
||||
// update the policy target and let it relaod the policy
|
||||
$('#controller-policy-target').combo('setSelectedOption', {
|
||||
'value': 'read'
|
||||
|
@ -289,26 +301,33 @@ nf.PolicyManagement = (function () {
|
|||
$('#component-policy-target').combo({
|
||||
options: [{
|
||||
text: 'view the component',
|
||||
value: 'read-component'
|
||||
value: 'read-component',
|
||||
description: 'Allows users to view component configuration details'
|
||||
}, {
|
||||
text: 'modify the component',
|
||||
value: 'write-component'
|
||||
value: 'write-component',
|
||||
description: 'Allows users to modify component configuration details'
|
||||
}, {
|
||||
text: 'view the provenance events',
|
||||
value: 'read-provenance-events'
|
||||
value: 'read-provenance-events',
|
||||
description: 'Allows users to access provenance events and content for this component'
|
||||
}, {
|
||||
text: 'view the policies',
|
||||
value: 'read-policies'
|
||||
value: 'read-policies',
|
||||
description: 'Allows users to view the list of users who can view/modify this component'
|
||||
}, {
|
||||
text: 'modify the policies',
|
||||
value: 'write-policies'
|
||||
value: 'write-policies',
|
||||
description: 'Allows users to modify the list of users who can view/modify this component'
|
||||
}, {
|
||||
text: 'receive data via site-to-site',
|
||||
value: 'write-receive-data',
|
||||
description: 'Allows this port to receive data from these NiFi instances',
|
||||
disabled: true
|
||||
}, {
|
||||
}, {
|
||||
text: 'send data via site-to-site',
|
||||
value: 'write-send-data',
|
||||
description: 'Allows this port to send data to these NiFi instances',
|
||||
disabled: true
|
||||
}],
|
||||
select: function (option) {
|
||||
|
@ -618,9 +637,6 @@ nf.PolicyManagement = (function () {
|
|||
|
||||
// allow removal and modification as the policy is not inherited
|
||||
$('#new-policy-user-button').prop('disabled', false);
|
||||
|
||||
// update the refresh timestamp
|
||||
$('#policy-last-refreshed').text(policyEntity.generated);
|
||||
|
||||
// see if the policy is for this resource
|
||||
if (resourceAndAction.resource === policy.resource) {
|
||||
|
@ -651,33 +667,54 @@ nf.PolicyManagement = (function () {
|
|||
url: '../nifi-api/policies/' + resourceAndAction.action + resourceAndAction.resource,
|
||||
dataType: 'json'
|
||||
}).done(function (policyEntity) {
|
||||
var policy = policyEntity.component;
|
||||
// return OK so we either have access to the policy or we don't have access to an inherited policy
|
||||
|
||||
$('#policy-message').text(policy.resource);
|
||||
// update the refresh timestamp
|
||||
$('#policy-last-refreshed').text(policyEntity.generated);
|
||||
|
||||
// populate the policy details
|
||||
populatePolicy(policyEntity);
|
||||
// ensure appropriate actions for the loaded policy
|
||||
if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
|
||||
var policy = policyEntity.component;
|
||||
|
||||
$('#policy-message').text(policy.resource);
|
||||
|
||||
// populate the policy details
|
||||
populatePolicy(policyEntity);
|
||||
} else {
|
||||
// reset the policy
|
||||
resetPolicy();
|
||||
|
||||
// show an appropriate message
|
||||
$('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
|
||||
$('#new-policy-message').hide();
|
||||
$('#override-policy-message').show();
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
}).fail(function (xhr, status, error) {
|
||||
if (xhr.status === 404) {
|
||||
// show an appropriate messate
|
||||
$('#policy-message').text('No policy for the specified resource. ');
|
||||
// reset the policy
|
||||
resetPolicy();
|
||||
|
||||
// show an appropriate message
|
||||
$('#policy-message').text('No policy for the specified resource.');
|
||||
$('#new-policy-message').show();
|
||||
$('#override-policy-message').hide();
|
||||
|
||||
// reset the current policy
|
||||
$('#policy-table').removeData('policy');
|
||||
deferred.resolve();
|
||||
} else if (xhr.status === 403) {
|
||||
// reset the policy
|
||||
resetPolicy();
|
||||
|
||||
// require non inherited policy for removal and modification
|
||||
$('#new-policy-user-button').prop('disabled', true);
|
||||
$('#delete-policy-button').prop('disabled', true);
|
||||
|
||||
// populate the table with no users
|
||||
populateTable([], []);
|
||||
// show an appropriate message
|
||||
$('#policy-message').text('Not authorized to access the policy for the specified resource.');
|
||||
$('#new-policy-message').hide();
|
||||
$('#override-policy-message').hide();
|
||||
|
||||
deferred.resolve();
|
||||
} else {
|
||||
resetPolicy();
|
||||
|
||||
deferred.reject();
|
||||
nf.Common.handleAjaxError(xhr, status, error);
|
||||
}
|
||||
|
@ -754,7 +791,23 @@ nf.PolicyManagement = (function () {
|
|||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (policyEntity) {
|
||||
populatePolicy(policyEntity);
|
||||
// ensure appropriate actions for the loaded policy
|
||||
if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
|
||||
var policy = policyEntity.component;
|
||||
|
||||
$('#policy-message').text(policy.resource);
|
||||
|
||||
// populate the policy details
|
||||
populatePolicy(policyEntity);
|
||||
} else {
|
||||
// reset the policy
|
||||
resetPolicy();
|
||||
|
||||
// show an appropriate message
|
||||
$('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
|
||||
$('#new-policy-message').hide();
|
||||
$('#override-policy-message').show();
|
||||
}
|
||||
}).fail(nf.Common.handleAjaxError);
|
||||
} else {
|
||||
nf.Dialog.showOkDialog({
|
||||
|
@ -769,7 +822,7 @@ nf.PolicyManagement = (function () {
|
|||
*/
|
||||
var showPolicy = function () {
|
||||
// show the configuration dialog
|
||||
nf.Shell.showContent('#policy-management').done(function () {
|
||||
nf.Shell.showContent('#policy-management').always(function () {
|
||||
reset();
|
||||
});
|
||||
|
||||
|
@ -786,11 +839,28 @@ nf.PolicyManagement = (function () {
|
|||
$('#override-policy-message').hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the policy.
|
||||
*/
|
||||
var resetPolicy = function () {
|
||||
resetPolicyMessage();
|
||||
|
||||
// reset button state
|
||||
$('#delete-policy-button').prop('disabled', true);
|
||||
$('#new-policy-user-button').prop('disabled', true);
|
||||
|
||||
// reset the current policy
|
||||
$('#policy-table').removeData('policy');
|
||||
|
||||
// populate the table with no users
|
||||
populateTable([], []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the policy management dialog.
|
||||
*/
|
||||
var reset = function () {
|
||||
resetPolicyMessage();
|
||||
resetPolicy();
|
||||
|
||||
// clear the selected policy details
|
||||
$('#selected-policy-type').text('');
|
||||
|
@ -800,10 +870,6 @@ nf.PolicyManagement = (function () {
|
|||
|
||||
// clear the selected component details
|
||||
$('div.policy-selected-component-container').hide();
|
||||
|
||||
// reset button state
|
||||
$('#delete-policy-button').prop('disabled', false);
|
||||
$('#new-policy-user-button').prop('disabled', false);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -885,7 +951,7 @@ nf.PolicyManagement = (function () {
|
|||
$('#selected-policy-component-id').text(d.id);
|
||||
populateComponentResource('controller-services');
|
||||
|
||||
return loadPolicy().done(showPolicy);
|
||||
return loadPolicy().always(showPolicy);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -913,7 +979,7 @@ nf.PolicyManagement = (function () {
|
|||
$('#selected-policy-component-id').text(d.id);
|
||||
populateComponentResource('reporting-tasks');
|
||||
|
||||
return loadPolicy().done(showPolicy);
|
||||
return loadPolicy().always(showPolicy);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -941,7 +1007,7 @@ nf.PolicyManagement = (function () {
|
|||
$('#selected-policy-component-id').text(d.id);
|
||||
populateComponentResource('templates');
|
||||
|
||||
return loadPolicy().done(showPolicy);
|
||||
return loadPolicy().always(showPolicy);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -995,7 +1061,7 @@ nf.PolicyManagement = (function () {
|
|||
// populate the initial resource
|
||||
populateComponentResource(resource);
|
||||
|
||||
return loadPolicy().done(showPolicy);
|
||||
return loadPolicy().always(showPolicy);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1021,7 +1087,7 @@ nf.PolicyManagement = (function () {
|
|||
$('#selected-policy-action').text('read');
|
||||
}
|
||||
|
||||
return loadPolicy().done(showPolicy);
|
||||
},
|
||||
return loadPolicy().always(showPolicy);
|
||||
}
|
||||
};
|
||||
}());
|
Loading…
Reference in New Issue