blob: ace5016771502ff4c9f36490eaebd99cf8b881e9 [file] [log] [blame]
/*
* 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.properties;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static java.util.Arrays.asList;
/**
* Decorator class for intermediate phase when {@link NiFiPropertiesLoader} loads the
* raw properties file and performs unprotection activities before returning a clean
* implementation of {@link NiFiProperties}.
* This encapsulates the sensitive property access logic from external consumers
* of {@code NiFiProperties}.
*/
class ProtectedNiFiProperties extends NiFiProperties implements ProtectedProperties<NiFiProperties>,
SensitivePropertyProtector<ProtectedNiFiProperties, NiFiProperties> {
private static final Logger logger = LoggerFactory.getLogger(ProtectedNiFiProperties.class);
private SensitivePropertyProtector<ProtectedNiFiProperties, NiFiProperties> propertyProtectionDelegate;
private NiFiProperties applicationProperties;
// Additional "sensitive" property key
public static final String ADDITIONAL_SENSITIVE_PROPERTIES_KEY = "nifi.sensitive.props.additional.keys";
// Default list of "sensitive" property keys
public static final List<String> DEFAULT_SENSITIVE_PROPERTIES = new ArrayList<>(asList(
SECURITY_KEY_PASSWD,
SECURITY_KEYSTORE_PASSWD,
SECURITY_TRUSTSTORE_PASSWD,
SENSITIVE_PROPS_KEY,
PROVENANCE_REPO_ENCRYPTION_KEY,
PROVENANCE_REPO_ENCRYPTION_KEY_PROVIDER_PASSWORD,
FLOWFILE_REPOSITORY_ENCRYPTION_KEY_PROVIDER_PASSWORD,
CONTENT_REPOSITORY_ENCRYPTION_KEY_PROVIDER_PASSWORD
));
public ProtectedNiFiProperties() {
this(new NiFiProperties());
}
/**
* Creates an instance containing the provided {@link NiFiProperties}.
*
* @param props the NiFiProperties to contain
*/
public ProtectedNiFiProperties(final NiFiProperties props) {
this.applicationProperties = props;
this.propertyProtectionDelegate = new ApplicationPropertiesProtector<>(this);
logger.debug("Loaded {} properties (including {} protection schemes) into ProtectedNiFiProperties", getApplicationProperties()
.getPropertyKeys().size(), getProtectedPropertyKeys().size());
}
/**
* Creates an instance containing the provided raw {@link Properties}.
*
* @param rawProps the Properties to contain
*/
public ProtectedNiFiProperties(final Properties rawProps) {
this(new NiFiProperties(rawProps));
}
@Override
public String getAdditionalSensitivePropertiesKeys() {
return getProperty(getAdditionalSensitivePropertiesKeysName());
}
@Override
public String getAdditionalSensitivePropertiesKeysName() {
return ADDITIONAL_SENSITIVE_PROPERTIES_KEY;
}
@Override
public List<String> getDefaultSensitiveProperties() {
return DEFAULT_SENSITIVE_PROPERTIES;
}
/**
* Returns the internal representation of the {@link NiFiProperties} -- protected
* or not as determined by the current state. No guarantee is made to the
* protection state of these properties. If the internal reference is null, a new
* {@link NiFiProperties} instance is created.
*
* @return the internal properties
*/
public NiFiProperties getApplicationProperties() {
if (this.applicationProperties == null) {
this.applicationProperties = new NiFiProperties();
}
return this.applicationProperties;
}
@Override
public NiFiProperties createApplicationProperties(final Properties rawProperties) {
return new NiFiProperties(rawProperties);
}
/**
* Retrieves the property value for the given property key.
*
* @param key the key of property value to lookup
* @return value of property at given key or null if not found
*/
@Override
public String getProperty(String key) {
return getApplicationProperties().getProperty(key);
}
/**
* Retrieves all known property keys.
*
* @return all known property keys
*/
@Override
public Set<String> getPropertyKeys() {
return propertyProtectionDelegate.getPropertyKeys();
}
/**
* Returns the number of properties, excluding protection scheme properties.
* <p>
* Example:
* <p>
* key: E(value, key)
* key.protected: aes/gcm/256
* key2: value2
* <p>
* would return size 2
*
* @return the count of real properties
*/
@Override
public int size() {
return propertyProtectionDelegate.size();
}
@Override
public Set<String> getPropertyKeysIncludingProtectionSchemes() {
return propertyProtectionDelegate.getPropertyKeysIncludingProtectionSchemes();
}
@Override
public List<String> getSensitivePropertyKeys() {
return propertyProtectionDelegate.getSensitivePropertyKeys();
}
@Override
public List<String> getPopulatedSensitivePropertyKeys() {
return propertyProtectionDelegate.getPopulatedSensitivePropertyKeys();
}
@Override
public boolean hasProtectedKeys() {
return propertyProtectionDelegate.hasProtectedKeys();
}
@Override
public Map<String, String> getProtectedPropertyKeys() {
return propertyProtectionDelegate.getProtectedPropertyKeys();
}
@Override
public Set<String> getProtectionSchemes() {
return propertyProtectionDelegate.getProtectionSchemes();
}
@Override
public boolean isPropertySensitive(final String key) {
return propertyProtectionDelegate.isPropertySensitive(key);
}
@Override
public boolean isPropertyProtected(final String key) {
return propertyProtectionDelegate.isPropertyProtected(key);
}
@Override
public NiFiProperties getUnprotectedProperties() throws SensitivePropertyProtectionException {
return propertyProtectionDelegate.getUnprotectedProperties();
}
@Override
public void addSensitivePropertyProvider(final SensitivePropertyProvider sensitivePropertyProvider) {
propertyProtectionDelegate.addSensitivePropertyProvider(sensitivePropertyProvider);
}
@Override
public Map<String, SensitivePropertyProvider> getSensitivePropertyProviders() {
return propertyProtectionDelegate.getSensitivePropertyProviders();
}
/**
* Returns the number of properties that are marked as protected in the provided {@link NiFiProperties} instance without requiring external creation of a {@link ProtectedNiFiProperties} instance.
*
* @param plainProperties the instance to count protected properties
* @return the number of protected properties
*/
public static int countProtectedProperties(final NiFiProperties plainProperties) {
return new ProtectedNiFiProperties(plainProperties).getProtectedPropertyKeys().size();
}
/**
* Returns the number of properties that are marked as sensitive in the provided {@link NiFiProperties} instance without requiring external creation of a {@link ProtectedNiFiProperties} instance.
*
* @param plainProperties the instance to count sensitive properties
* @return the number of sensitive properties
*/
public static int countSensitiveProperties(final NiFiProperties plainProperties) {
return new ProtectedNiFiProperties(plainProperties).getSensitivePropertyKeys().size();
}
@Override
public String toString() {
final Set<String> providers = getSensitivePropertyProviders().keySet();
return new StringBuilder("ProtectedNiFiProperties instance with ")
.append(size()).append(" properties (")
.append(getProtectedPropertyKeys().size())
.append(" protected) and ")
.append(providers.size())
.append(" sensitive property providers: ")
.append(StringUtils.join(providers, ", "))
.toString();
}
}