/*
* 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.authorization;
import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.web.ResourceNotFoundException;
import java.util.Map;
import java.util.Objects;
/**
* Authorizes references to Controller Services. Utilizes when Processors, Controller Services, and Reporting Tasks are created and updated.
*/
public final class AuthorizeControllerServiceReference {
/**
* Authorizes any referenced controller services from the specified configurable component.
*
* @param authorizable authorizable that may reference a controller service
* @param authorizer authorizer
* @param lookup lookup
*/
public static void authorizeControllerServiceReferences(final ComponentAuthorizable authorizable, final Authorizer authorizer,
final AuthorizableLookup lookup, final boolean authorizeTransitiveServices) {
// consider each property when looking for service references
authorizable.getPropertyDescriptors().stream().forEach(descriptor -> {
// if this descriptor identifies a controller service
if (descriptor.getControllerServiceDefinition() != null) {
// get the service id
final String serviceId = authorizable.getValue(descriptor);
// authorize the service if configured
if (serviceId != null) {
try {
final ComponentAuthorizable currentServiceAuthorizable = lookup.getControllerService(serviceId);
currentServiceAuthorizable.getAuthorizable().authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
if (authorizeTransitiveServices) {
authorizeControllerServiceReferences(currentServiceAuthorizable, authorizer, lookup, authorizeTransitiveServices);
}
} catch (ResourceNotFoundException e) {
// ignore if the resource is not found, if the referenced service was previously deleted, it should not stop this action
}
}
}
});
}
/**
* Authorizes the proposed properties for the specified authorizable.
*
* @param proposedProperties proposed properties
* @param authorizable authorizable that may reference a controller service
* @param authorizer authorizer
* @param lookup lookup
*/
public static void authorizeControllerServiceReferences(final Map<String, String> proposedProperties, final ComponentAuthorizable authorizable,
final Authorizer authorizer, final AuthorizableLookup lookup) {
// only attempt to authorize if properties are changing
if (proposedProperties != null) {
final NiFiUser user = NiFiUserUtils.getNiFiUser();
for (final Map.Entry<String, String> entry : proposedProperties.entrySet()) {
final String propertyName = entry.getKey();
final PropertyDescriptor propertyDescriptor = authorizable.getPropertyDescriptor(propertyName);
// if this descriptor identifies a controller service
if (propertyDescriptor.getControllerServiceDefinition() != null) {
final String currentValue = authorizable.getValue(propertyDescriptor);
final String proposedValue = entry.getValue();
// if the value is changing
if (!Objects.equals(currentValue, proposedValue)) {
// ensure access to the old service
if (currentValue != null) {
try {
final Authorizable currentServiceAuthorizable = lookup.getControllerService(currentValue).getAuthorizable();
currentServiceAuthorizable.authorize(authorizer, RequestAction.READ, user);
} catch (ResourceNotFoundException e) {
// ignore if the resource is not found, if currentValue was previously deleted, it should not stop assignment of proposedValue
}
}
// ensure access to the new service
if (proposedValue != null) {
final Authorizable newServiceAuthorizable = lookup.getControllerService(proposedValue).getAuthorizable();
newServiceAuthorizable.authorize(authorizer, RequestAction.READ, user);
}
}
}
}
}
}
}